SDD Workflow Guide
SDD (spec-driven development) is one chain that takes a rough idea to a merged PR. It joins two
systems that already existed in this repo but did not talk to each other: OpenSpec (OPSX), which produces the
written spec and task list, and Superpowers, which does the actual implementation work.
The rule is simple:
OpenSpec owns what to build. Superpowers owns how it gets built.The workflow covers four independent OpenSpec roots:
Mobile roots are outside this workflow.
Why This Exists
Before this, both systems were installed and both wanted to be in charge. That caused three concrete problems. Two plans competed./opsx:propose writes tasks.md. superpowers:writing-plans writes its own
plan file. Nothing said which one was authoritative, so an agent could implement from one while the other quietly
went stale — and reviewers would read the stale one.
Agents had to guess which code review to run. Saying “review this” could mean any of five things:
code-review-to-github, code-review-workflow:respond, review-fix-loop, pr-workflow, or the built-in
/code-review. Two of those are deliberately partial — code-review-to-github reviews but cannot post to GitHub,
code-review-workflow:respond posts but needs threads to already exist — so picking the wrong one fails
silently and looks like it worked.
The chain had no PR step. The review skills operate on an open GitHub pull request, but nothing in the
workflow created one, so review had nothing to attach to.
What’s Good About It
The Chain
Every arrow is a manual gate. No step auto-chains into the next. PR creation, merge, and archive are
outward-facing or hard to undo, so a human decides when they happen.
Step-by-Step Guide
Run everything from the root that owns the change —backend/go, backend/bun, frontend/astro, or
frontend/solidstart. Each has its own openspec/ directory; they are separate OpenSpec roots, not one shared one.
Step 1 — Brainstorm
/opsx:explore — it covers the same ground.
Step 2 — Propose the change
openspec/changes/<change-name>/:
The schema is picked up automatically from
openspec/config.yaml, which is set to spec-driven-superpowers in
both backend roots and spec-driven-superpowers-fe in both frontend roots. You do not need to pass --schema.
Step 3 — Check the task shape
This is the one artifact that differs from stock OpenSpec, so it is worth a look before executing. Backend tasks use a**TDD:** line:
**Verify:** instead:
If a task needs two methods, split it into two tasks — for example, logic under
TDD and presentation under
render-test or browser. The WHEN/THEN scenarios in specs/ already provide the BDD layer; do not duplicate
them in Cucumber, .feature files, or a Gherkin runner.
Rules both schemas enforce:
- The checkbox line is the task. Never add a bare
- [ ] Completeat the end of a task block. The parser captures the checkbox text as the task name, so every task would end up named “Complete” andopenspec statusbecomes unreadable. - One task = one meaningful, independently-shippable outcome. No micro-steps. If a task cannot be verified on its own, fold it into its parent.
**Depends on:**names other task numbers, ornone.
2.1 Add PostgreSQL reservation repository), and schemaName
should be spec-driven-superpowers for backends or spec-driven-superpowers-fe for frontends.
Step 4 — Execute
/sdd:execute — it infers the change from context, auto-selects when only one is active, and asks when
ambiguous.
This is the only step with automation inside it. The skill:
- Resolves the change and loads
openspec instructions apply --json, reading every file incontextFiles. - Checks
schemaName(see legacy changes below). - Picks the next unticked task, verifying its
Depends on:prerequisites are already[x]. - Dispatches that one task to
superpowers:subagent-driven-development. Backend tasks followsuperpowers:test-driven-development; frontend tasks follow their stated**Verify:**method. On an unexplained failure it usessuperpowers:systematic-debuggingbefore any fix. - Ticks
- [ ]→- [x]once the task’s verification passes and its acceptance criteria hold: green tests forTDD,render-test, ande2e, or a reported browser check forbrowser. - Loops until no unticked tasks remain.
- Runs
openspec validate "<name>" --strictandsuperpowers:verification-before-completion. - Prints
Next: /pr-workflow:createand stops.
tasks.md (only the orchestrator writes it, so
progress stays trustworthy after a failure), and the skill never touches GitHub — no git push, no gh, no
PR, no archive.
Step 5 — Open the PR
@alvincheah88.
Step 6 — Review until clean
/code-review, and do not call the sub-skills yourself. They stay available
when you name them explicitly:
If you name one, that one runs and nothing else.
Step 7 — Merge
Normal GitHub merge. Nothing special here — but it must happen before the next step.Step 8 — Archive
openspec archive folds the change’s delta specs into the root openspec/specs/ — the record of what the system
does now.
Commit the archive result as its own small bookkeeping commit. Keep it out of the feature PR.
Legacy Changes
A change created before this workflow pins its own schema in<change>/.openspec.yaml, and that overrides
the root config.yaml. Changing the root default does not migrate existing changes:
spec-driven, and its tasks carry no Depends on: or acceptance-criteria
metadata. /sdd:execute detects this from schemaName, announces it, and runs the tasks strictly in listed
order. It will not rewrite a live change’s tasks.md into the new shape.
Reference
Files
Useful commands
openspec validate --strict with no target fails outside an interactive terminal. Always name the change.Schema copies, kept in sync by hand
Each schema exists as two real directories:spec-driven-superpowers in the two backend roots and
spec-driven-superpowers-fe in the two frontend roots. Keep copies of the same schema in sync; the backend
**TDD:** and frontend **Verify:** task formats intentionally differ.
Symlinking does not work: the OpenSpec runtime enumerates the schemas directory and skips symlinks, because
isDirectory() is false for one. The failure is confusing — openspec schema which reports success (it checks
the path directly and bypasses enumeration), then openspec status fails with
Unknown schema 'spec-driven-superpowers'. Available: spec-driven.
If you edit one copy, edit the other copy of that schema. Only the tasks artifact is customised, so drift has a small
surface — but it is real.
Related
- Review-Fix Loop Guide — the review step in detail
- Code Review Process — how findings are triaged and answered
backend/go/AGENTS.md,backend/bun/AGENTS.md,frontend/astro/AGENTS.md, andfrontend/solidstart/AGENTS.md— the routing rules agents read