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

CommandEffect
/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_statusCapability and delta inventory
/dc-run spec_query ui/themeOne capability's requirements and scenarios
/dc-run spec_coverage <slug>Uncovered scenarios, tasks without checks
/dc-run spec_graph capabilitiesMermaid 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/themeui/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: pi delegates a bounded step to pi with exactly the listed tools; executor: dml uses contained model reasoning.
  • satisfies links the step to delta scenarios; /dc-check fails 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_run tool.
  • Snapshots: /dc-apply records a git ref before running and refuses to start on a dirty tree.
  • Resume: if a run stops, the tree and done/failed statuses are preserved; re-run /dc-apply to continue from the remaining tasks.
  • Abort: /dc-apply <change> --abort restores the snapshot and resets task statuses.

Limits

  • RENAMED deltas are validated but not merged yet.
  • There is no digest/drift check beyond the merge guard; run /dc-check after editing specs by hand.
  • /dc-archive does not run /dc-check for you, and it writes per capability.