npx skills add ...
npx skills add microsoft/apm --skill docs-sync
npx skills add microsoft/apm --skill docs-sync
Use this skill whenever a pull request is opened, reopened, or synchronized in microsoft/apm to assess whether and how the documentation corpus must change to stay truthful with the proposed code change. Activate even when the PR title or body says nothing about docs -- the skill must run on every PR to detect silent drift between code and docs. Classifies impact as no-change, in-place edit (one to a few paragraphs), or structural change (new page or TOC reshape), then orchestrates a CDO + doc-writer + python-architect + editorial-owner + growth-hacker loop to produce a patch-ready advisory. Does NOT review code quality, security, or test coverage. Does NOT auto-merge or auto-push doc edits.
The docs corpus drifts silently and constantly. This skill catches drift at PR-open time, classifies its impact, and orchestrates a persona panel to produce a patch-ready advisory comment.
The pattern is A1 PANEL + B1 FAN-OUT/SYNTHESIZER + A8 ALIGNMENT LOOP. The classifier is the cost gate (~70% of PRs short-circuit to no-change with ~1 LLM call). When the panel does fan out, every agent reads a bounded context (~10 KB) -- never the full corpus.
This skill is ADVISORY. It does not gate merge, apply verdict labels, or push to the contributor's fork. The orchestrator is the sole writer to the PR: exactly one comment per run (idempotent edit-in-place), plus optional label sweeps.
N/15 for observability.gh write command, post comments, or touch PR state.## Docs sync advisory. Re-runs edit-in-place using gh pr comment --edit-last.docs-sync-confirm label) open from a bot branch in the BASE repo; never pushed to the contributor's fork..apm/docs-index.yml, NOT the corpus itself. The corpus is sampled only by the localizer (which reads the specific candidate pages) and by per-page panelists (which read one page each).apm --help, grep, and python -c commands to verify doc claims, never assert from prose.| Role | Agent | Always active? |
|---|---|---|
| Classifier | doc-analyser inside docs-impact-classifier | Yes (every run) |
| Localizer | docs-impact-localizer | Only on in_place verdict |
| Architect | docs-impact-architect | Only on structural verdict |
| Writer | doc-writer | Per candidate page (fan-out) |
| Verifier | python-architect | Per candidate page (fan-out, S7) |
| Editorial | editorial-owner | Once across all redrafts |
| Growth | oss-growth-hacker | Once across all redrafts |
| Synthesizer | cdo | Once, with ALIGNMENT LOOP up to 3 redrafts |
Spawn ONE task: load the docs-impact-classifier skill, pass it the
PR number. It returns the classifier JSON.
Validate the JSON against assets/classifier-return-schema.json.
On schema failure, abort the run with a comment explaining the
internal error.
If verdict is no_change: skip to Step 6 with a brief advisory
("No docs impact detected. Reason: . LLM calls: 1/15.")
For in_place: spawn ONE task that loads the
docs-impact-localizer skill with the classifier output. Returns
per-page task briefs.
For structural: spawn ONE task that loads the
docs-impact-architect skill with the classifier output. Returns
TOC delta + new-page outlines + downstream in-place pages. THEN
spawn the localizer for those downstream pages.
Cascade-size mitigation (PR 1244 class). If scope_pages[] has
8 entries, the per-page fan-out at one writer call per page would approach the 15-call ceiling with no headroom for verifier redrafts. BEFORE spawning, group
scope_pages[]into SECTIONS:
consumer/**) with the
SAME conceptual fix (e.g. "rename apm update -> apm self-update in
every mention") become ONE writer task with a pages_in_section[]
array in its brief.The python-architect verifier still runs per verify_claims[] (not
per page), because S7 evidence is keyed on claims, not pages.
For each page-or-section in the per-page task brief, spawn TWO parallel tasks:
before:, after: for each location.verify_claims[] in the page brief, run the actual command (S7 tool bridge: apm <verb> --help, grep -n <symbol> src/). Output: JSON with claim: verified | refuted | inconclusive per claim.In parallel with the per-page fan-out, spawn ONCE each:
All panelist tasks return JSON matching assets/panelist-return-schema.json.
Schema-validate every return; on failure, abort.
Cross-check:
verify_claims from a python-architect comes back verified or inconclusive (never refuted). If any are refuted, the doc-writer's draft is wrong; re-run the writer for that page with the refutation as context.Spawn ONE task: load the cdo persona with the full panel return
(writer drafts + verifier reports + editorial notes + growth notes
.apm/docs-index.yml.The CDO returns one of three verdicts:
agree: ship. Proceed to Step 6.revise: re-spawn the writer panelists with the CDO's specific
concerns as additional context. Re-run the editorial and growth
passes if needed. Bounded N <= 3 redrafts. Increment a redraft
counter; if it hits 3 and CDO still disagrees, ship with
cdo_disagreement_noted: true.ship_with_disagreement: ship as-is with the disagreement
surfaced in the comment for the maintainer to weigh.Render assets/advisory-comment-template.md with the final results.
Write it via safe-outputs.add-comment. Header is exactly
## Docs sync advisory (stable for idempotent edit-in-place).
The comment MUST include the cost header:
Only on structural verdict AND docs-sync-confirm label present
on the PR (the A9 SUPERVISED EXECUTION boundary; the maintainer
ratifies the structural proposal before any PR is opened).
If both conditions hold:
docs-sync/companion-<PR_NUMBER> in the BASE repo..apm/docs-index.yml entries +
new page files + redirects on retired pages).This step is intentionally GATED. The default behaviour (no
docs-sync-confirm label) is to recommend the patches in the
comment without opening a PR.
The orchestrator maintains a running LLM-call counter:
| Step | Min calls | Max calls |
|---|---|---|
| Step 1 classify | 1 | 1 |
| Step 2 localize/architect | 0 | 2 |
| Step 3 fan-out (N pages) | 0 | 2N + 2 |
| Step 5 CDO | 0 | 1 + 3 redrafts |
| Total | 1 | 15 |
If the counter would exceed 15, the orchestrator stops spawning,
ships the partial result with cost_ceiling_hit: true, and the
comment surfaces the truncation.
refuted verify_claims. That's silent drift you're shipping.docs-sync label on PR. Maintainer opts in.pull_request_target event. Enabled only after shadow validation.The workflow file controls which rung is active. The skill body is identical for both.**
Verdict: <verdict> * Pages affected: N * LLM calls: M/15 * Took: Xs