Skip to content
Agentmart
Submit a tool

sdd:drift

SDD — Spec-Driven Development: detect code that drifted from .specs/<domain>/spec.md (changed without spec update).

Skill by alfredoperez

IndexedMIT★ 2
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/alfredoperez-sdd-drift

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

SDD — Spec-Driven Development: detect code that drifted from .specs/<domain>/spec.md (changed without spec update).

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/sdd-drift

What's inside

Skill name
sdd:drift
Description
SDD — Spec-Driven Development: detect code that drifted from .specs/<domain>/spec.md (changed without spec update).
License
MIT
Instructions
90 lines in SKILL.md · view on GitHub

Agent Skills spec issues

  • name: only lowercase letters, digits and single hyphens allowed
  • name: "sdd:drift" does not match folder "drift"

Files (1)

  • SKILL.md

SKILL.md (first lines)

Usage: `/sdd:drift` (no arguments — scans every domain via the union discovery in [layered-context](../../lib/instructions/layered-context.md#domain-discovery-all-domains)).

Detects files that have changed since the corresponding domain's living spec (centralized `.specs/<domain>/spec.md` or a colocated `specPath`) was last updated. Useful for catching code that evolved without going through `/sdd:specify` → `/sdd:plan` → `/sdd:implement`, so the living spec is now lying.

## Steps

### 1. Load configuration

Read `.sdd.json` (if present):
- `specExempt`: glob list of paths to ignore. Default: `["*.config.*", "*.test.*", "**/migrations/**", "scripts/**"]`.
- `driftCheck`: `"off"` | `"warn"` | `"gate"`. Default: `"warn"`. `off` short-circuits the skill (`✓ Drift check disabled (.sdd.json#driftCheck = off)`); `warn` and `gate` both run the report — `gate` is informational here (the gating decision is up to the surrounding workflow / CI).
- `domains`: same map used by [layered-context](../../lib/instructions/layered-context.md). Used to resolve which files belong to which domain and to discover colocated domains.

Stop only if there are **both** no configured domains in `.sdd.json#domains` **and** no `.specs/*/spec.md` on disk, with: `No domains configured and no .specs/ folder — nothing to check. Run /sdd:init or seed .specs/<domain>/spec.md first.`

### 2. Discover domains + last-spec-update commit

Enumerate domains and orphans by **running the resolver script**:

```bash
python3 lib/scripts/resolve-spec-paths.py --all
```

The JSON `domains[]` is the union of `.sdd.json#domains` and the `.specs/*/spec.md` glob (de-duplicated by resolved path), each with its resolved `specPath`. The JSON `orphans[]` is the orphan list (see below).

For each discovered domain:

1. Take its resolved `specPath` from the script output (colocated or centralized — already computed).
2. Get the last commit that modified that resolved path:
   ```bash
   git log -n 1 --format=%H -- <resolved-spec-path>
   ```
   Skip the domain if the file is untracked (no commits yet) — log `ℹ <domain>: spec.md not yet committed; skipping drift check`.

Also report each entry in the script's `orphans[]` (a `*.spec.md` in the tree that no configured `specPath` claims): `ℹ Orphan living spec <path> — not referenced by any .sdd.json domain`.

### 3. Find drifted files per domain

For each domain with a tracked spec:

1. Resolve the domain's file pattern:
   - If `.sdd.json#domains.<domain>.pattern` exists, use that regex.
   - Otherwise, fall back to a path prefix match against `<domain>/` and `src/<domain>/` (anything inside a directory whose basename equals the domain name).
2. List files changed since the spec's last commit:
   ```bash
   git log --since-commit=<spec-commit> --name-only --pretty=format: -- <pattern-paths>
   ```
   Or equivalently `git diff --name-only <spec-commit>..HEAD -- <pattern-paths>`. Pick the form that respects the pattern.
3. Filter out:
   - Files matching any glob in `specExempt`.
   - The spec.md itself.
   - Files outside the matching pattern.
4. The result is the drift list for this domain.

### 4. Severity heuristic

Per drifted file, classify:

| Signal | Severity |
|---|---|
| File listed in any `specs/*/.spec-context.json#files_modified` since the spec's last commit | `tracked` (changed via SDD pipeline — Layer 1 wasn't synced; treat as a missed sync) |
| File outside `files_modified` of any spec | `unspeced` (changed entirely outside SDD) |
| File matches `specExempt` | (filtered out earlier; never appears) |

`unspeced` is more concerning than `tracked` — `tracked` may just mean the spec author didn't add a delta block, while `unspeced` means SDD never saw the change at all.

### 5. Report

Display per-domain:

```
🔍 Spec drift report

📁 <resolved-spec-path>   (last updated <YYYY-MM-DD>, commit <abbrev>)
   <N> files changed since spec was last updated:

   tracked  src/auth/login.ts        — touched in spec 014-add-rate-limit (no delta block)
   tracked  src/auth/session.ts      — touched in spec 014-add-rate-limit (no delta block)
   unspeced src/auth/oauth.ts        — changed outside SDD pipeline

   👉 Run /sdd:specify to add a delta spec, or add the path to specExempt in .sdd.json.
```

If a domain has no drift, output `✓ <domain> — in sync` on a single line.

If every domain is in sync, the final line is `✓ All domains in sync.` and nothing else.

Always exit with success (this skill never halts the pipeline). Surrounding workflows can choose to treat `unspeced` rows as gates.

From alfredoperez/sdd, MIT.

Signals

Stars
2
Forks
0
Open issues
0
Last commit (this folder)
May 23, 2026 (5 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from alfredoperez

Cite this page

sdd:drift skill. Agent Mart. https://agentmart.dev/skills/alfredoperez-sdd-drift (last updated 2026-10-24)