pi extension · SDD · SpecKit
Spec-driven development with SpecKit
Spec-driven changes for pi, without leaving the session. Markdown specs are the source of truth; a change is a reviewed proposal; and validation, merging and coverage are deterministic DML.
What it is
- Specs describe behaviour. Plain Markdown under
.pi/deepclause/specs/is the source of truth. - A change is a reviewed proposal.
.pi/deepclause/changes/<slug>/holds a proposal, delta specs, optional design notes, and an executable task plan. - Only the model touches prose. Parsing, validation, merging, coverage, verification and rollback are deterministic DML — no model calls.
- Nothing lands silently. Every step that writes or executes is a gated, reviewable command.
Most spec tools are a Markdown convention plus a program that parses it. The convention is the good idea; the program is where it gets fragile, because parsing and merging structured text is usually written as regexes and imperative branches. Spec work is logic: a requirement is a term; every requirement has at least one scenario is a rule; merging a delta is matching and rewriting; coverage and conflicts are queries. DML expresses these directly.
The change loop
The bootstrap is conversation → change → applied → spec.
git init
printf 'node_modules/\ndist/\n' > .gitignore
git add -A && git commit -m "init"
Then, in pi:
/dc
/dc-plan build a URL shortener with slugs and click counts --change=url_shortener
git add -A && git commit -m "plan: url_shortener"
/dc-check url_shortener # grammar, delta, scenario coverage (0 tokens)
/dc-apply url_shortener # shows the tasks and command set -> confirm
/dc-archive url_shortener # shows the merge diff -> confirm
Archiving creates specs/shortener/links.spec.md and moves the
change to changes/archive/. Every later feature is the same
loop, but pi reads the existing specs first and writes
## MODIFIED Requirements when it changes existing behaviour.
Commands
| Command | Effect |
|---|---|
/dc-plan <request> --change=<slug> | Change plan: proposal + delta specs + tasks.dml |
/dc-check <slug> | Validate every spec, delta and coverage hole (0 tokens) |
/dc-apply <slug> | Execute tasks; verify, retry, resume |
/dc-archive <slug> | Merge the delta into specs/ and move the change to archive/ |
/dc-run spec_status | Capability and delta inventory |
/dc-run spec_query ui/theme | One capability's requirements and scenarios |
/dc-run spec_coverage <slug> | Uncovered scenarios, tasks without checks |
/dc-run spec_graph capabilities | Mermaid graph of capabilities and changes |
/dc-run refuses skills marked % Mutating: true, so
mutating steps always go through the reviewed /dc-apply and
/dc-archive paths.
Writing specs
# Theme Specification
## Purpose
Lets users choose between light and dark themes, defaulting to the OS preference.
## Requirements
### Requirement: Theme selection
The app SHALL let users switch between light and dark themes at runtime.
#### Scenario: User toggles dark mode
- **WHEN** the user clicks the theme toggle
- **THEN** the app switches to dark mode and persists the choice
The validator enforces:
- exactly three hashes for
### Requirement:and four for#### Scenario:; - every requirement has at least one scenario;
- no duplicate requirement names;
- specs are behaviour only — no commands, paths, or library choices.
A delta wraps requirements in ## ADDED Requirements,
## MODIFIED Requirements, ## REMOVED Requirements
or ## RENAMED Requirements. MODIFIED carries the
full replacement; MODIFIED/REMOVED must name a
requirement that exists, otherwise /dc-archive refuses rather
than silently dropping it.
Scenario ids are the join key between specs and tasks:
Theme selection in ui/theme →
ui/theme#theme-selection.
The task plan
tasks.dml is data, not a program:
plan_task("1.1", task{
executor: pi,
do: "Add a ThemeProvider context exposing theme and setTheme.",
tools: ["read", "edit"],
expected: "src/theme/ThemeProvider.tsx exports ThemeProvider and typechecks.",
satisfies: ["ui/theme#theme-selection"],
checks: [ exists("src/theme/ThemeProvider.tsx"),
cmd("npm run typecheck") ]
}).
% --- execution state (managed by apply.dml; do not edit by hand) ---
plan_task_status("1.1", pending).
executor: pidelegates a bounded step to pi with exactly the listed tools;executor: dmluses contained model reasoning.satisfieslinks the step to delta scenarios;/dc-checkfails if any delta scenario is uncovered.- Checks are declarative:
exists("path"),cmd("command"),model("question").
Verify, resume, rollback
- Checks run after each step. A failed check retries the step (up to 3 attempts) with the failure evidence threaded into the repair instruction.
- Verification commands are approved once per run and then executed through the allowlisted
dc_verify_runtool. - Snapshots:
/dc-applyrecords a git ref before running and refuses to start on a dirty tree. - Resume: if a run stops, the tree and
done/failedstatuses are preserved; re-run/dc-applyto continue from the remaining tasks. - Abort:
/dc-apply <change> --abortrestores the snapshot and resets task statuses.
Limits
RENAMEDdeltas are validated but not merged yet.- There is no digest/drift check beyond the merge guard; run
/dc-checkafter editing specs by hand. /dc-archivedoes not run/dc-checkfor you, and it writes per capability.