Skip to content

Latest commit

 

History

History
513 lines (346 loc) · 23.2 KB

File metadata and controls

513 lines (346 loc) · 23.2 KB
title Workflow Guide
section Reference
order 2

End-to-end walkthrough of the verified SpecSync 6.0 change workflow.


The 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.

1. Create and Interview

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 --json

Acceptance 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.

2. Approve and Implement

Complete selected artifacts and semantic deltas, then obtain explicit human approval:

specsync change approve CHG-0001-add-passkeys

Requirements 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.

3. Check, Review, and Finalize

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 merge

change 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.

4. Reopen After Accepted Review Fixes

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.

5. Correct Accepted Classification Metadata

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.


Project Setup

Initialize a project

specsync init

This 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.

Install hooks and agent instructions

specsync hooks install

This installs:

  • Agent instructionsCLAUDE.md, .cursor/rules, .github/copilot-instructions.md, AGENTS.md — so AI coding tools know to respect specs
  • Pre-commit hook — runs specsync check before every commit, blocking commits with spec errors

Check what's installed with specsync hooks status.


Creating Canonical Specs

Option A: Scaffold a single module

specsync add-spec auth

Creates 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 ## Requirements or ## Acceptance Criteria sections will produce a warning.

Option B: Scaffold all unspecced modules

specsync generate                       # deterministic guided starter specs
specsync agents install                 # install native agent workflow

Generation 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.

Option C: Write specs by hand

Create specs/<module>/<module>.spec.md with the required frontmatter (module, version, status, files) and sections. See Spec Format for the full reference.


3. Validating Specs

Basic validation

specsync check

Three stages run in order:

  1. Structural — required frontmatter fields, file existence, required sections
  2. API surface — spec symbols vs. actual code exports (bidirectional)
  3. Dependenciesdepends_on paths, db_tables against schema

Errors mean the spec references something that doesn't exist in code. Warnings mean code exports something the spec doesn't document.

Auto-fix undocumented exports

specsync check --fix

Adds 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.

Strict mode (for CI)

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.


4. Iterating Until Clean

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 clean

Common 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 check

5. Measuring Quality

Coverage

specsync coverage

Shows 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.

Quality score

specsync score

Scores 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.


6. Ongoing Maintenance

Watch mode

specsync watch

Re-validates on every file change (500ms debounce). Useful during active development — you'll see spec drift the moment it happens.

Diffing against a ref

specsync diff --base main
specsync diff --base HEAD~5

Shows API changes since a git ref — what was added, removed, or changed. Good for reviewing what spec updates a PR needs.

Keeping specs in sync with code changes

When you rename, add, or remove exports:

  1. Run specsync check to see what drifted
  2. Update the spec's Public API table
  3. Bump the version in frontmatter
  4. Add a Change Log entry
  5. Run specsync check to confirm

When you add new source files:

  1. Add the file path to the relevant spec's files list
  2. Add any new exports to the Public API table
  3. Run specsync check to confirm

When you create a new module:

  1. specsync add-spec <name> or specsync generate to scaffold
  2. Complete the spec content
  3. Run specsync check to validate

7. Compaction and Archival

As specs accumulate changelog entries and tasks get completed, companion files grow. Two commands handle this:

Compact changelogs

specsync compact --keep 10              # keep last 10 entries per spec
specsync compact --keep 5 --dry-run     # preview what would be removed

Trims older changelog entries to prevent unbounded growth. Use --dry-run first to preview.

Archive completed tasks

specsync archive-tasks                  # move completed tasks to archive
specsync archive-tasks --dry-run        # preview what would be archived

Moves completed checkboxes from tasks.md files to an archive section, keeping active work visible.


8. Cross-Project References

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 --remote

See Cross-Project References for the full setup.


9. CI Integration

GitHub Actions

- name: Validate specs
  run: specsync check --strict --require-coverage 80

See GitHub Action for the official action with caching and PR comments.

Pre-commit hook

specsync hooks install sets up a pre-commit hook that runs specsync check before every commit. If specs are invalid, the commit is blocked.

Recommended CI pipeline

specsync check --strict                  # no warnings allowed
specsync check --require-coverage 80     # enforce coverage threshold
specsync score --json                    # track quality over time

10. Working with AI Agents

SpecSync is designed for AI-assisted development. Three integration modes:

MCP server (recommended)

specsync mcp                 # read-only tools
specsync mcp --allow-write   # opt in to root-confined init/generate tools

The 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.

Agent instruction files

specsync hooks install

Generates 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.

JSON output for scripting

Every command supports --json (or --format json) for structured output. Pipe to an LLM for automated spec maintenance:

specsync check --json | your-agent-script

Companion Files in Practice

The canonical spec plus four required companion files gives each module structured context beyond the technical contract. Projects can also enable the optional design companion.

<module>.spec.md — The contract

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.

requirements.md — The intent

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.

tasks.md — The work

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.

context.md — The background

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.

testing.md — The evidence plan

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.

design.md — The optional experience contract

Layout, component hierarchy, interaction states, accessibility expectations, and design tokens for changes where design artifacts are enabled.


Common Workflows

Adding a new module to an existing project

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 up

Reviewing spec drift in a PR

specsync diff --base main               # what changed since main
specsync check                          # any drift?
specsync check --fix                    # auto-stub new exports
# Review generated rows and finalize descriptions

Bootstrapping specs for an existing project

specsync 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 + hooks

Onboarding a new team member

Point them to:

  1. specsync coverage — what's specced and what isn't
  2. The specs/ directory — read the specs for their area
  3. specsync hooks install — set up their local hooks
  4. This guide — understand the workflow