sdd — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited sdd (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Route user intent to the correct sdd-* child skill. Classify first, then confirm with the user before routing.
When this skill is invoked, announce: "Using sdd to route your spec-driven development request."
Should trigger:
Should not trigger:
A SPECS_ROOT is a directory whose direct children conform to the SDD layout: specs/, changes/, and schemas/ (with optional .sdd/). The conventional location is a hidden .specs/ at a project root; in a monorepo, each package may have its own <package>/.specs/.
Before routing, run the discovery script and parse its JSON:
skills/sdd/scripts/find-specs-roots.py [--explicit PATH]Pass --explicit PATH only if the user named a specific directory. The script anchors at the repo root (or cwd when not in a git repo), discovers .specs/ candidates, analyzes any SPECS_ROOT pointer files, and falls back to specs/ discovery if no .specs/ is found.
The agent — not the script — drives the user-facing dialogue. See references/find-specs-roots.md for the output schema, decision branches, and `SPECS_ROOT` pointer-file format.
Summary of behavior:
.specs/ candidates → ask which to use..specs/ with a pointer → if multiple targets, list and ask which to use; if one target, follow it once; surface any malformed/broken/out-of-workspace pointer (or a target that exists but lacks the SPECS_ROOT layout — likely the user pointed at the parent of .specs/ instead of the .specs/ directory itself) instead of silently falling back..specs/ but specs/ fallback hits → confirm with user (default: parent of specs/).Call the resolved path SPECS_ROOT. All child skills use SPECS_ROOT in place of .specs/.
| User Intent | Route | Notes |
|---|---|---|
| Think before acting, explore ideas | sdd-explore | Always available |
| Convert existing specs from another tool | sdd-translate | Bootstrap path |
| Generate specs from codebase analysis | sdd-derive | Bootstrap or change |
| Create a change with all artifacts | sdd-propose | Change path |
| Implement tasks from tasks.md | sdd-apply | Requires tasks.md |
| Verify implementation matches specs | sdd-verify | Requires active change |
| Merge delta specs into main specs | sdd-sync | Requires delta specs |
| Complete and archive a change | sdd-archive | Requires active change |
The chart focuses on intent routing. Discovery details (thespecs/fallback andSPECS_ROOTpointer-file redirect) are described in Locate Specs Root above and elided here for readability.
digraph sdd_router {
rankdir=TB;
node [fontname="Helvetica", fontsize=10];
edge [fontname="Helvetica", fontsize=9];
start [label="User intent", shape=ellipse];
locate_root [label="Locate SPECS_ROOT\n(.specs/ directories)", shape=box];
multi_specs [label="Multiple .specs/\nfound?", shape=diamond];
ask_which [label="Ask user which\nto use", shape=box];
explore_first [label="Wants to think\nbefore acting?", shape=diamond];
explore [label="sdd-explore", shape=box];
has_specs [label="SPECS_ROOT/specs/ exists?", shape=diamond];
confirm_mode [label="Confirm intent\nwith user", shape=box];
translate [label="sdd-translate", shape=box];
derive [label="sdd-derive", shape=box];
propose [label="sdd-propose", shape=box];
has_change [label="Active change exists?", shape=diamond];
which_change [label="Which change?\n(ask if multiple)", shape=box];
has_tasks [label="tasks.md exists?", shape=diamond];
stop [label="STOP:\nrun sdd-propose first", shape=octagon, style=filled, fillcolor=red, fontcolor=white];
apply [label="sdd-apply", shape=box];
verify [label="sdd-verify", shape=box];
sync [label="sdd-sync", shape=box];
archive [label="sdd-archive", shape=box];
start -> locate_root;
locate_root -> multi_specs;
multi_specs -> ask_which [label="yes"];
multi_specs -> explore_first [label="no (0 or 1)"];
ask_which -> explore_first;
explore_first -> explore [label="yes"];
explore_first -> has_specs [label="no, ready to act"];
explore -> has_specs [label="crystallized,\nready to act", style=dashed];
has_specs -> confirm_mode;
confirm_mode -> translate [label="convert existing specs"];
confirm_mode -> derive [label="spec from code"];
confirm_mode -> propose [label="new change"];
confirm_mode -> has_change [label="apply/verify/\nsync/archive"];
confirm_mode -> explore [label="think more"];
has_change -> which_change [label="yes"];
has_change -> propose [label="no", style=dashed];
which_change -> has_tasks [label="apply"];
which_change -> verify [label="verify"];
which_change -> sync [label="sync"];
which_change -> archive [label="archive"];
has_tasks -> apply [label="yes"];
has_tasks -> stop [label="no"];
}.specs/ before routing; ask if multiple exist or user specifies a pathSPECS_ROOT/specs/ existence — but always confirm with user before routingsdd-apply requires tasks.md at SPECS_ROOT/changes/<change-name>/tasks.md; if missing, stop and route to sdd-propose| Action | Expected prerequisite | Warning if missing |
|---|---|---|
| sdd-apply | SPECS_ROOT/changes/<name>/tasks.md | Hard block — "No tasks to implement. Run sdd-propose first." |
| sdd-verify | Some completed tasks in tasks.md | "No completed tasks yet — verify output will be limited." |
| sdd-sync | Delta specs in change directory | "No delta specs to sync." |
| sdd-archive | All tasks complete | "Incomplete tasks remain. Archive anyway?" (ask user) |
| design.md | proposal.md exists | "Consider writing a proposal first for context." |
All SDD skills operate on SPECS_ROOT — resolved at session start (see Locate Specs Root above). The default is .specs/ at the project root, but monorepos or user preference may place it elsewhere (e.g., packages/api/.specs/, services/auth/.specs/).
Child skills replace .specs/ with SPECS_ROOT in all paths.
<SPECS_ROOT>/ # e.g. .specs/ or packages/api/.specs/
├── NORTH-STAR.md # Product elevator pitch — durable singleton; change user stories ladder to it
├── specs/ # Main specs (source of truth)
│ └── <capability>/
│ └── spec.md
├── schemas/ # Schema snapshots (generated from code)
│ ├── .schema-sources.yaml # Manifest: generation date and source per schema
│ └── <schema-type> # e.g., openapi.yaml, db-schema.sql, schema.graphql
├── changes/
│ ├── <change-name>/ # In-progress changes (kebab-case)
│ │ ├── proposal.md
│ │ ├── design.md
│ │ ├── tasks.md
│ │ ├── .verify/ # Transient verify scratch (self-gitignored) — test log + report; never committed or archived
│ │ ├── schemas/ # Schema snapshots scoped to this change
│ │ │ ├── before/ # Snapshot taken at propose/derive time
│ │ │ ├── after/ # Snapshot taken at verify time
│ │ │ └── expected.md # Prose: expected schema changes
│ │ └── specs/ # Delta specs
│ │ └── <capability>/
│ │ └── spec.md
│ └── archive/ # Completed changes (schemas travel with change)
│ └── YYYY-MM-DD-<name>/
├── .sdd/ # SDD tooling metadata
│ ├── schema-config.yaml # Project schema extraction config
│ └── suggested-tools # Tracks one-time tool suggestionsAn active change is any directory directly under SPECS_ROOT/changes/ (not under archive/). Archived changes live in SPECS_ROOT/changes/archive/YYYY-MM-DD-<name>/. Schema snapshots travel with the change directory into the archive — no separate schema archive path is needed.
Everything in a change directory is durable and committed — proposal, design, tasks, delta specs, and schema snapshots all travel into the archive as the change's record. The one exception is .verify/: run-scoped scratch (the captured test output and any persisted verification report) that sdd-verify regenerates on each run. It is self-gitignored — sdd-verify writes a .gitignore containing * into the directory — so it never enters a commit or the archive. A verification report is a derived snapshot, not a source of truth: its durable consequences (waivers, overrides, remediation tasks) are written back into design.md and tasks.md, which are committed.
NORTH-STAR.md is the product elevator pitch — a durable, project-global singleton that names the product's reason for being. It is the apex of the value chain north star → user story → requirement: each change's user stories (in proposal.md) ladder up to it, and each delta requirement's Serves: backlink points at a story. It is seeded once (see sdd-propose) and changes rarely. Unlike baseline specs, it carries product intent, not contracts — keep it short.
references/sdd-spec-formats.md — baseline spec, delta spec, scenario formatsreferences/sdd-change-formats.md — proposal, design, tasks formatsreferences/sdd-schema.md — schema artifacts and lifecycle policyreferences/sdd-router.dot — canonical DOT source for the routing flowchart abovereferences/find-specs-roots.md — output schema for the discovery script used in Locate Specs Rootscripts/find-specs-roots.py — discovery script that resolves .specs/, fallback specs/, and SPECS_ROOT pointer files~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.