--- name: wf-spec-drift description: Classify how far what shipped diverged from what was specced, and record it on the spec: every item marked satisfied, diverged, not implemented, or superseded, unspecified work called out, and an Outcome section appended. Writes to the spec and may mark it stale. Use after an implementation lands and the spec should carry the verdict. argument-hint: [commit-range] --- # Spec-Implementation Drift Compare what a dispatched task actually built against what the spec asked for. This is the non-deterministic layer 2 of the task completion feedback loop — it goes beyond the mechanical status flip (layer 1) to assess whether the implementation truly satisfies the spec's intent. ## Step 0: Parse arguments $ARGUMENTS has the form: ` [commit-range]` - The **first token** is the spec file path. - The optional **second token** is a git commit range (e.g., `abc123..HEAD`). ## Step 1: Load the spec 1. Read the spec file in full. **Parse YAML frontmatter** — extract `title`, `status`, `depends_on`, `affects`, `effort`, `dispatched_task_id`. 2. Verify `dispatched_task_id` is non-null. If null, the spec was not dispatched. It may instead have been implemented directly in-session (no task UUID, but real commits on the `affects` files). In that case: - To **finalize** it (Outcome + status + README), use `/wf-spec-wrapup`, which is lifecycle-aware and reconstructs the Outcome from the git history of the `affects` files. That is the canonical Outcome writer for the direct path. - To only **review** the implementation against the spec (no Outcome write), use `/wf-spec-review-impl`, which works without a dispatch link. - You may still run *this* skill's divergence analysis on a direct-implement spec if the user passes an explicit `[commit-range]` (Step 2 then uses it instead of the task UUID) — but do not also write `## Outcome` here if wrap-up already owns it (see Step 6). 3. Extract the acceptance criteria from the spec body: - Design specs: items from Options (chosen option), Components, Architecture - Task specs: items from "What to do", "Goal", "Tests" - Any numbered or bulleted requirements 4. If the spec is non-leaf, read child specs recursively and aggregate their criteria. ## Step 2: Load the implementation 1. If a commit range was provided, use it directly. 2. Otherwise, infer the range: find commits associated with the dispatched task. Look for the task UUID in commit messages, or use the task's worktree diff via `GET /api/tasks/{id}/diff` where a task board exposes one; otherwise from git history over the spec's `affects` paths. 3. Get the diff: `git diff --stat` for file list, `git diff ` for full changes. 4. Get commit messages: `git log --oneline`. Use Agent subagents (Explore type) to parallelize diff analysis across independent packages if the change spans many files. ## Step 3: Classify each spec item For every acceptance criterion or deliverable in the spec: - **Satisfied** — the diff contains clear evidence of implementation. The code matches what the spec described (types, functions, behavior). - **Diverged** — the item was addressed but the implementation differs from what the spec specified. Note *what* the spec said vs *what* was built and *why* the divergence may have occurred (common reasons: runtime constraints, API changes, simpler approach found). - **Not implemented** — no evidence in the diff. The item was skipped or deferred. - **Superseded** — the item was replaced by a different approach that achieves the same goal. Note the replacement. For each classification, cite specific files, functions, and diff hunks as evidence. ## Step 4: Identify unspecified work Scan the diff for changes not traceable to any spec item: - New files, types, or functions not mentioned in the spec - Refactoring of existing code beyond what the spec required - Test additions beyond what the spec's "Tests" section listed Classify each as: - **Necessary scaffolding** — required to make the spec work (e.g., imports, helper types, error handling) - **Improvement** — reasonable enhancement discovered during implementation - **Scope creep** — work that belongs in a different spec or wasn't requested ## Step 5: Assess overall drift Compute a drift summary: - **Satisfaction rate**: N of M spec items satisfied (percentage) - **Divergence count**: how many items were implemented differently - **Unimplemented count**: how many items were skipped - **Unspecified count**: how many changes weren't in the spec Based on these numbers, determine the drift level: - **Minimal** (>90% satisfied, ≤1 divergence) — spec is accurately complete - **Moderate** (70-90% satisfied, or 2-3 divergences) — spec is mostly complete but the Outcome section should document the deviations - **Significant** (<70% satisfied, or major divergences) — the spec should transition to `stale` rather than `complete`, as it no longer accurately describes what was built ## Step 6: Write the Outcome section `## Outcome` is the single canonical completion section, shared with `/wf-spec-wrapup`. **If you are running as wrap-up's analysis engine (wrap-up Step 2a):** stop here — do **not** write or update the Outcome, and do **not** touch frontmatter/status. Return the classified findings (Satisfied / Diverged / Not implemented / Superseded items, unspecified work, drift level, satisfaction rate) to wrap-up, which composes the one Outcome and sets status from the drift. Steps 7–8 below (tests, report) are wrap-up's job in that mode. **If you are running standalone,** you own the Outcome — but still don't blindly append a second one. Check whether the spec already has an `## Outcome`: - **None yet** — write the divergence-flavored Outcome below. - **Already present** (e.g. wrap-up finalized a direct-implement spec, or a prior diff ran) — do not duplicate it. Merge your divergence findings into the existing section (add/refresh the Design Evolution / Not Implemented / Unspecified Work subsections) and leave its Summary/What-Shipped intact. The divergence analysis augments the finalizer's Outcome; it does not replace it. When writing a fresh Outcome standalone, append it before any "Future Work" or "Open Questions" sections: ````markdown ## Outcome **Drift**: Minimal | Moderate | Significant **Satisfaction**: N/M items (X%) ### What Shipped - ### Design Evolution - ****: spec said X, implementation does Y. Reason: ### Not Implemented - ****: ### Unspecified Work - ****: ```` Update the spec's status — honoring the lifecycle gate (`validated → complete` is illegal; `complete` is reached only through `testing`) and the hybrid rule (prefer a transition API where the repo has one, since it validates the edge; otherwise a legal-edge frontmatter edit). A dispatched task reaching `done` means the **server** already moved the spec along `validated → testing → complete/stale`, so usually you are only recording the verdict, not setting the status: - **Minimal**: the server's `complete` stands; leave `status` as is. - **Moderate**: leave `complete`, but the Outcome documents the divergences; suggest `/wf-spec-refine` to align the spec text. - **Significant**: your analysis overrides the server's optimistic complete — set `status: stale` (`complete → stale` is legal). Recommend `/wf-spec-refine`, then `/wf-spec-dispatch` again for the remaining work. - If the spec is unexpectedly still `validated` (no server hook ran) or `testing` (verdict pending), do not jump to `complete`: hand off to `/wf-spec-wrapup`, which walks the `testing` gate properly. Never write `validated → complete`. Set `updated` to today's date whenever you change the status. ## Step 7: Run tests If the spec has a "Tests" or "Testing Strategy" section: 1. Discover and run the affected repository's documented test command. 2. Cross-reference test results against the spec's test requirements. 3. Note any spec-required tests that are missing or failing. Include test results in the Outcome section. ## Step 8: Summary Report to the user: ``` ## Spec Diff: Task: Commits: N commits, M files changed Drift: Minimal | Moderate | Significant Satisfaction: N/M items (X%) ### Satisfied - — in ### Diverged - — spec: X, impl: Y ### Not Implemented - ### Unspecified - : ### Recommendation - ``` ## Guidelines - This skill bridges the gap between "task done" and "spec accurately complete." The server-side hook (layer 1) marks the spec `complete` immediately. This skill (layer 2) verifies that claim and corrects it if needed. - Be factual, not judgmental. Divergences aren't failures — implementations often improve on specs. Document what happened and why. - Preserve the spec's existing content. The Outcome section is additive. - If you can't determine whether an item was satisfied (ambiguous spec language, unclear diff), classify it as "Cannot determine" and flag it for human review. - This skill is most valuable for design specs where the implementation had latitude to interpret. For task specs with precise "What to do" steps, the assessment is usually straightforward.