Audit already-implemented Data warehouse import sources for endpoints, schemas, and tables the vendor's API offers but we never wired up. Use when asked whether a source is missing endpoints, to find new endpoints a vendor has added since a source was built, to refresh COVERAGE_GAPS.md, to prioritize which source to deepen next, or to check coverage before an integration review. Covers dumping our real endpoint inventory credential-free, ranking sources by production adoption, diffing against vendor OpenAPI/GraphQL specs, and recording findings. Not for implementing a source (use implementing-warehouse-sources), adding a vendor API version (warehouse-source-new-version), or writing source docs (documenting-warehouse-sources).
npx skills add https://github.com/PostHog/posthog --skill auditing-warehouse-source-coverage
Finds endpoint gaps in sources that already work: the vendor exposes an object users want,
and we never added a table for it.
This is the reverse of implementing a new source.
Nothing here is about the ~646 scaffolded stubs.
Output goes in
products/warehouse_sources/backend/temporal/data_imports/sources/COVERAGE_GAPS.md.
Read it first: it records what a previous audit already found, so you extend it rather than rediscover it.
There are ~586 implemented sources.
You cannot diff all of them against vendor docs in one pass, and a flat list of "source X has N tables"
tells you nothing, because N should be 3 for some vendors and 40 for others.
So the audit is: **establish our real inventory, rank by who actually uses it, diff the top of that
ranking by hand, and sweep the long tail with a batched workflow.**
Depth over breadth on the sources that matter; breadth via fan-out for the rest.
Ten spec-verified sources beat 200 guesses.
Both halves have been run once. COVERAGE_GAPS.md holds the hand-audited high-adoption sources and
COVERAGE_GAPS_APPENDIX.md holds the swept remainder, so a re-run is a refresh, not a cold start.
The tail is too big to audit inline but parallelizes perfectly, since sources are independent.
What worked: one parallel() fan-out, batches of 8 sources per agent, 69 agents for 547 sources.
It cost about 6.8M subagent tokens and 3,000 tool calls, and returned 4,540 findings with zero agent
errors, so budget accordingly before starting.
Requires explicit user opt-in to run a workflow at that scale.
Design notes that mattered:
[{s, l, t, d}] (source type, label, current tables, known docs URLs) to a scratchpad JSON, give each agent an index range, and have it read its own slice. Inlining 136KB of source data into 69 prompts is pure waste.get_schemas() and is authoritative, so agents spend their budget on vendor research instead of re-reading our code.verified boolean and the exact doc_url diffed against. That URL is what makes the result auditable afterwards.gaps/thin/adequate results were verified: true and only the 5 genuine failures came back could-not-verify.Then validate the output before trusting it:
doc_urls with curl -o /dev/null -w "%{http_code}". About 95% should return 200; a low rate means agents were inventing sources.Do not read settings.py files by hand and do not trust canonical_descriptions.py alone
(it can lag the real endpoint map).
Use the registry, which reports what get_schemas actually returns.
Run scripts/dump_source_inventory.py from the repo root:
flox activate -- bash -c "PYTHONPATH=. python .agents/skills/auditing-warehouse-source-coverage/scripts/dump_source_inventory.py > /tmp/inventory.json"
It leans on Source.get_documented_tables(), which builds a credential-free placeholder config,
so it needs no secrets and hits no vendor API.
Gotchas:
{.SQLSource subclasses (Postgres, MySQL, BigQuery, Snowflake, MongoDB, Supabase, Redshift, MSSQL, ClickHouse, Neon, Convex) and file sources (Google Sheets, Custom) introspect user schemas and legitimately return nothing. Exclude them from the audit entirely; there is no fixed endpoint set to be missing.A gap only matters in proportion to who hits it.
Rank by distinct projects with a live connection of that source type, pulling the synced Postgres
replicas in the internal dogfood project (US project 2), which cover both regions:
SELECT source_type, count() AS connections, count(DISTINCT team_id) AS teams
FROM (
SELECT source_type, team_id FROM postgres_posthog_externaldatasource WHERE deleted = false
UNION ALL
SELECT source_type, team_id FROM eu_postgres_posthog_externaldatasource WHERE deleted = false
)
GROUP BY source_type
ORDER BY teams DESC
Confirm column names against system.information_schema.columns first; the replica schema drifts.
See the analyzing-insights-across-teams skill for how these replicas are set up.
Then join the ranking to the inventory table counts.
The interesting signal is a low table count with high adoption — that is where a small amount of
work reaches the most people.
Connection counts are internal operational data.
Use them to prioritize, but never write them into a committed doc, PR description, or commit message.
This repo is public. Convert them to relative tiers before publishing anything.
Work down the ranking. For each source, get a machine-readable spec and diff it against our
endpoint list.
Prefer specs over prose docs, and prefer curl over WebFetch.
WebFetch summarizes with a small model and reliably drops most of an API reference; it answered
"I cannot find a list of resources" for both the Stripe and HubSpot references. Fetch the spec and
parse it yourself instead.
Specs that worked on 2026-07-26:
| Vendor | Spec |
| ---------- | -------------------------------------------------------------------------------------------------------------------- |
| Stripe | https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json |
| GitHub | https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json |
| Klaviyo | https://raw.githubusercontent.com/klaviyo/openapi/main/openapi/stable.json |
| Clerk | https://raw.githubusercontent.com/clerk/openapi-specs/main/bapi/2024-10-01.yml |
| Zendesk | https://developer.zendesk.com/zendesk/oas.yaml |
| Mailchimp | https://api.mailchimp.com/schema/3.0/Swagger.json?expand |
| Sentry | https://raw.githubusercontent.com/getsentry/sentry-api-schema/main/openapi-derefed.json |
| Cloudflare | https://raw.githubusercontent.com/cloudflare/api-schemas/main/openapi.json |
For a vendor with no published spec, try in order: an llms.txt, a public SDK's resource modules
(client libraries enumerate every resource), the GraphQL introspection schema, then the docs sitemap.
HubSpot's llms.txt covers only apps and CMS, not the API reference, so it is not useful here.
Extract the resource list by pattern-matching paths that are collection GETs, then set-difference
against our tables. Sketch:
import json, re
spec = json.load(open("spec.json"))
tops = {
m.group(1)
for p, ops in spec["paths"].items()
if "get" in ops and (m := re.fullmatch(r"/v1/([a-z0-9_]+(?:/[a-z0-9_]+)?)", p))
}
Two things to get right:
issues/comments and pulls/comments, which are two of its most valuable endpoints. Run the extraction at one and two segments and read both.reports/{id}/email-activity and Klaviyo's flow messages are nested under a parent we already sync, so a top-level-only diff reports full coverage.A raw set difference is noise. Most vendors have endpoints nobody wants in a warehouse.
For each missing endpoint ask:
dealstage ID with no pipelines table; Linear issues carry a state ID with no workflow_states. Small endpoint, large unlock. Always check for these first.sessions, Zendesk satisfaction_ratings, Mailchimp per-recipient opens and clicks. If a vendor's own marketing leads with a number we cannot produce, that is a real gap.ENDPOINTS tuple. Flag these separately; they need design.Also check our side for half-finished threads before writing a gap up as new work:
cd products/warehouse_sources/backend/temporal/data_imports/sources
grep -rniE "TODO|FIXME|not (yet )?(supported|implemented)" <source>/*.py | grep -vi test
HubSpot's WEB_ANALYTICS_EVENTS_ENDPOINT is defined in settings.py and referenced nowhere,
which makes it a cheaper item than it looks.
Before writing up, re-read your per-source findings for repeats.
Themes are more actionable than 40 separate bullets, and they change how the work gets scheduled.
Tag the findings rather than eyeballing them. Regex the endpoint and why fields of every gap into
theme buckets and count. A measured prevalence is far more persuasive to whoever schedules the work
than "this seems common", and it tells you which theme to fund first.
Patterns found so far, all still open, with their measured share of the 4,540 swept gaps:
When you find a new theme, add it to the patterns section of COVERAGE_GAPS.md.
Update COVERAGE_GAPS.md in place. Keep its conventions:
State these rather than letting a reader assume otherwise:
fields[...] params, or properties allowlists. That is a separate and probably larger audit than this one.implementing-warehouse-sources — building a source, or adding the endpoints this audit found.warehouse-source-new-version — a vendor shipped a new API version. A version bump often adds endpoints, so it is a good trigger to re-audit that one source.documenting-warehouse-sources — the public posthog.com docs for a source, which render from get_documented_tables(), the same call this audit uses.Document technical debt, anti-patterns, and patterns to avoid from analyzed frameworks. Use when (1) creating a "Do Not Repeat" list from framework analysis, (2) categorizing observed code smells and issues, (3) assessing severity of architectural problems, (4) generating remediation suggestions, or (5) synthesizing lessons learned across multiple frameworks.
> Run an AI impact assessment — structured intake, risk analysis, regulatory classification per regime in scope, policy consistency diff, and recommendation with conditions. Uses the house-style structure learned from the seed impact assessment in `~/.claude/plugins/config/claude-for-legal/ai-governance-legal/CLAUDE.md`. Use when user says "impact assessment for", "assess this AI use case", "run an AIA", "generate an AIA", "we need to document this AI system", "AI risk assessment for X", or follows a conditional triage result.
Produce a proposed marked-up policy redraft that closes a gap found by /regulatory-legal:gaps or /regulatory-legal:policy-diff. A first draft for internal review — not for direct application to approved policy documents. Use when the user says "redraft the policy", "draft the policy fix", "mark up the policy", or when gap-surfacer hands off a gap for drafting.
> Scan the Obsidian wiki and automatically discover missing cross-references between pages. Use this skill when the user says "link my pages", "find missing links", "cross-reference", "connect my wiki", "add wikilinks", "what pages should be linked", or after any large ingestion to ensure new pages are woven into the existing knowledge graph. Also trigger when the user mentions "orphan pages" in the context of wanting to connect them, or says things like "my wiki feels disconnected" or "pages aren't linked well". This is a write-heavy skill — it actually modifies pages to add links, unlike wiki-lint which just reports issues.
> Scan the Obsidian wiki for page-level identity collisions — different pages covering the same concept under different names (e.g. "RSC" vs "React Server Components") — and merge them. Use this skill when the user says "dedup my wiki", "find duplicate pages", "merge duplicates", "identity resolution", "consolidate my wiki", "I have duplicate pages", or "my wiki has two pages for the same thing". Distinct from wiki-lint (which checks structure) and cross-linker (which adds links) — this skill makes destructive page-level merges and requires careful confirmation.
> Audit and maintain the health of the Obsidian wiki. Use this skill when the user wants to check their wiki for issues, find orphaned pages, detect contradictions, identify stale content, fix broken wikilinks, or perform general maintenance on their knowledge base. Also triggers on "clean up the wiki", "what needs fixing", "audit my notes", or "wiki health check". Add --consolidate to switch from for orphans, corrects lifecycle states, demotes stale peripheral pages, normalizes tag aliases, and adds contradiction callouts — all with a dry-run preview and explicit user confirmation before any writes.
Use when building or maintaining a personal LLM-powered knowledge base. Triggers: ingesting sources into a wiki, querying wiki knowledge, linting wiki quality, 'add to wiki', 'what do I know about', or any mention of 'LLM wiki' or 'Karpathy wiki'.
Reviews an ADK integration documentation page (a Markdown file under docs/integrations/) or an integration pull request for correctness, structure, style, working code, valid links, and catalog conventions. Produces a prioritized review report, a recommended decision (approve, request changes, or close PR), a top-level review response, and draft line-anchored comments; only fixes issues when explicitly asked. Triggers on "integration-review", "review integration page", "review integration PR", "review this integration", "check integration docs".
Take posthog/auditing-warehouse-source-coverage from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.