| name | missing_docs |
| description | Find documentation gaps in Warp's Astro Starlight docs by auditing coverage against code surfaces in the public warp client repo and warp-server and against the weekly release changelog, decide which gaps actually warrant docs, then draft only those. Use when asked to find missing docs, audit documentation coverage, identify undocumented features, draft docs for new features, detect doc-impacting code changes since the last audit, or do a docs coverage check. Runs a Python audit script (coverage + snapshot-based change detection), gates every candidate against the documentation-worthiness criteria, then researches source code and writes first-pass doc pages for the ones that pass. Can run audit-only, draft-only, drift-watch (release-triggered recurring agent), or end-to-end. |
Missing Docs
Find documentation gaps, detect doc-impacting code changes, and draft missing pages.
Requirements
The audit compares docs against code, so both source repos must be available:
- the public warp client repo (warpdotdev/warp)
and
warp-server, auto-detected as siblings of the docs repo root (e.g.
/workspace/docs next to /workspace/warp and /workspace/warp-server; a
sibling named warp-internal is accepted as a fallback), or passed explicitly
via --warp PATH / --warp-server PATH (--warp-internal is a deprecated alias).
The script FAILS LOUD when a repo is missing OR when an extraction sanity guard
trips (a parser returning implausibly few surfaces means the source layout
changed and the parser needs fixing): it exits with code 2 and lists the skipped
audits in the report's audits_skipped field (extraction:* entries identify
broken parsers). Never treat an exit-2 run as a clean audit — fix the problem
and re-run. Exit 0 means all requested audits ran (findings may still exist).
Run every command from the docs repo root
Every path in this skill — scripts, references, doc pages — is relative to the docs
repo root, and nothing resolves them for you. A sandbox commonly starts a run one level
up (/workspace, with the checkout at /workspace/docs), so cd before anything else:
cd "$(git rev-parse --show-toplevel)"
A wrong working directory fails in a way that reads like a real failure: python3 exits
2 with can't open file, the same exit code audit_docs.py uses to fail loud on a
broken environment. Read the message before concluding a sanity guard tripped.
Install Node dependencies before the first build
npm run build is the only validation this repo has, and it needs node_modules, which
a fresh sandbox does not have. Install once per sandbox:
npm ci
Regenerate the snapshot only from current checkouts
--update-snapshot rewrites references/surface_snapshot.json from whatever the sibling
repos hold at that moment, and it cannot tell a current checkout from a stale one. Running
it against an old or feature-branched warp / warp-server writes a baseline describing
surfaces that are not on the default branch, and the next --diff then reports the gap
between two wrong baselines as real drift. Confirm both repos are current and on their
default branch — master for warp, develop for warp-server — before regenerating:
for repo in ../warp ../warp-server; do
git -C "$repo" fetch --quiet origin
echo "$repo $(git -C "$repo" rev-parse --abbrev-ref HEAD) \
$(git -C "$repo" log -1 --format=%cd --date=short)"
done
A cloud sandbox provisions fresh checkouts and satisfies this by construction; a
developer's machine usually does not. When you cannot confirm it, leave the regen to a
scheduled run rather than committing a snapshot you cannot vouch for.
Public vs. private surfaces (what you may document)
Only document surfaces that are publicly released. This is the most important guardrail in this skill: do not reveal private or unreleased surfaces in public docs. Two independent gates, both required:
- Source / exposure. The OSS warp client repo (warpdotdev/warp; locally
warp, or the warp-internal fallback) is public — its feature flags, CLI commands, settings, and slash commands are documentable. warp-server is a private repo and is not public until released; its source and most of its surfaces must NOT be documented. The one exception is the public Oz Agent API, whose released surface is exactly the set of endpoints already present in the OpenAPI spec (developers/agent-api-openapi.yaml).
- Rollout status. Even for public-repo surfaces, only document GA features. Never document dogfood, preview, or research-preview surfaces (for example, Agent Memory is research preview, so its
oz memory* CLI and /memory_stores API must not be documented yet).
Rules of thumb:
- A
warp-server API endpoint that is not already in the OpenAPI spec is treated as not-yet-public: do NOT hand-write docs for it. Either confirm it has been publicly released and let the sync-openapi-spec skill bring it into the spec, or map it -> internal / defer it. When unsure, defer — never expose an unreleased endpoint or feature in public docs.
- A CLI command or API route gated by a non-GA feature flag should be mapped
-> gated:<Flag> (for example, gated:AIMemories) rather than -> internal: the audit auto-defers it while the flag is non-GA and auto-surfaces it for docs once the flag goes GA. (Feature flags and settings already auto-defer by rollout status; gated: extends that to CLI/API.)
- A published docs page is not evidence that an API is released. Early Access features routinely have public pages describing what the product does while their REST routes stay out of the released spec, so "we already document this feature" does not clear Gate 0 for an endpoint. For API surfaces the released OpenAPI spec is the only test. The Factory pages describe dispatching a run, yet no
/factory path appears in developers/agent-api-openapi.yaml — those routes are Gate 0 deferrals despite the prose.
- The audit still detects these as gaps (useful signal), but detection is not permission to document. Every resolution must respect this boundary.
This section is the source of truth for Gate 0 in
.agents/references/docs-worthiness-criteria.md. Passing Gate 0 only establishes that a
surface may be documented — it does not establish that it should be. Work through the
remaining gates before treating any finding as actionable.
Workflows
Phase 1: Audit (coverage)
Run the audit script to identify gaps:
python3 .agents/skills/missing_docs/scripts/audit_docs.py
Options:
--category features|cli|api|slash|settings|structure|staleness|map — run a single audit category
--severity high|medium|low — filter by minimum severity
--weak-coverage — also flag GA features whose mapped doc exists but doesn't mention feature keywords (low-severity, noisy)
--output report.json — save JSON report to file
--warp PATH / --warp-server PATH — explicit repo paths (--warp-internal is a deprecated alias)
--diff — change detection against the committed snapshot (see Phase 2)
--update-snapshot — regenerate references/surface_snapshot.json (full runs only)
The script resolves doc paths from the docs repo root and accepts .md and .mdx
interchangeably (and README.md ↔ index.mdx), so surface-map entries can use the
canonical filename even when the on-disk extension differs.
The script performs these coverage audits:
-
Feature flag coverage — classifies every FeatureFlag by rollout status using
the cargo-feature→flag bridge in the warp client repo's app/src/features.rs plus
RELEASE_FLAGS/PREVIEW_FLAGS/DOGFOOD_FLAGS in crates/warp_features/src/lib.rs.
GA flags must be mapped in the surface map or covered in docs; Preview flags produce
low-severity "docs needed soon" findings; dogfood/other flags are tracked by the
snapshot only.
-
CLI command coverage — parses the full oz command tree from
crates/warp_cli/src/ (recursive subcommands like oz run message send, skipping
hide = true) and checks the CLI reference docs. Per-module --long flags are
additionally tracked in the snapshot for change detection.
-
API endpoint coverage — extracts public routes from warp-server
router/handlers/public_api/*.go (nested gin groups resolved, caller-passed group
prefixes matched positionally) and checks them against
developers/agent-api-openapi.yaml (param-name-insensitive: {runId} matches
{run_id}) and the API reference docs. For spec drift, run the docs
sync-openapi-spec skill (or warp-server's update-open-api-spec) instead of
hand-editing the YAML. warp-server is private (see Public vs. private
surfaces): a flagged endpoint is documentable only once it is part of the
released public Oz Agent API. Never hand-draft API docs or reveal an unreleased
endpoint — resolve released endpoints via sync-openapi-spec, and -> internal/
defer the rest.
-
Slash command coverage — parses the static registry in the warp client repo's
app/src/search/slash_command_menu/static_commands/ and checks each /command
is mentioned in docs.
Known limitation: this check is repo-wide, not surface-scoped. A command counts as
covered when any page mentions it (audit_slash_commands in scripts/audit_docs.py
searches every docs page), so a command documented on the GUI slash-commands page reads
as covered even when the CLI reference omits it. That is how /usage reached a release
undocumented for CLI users — only the changelog cross-check caught it. The CLI and
settings audits scope their search to the pages that own those surfaces; this one does
not. Until that is fixed, do not read a slash command's bucket as
"documented in the right place."
Snapshot-only surfaces (no standing coverage audit, but added/removed/changed items
are reported by --diff): Oz web app routes (AgentsApp.tsx), server-side agent
tools (multi_agent tool registries), bundled + channel-gated skills
(resources/bundled/skills, resources/channel-gated-skills), and per-module CLI
flags.
Present the report to the user, grouped by category and sorted by severity.
Adjacent checks owned by other skills (do not duplicate them here):
- UI menu paths and Command Palette names →
validate_ui_refs
- Platform error-code pages →
sync-error-docs
- Broken links and 404s/redirects →
check_for_broken_links / weekly-404-monitor
- Terminology/style sweeps →
style_lint
Completeness accounting (the no-slip guarantee)
Every full run computes a completeness accounting and embeds it in the report
(summary.accounting in JSON, a COMPLETENESS ACCOUNTING block in the printed
output). It partitions every extracted surface item into exactly one
accountability bucket and proves totality:
- Feature flags: every GA/Preview flag is
mapped (surface map verified),
ignored (curated internal list), or a visible finding; every dogfood/other
flag is tracked_non_ga (snapshot diff fires on promotion or removal).
- CLI commands:
mapped, doc_covered, gated_non_ga (deferred via
gated:<Flag> while its gating flag is non-GA), finding, parent_flagged
(suppressed because the parent command is already flagged), or hidden.
- API routes:
mapped, spec_covered, docs_covered, gated_non_ga
(deferred via gated:<Flag> while its gating flag is non-GA), or finding.
- Slash commands:
mapped, doc_covered, or finding.
- Settings:
private, tracked_non_ga, mapped, doc_covered, or finding.
If any item escapes every bucket, the run reports integrity:accounting in
audits_skipped and exits 2 — an unaccounted item means the audit logic itself
regressed, never that the item is fine. Map hygiene additionally rejects
integrity bugs in the surface map: entries that are both mapped and ignored
(the ignore silently wins) and duplicate keys within a section.
How every change path is caught, end to end:
- New surface item appears (flag, command, route, slash, setting, web
route, tool, bundled skill) → the snapshot
--diff reports it AND, once
GA/user-facing, the coverage audit produces a standing finding until it is
documented + mapped or ignored with a comment.
- Item is promoted (dogfood→preview→ga, setting status change, skill
channel change) →
--diff status-change finding + coverage finding appears.
- Item is removed/renamed →
--diff removal finding + map hygiene flags
the dead map entry + stale-doc-reference checks flag docs still naming it.
- Launch with no client-code change (server-side experiment flips to 100%,
Oz web app backend feature) → the changelog cross-check is the net: every
"New features"/"Improvements"/"Oz updates" bullet newer than the snapshot
becomes a verification finding.
- The audit itself rots (source layout moves, parser breaks) → extraction
sanity guards trip, dependent audits skip, exit 2.
- The map rots (dead entries, conflicts, duplicates, missing doc targets,
unmapped-but-mentioned features) → map hygiene + fallback-transparency
findings keep pressure until fixed.
The mapping is updated through three enforced paths: Phase 3 step 8 makes the
map+snapshot update a mandatory part of drafting; the drift-watch triage step
requires a mapping/ignore/allowlist decision for every finding; and map hygiene
findings force pruning when code moves underneath the map.
Phase 2: Change detection (diff mode)
The snapshot at references/surface_snapshot.json records all extracted surfaces
(flags + rollout status, CLI commands and per-module flags, API routes, slash
commands, settings + status, Oz web app routes, server-side agent tools, bundled
skills) plus the last-seen docs-changelog version. It makes change detection
possible: a feature flag that is deleted after stabilizing (per the warp repo's
remove-feature-flag policy) would otherwise vanish from the audit's universe
silently. When a new surface type is introduced, diffing against an older snapshot
emits a one-time "surface type newly tracked" note instead of false positives.
python3 .agents/skills/missing_docs/scripts/audit_docs.py --diff
Diff mode reports, since the snapshot was last updated:
-
Added / removed / promoted surfaces — e.g. a new GA flag (high), a flag promoted
dogfood→ga (high), a removed flag ("feature stabilized or killed — verify docs and
map entry"), new/removed CLI commands and --flags, API routes, slash commands,
settings (with status promotions), Oz web app routes, server-side agent tools, and
bundled skills.
-
Changelog items to verify — "New features", "Improvements", and "Oz updates"
bullets from src/content/docs/changelog/<year>.mdx entries newer than the
snapshot's last-seen version. This is the best signal for launches no static code
parse can see (server-side features, Oz web app, experiment rollouts). A changelog
mention is NOT documentation — verify each item has real doc coverage. ("Bug fixes"
bullets are deliberately untracked to keep weekly triage volume manageable.)
A changelog item is a candidate, not a work item. Detection is not permission to
document. Every item must pass .agents/references/docs-worthiness-criteria.md before
it becomes actionable — most will not. Read
references/changelog_decisions.md first and skip any PR number already decided.
Sources beyond the client changelog
The client changelog only covers warpdotdev/warp. Server and platform features ship
continuously and never appear in it, which is how they used to reach docs through the
retired spec-scan path — and why that path produced most of the unvetted drafts. Cover
them through these three layers instead, in order of preference:
-
oz_updates — the separate array in the same client_version payload the release
gate already fetches. Release-gated, low-noise, and currently the most direct signal
for platform-side changes. Triage these bullets exactly like changelog bullets: same
gates, same ledger, same evidence requirement.
check_new_release.py prints them; the audit never sees them, because it is offline
by design and they are not part of the markdown changelog it parses. Read them from
the gate's output, or --json for the full array. oz_updates is the API's field
name and stays as-is regardless of product naming.
-
The public Agent API surface — already covered by audit category 3 and
sync-openapi-spec. No new machinery; just confirm the release run actually triages
these findings rather than deferring them by habit. A released endpoint reaches docs
through the spec, never through hand-drafting.
-
warp-server product specs — the last resort, and the most conservative layer.
Apply a hard rollout check before the worthiness gates: only consider a spec whose
feature is verifiably enabled for users. A merged spec is not a shipped feature. If
you cannot confirm the rollout from code or the changelog, defer it and record the
blocking condition — do not draft against the spec text.
Layer 3 is where the old pipeline went wrong: it treated spec merge as the trigger, so it
drafted for features that had not shipped and sometimes never would. Reach for it only
when layers 1 and 2 cannot see a user-visible change you have independent evidence has
shipped.
After triaging and addressing diff findings, refresh the snapshot and commit it with
your PR so the next run diffs against the new baseline:
python3 .agents/skills/missing_docs/scripts/audit_docs.py --update-snapshot
Phase 3: Draft
Preconditions — do not draft without both:
- A recorded pass verdict. The finding must have passed
.agents/references/docs-worthiness-criteria.md, with the gate and its concrete
evidence written down. No recorded verdict means no drafting. For changelog-derived
findings the verdict also belongs in references/changelog_decisions.md.
- A content design plan. Route it with the rule in
.agents/references/content-design-plan.md: a new page gets the full form in
.agents/templates/content-design-plan.md, an update that adds a concept gets the
three-line short form, and a correction gets no plan. Write it before opening a page
template — the plan decides the content type; the template does not. Carry it into the PR
body verbatim: a scheduled run has no one to present it to, so the PR body is the only
place a human will see the reasoning.
A finding that passes the gate with the update an existing page outcome is still a
drafting task — it just edits a page instead of creating one. Prefer it; new pages need
to be justified against the existing information architecture, not just against the
change.
For each gap to address (prioritize high → medium → low):
-
Read references/feature_surface_map.md to determine the target doc section
-
Read AGENTS.md in the docs repo root for the complete style guide
-
Read 2-3 strong examples in the target section to match formatting patterns
-
Research the relevant source code:
- Feature gaps → read the implementation in the warp client repo's
app/src/, check UI code, settings, user-facing strings
- CLI gaps → read command definition in
crates/warp_cli/src/, extract flags, arguments, help text
- API gaps → read handler in warp-server
router/handlers/public_api/, route definition, request/response types; prefer fixing the OpenAPI spec via the sync-openapi-spec skill. Only act on endpoints already publicly released (see Public vs. private surfaces); never draft docs for unreleased warp-server endpoints.
- Slash command gaps → read the registry entry and gating flags in
app/src/search/slash_command_menu/
Then look for a product spec. Code tells you what a surface does; it never tells you who
it is for or what problem it solves — and those are the content design plan's first three
fields. Check warp-server for specs/<id>/PRODUCT.md. Only some specs have one, and
TECH.md is the implementation plan, not a substitute. Where it exists, its Problem,
Goals, Non-goals, and User experience sections map onto the plan's Problem, Goals,
Excludes, and high-impact scenarios almost directly.
Three limits, all load-bearing:
- Framing only, never behavior. Labels, flags, and defaults drift between spec and ship,
so every concrete claim is still verified against code. A spec is context, not a source of
truth.
- Never evidence that something shipped. A merged spec is not a release. Gate 0 is
settled before this step, and a spec cannot reopen it.
- Never quoted into a public page. warp-server is private and specs routinely describe
unshipped plans. Use one to understand the reader, then write the page from scratch.
If no spec exists, proceed without one and record that in the content design plan. An
acknowledged gap is reviewable; an invented audience is not.
-
Draft the doc following style guide conventions:
Resolution patterns
Not every finding needs a new doc page — pick the lightest correct fix and verify it against source before applying:
- No docs needed — the finding failed every worthiness gate, or a disqualifier applied.
This is a first-class resolution, not a silent skip: record the verdict, the
disqualifier or failed gates, and a one-line reason. Changelog items go in
references/changelog_decisions.md; code surfaces go in the surface map as an ignore
entry with a comment. An unrecorded rejection is re-proposed next run and has to be
rejected again by the same reviewer.
- Deferred (Gate 0) — real user-facing surface, but not yet GA or not yet public.
Record it with the blocking condition so it re-surfaces when the flag goes GA or the
endpoint reaches the released OpenAPI spec. Never draft ahead of the release; a page
written for an unshipped feature is stale before it merges.
- User-facing setting — document it in
terminal/settings/all-settings.mdx under its TOML section (type/default/options come from the toml_path registration).
- Internal or state-only setting (one-time banners, migration flags, telemetry-modeled state) — map
section.key -> internal in the surface map instead of documenting it.
- Feature flag with a dedicated doc page — map the flag to that page.
- Feature flag whose only user-facing surface is an already-documented setting — map the flag to that setting's doc page rather than writing a new page (for example, a tab-bar visibility flag maps to the all-settings reference).
- Preview or pre-launch feature with no docs yet — add it to the surface-map ignore list with a comment; the snapshot diff re-flags it when it promotes to GA.
- Stale map entry or doc reference (map hygiene) — confirm the surface is gone from code, then prune the dead entry.
- warp-server API endpoint not in the released OpenAPI spec — do not hand-document it (warp-server is private). If it is part of the released public Oz Agent API, hand it to the
sync-openapi-spec skill; if it is unreleased or internal, map it -> internal with a comment. Never expose an unreleased endpoint or feature in public docs.
- CLI command or API route gated by a non-GA feature flag — map it
-> gated:<Flag> so it auto-defers while the flag is non-GA and auto-surfaces for docs when it GAs (e.g. Agent Memory's oz memory* and /memory_stores/* use gated:AIMemories). Prefer this over -> internal, which never re-surfaces.
Reviewer routing
Assign the engineer who owns the code behind each change, so a human with real context reviews the PR. Every finding traces to a source surface; map that surface's defining file to its owner using the ownership files that already live in the code repos (CODEOWNERS format, last-match-wins):
- warp client repo:
.github/STAKEHOLDERS
- warp-server:
.github/STAKEHOLDERS (advisory) + .github/CODEOWNERS (enforced)
These are the source of truth (warp-server keeps STAKEHOLDERS fresh via the sync-stakeholders skill), so never hardcode owner lists here.
For each addressed finding, note the defining source file you already consulted in Phase 3 step 4:
- Setting → the file holding its
toml_path registration (usually under app/src/settings/).
- Slash command →
app/src/search/slash_command_menu/static_commands/.
- Feature flag → the flag's primary usage site in
app/src/ (grep the flag name); fall back to crates/warp_features/src/lib.rs.
- CLI command →
crates/warp_cli/src/.
- API route → warp-server
router/handlers/public_api/ (API gaps usually go to sync-openapi-spec).
Resolve owners and get a ready-to-run assignment command:
python3 .agents/skills/missing_docs/scripts/suggest_reviewers.py \
--warp ../warp --warp-server ../warp-server \
warp:app/src/settings/ssh.rs \
warp:app/src/search/slash_command_menu/static_commands/commands.rs
Add --reviewers-only to get just the comma-joined --add-reviewer argument (empty output when nothing resolved), which is the form the mandatory request step below consumes.
Then actually request the review on GitHub with gh pr edit <PR> --add-reviewer <logins/teams>. A /cc @engineer line in the PR body is not a review request: it puts nothing in the engineer's review queue. All four ambient-drafted docs PRs (#414, #415, #416, #417) named reviewers in prose and got zero reviews, three of them with an empty requested-reviewers list.
An individual unresolved path is non-fatal — other paths usually resolve the same owner. An empty result is not: fall back to dannyneira rather than opening the PR with no reviewer. See step 7 of drift-watch mode for the required command.
Expect warp-server-only findings to fall back. The warp client repo's ownership file has a root rule, so nearly any path in it resolves. warp-server's does not, and whole areas — the /factory handlers among them — carry no entry, so a finding whose only source file is a warp-server handler resolves to nothing and lands on dannyneira. That is the fallback doing its job; report it that way rather than as a resolution failure. Do not hardcode an owner here to paper over it — the fix belongs in warp-server's ownership file, and once an entry exists resolution starts working with no change to this skill.
PR strategy: one PR per feature
Ship each documented feature as its own focused PR so the owning engineer reviews only
their area. Do NOT bundle unrelated features into a single mega PR.
-
One feature → one PR. Each documented feature (or standalone correction, e.g. a
duplicate-heading fix) gets its own branch and PR, titled and scoped to that item, with
the owning reviewer assigned. This is the default; the rules below are the only
exceptions.
-
Group only when features share a doc file or owner. Two features that edit the same
page (e.g. tab groups and drag-a-tab-to-another-window, both in
terminal/windows/tabs.mdx) go in one PR — separate PRs touching the same file would
conflict, and they usually share an owner anyway. Prefer grouping by owning engineer
when the same file is involved.
-
Collect all surface-map + snapshot edits into a single companion "audit bookkeeping"
PR. references/feature_surface_map.md and references/surface_snapshot.json are
shared files; editing them across many feature PRs causes merge conflicts, and the
snapshot is a wholesale regen. Put every Flag -> page mapping, ignore/internal/
gated: entry, and the --update-snapshot regen into one bookkeeping PR. Its mappings
may point at pages that land in the sibling feature PRs — map hygiene only requires the
target page to exist on the base branch, so the bookkeeping PR merges independently of
those feature PRs, in any order. If a run documents exactly one feature, fold its map +
snapshot changes into that single PR and skip the companion.
-
Keep at most one bookkeeping PR open. Extend the open one rather than opening a
second. The independence above holds against feature PRs; it does not hold against
another bookkeeping PR. Two of those edit the same shared files, and
surface_snapshot.json is regenerated wholesale, so a conflict between them cannot be
resolved by hand — it has to be regenerated on the merged tree. Look for an existing one
before opening yours:
gh pr list --state open --search '"bookkeeping for" in:title' \
--json number,headRefName,title,reviewDecision
Match on the quoted phrase, not the two words separately. An unquoted
missing_docs bookkeeping in:title search ANDs the two words anywhere in the title, so
it also matches this rule-only PR's own title ("...keep at most one bookkeeping PR
open") — the next run would then check out and extend this PR's branch instead of a real
bookkeeping PR.
If one exists and reviewDecision is not APPROVED, check out its branch and add this
run's map entries and ledger rows on top, then re-run and
there so the marker and snapshot stay a single regen covering every
release the PR now carries. Update its title and body to name them all. The one
exception: if is already (it's about to merge), wait for the
merge and branch from the result instead of extending it.
Drift-watch mode (recurring scheduled agent)
This is the end-to-end workflow for the scheduled cloud agent that keeps docs in sync
with the product. Each run:
-
Release gate: check whether a new stable release has shipped since the last
processed run. The schedule runs daily so it can catch a release whenever it lands,
but the work only happens once per release:
python3 .agents/skills/missing_docs/scripts/check_new_release.py
Exit 0 means a new stable release is available — continue. Exit 10 means no new
release; record the no-op outcome in run output and stop. Exit 1 is a fetch or
parse failure; report it and stop rather than proceeding as if nothing shipped. Exit
2 with can't open file is not a gate outcome at all — it is python3 reporting the
wrong working directory. cd to the docs repo root and re-run.
The gate also prints any oz_updates bullets for the release. Keep them — they are
platform-side changes the audit cannot see, and this is the only place they surface.
Do not update the state file yet. It is written in step 5, after triage, so a run that
crashes mid-triage retries the same release instead of skipping it.
-
Audit: run both modes and save reports. Pass explicit repo paths; verify
exit code 0 — if the script exits 2, STOP and report the environment problem
instead of concluding "no gaps":
python3 .agents/skills/missing_docs/scripts/audit_docs.py \
--warp ../warp --warp-server ../warp-server \
--diff --output /tmp/docs_audit.json
-
Triage: read references/changelog_decisions.md first and drop any changelog item
already decided. Read the ledger and surface map as they stand on any open bookkeeping
PR too, not only the copies on main — a verdict recorded in an unmerged PR is still a
verdict, and re-triaging it burns the run and produces duplicate map entries. Then work
through surface_changes and changelog_review (what changed since last run), then
standing coverage findings (high → medium → low) across all categories: features, CLI,
API, slash commands, settings, stale doc references, unlisted pages, map hygiene,
staleness.
Apply .agents/references/docs-worthiness-criteria.md to every remaining item
before deciding anything else. The default is no docs; the burden is on the change
to earn a page. Record a verdict for each item with the gate it passed (or the
disqualifier that stopped it) and the concrete evidence — a setting key, CLI flag,
quoted error string, changed default, or API field. Restating the changelog entry is
not evidence. Expect most items to resolve to "no docs needed"; a run that passes
everything it looked at has not applied the gate.
A run that gates out every candidate is a successful run. It opens no feature PRs and
only the bookkeeping PR recording the verdicts. Do not manufacture work to justify the
run.
Schedule setup
Two configuration choices decide whether the schedule behaves, and neither is visible from
the prompt below:
- Select a cloud agent, not Quick run. Quick run executes as the calling user, so its
pull requests are authored by that person — which for a schedule means whoever created
it. Selecting a cloud agent runs as that agent instead, and with team GitHub
authorization configured its pull requests are authored by the Warp Factories GitHub
App. Any schedule that opens PRs wants the agent. See
Cloud agent accounts.
- Give that agent this skill and nothing else. A run inherits every skill attached to
the agent it runs as, and the schedule form will not let you detach an agent-level
skill. Pointing drift-watch at a general-purpose docs agent therefore pulls that agent's
other skills into every run — and a weekly release-updates skill that defaults to
running all of its tasks will do exactly that, daily. Create a dedicated agent rather
than reusing one that already carries other work.
Recommended scheduled-agent prompt (copy when setting up the agent):
Run the missing_docs skill in drift-watch mode. Work from the docs repo root — every
path below is relative to it, and a python exit code of 2 with "can't open file" means
you are in the wrong directory, not that a check failed. First run
.agents/skills/missing_docs/scripts/check_new_release.py; if it reports no new stable
release, record the no-op outcome and stop. Otherwise use the audit script with
explicit --warp (public warpdotdev/warp checkout) and --warp-server paths and --diff.
If the script exits non-zero with skipped audits, report the environment problem and
stop. Otherwise read references/changelog_decisions.md and drop already-decided items,
then triage the remaining surface_changes and changelog_review findings plus
high/medium coverage findings against .agents/references/docs-worthiness-criteria.md.
The default is no docs: record a verdict and concrete evidence for every item, and
expect most to fail. For items that pass, write a content design plan per
.agents/references/content-design-plan.md before drafting, prefer updating an existing
page over creating a new one, and use the sync-openapi-spec skill for API spec gaps.
Update the surface map for every triaged flag, append every verdict to
changelog_decisions.md, and regenerate the surface snapshot with --update-snapshot.
Resolve reviewers by running
.agents/skills/missing_docs/scripts/suggest_reviewers.py --reviewers-only against the
source files behind each addressed finding. Open one focused PR per documented feature
(grouping only features that share a doc file or owner), each opening with the required
"## What this feature does" summary and carrying the content design plan as a section in
its body, plus the bookkeeping changes to feature_surface_map.md,
changelog_decisions.md, last_release_processed.json, and surface_snapshot.json. Before
opening a bookkeeping PR, search for an open one with gh pr list --state open --search
'"bookkeeping for" in:title' --json number,headRefName,title,reviewDecision — the quoted
phrase, not the two words separately, so the search doesn't also match this rule-only
PR's own title. Extend that branch instead of opening a second, unless reviewDecision is
already APPROVED, in which case wait for the merge and branch from the result; two open
bookkeeping PRs conflict on a snapshot that is regenerated wholesale. Title a new one
"chore(missing_docs): bookkeeping for ".
Request the resolved owner as reviewer on every PR with gh pr edit --add-reviewer,
falling back to dannyneira when nothing resolves, and verify the requested-reviewers
list is non-empty before you finish — a PR with no requested reviewer is an incomplete
run, not a delivered one. List any findings you deferred in the relevant PR body.
Invocation modes
The user can trigger any subset:
- "Run a docs audit" or "Check docs coverage" → Phase 1 only
- "What changed since the last audit?" → Phase 1 + 2 (
--diff)
- "Draft docs for [specific gap]" → Phase 3 only (skip audit)
- "Find and fix missing docs" → Phases 1–3 end-to-end
- Scheduled/recurring run → Drift-watch mode
Drafting standards
- Produce complete, ready-to-commit markdown — not outlines or stubs
- For CLI docs: include command syntax, all flags with descriptions, practical examples
- For feature docs: lead with user benefit, include how-to, cross-reference related features
- For API docs: include request/response schemas, auth requirements, curl examples
- Use
codebase_semantic_search and grep on source repos for technical accuracy
Tests
The skill's scripts have a stdlib-only test suite (no third-party dependencies):
python3 .agents/skills/missing_docs/scripts/test_suggest_reviewers.py
python3 .agents/skills/missing_docs/scripts/test_audit_docs.py
python3 .agents/skills/missing_docs/scripts/test_check_new_release.py
test_check_new_release.py unit-tests the release gate with the network stubbed: exit-code
contract (0 new / 10 no-op / 1 fetch failure), that a fetch failure is never reported as
"no new release", that a plain check never writes state, and the full
check → commit → no-op → next-release cycle.
test_suggest_reviewers.py unit-tests reviewer resolution (CODEOWNERS matching, last-match-wins, user/team split, dedup, unresolved paths).
test_audit_docs.py runs behavioral checks against the sibling code repos — clean exit, completeness accounting (unaccounted empty), category/severity scoping, fail-loud (exit 2) on a missing repo, snapshot round-trip, and research-preview deferral (the public/private boundary) — and skips gracefully when those repos aren't checked out.
References
references/feature_surface_map.md — curated mapping of flags/commands/routes/slash
commands/settings to doc pages, ignore list for internal flags, allowlist for
intentionally unlisted pages, the internal sentinel for surfaces that
intentionally have no public docs, and the gated:<Flag> sentinel for CLI/API
surfaces deferred until their gating flag goes GA. Update it with every docs PR
that ships a feature.
references/surface_snapshot.json — generated snapshot of all code surfaces used by
--diff. Regenerate with --update-snapshot; never hand-edit.
references/last_release_processed.json — the release gate's state: which stable
version was last triaged. Written by check_new_release.py --commit, never by hand.
Deliberately separate from surface_snapshot.json, which is regenerated wholesale and
would lose the marker. Delete it to force a re-run of the current release.
references/changelog_decisions.md — append-only ledger of docs-worthiness verdicts on
changelog items. Read before triage to skip already-decided items; append a row for
every item evaluated, rejections included. Commit it in the companion bookkeeping PR.
references/stale_terms.md — renamed/removed-feature terms to flag during staleness
audits. Pure terminology/style policing belongs to the style_lint skill.
.agents/references/docs-worthiness-criteria.md — the gate that decides whether a
finding should produce docs at all. Applied during triage, before any drafting.
.agents/references/content-design-plan.md — the audience, problem, goals, and content
type decisions required before drafting a page that passed the gate.
scripts/check_new_release.py — the release gate. Compares the current stable version
from app.warp.dev/client_version against last_release_processed.json so a daily
schedule does per-release work. Run it first in drift-watch mode; run it again with
--commit only after triage succeeds.
scripts/suggest_reviewers.py — resolves PR reviewers from the warp and warp-server
.github/STAKEHOLDERS and CODEOWNERS files (CODEOWNERS-format, last-match-wins),
given the source files behind each finding. Used by the drift-watch reviewer-routing step.
AGENTS.md (docs repo root) — full documentation style guide