| title | Workflow Guide |
|---|---|
| section | Reference |
| order | 2 |
End-to-end walkthrough of the verified SpecSync 6.0 change workflow.
Every new delivery follows one predictable path:
new → one scope approval → implement → check → PR review → finalize → GitHub merge
| State | What happens | Key commands |
|---|---|---|
| Draft | Deterministic interview selects scope and adaptive artifacts | change new, change answer |
| Approved | A human approves the scope/definition digest once | change approve |
| Implementing | Code, canonical specs, and tests follow the approved package | change check |
| Verifying | Targeted evidence is current and one scoped PR review is required | change check, ordinary PR review |
| Archived | Finalization atomically applies deltas and moves the package to dated history in the same PR | change finalize |
Module maturity (draft → review → active → stable → deprecated → archived) remains separately available through specsync lifecycle.
specsync change new "Add passkeys" --spec auth --path src/auth.rs --json
specsync change answer CHG-0001-add-passkeys acceptance_criteria \
"A registered passkey authenticates the user" --json
specsync change answer CHG-0001-add-passkeys public_contract yes --json
specsync change answer CHG-0001-add-passkeys architecture_risk yes --jsonAcceptance criteria preserve the submitted prose as one criterion, including commas and line breaks. To submit more than one criterion, pass an explicit JSON string array such as '["Passkey login works", "Recovery remains available"]'. Scope questions such as affected_specs and affected_paths continue to accept comma- or newline-separated lists.
The shared deterministic engine asks only unresolved questions and selects requirements, research, design, plan, tasks, context, testing, docs, or custom artifacts according to change type and risk. Agent skills present the same questions conversationally.
Every new change also updates .specsync/change-sequence.json. Because that protected claim is committed, two branches that independently select the same numeric sequence conflict during Git integration instead of silently creating duplicate CHG-NNNN records. Sequences use at least four digits and continue past CHG-9999. Strict lifecycle checking scans active and archived workspaces together. Historical collisions can be preserved only by listing the exact sequence and complete set of immutable accepted or archived full IDs under acknowledged_collisions; adding or removing an ID, or including a mutable lifecycle state, makes the baseline fail closed.
Complete selected artifacts and semantic deltas, then obtain explicit human approval:
specsync change approve CHG-0001-add-passkeysRequirements use stable IDs, normative SHALL statements, and acceptance criteria. Only a change to the approved stable intent, contract, acceptance criteria, or affected scope requires renewed human approval. Implementation details, tests, evidence, canonical delta materialization, and lifecycle metadata preserve that approval while automated verification and the independent scoped review are refreshed.
specsync change check CHG-0001-add-passkeys
# open or update the PR, then complete ordinary PR review
# after an independent scoped reviewer passes the change package, diff, spec delta, and evidence:
specsync change review CHG-0001-add-passkeys --reviewer "Ada Reviewer"
specsync change finalize CHG-0001-add-passkeys
# commit the metadata/archive-only result; GitHub performs the mergechange check applies approved semantic deltas and runs the affected component's configured
verification for this change only. It does not re-validate archived terminal evidence —
archives are history. Use change audit for project health over active workspaces and living
specs. Explicit --strict, project policy, and deterministic release/security classification add
validators to the same scoped evidence path. Source, test, configuration, or contract edits stale
verification; implementation edits after scoped review stale the review. change status prints the
exact change review command when this independent review is the next required action; change review records the completed review and does not replace the repository's ordinary PR review.
The reviewer value is a stable ASCII claim recorded with an append-only pass/block trail. It is not
the trust root: required CI authenticates the official SpecSync scoped review GitHub Actions check
on the exact implementation parent before the finalization child can merge.
change finalize requires current verification and independent review, writes domain-separated
finalization evidence, and moves the package to .specsync/archive/changes/YYYY-MM-DD-<id>/ in one
metadata/archive-only commit. Its lightweight CI lane proves the parent implementation checks were
green and the child changed only approved lifecycle/archive paths; it does not rerun product tests
or scoped review. GitHub branch protection or merge queue owns the merge. A post-merge job binds the
actual merge commit/tree to a compact archive event before release validation can proceed.
Historical start, verify, accept, archive, reopen, correct, and correct-owner
commands remain available to validate or repair older two-approval evidence. They are compatibility
surfaces, not steps in the new-change workflow.
If final review changes a governed source, test, configuration, policy, or contract input after acceptance, strict checking correctly rejects the stale closing evidence. Do not edit lifecycle JSON or archive the active workspace. Record an audited transition instead:
specsync change reopen CHG-0001-add-passkeys \
--actor "Ada Reviewer" \
--reason "Final review changed the authentication policy and tests"
specsync change verify CHG-0001-add-passkeys
specsync change accept CHG-0001-add-passkeys --actor "Ada Reviewer"Reopen is allowed only when the accepted delivery-input digest is stale. It moves the change back to verifying, embeds the prior verification and superseded closing approval in append-only audit history, and leaves strict CI red until a fresh verification succeeds. Reacceptance records a new closing approval without applying the already-canonical semantic delta a second time. Use global --json to receive the deterministic change and versioned audit objects.
Squash-integrated changes and changes partially superseded by later canonical work may also reopen when current Git history records their accepted state or later recorded canonical changes govern every affected contract surface. The unchanged definition, passed evidence, valid closing approval, stale delivery inputs, explicit actor, and audit reason remain mandatory; copied or arbitrary off-history evidence is rejected.
The reopened definition must remain identical to the contract that originally applied the canonical delta. If review requires new or changed requirements, deltas, or other definition artifacts, create a new change workspace; reacceptance fails closed instead of silently ignoring those edits.
If re-verification proves that an already-scoped production input had another canonical owner omitted from the historical affected-spec list, record that exact ownership correction after reopening:
specsync change correct-owner CHG-0001-add-passkeys \
--path src/auth.rs \
--spec auth-policy \
--actor "Ada Reviewer" \
--reason "The historical definition omitted the canonical auth-policy owner"
specsync change approve CHG-0001-add-passkeys --actor "Ada Reviewer"
specsync change verify CHG-0001-add-passkeys
specsync change accept CHG-0001-add-passkeys --actor "Ada Reviewer"correct-owner is intentionally exact and additive. The path must already be inside the original delivery scope, the named module's current canonical spec must list that source file, and the change must be already applied and in verifying through an audited reopen. The command cannot add paths, affected specs, requirements, or semantic deltas. It preserves prior approval and reopen evidence, makes the definition approval stale, and requires fresh approval, verification, and closing approval. Reacceptance adds the corrected module only to that manifest entry and does not apply the canonical delta again. If the needed change is a real semantic rescope, create a successor change instead.
When a later canonical change expands a governed contract, it can keep an accepted predecessor from deadlocking implementation only when it is an exact successor: it has a higher sequence, current human-approved definition, semantic deltas, and complete coverage of every predecessor spec and path. A verifying successor also needs fresh passed evidence. Draft, no-spec, partial, failed, stale-definition, or abandoned records never suppress predecessor errors.
Use change correct when the accepted delivery evidence is current but review proves that the original public_contract or architecture_risk answer was wrong:
specsync change correct CHG-0001-add-passkeys architecture_risk yes \
--actor "Ada Reviewer" \
--reason "The persistence boundary makes this an architectural change"
# complete any newly selected research/design/plan/tasks/testing artifacts
specsync change approve CHG-0001-add-passkeys --actor "Ada Reviewer"
specsync change verify CHG-0001-add-passkeys
specsync change accept CHG-0001-add-passkeys --actor "Ada Reviewer"Correction is intentionally narrower than editing an accepted definition. It supports only the two closed yes/no classification fields. The original answers, selected artifacts, approvals, and verification remain unchanged and inspectable; corrections.json records the actor, reason, values, portable view digests, prior evidence, and artifacts added by each correction. Effective artifacts are monotonic, so changing a value back to no never removes scrutiny already recorded.
Correction moves accepted to verifying and requires a fresh definition approval before verification plus a fresh closing approval before reacceptance. A second correction is available only after the first is reaccepted. Because canonical application remains recorded, reacceptance never applies or version-bumps the semantic delta twice. Use change reopen instead when the definition is unchanged and only governed delivery inputs made accepted evidence stale.
The repository includes executable examples for a complete lifecycle, ordered concurrent changes, and a five-epic product evolution. Each creates a disposable Git project and runs the real CLI end to end.
specsync initThis creates .specsync/config.toml, .specsync/sdd.json, the change/archive directories, detects
verification commands, and offers native agent integration plus a first change interview. Existing
projects remain unchanged until specsync change adopt; adoption preserves their policy and
historical evidence while routing subsequent changes through this workflow. Commit and integrate
every active legacy change first: adoption refuses to publish a partial migration when a v1 record
is absent from the trusted comparison cutoff.
specsync hooks installThis installs:
- Agent instructions —
CLAUDE.md,.cursor/rules,.github/copilot-instructions.md,AGENTS.md— so AI coding tools know to respect specs - Pre-commit hook — runs
specsync checkbefore every commit, blocking commits with spec errors
Check what's installed with specsync hooks status.
specsync add-spec authCreates specs/auth/ with five files by default, plus optional design.md when design artifacts are enabled:
| File | Purpose | Who writes it |
|---|---|---|
auth.spec.md |
Technical contract — frontmatter, Public API, Invariants | Developer / Architect |
requirements.md |
User stories, acceptance criteria, constraints | Product / Design |
tasks.md |
Outstanding work items, review sign-offs | Anyone |
context.md |
Design decisions, key files, current status | Developer / Agent |
testing.md |
Test strategy, QA checklists, edge cases | QA / Developer |
design.md (opt-in) |
Layout, component hierarchy, design tokens | Design / Frontend |
The spec file is validated bidirectionally against code. Companion files provide structured context for humans and AI agents, and strict mode also rejects known generated scaffold markers left in context.md, requirements.md, testing.md, tasks.md, or design.md. Diagnostics identify the artifact path and line; fenced examples containing a marker are ignored.
Convention: Requirements (user stories, acceptance criteria) belong in
requirements.md, not as inline sections in the spec. Non-draft specs with inline## Requirementsor## Acceptance Criteriasections will produce a warning.
specsync generate # deterministic guided starter specs
specsync agents install # install native agent workflowGeneration never sends source to a model. Your coding agent can enrich the scaffold through the installed skill or MCP, using its own permissions. Always review the result and run specsync check immediately after.
Create specs/<module>/<module>.spec.md with the required frontmatter (module, version, status, files) and sections. See Spec Format for the full reference.
specsync checkThree stages run in order:
- Structural — required frontmatter fields, file existence, required sections
- API surface — spec symbols vs. actual code exports (bidirectional)
- Dependencies —
depends_onpaths,db_tablesagainst schema
Errors mean the spec references something that doesn't exist in code. Warnings mean code exports something the spec doesn't document.
specsync check --fixAdds review rows to your Public API tables for any undocumented exports. You still need to replace the generated description prompts, but the symbol names are correct.
specsync check --strict
specsync check --strict --require-coverage 100--strict promotes warnings to errors — every export must be documented. --require-coverage fails if file coverage drops below the threshold.
The typical iteration loop:
specsync check # see what's wrong
# fix errors — rename symbols, add missing exports, update file paths
specsync check # verify fixes
# repeat until cleanCommon fixes:
| Error | Fix |
|---|---|
Phantom export foo not found in source |
Remove foo from the spec, or add it to the code |
Undocumented export bar |
Add bar to the Public API table |
File src/old.ts not found |
Update the files list in frontmatter |
| Required section missing | Add the section heading and content |
When working with an AI agent, pipe --json output for structured error handling:
specsync check --json
# Agent reads JSON, fixes each error, re-runs checkspecsync coverageShows file and LOC coverage — what percentage of your source code has a spec. HTML, HTM, and CSS are auto-detected and measured by default alongside language sources, so zero-config static repositories produce real covered and uncovered counts rather than disappearing from the denominator. Use --json to get machine-readable output with uncovered_files sorted by size, so you can prioritize the largest gaps.
specsync scoreScores each spec on a 0–100 scale based on completeness, detail, API table coverage, behavioral examples, and more. Each spec gets a letter grade and specific improvement suggestions.
specsync watchRe-validates on every file change (500ms debounce). Useful during active development — you'll see spec drift the moment it happens.
specsync diff --base main
specsync diff --base HEAD~5Shows API changes since a git ref — what was added, removed, or changed. Good for reviewing what spec updates a PR needs.
When you rename, add, or remove exports:
- Run
specsync checkto see what drifted - Update the spec's Public API table
- Bump the
versionin frontmatter - Add a Change Log entry
- Run
specsync checkto confirm
When you add new source files:
- Add the file path to the relevant spec's
fileslist - Add any new exports to the Public API table
- Run
specsync checkto confirm
When you create a new module:
specsync add-spec <name>orspecsync generateto scaffold- Complete the spec content
- Run
specsync checkto validate
As specs accumulate changelog entries and tasks get completed, companion files grow. Two commands handle this:
specsync compact --keep 10 # keep last 10 entries per spec
specsync compact --keep 5 --dry-run # preview what would be removedTrims older changelog entries to prevent unbounded growth. Use --dry-run first to preview.
specsync archive-tasks # move completed tasks to archive
specsync archive-tasks --dry-run # preview what would be archivedMoves completed checkboxes from tasks.md files to an archive section, keeping active work visible.
When modules depend on other repositories:
# In the dependency repo: publish a registry
specsync init-registry
# In your repo: reference the dependency
# In frontmatter: depends_on: ["corvid-labs/algochat@messaging"]
# Validate local refs
specsync resolve
# Validate cross-project refs (fetches from GitHub)
specsync resolve --remoteSee Cross-Project References for the full setup.
- name: Validate specs
run: specsync check --strict --require-coverage 80See GitHub Action for the official action with caching and PR comments.
specsync hooks install sets up a pre-commit hook that runs specsync check before every commit. If specs are invalid, the commit is blocked.
specsync check --strict # no warnings allowed
specsync check --require-coverage 80 # enforce coverage threshold
specsync score --json # track quality over timeSpecSync is designed for AI-assisted development. Three integration modes:
specsync mcp # read-only tools
specsync mcp --allow-write # opt in to root-confined init/generate toolsThe default server exposes validation, coverage, listing, scoring, and issue-verification tools.
--allow-write additionally exposes deterministic generation and initialization at the configured
server root. Claude Code, Cursor, and Windsurf can call them directly. See For AI Agents for setup and confinement details.
specsync hooks installGenerates instruction files (CLAUDE.md, .cursor/rules, etc.) that tell AI agents to read specs before modifying code, update specs when changing APIs, and run validation after changes.
Every command supports --json (or --format json) for structured output. Pipe to an LLM for automated spec maintenance:
specsync check --json | your-agent-scriptThe canonical spec plus four required companion files gives each module structured context beyond the technical contract. Projects can also enable the optional design companion.
The source of truth for what the module does and what it exports. SpecSync validates this against code. Keep it accurate — if the spec says authenticate exists, it must exist in the source files.
Written by Product or Design. User stories, acceptance criteria, constraints, out-of-scope items. Helps developers and agents understand why the module exists, not just what it exports.
Checkboxes for outstanding work. Review sign-offs (Product, QA, Design, Dev). Helps teams track what's done and what's left. Use specsync archive-tasks to clean up completed items.
Design decisions, constraints, key files to read first, current status notes. The "tribal knowledge" file — things that aren't obvious from the code alone. Especially valuable for AI agents that need to understand why things are the way they are.
Test strategy, requirement coverage, QA checks, fixtures, and edge cases. It records how the contract will be proved rather than only describing the intended implementation.
Layout, component hierarchy, interaction states, accessibility expectations, and design tokens for changes where design artifacts are enabled.
specsync add-spec payments # scaffold spec + companions
# Edit specs/payments/payments.spec.md — complete Purpose, Public API, etc.
specsync check # validate
specsync coverage # confirm it shows upspecsync diff --base main # what changed since main
specsync check # any drift?
specsync check --fix # auto-stub new exports
# Review generated rows and finalize descriptionsspecsync init # create config
specsync generate # deterministic local scaffolds
specsync agents install # agent refines them in its own trust boundary
specsync check # validate generated specs
specsync score # check quality
# Iterate: fix errors, improve low-scoring specs
specsync hooks install # set up agent instructions + hooksPoint them to:
specsync coverage— what's specced and what isn't- The
specs/directory — read the specs for their area specsync hooks install— set up their local hooks- This guide — understand the workflow