Spec Drift Audit
Operationalises spec/project/spec-drift-audit/<canonical_language>.md — reconciles every in-scope spec's Requirements and Acceptance Criteria against the actual repository state, persists the result as a dated artifact, and drives findings to a documented decision. The audit artifact is the deliverable; this skill is the procedure that creates, updates, and closes it.
Why this is a skill, not an agent
- Mid-flow interactivity — the user decides per finding: adjust the implementation, adjust the spec, or flag as an Open Question. An agent's fire-and-forget contract loses that deliberation loop.
- Persistent on-disk output — the audit artifact under
.audits/spec-drift/YYYY-Q<n>.md (or a GitHub issue) must survive past the current turn and be worked off incrementally; skills own persistent artifacts, agents return ephemeral reports.
- Orchestration role — the audit dispatches
project-structure-apply and vocab-drift-audit as partial auditors in the same session; the skill-orchestrates-agent-executes pattern defaults the orchestrator to skill form.
- Counter-dimension considered: context-window load from reading all specs plus their implementation surfaces could bias toward an agent, but the audit is inherently interactive and scoped per cycle — the user controls which specs are in scope and confirms each finding disposition. Inline execution in the skill form wins.
German trigger phrases
This skill also triggers on equivalent German-language requests, including:
- "führe den quartalsweisen Spec-Drift-Audit durch"
- "Spec gegen Implementierung prüfen"
- "Spec-Drift-Abstimmung"
- "alle Specs gegen das Repo auditieren"
- "nächsten Quartals-Audit öffnen"
- "Spec-Änderung erfordert Teil-Audit"
Preconditions
Before any operation, verify:
spec/.spec-config.yml is present — read it to determine canonical_language (fall back to en).
spec/project/spec-drift-audit/<canonical_language>.md is present — this is the governing spec; stop if missing.
.audits/spec-drift/ exists or can be created (check git ls-files .audits/spec-drift/.gitkeep); create .audits/spec-drift/.gitkeep if the folder is absent.
Operations
1. audit — produce the audit artifact
Interactive. Confirm scope and trigger with the user before proceeding.
- Determine trigger and scope. Ask (or infer from the message): quarterly full-scope, or thematic partial triggered by a specific spec change or new skill/agent? Record the trigger. For thematic audits, confirm which spec topic is in scope.
- Determine the Git revision. Run
git rev-parse HEAD; record it as repo-revision.
- Collect in-scope specs. Walk
spec/<topic>/<slug>/<canonical_language>.md for every file whose ## Requirements or ## Acceptance Criteria section is non-empty. Status: draft specs are included. For a thematic audit, narrow to the declared topic area — record the narrowing.
- Dispatch partial auditors. For the implementation surfaces covered by existing skills, delegate and capture their output:
- Run
project-structure-apply (audit mode only) to check .github/, Taskfile.yml, MkDocs, Renovate, and Probot alignment.
- Run
vocab-drift-audit to check Vale vocabulary against the pinned upstream release.
- Run
task lint and record the result.
Record each tool's name and version (or git SHA) in the artifact's tools-used list.
- Per-criterion check. For each remaining spec criterion not covered by a dispatched tool, evaluate against the implementation: produce one of
pass, fail, blocked (tooling missing), or not-applicable (with reason). Record the result. For each fail or blocked finding, the auditor MUST additionally record a Specialist disposition (mandatory field in the finding template per spec/project/continuous-improvement/<canonical_language>.md AC "No in-scope finding from the most recent spec-drift-audit run is recorded as 'no specialist considered'"): either (a) the dispatched specialist that will handle the remediation, naming both its display name and its subagent_type (or matching skill name), or (b) the explicit note no matching specialist exists — generalist handled. A finding recorded without one of these two values is incomplete and MUST NOT be written.
5b. Audience-surface drift check. Per spec/project/audience-identification/<canonical_language>.md (its AC "The spec-drift-audit skill can flag a module whose documented audiences no longer match its actual interaction surface"), reconcile each in-scope bounded context's audience artifact against its real interaction surface:
- Locate the audience artifact for each context:
AUDIENCES.md at the context root, or the acceptable alternatives that spec permits (a README ## Audiences / ## Intended consumers section, or an ADR). A context that ships an audience-claiming downstream artifact (README, mission, roadmap, docs tracks, release notes, SLAs) but has no audience artifact is itself a fail.
- For each documented audience, confirm its recorded
interaction surface (API, CLI, config, docs, dashboard, incident channel, …) still exists in the repository. A documented surface that no longer exists is drift (fail).
- Scan for undocumented interaction surfaces — a new public CLI command, a new config schema, a new dashboard or API — that no audience entry accounts for. An interaction surface with no documented audience is drift (
fail).
- Record each mismatch as a finding with the standard Specialist disposition; the natural remediation specialist is
audience-identify (re-run the audience methodology), so name it (or the no matching specialist exists — generalist handled note).
- Draft the artifact. Read
templates/audit.template.md for the Markdown template. Fill every frontmatter field. List all findings with fail or blocked status in ## Findings. Leave ## Decisions empty at creation.
- Write the artifact to
.audits/spec-drift/<YYYY>-Q<n>.md (or .audits/spec-drift/<YYYY>-Q<n>-<topic>.md for thematic audits). Confirm the path with the user.
- Fold the specialist-coverage review (continuous-improvement integration). Per
spec/project/continuous-improvement/<canonical_language>.md §"Continuous loop and quarterly coverage review", the quarterly specialist-coverage review SHOULD be folded into this spec-drift-audit run by default. On a quarterly full-scope audit (and on any audit run in a quarter that has no coverage-review artifact yet), prompt the user: "Fold the quarterly specialist-coverage review into this artifact, or keep it standalone under .audits/continuous-improvement/<YYYY-QN>.md?" — default to folding.
- Folded: keep the template's
## Specialist coverage review section (it is the named landing spot mandated by the spec's "present it as a named, dedicated section" MUST), then dispatch continuous-improvement-triage (audit operation) to produce the review content and populate that section. The section MUST stay full-portfolio in scope even on a thematic partial audit — partial-audit narrowing applies to drift, not to coverage, and a narrowed audit that suppresses it is itself a finding for the next cycle.
- Standalone: delete the
## Specialist coverage review section from this artifact and dispatch continuous-improvement-triage to write its own .audits/continuous-improvement/<YYYY-QN>.md artifact for the same quarter.
- Offer to stage and commit. Show the artifact path. Do not commit without explicit user confirmation.
Read examples/01-quarterly-audit.md when running a full-scope quarterly audit to see a realistic walkthrough.
Read examples/02-spec-change-trigger.md when running a thematic partial audit triggered by a spec update.
2. update — record decisions on findings
When the user reports decisions for one or more findings:
- Read the current audit artifact from
.audits/spec-drift/.
- Verify each claimed closure: re-read the relevant spec criterion and the referenced implementation file. Do not accept "done" without spot-checking.
- Record the decision per finding:
adjust-impl, adjust-spec, or open-question. Update the ## Decisions section. Carry the Specialist disposition forward from the finding into the decision entry: each ## Decisions block MUST restate the dispatched specialist (display name + subagent_type / skill name) or the no matching specialist exists — generalist handled note recorded in step 5 of audit, so the remediation PR's Risk / rollout notes can name it per spec/project/continuous-improvement/<canonical_language>.md.
- Append one log line to
## Processing log per decision: YYYY-MM-DD — <finding-id> — <decision> — verified: <method>.
- Flip
status in artifact frontmatter to in-progress on first decision.
- Show the diff. Do not commit automatically.
Read examples/03-finding-resolution.md when working off findings via update and close operations.
3. close — seal the audit cycle
- Read the current audit artifact.
- Refuse if any
fail finding lacks a decision. blocked findings may be closed with an open-question decision plus a tracking issue URL.
- Flip
status in frontmatter to closed. Record the closing date.
- Compose the commit message:
chore(audit): close <YYYY>-Q<n> spec-drift audit — <F> findings, <D> decisions in the subject; body lists open-question URLs and repo-revision.
- Run the commit only with explicit user confirmation. Show the message first.
Examples
- Read
examples/01-quarterly-audit.md for a full-scope quarterly audit with multiple findings and mixed decisions.
- Read
examples/02-spec-change-trigger.md for a thematic partial audit triggered by a specific spec update.
- Read
examples/03-finding-resolution.md for working off findings with the update and close operations.
Gotchas
spec/.spec-config.yml must be read first. The canonical language for spec paths depends on canonical_language in that config. Defaulting to en without reading the config silently routes to the wrong language in repos with a different canonical.
Status: draft specs are in scope. The governing spec explicitly includes draft specs in the audit perimeter. Do not skip them.
- Partial auditors only cover their slice.
project-structure-apply and vocab-drift-audit are delegated tools but each covers only one surface. Remaining spec criteria need direct per-criterion evaluation — never assume "dispatched means done".
- Artifact location is repository-consistent. If
.audits/spec-drift/ already contains prior artifacts, match the existing naming convention rather than inventing a new one. Check for prior artifacts before writing.
- Calendar quarter, not rolling. Q1 = Jan–Mar, Q2 = Apr–Jun, Q3 = Jul–Sep, Q4 = Oct–Dec. A
2026-Q2 audit covers the April–June window regardless of the actual date within the quarter.
Resumability
Per spec/claude/resumable-work/, this skill is resumable: true. State is persisted to .resume/spec-drift-audit/<run-id>.yml after every successful user-approval gate and after each named phase boundary. On re-invocation, scan that directory for files with status: in_progress whose inputs: snapshot matches the current invocation; if one matches, prompt the operator with Resume run <run_id> from phase <phase> (last checkpoint <last_checkpoint_at>)? [resume / start-new / discard]. The state-file envelope (schema_version, run_id, inputs, phase, decisions[], status, ...) and the fail-closed semantics on schema or YAML errors are load-bearing in the spec; don't duplicate those rules here.
Hard rules
- Every
fail finding needs a documented decision before close. Silent deferrals violate the governing spec and the audit history requirement.
- Record the Git revision. Every artifact must carry
repo-revision so the audit can be reproduced. unknown is acceptable for detached HEADs; omission is not.
- No tool without a version. Every dispatched tool (skill, CLI, action) must appear in
tools-used with its version or SHA.
- No invented pass/fail. If a criterion can't be evaluated (tooling absent, access missing), mark
blocked — never guess pass.
- One artifact per audit cycle. A re-run for the same quarter-scope supersedes; never merge two partial audits into a single file retroactively.
- English artifact structure, user language in prose. Section headings (
## Findings, ## Decisions, etc.) stay in English for grepping and downstream tooling; finding prose follows the user's language.
Multi-model testing
Examples and operations in this skill are verified on Claude Sonnet as the default model; spot-checked on Haiku for lightweight partial audits; Opus is appropriate for full-scope audits requiring deeper cross-spec reasoning. The skill has no model-specific assumptions beyond standard tool-call semantics.
1---2name: spec-drift-audit3description: Audits every spec under spec/<topic>/<slug>/ against the repository implementation (source code, config, workflows, docs) and produces a traceable audit artifact per spec/project/spec-drift-audit/. Invoke when the user asks to "run the quarterly spec-drift audit", "check spec versus implementation", "spec drift reconciliation", "audit all specs against the repo", "find spec vs code drift", "open the next quarterly audit", or when a spec changes and requires a matching partial audit. Also handles equivalent German-language requests. Do NOT use for continuous CI health checks (use workflow-health-triage), single-spec readiness review (use spec-readiness-reviewer agent), or feature-level code drift on new features (use feature-consistency-reviewer agent within feature-decompose scope). Supports resume on re-invocation per `spec/claude/resumable-work/`.4---56# Spec Drift Audit78Operationalises `spec/project/spec-drift-audit/<canonical_language>.md` — reconciles every in-scope spec's Requirements and Acceptance Criteria against the actual repository state, persists the result as a dated artifact, and drives findings to a documented decision. The audit artifact is the deliverable; this skill is the procedure that creates, updates, and closes it.910## Why this is a skill, not an agent1112- **Mid-flow interactivity** — the user decides per finding: adjust the implementation, adjust the spec, or flag as an Open Question. An agent's fire-and-forget contract loses that deliberation loop.13- **Persistent on-disk output** — the audit artifact under `.audits/spec-drift/YYYY-Q<n>.md` (or a GitHub issue) must survive past the current turn and be worked off incrementally; skills own persistent artifacts, agents return ephemeral reports.14- **Orchestration role** — the audit dispatches `project-structure-apply` and `vocab-drift-audit` as partial auditors in the same session; the skill-orchestrates-agent-executes pattern defaults the orchestrator to skill form.15- Counter-dimension considered: *context-window load* from reading all specs plus their implementation surfaces could bias toward an agent, but the audit is inherently interactive and scoped per cycle — the user controls which specs are in scope and confirms each finding disposition. Inline execution in the skill form wins.1617## German trigger phrases1819This skill also triggers on equivalent German-language requests, including:2021- "führe den quartalsweisen Spec-Drift-Audit durch"22- "Spec gegen Implementierung prüfen"23- "Spec-Drift-Abstimmung"24- "alle Specs gegen das Repo auditieren"25- "nächsten Quartals-Audit öffnen"26- "Spec-Änderung erfordert Teil-Audit"2728## Preconditions2930Before any operation, verify:31321. `spec/.spec-config.yml` is present — read it to determine `canonical_language` (fall back to `en`).332. `spec/project/spec-drift-audit/<canonical_language>.md` is present — this is the governing spec; stop if missing.343. `.audits/spec-drift/` exists or can be created (check `git ls-files .audits/spec-drift/.gitkeep`); create `.audits/spec-drift/.gitkeep` if the folder is absent.3536## Operations3738### 1. `audit` — produce the audit artifact3940Interactive. Confirm scope and trigger with the user before proceeding.41421. **Determine trigger and scope.** Ask (or infer from the message): quarterly full-scope, or thematic partial triggered by a specific spec change or new skill/agent? Record the trigger. For thematic audits, confirm which spec topic is in scope.432. **Determine the Git revision.** Run `git rev-parse HEAD`; record it as `repo-revision`.443. **Collect in-scope specs.** Walk `spec/<topic>/<slug>/<canonical_language>.md` for every file whose `## Requirements` or `## Acceptance Criteria` section is non-empty. `Status: draft` specs are included. For a thematic audit, narrow to the declared topic area — record the narrowing.454. **Dispatch partial auditors.** For the implementation surfaces covered by existing skills, delegate and capture their output:46 - Run `project-structure-apply` (audit mode only) to check `.github/`, `Taskfile.yml`, MkDocs, Renovate, and Probot alignment.47 - Run `vocab-drift-audit` to check Vale vocabulary against the pinned upstream release.48 - Run `task lint` and record the result.49 Record each tool's name and version (or git SHA) in the artifact's `tools-used` list.505. **Per-criterion check.** For each remaining spec criterion not covered by a dispatched tool, evaluate against the implementation: produce one of `pass`, `fail`, `blocked` (tooling missing), or `not-applicable` (with reason). Record the result. For each `fail` or `blocked` finding, the auditor **MUST** additionally record a **Specialist** disposition (mandatory field in the finding template per `spec/project/continuous-improvement/<canonical_language>.md` AC "No in-scope finding from the most recent `spec-drift-audit` run is recorded as 'no specialist considered'"): either (a) the dispatched specialist that will handle the remediation, naming both its display name and its `subagent_type` (or matching skill name), or (b) the explicit note `no matching specialist exists — generalist handled`. A finding recorded without one of these two values is incomplete and **MUST NOT** be written.515b. **Audience-surface drift check.** Per `spec/project/audience-identification/<canonical_language>.md` (its AC "The `spec-drift-audit` skill can flag a module whose documented audiences no longer match its actual interaction surface"), reconcile each in-scope bounded context's audience artifact against its real interaction surface:52 - Locate the audience artifact for each context: `AUDIENCES.md` at the context root, or the acceptable alternatives that spec permits (a README `## Audiences` / `## Intended consumers` section, or an ADR). A context that ships an audience-claiming downstream artifact (README, mission, roadmap, docs tracks, release notes, SLAs) but has *no* audience artifact is itself a `fail`.53 - For each documented audience, confirm its recorded `interaction surface` (API, CLI, config, docs, dashboard, incident channel, …) still exists in the repository. A documented surface that no longer exists is drift (`fail`).54 - Scan for *undocumented* interaction surfaces — a new public CLI command, a new config schema, a new dashboard or API — that no audience entry accounts for. An interaction surface with no documented audience is drift (`fail`).55 - Record each mismatch as a finding with the standard Specialist disposition; the natural remediation specialist is `audience-identify` (re-run the audience methodology), so name it (or the `no matching specialist exists — generalist handled` note).566. **Draft the artifact.** Read `templates/audit.template.md` for the Markdown template. Fill every frontmatter field. List all findings with `fail` or `blocked` status in `## Findings`. Leave `## Decisions` empty at creation.577. **Write the artifact** to `.audits/spec-drift/<YYYY>-Q<n>.md` (or `.audits/spec-drift/<YYYY>-Q<n>-<topic>.md` for thematic audits). Confirm the path with the user.588. **Fold the specialist-coverage review (continuous-improvement integration).** Per `spec/project/continuous-improvement/<canonical_language>.md` §"Continuous loop and quarterly coverage review", the quarterly **specialist-coverage review** SHOULD be folded into this `spec-drift-audit` run by default. On a quarterly full-scope audit (and on any audit run in a quarter that has no coverage-review artifact yet), prompt the user: *"Fold the quarterly specialist-coverage review into this artifact, or keep it standalone under `.audits/continuous-improvement/<YYYY-QN>.md`?"* — default to folding.59 - **Folded:** keep the template's `## Specialist coverage review` section (it is the named landing spot mandated by the spec's "present it as a named, dedicated section" MUST), then dispatch `continuous-improvement-triage` (`audit` operation) to produce the review content and populate that section. The section **MUST** stay full-portfolio in scope even on a thematic partial audit — partial-audit narrowing applies to drift, not to coverage, and a narrowed audit that suppresses it is itself a finding for the next cycle.60 - **Standalone:** delete the `## Specialist coverage review` section from this artifact and dispatch `continuous-improvement-triage` to write its own `.audits/continuous-improvement/<YYYY-QN>.md` artifact for the same quarter.619. **Offer to stage and commit.** Show the artifact path. Do not commit without explicit user confirmation.6263Read `examples/01-quarterly-audit.md` when running a full-scope quarterly audit to see a realistic walkthrough.64Read `examples/02-spec-change-trigger.md` when running a thematic partial audit triggered by a spec update.6566### 2. `update` — record decisions on findings6768When the user reports decisions for one or more findings:69701. **Read** the current audit artifact from `.audits/spec-drift/`.712. **Verify** each claimed closure: re-read the relevant spec criterion and the referenced implementation file. Do not accept "done" without spot-checking.723. **Record the decision** per finding: `adjust-impl`, `adjust-spec`, or `open-question`. Update the `## Decisions` section. **Carry the Specialist disposition forward** from the finding into the decision entry: each `## Decisions` block **MUST** restate the dispatched specialist (display name + `subagent_type` / skill name) or the `no matching specialist exists — generalist handled` note recorded in step 5 of `audit`, so the remediation PR's **Risk / rollout notes** can name it per `spec/project/continuous-improvement/<canonical_language>.md`.734. **Append one log line** to `## Processing log` per decision: `YYYY-MM-DD — <finding-id> — <decision> — verified: <method>`.745. **Flip `status`** in artifact frontmatter to `in-progress` on first decision.756. **Show the diff.** Do not commit automatically.7677Read `examples/03-finding-resolution.md` when working off findings via update and close operations.7879### 3. `close` — seal the audit cycle80811. **Read** the current audit artifact.822. **Refuse if any `fail` finding lacks a decision.** `blocked` findings may be closed with an `open-question` decision plus a tracking issue URL.833. **Flip `status`** in frontmatter to `closed`. Record the closing date.844. **Compose the commit message**: `chore(audit): close <YYYY>-Q<n> spec-drift audit — <F> findings, <D> decisions` in the subject; body lists open-question URLs and `repo-revision`.855. **Run the commit only with explicit user confirmation.** Show the message first.8687## Examples8889- Read `examples/01-quarterly-audit.md` for a full-scope quarterly audit with multiple findings and mixed decisions.90- Read `examples/02-spec-change-trigger.md` for a thematic partial audit triggered by a specific spec update.91- Read `examples/03-finding-resolution.md` for working off findings with the `update` and `close` operations.9293## Gotchas9495- **`spec/.spec-config.yml` must be read first.** The canonical language for spec paths depends on `canonical_language` in that config. Defaulting to `en` without reading the config silently routes to the wrong language in repos with a different canonical.96- **`Status: draft` specs are in scope.** The governing spec explicitly includes draft specs in the audit perimeter. Do not skip them.97- **Partial auditors only cover their slice.** `project-structure-apply` and `vocab-drift-audit` are delegated tools but each covers only one surface. Remaining spec criteria need direct per-criterion evaluation — never assume "dispatched means done".98- **Artifact location is repository-consistent.** If `.audits/spec-drift/` already contains prior artifacts, match the existing naming convention rather than inventing a new one. Check for prior artifacts before writing.99- **Calendar quarter, not rolling.** Q1 = Jan–Mar, Q2 = Apr–Jun, Q3 = Jul–Sep, Q4 = Oct–Dec. A `2026-Q2` audit covers the April–June window regardless of the actual date within the quarter.100101## Resumability102103Per `spec/claude/resumable-work/`, this skill is `resumable: true`. State is persisted to `.resume/spec-drift-audit/<run-id>.yml` after every successful user-approval gate and after each named phase boundary. On re-invocation, scan that directory for files with `status: in_progress` whose `inputs:` snapshot matches the current invocation; if one matches, prompt the operator with `Resume run <run_id> from phase <phase> (last checkpoint <last_checkpoint_at>)? [resume / start-new / discard]`. The state-file envelope (`schema_version`, `run_id`, `inputs`, `phase`, `decisions[]`, `status`, ...) and the fail-closed semantics on schema or YAML errors are load-bearing in the spec; don't duplicate those rules here.104105## Hard rules106107- **Every `fail` finding needs a documented decision before `close`.** Silent deferrals violate the governing spec and the audit history requirement.108- **Record the Git revision.** Every artifact must carry `repo-revision` so the audit can be reproduced. `unknown` is acceptable for detached HEADs; omission is not.109- **No tool without a version.** Every dispatched tool (skill, CLI, action) must appear in `tools-used` with its version or SHA.110- **No invented pass/fail.** If a criterion can't be evaluated (tooling absent, access missing), mark `blocked` — never guess `pass`.111- **One artifact per audit cycle.** A re-run for the same quarter-scope supersedes; never merge two partial audits into a single file retroactively.112- **English artifact structure, user language in prose.** Section headings (`## Findings`, `## Decisions`, etc.) stay in English for grepping and downstream tooling; finding prose follows the user's language.113114## Multi-model testing115116Examples and operations in this skill are verified on Claude Sonnet as the default model; spot-checked on Haiku for lightweight partial audits; Opus is appropriate for full-scope audits requiring deeper cross-spec reasoning. The skill has no model-specific assumptions beyond standard tool-call semantics.