From spec-mirror
Drift-check the current implementation against the existing specs/ directory. Use when the user wants to verify the spec is still accurate, catch undocumented changes, or run the safety-net check after recent code edits. Triggers include "spec compare", "drift check", "verify spec", "is the spec stale", "check spec drift", "스펙 비교", "스펙 드리프트", "스펙 확인", "스펙 검증". Produces specs/DRIFT.md categorizing added / removed / changed elements per layer and per flow, with severity ratings. Does NOT modify the existing specs — only reports.
How this skill is triggered — by the user, by Claude, or both
Slash command
/spec-mirror:compareThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Compare the **current implementation** against the **existing `specs/` directory** and emit a drift report. This skill is the safety-net counterpart to `/spec-mirror:generate`: it never edits the spec files themselves, only reports what has diverged.
Compare the current implementation against the existing specs/ directory and emit a drift report. This skill is the safety-net counterpart to /spec-mirror:generate: it never edits the spec files themselves, only reports what has diverged.
Invoke when the user says any of:
Pre-condition: a specs/ directory generated by /spec-mirror:generate must already exist at the project root. If it doesn't, stop and tell the user to run /spec-mirror:generate first.
Do not invoke for: writing or updating specs (that's generate), explaining code, or general code review.
This skill produces exactly one file:
specs/
└── DRIFT.md # <- the only file this skill writes
It MUST NOT modify any existing specs/** file. If the user wants the specs updated, they should run /spec-mirror:generate (with the "update existing files" option).
DRIFT.md structure# Spec Drift Report
- **Spec generated:** <ISO timestamp from specs/README.md>
- **Compared at:** <ISO timestamp now>
- **Verdict:** [OK | WARN | DRIFT]
## Summary
| Layer | Added | Removed | Changed |
|----------|-------|---------|---------|
| frontend | N | N | N |
| backend | N | N | N |
| domain | N | N | N |
| flows | N | N | N |
## Critical (severity: 🔴)
…
## Warnings (severity: 🟡)
…
## Info (severity: 🔵)
…
## Suggested actions
- Run `/spec-mirror:generate` with "update existing files" to refresh sections X, Y.
- Manually review flow `02-checkout.md` — its referenced endpoint was removed.
Classify every diff into exactly one bucket. Be conservative: when unsure, escalate one level.
| Severity | Definition | Examples |
|---|---|---|
| 🔴 Critical | Spec claims something that is now broken: dangling cross-references, removed endpoints/handlers that flows still reference, removed invariants the spec claimed were enforced. | Flow 01-signup.md links to POST /api/auth/signup but that route no longer exists. |
| 🟡 Warning | New behavior in code that is undocumented in spec, or changed signatures/contracts. Safety net is partial. | New endpoint POST /api/auth/oauth added but no spec entry. Handler's input shape changed. |
| 🔵 Info | Cosmetic or non-behavioral: renamed private helpers, moved files (same exports), reformatted code. | UserService moved from services/ to domain/services/ but exports unchanged. |
specs/README.md exists. If not → stop, instruct user to run /spec-mirror:generate.specs/README.md to learn the recorded stack + generation timestamp.specs/layers/{frontend,backend,domain}.md) and the specs/flows/ directory exist. Missing files are themselves drift — record them as critical findings but continue.Re-run the same detection logic as /spec-mirror:generate Phase 0–2, but do not write any files. Build an in-memory map keyed by canonical element id:
frontend:<route-or-component-name>backend:<METHOD> <path> or backend:handler:<name>domain:<entity-or-vo-name>generateEach element carries: source file, source line, signature/shape summary, and a content hash of its description-relevant fields (path, params, return shape, invariants).
Parse each layered file and each flow file. Extract elements by their headings + the trailing source reference (→ src/...:42). Build a second in-memory map with the same keying.
Be tolerant of human edits inside <!-- KEEP --> blocks — treat their contents as opaque and skip diffing inside them.
For each element id, classify:
For each flow file, additionally:
../layers/*.md#anchor. Verify the anchor still exists in the corresponding layered map (post-diff). Dangling link → 🔴.specs/DRIFT.mdRender the report using the structure above. Group findings by severity, then by layer. For each finding include:
- **<element id>** — <what changed>
- Spec said: `<short quote or signature>` (`specs/layers/<file>.md#anchor`)
- Code now: `<short quote or signature>` (`<source-path>:<line>`)
- Impact: <one sentence on what this affects, especially which flows>
After writing DRIFT.md, post a short summary in chat:
Drift verdict: <OK | WARN | DRIFT>
- 🔴 Critical: N
- 🟡 Warning: N
- 🔵 Info: N
Top 3 things to look at: …
Full report: specs/DRIFT.md
If verdict is OK, still write DRIFT.md (with empty sections + the timestamp) so a CI gate or follow-up run can rely on its presence.
OK — zero 🔴 and zero 🟡 findings.WARN — any 🟡 findings, no 🔴.DRIFT — at least one 🔴 finding.<!-- KEEP --> blocks.Unlike /spec-mirror:generate, this skill does not ask the user clarifying questions during the run. It must be safe to invoke in CI / as a pre-commit / repeatedly without prompting. The only exception is the precondition failure in Phase 0.
You are done when:
specs/DRIFT.md exists at the project root.specs/ other than DRIFT.md was modified.npx claudepluginhub edonghyun/donghyuns-agent-tools --plugin spec-mirrorProvides a checklist for code reviews covering functionality, security, performance, maintainability, tests, and quality. Use for pull requests, audits, team standards, and developer training.