skills/specops-implementation-drift/SKILL.md
Audit migrated code by re-running the SpecOps analysis on the new target folder, comparing it against the original analysis spec, and generating corrective specs for each behavioral divergence so the next code-generation iteration converges toward the original behavior. Use this skill whenever the user mentions checking whether migrated code preserves original behavior, comparing migrated code against the original analysis, finding drift between legacy and migrated implementations, post-implementation verification, generating correction specs from a code analysis diff, closing the loop on a code-gen iteration, or reanalyzing a migrated module. Also trigger when the user describes "does the new code do what the old code does," "find where the migration drifted," "diff the migrated implementation against the spec," or "generate corrective specs based on a code diff." Run this after any round of code generation in a SpecOps migration, then iterate until corrections converge.
npx skillsauth add ryan-mahoney/ryan-llm-skills specops-implementation-driftInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
After a round of code generation in a SpecOps migration, the question is: does the migrated code actually do what the legacy code did? Spec-level audits (ambiguity, conformance) can verify that the specs are sound, but they can't see what the code generator actually produced. Bugs introduced during code generation — dropped error handlers, weakened concurrency, lost edge cases — are invisible to spec audits.
This skill closes the loop. It re-runs the SpecOps analysis on the migrated code (treating it as if it were itself "legacy"), then diffs that new analysis against the original analysis to find behavioral divergences. For each real divergence, it generates a corrective spec describing what needs to change so the next code-gen iteration moves toward convergence.
The cycle is: code-gen → drift audit → corrections → code-gen → drift audit → ... until corrections become insignificant.
Confirm with the user before starting:
Original analysis spec — the verified analysis derived from legacy code (e.g., docs/specs/analysis/core/orchestrator.md).
Migrated source files — the code produced by the most recent code-gen iteration (e.g., src-ts/core/orchestrator.ts and related files).
Analysis prompt — the project's existing analysis prompt template (typically docs/specops/analysis-prompt.md). The same prompt that produced the original analysis must be used here, otherwise the diff is comparing apples to oranges.
Output locations (defaults shown — all generated artifacts live under analysis-target/, mirroring the structure of the original analysis/ directory so the two trees can be diffed directly):
docs/specs/analysis-target/<module-path>.mddocs/specs/analysis-target/<module-path>.drift.mddocs/specs/analysis-target/<module-path>.corrections.mdExample: if the original is docs/specs/analysis/core/orchestrator.md, the re-analysis goes to docs/specs/analysis-target/core/orchestrator.md, with .drift.md and .corrections.md siblings.
If the user names only the module, infer the rest from the project's analysis-orchestration.md (which lists the source files and analysis output paths per module).
Spawn a single subagent that runs the project's analysis prompt against the migrated source files, producing a fresh analysis spec. Use exactly the same prompt template and section structure as the original analysis — symmetry is essential for the diff to be meaningful.
You are running a SpecOps analysis on a migrated implementation. Use the project's analysis prompt template, with the migrated source files as the input.
# Analysis prompt template
<contents of docs/specops/analysis-prompt.md>
# Module variables
- MODULE_NAME: <module name, matching the original analysis>
- SOURCE_FILES: <list of migrated source file paths>
# Your task
Read the source files completely. Produce the analysis spec following the prompt's section structure exactly. Be exhaustive within each section — match the rigor of the original analysis. Describe behavior in implementation-language-agnostic terms (no language-specific syntax in prose).
# Output
Write the resulting analysis to: <path to migrated analysis output>
This subagent runs alone (the analysis is one cohesive task). Wait for it to finish before Phase 2.
Read both analyses end-to-end. Enumerate every concrete behavioral claim in the original analysis and check whether the migrated analysis reflects it. Also enumerate claims in the migrated analysis that have no counterpart in the original (additions or scope drift).
Both analyses are LLM-generated descriptions of code behavior. Many surface-level "differences" are just prose variation describing the same behavior. The diff must distinguish real behavioral divergence from prose noise. The unifying test:
"If both analyses are accurate descriptions of their respective code, would a caller observe a different behavior?"
If not, the difference is cosmetic and should be filtered out.
Missing behavior
Weakened behavior
Changed behavior
Lost edge case or error mode
Type / schema drift
Side-effect drift
Dependency drift
Unjustified addition
Classify each real divergence:
Write the drift report to docs/specs/analysis-target/<module-path>.drift.md:
# Drift Report: <module>
- **Original analysis:** <path>
- **Migrated analysis:** <path>
- **Migrated source:** <list>
- **Audited:** <date>
## Divergences
### D1
- **Type:** Missing behavior
- **Severity:** Critical
- **Original section:** Behavioral Contracts
- **Original claim:** "Status writes are serialized through a single-writer queue to prevent torn reads under concurrent access."
- **Migrated analysis:** Section 4 describes status writes as direct file writes; no mention of serialization.
- **Question for subagent:** Verify divergence is real by inspecting migrated code. If real, generate a correction spec.
### D2
- **Type:** Weakened behavior
- **Severity:** Important
- **Original section:** Error Handling
- **Original claim:** "Retries up to 3 times with exponential backoff (100ms, 200ms, 400ms)."
- **Migrated analysis:** "Retries with backoff."
- **Question for subagent:** Is the migrated code actually doing the right thing (analysis is just imprecise) or is the retry behavior actually different?
### D3
- **Type:** Unjustified addition
- **Severity:** Cosmetic (pending verification)
- **Migrated claim:** "All public functions return Result<T, E> discriminated unions."
- **Original equivalent:** Original describes errors as thrown.
- **Question for subagent:** Does this preserve observable behavior at the module boundary, or does it change how callers must consume the API?
...
The audit runs end-to-end without pausing. Phase 2 produces the divergence list; Phase 3 starts immediately.
Spawn one subagent per divergence, all in the same turn. Each subagent's job is to verify the divergence is real (by reading the migrated code, not just the analyses) and produce the correction spec content.
You are verifying a single behavioral divergence in a SpecOps drift audit and generating a corrective spec entry. The original analysis describes the legacy code's behavior; the migrated analysis describes the migrated code's behavior. Your job is to (1) confirm whether the divergence is real by reading the actual migrated code, and (2) if real, produce a correction spec that describes what must change.
# The divergence
- Type: <type>
- Severity: <severity>
- Original section: <section>
- Original claim: "<quoted original behavior>"
- Migrated analysis: "<what migrated analysis says>"
- Question: <verification question>
# Documents to read
- Original analysis spec: <path>
- Migrated analysis spec: <path>
- Migrated source files: <list>
- (Optional) Legacy source files: <list> — read only as a tiebreaker if the original analysis is itself ambiguous
# Your task
1. Read the relevant sections of both analyses.
2. Read the migrated code directly. The migrated analysis is an LLM-generated description and may itself be imprecise — the code is ground truth for what currently exists.
3. Determine whether the divergence is real:
- If the migrated code actually preserves the original behavior and only the migrated analysis was imprecise, report `divergence_real: false` and quote the relevant lines of migrated code.
- If the migrated code actually behaves differently, the divergence is real.
4. For "Unjustified addition" cases, decide:
- Legitimate translation choice (preserves observable behavior at module boundary, justified by target language idioms) — `divergence_real: true` but `correction_needed: false`. The correction spec just annotates the rationale.
- Scope expansion or behavior change — `divergence_real: true, correction_needed: true`.
5. If a correction is needed, produce a correction spec entry that describes what must change in the migrated code, in implementation-language-agnostic terms. Specify the required behavior, not the exact code. Leave the implementer free to choose mechanism as long as the behavioral contract is met.
# Output format
Return a JSON object only:
{
"divergence_id": "<like D1>",
"divergence_real": <true | false>,
"correction_needed": <true | false>,
"code_evidence": [
{"file": "<migrated file>", "lines": "<range>", "excerpt": "<relevant code>"}
],
"correction_spec": {
"title": "<short title>",
"severity": "<critical | important | cosmetic>",
"original_behavior": "<concise statement of what the original does>",
"current_behavior": "<concise statement of what the migrated currently does>",
"required_change": "<what must be true after the fix, behaviorally>",
"constraints": "<any invariants the fix must preserve>",
"rationale": "<why this matters: what breaks if not corrected>"
},
"annotation_only": <true | false>,
"annotation_note": "<if annotation_only is true: the rationale for accepting the divergence>"
}
Spawn all subagents in one turn. Each runs independently and reads the migrated code directly — the analyses are starting points, the code is the source of truth.
If the host has no subagent capability, fall back to processing each divergence serially in the main loop using the same prompt and output format.
When all subagents return:
Sort results.
divergence_real: false — false positive (migrated analysis was imprecise; migrated code actually matches). Note in drift report; no correction needed.divergence_real: true, correction_needed: false — legitimate translation choice. Generate an annotation entry rather than a correction.divergence_real: true, correction_needed: true — generate a correction entry.Write the corrections file at docs/specs/analysis-target/<module-path>.corrections.md:
# Corrections: <module>
- **Source:** Drift audit on <date>
- **Migrated source:** <list>
- **Drift report:** <path>
## Required corrections
### CS-1: <title>
- **Severity:** Critical
- **Original behavior:** <from subagent>
- **Current behavior:** <from subagent>
- **Required change:** <from subagent>
- **Constraints:** <from subagent>
- **Rationale:** <from subagent>
- **Code reference:** <file:lines from evidence>
### CS-2: <title>
...
## Accepted divergences (annotations)
### AN-1: <title>
- **Original behavior:** <...>
- **Migrated behavior:** <...>
- **Why accepted:** <legitimate translation rationale>
Update the original analysis spec's audit log. Append:
### <YYYY-MM-DD> — Drift audit (post code-gen iteration <N>)
- Migrated source: <list>
- Migrated analysis: `<path to migrated analysis>`
- Divergences identified: <count>
- False positives (analysis was imprecise, code matches): <count>
- Real corrections needed: <count> (Critical: <n>, Important: <n>, Cosmetic: <n>)
- Accepted as legitimate translation: <count>
- Drift report: `<path>`
- Corrections: `<path>`
Assess convergence. Compute:
Recommend:
Summarize for the user.
User: "Run a drift audit on the orchestrator module. The migrated code is in src-ts/core/orchestrator.ts."
docs/specs/analysis/core/orchestrator.md) and the project's analysis prompt.src-ts/core/orchestrator.ts using the same prompt; write to docs/specs/analysis-target/core/orchestrator.md.docs/specs/analysis-target/core/orchestrator.drift.md.Result<T, E> in place of thrown errors, with module-boundary behavior preserved).docs/specs/analysis-target/core/orchestrator.corrections.md with 9 CS entries and 3 AN entries.analysis-target/core/orchestrator.corrections.md. Compared to the previous drift audit (which had 6 Critical), the migration is improving."This skill is the post-implementation iteration gate. The full verification chain:
Steps 2 and 5 are spec-level verification (catching errors in description). Step 7 is code-level verification (catching errors in generation). Each catches a class of drift the others can't see, and they compound — running all three drives the migration toward behavioral fidelity faster than any one alone.
documentation
This skill should be used when the user asks to "write a spec", "create a spec", "spec this out", "plan this feature", or "write an implementation plan" for a feature or change. Creates a structured implementation spec in .specs/<slug>/spec.md and mirrors it to GitHub only when the current repository is hosted on GitHub.
data-ai
This skill should be used when the user asks to "execute the spec", "run the plan", "implement the spec", "implement the issue", "run all steps", or "run spec". Implements all steps from .specs/<slug>/spec.md, using a subagent per step when the harness supports subagents.
testing
This skill should be used when the user asks to "review a spec", "review an issue", "check the plan", "review the implementation plan", "find gaps in the spec", or "review spec". Reviews .specs/<slug>/spec.md for gaps and viability, edits it when needed, and mirrors changes to GitHub only when a GitHub mirror exists.
development
This skill should be used when the user asks to "remediate the audit findings", "fix the spec violations", "close the audit findings", "fix conformance violations", or "spec remediate". Reads a spec-audit report, drives one smart subagent per VIOLATION to converge the code back to the frozen spec, and re-audits until clean. Edits production code; never rewrites the spec.