Skip to content

Managed Workflow

Samy K. Abushanab edited this page Nov 6, 2026 · 1 revision

Published from docs/scenarios/managed-workflow.md at 835522e. Edit the source in the repository, not this page.

Goal: take one GitHub issue from scope to a verified pull request with one command, and resume it in a new session if you are interrupted.

The managed Workflow adds a dispatcher. It decides which stage runs next, takes a claim on it, and checks the receipt before it moves on.

Prerequisites

  • A Spec Kit project with the Sanduq catalog registered. See set up Spec Kit.
  • Python 3.11 or later (Workflow runs on 3.10; Memory and Progress need 3.11), Git, and gh signed in with Project scopes. See prerequisites.
  • A GitHub Project (v2) board linked to the repository, unless you choose board mode none. See board.

Board

init --board full|minimal|none picks how much Workflow writes to the board (full when omitted): full moves the card at every phase and creates task sub-issues; minimal writes only Ready, In progress, In review and Done and creates no task sub-issues; none needs no board at all. doctor prints the mode as board_sync. Changing the mode later never invalidates a feature in flight. In full and minimal mode every managed claim checks the board first. Without a configured board, doctor and claim stop with one error, PROJECT_NOT_CONFIGURED, naming /speckit-project-init; a partly mapped board gets PROJECT_SCOPE_STATUS_MISSING and PROJECT_PHASE_UNMAPPED codes that name the column each expects. The board's Status field needs these seven options, spelled exactly like this:

Backlog, Feature Specification, Need Clarifications, Ready, In progress, In review, Done

A new GitHub board has In Progress with a capital P. Rename it, or let /speckit-project-init create the missing columns (--auto-create-columns in the script). Changing columns gives every option a new id; Project init saves and restores each item's Status while it does this.

First-run checklist

Follow these in order. Each step links to its detail.

  1. Install Spec Kit, Python 3.11 or later, Git and gh (prerequisites).
  2. Sign in to GitHub and add the Project scopes: gh auth login, then gh auth refresh -h github.com -s project,read:project.
  3. Create the repository and clone it: gh repo create <owner>/<name> --private --clone, then cd <name>. In it, run specify init --here --integration codex (or --integration claude). The clone is not empty, so it asks Current directory is not empty (2 items) ... [y/N] (the count varies); answer y. Then register the Sanduq catalog at priority 1 (set up Spec Kit).
  4. Create a GitHub Project (v2) and link it to the repository: gh project create --owner <owner> --title "<name>" --format json --jq .number prints the board number (without --format json a non-terminal shell prints nothing); then gh project link <number> --owner <owner> --repo <owner>/<name>. Do not add the Status options by hand: gh cannot edit them, and step 7 creates the seven statuses.
  5. Run specify extension add workflow.
  6. Run /speckit-workflow-init with your choices (see install). The host command runs Workflow's installer for you. The script workflow.py init does not install anything: until install.py --apply has run, it prints ok: false with DEPENDENCY_UNAVAILABLE, SOURCE_MISMATCH, COMMAND_UNAVAILABLE and PRESET_REQUIRED errors. They are expected at that point; install.py --apply clears them.
  7. Map the board with required sync: python .specify/extensions/project/scripts/project_init.py --number <number> --hooks-mode required --auto-create-columns. --auto-create-columns creates the seven statuses that are missing, and the script maps them to the lifecycle phases. Without --number the script exits 4 and lists the owner's boards.
  8. Run python .specify/extensions/workflow/scripts/workflow.py doctor --project until it reports ok: true.
  9. On Codex, approve the guard hook once in /hooks. Start a new agent session so the host loads the new commands.
  10. Create an issue: gh issue create --title "<what to build>" --body "<details>" prints its URL; the last number is the issue number. Run /speckit-workflow-scope <number> on it. The first claim has succeeded when Scope starts its analysis of the issue instead of stopping on doctor errors; python .specify/extensions/workflow/scripts/workflow.py status --feature specs/<slug> shows the claim.

Install

specify extension add workflow

Then initialize. The host command records your choices and runs Workflow's installer, which adds the extensions it needs.

Claude Code
/speckit-workflow-init Enable QA and User Manual for the booking application. Use our existing GitHub Project and an advisory managed-only evidence gate.
/speckit-workflow-doctor Verify project readiness and installed host commands.
Codex
$speckit-workflow-init Enable QA and User Manual for the booking application. Use our existing GitHub Project and an advisory managed-only evidence gate.
$speckit-workflow-doctor Verify project readiness and installed host commands.

The script equivalent is:

python .specify/extensions/workflow/scripts/workflow.py init --qa on --manual on --gate-mode advisory --gate-scope managed-only
python .specify/extensions/workflow/scripts/install.py
python .specify/extensions/workflow/scripts/install.py --apply
python .specify/extensions/workflow/scripts/workflow.py doctor --project

The script init only records the choices; its doctor errors (DEPENDENCY_UNAVAILABLE, SOURCE_MISMATCH, COMMAND_UNAVAILABLE, PRESET_REQUIRED) are expected until install.py --apply has run. The first install.py call previews. The second backs up, applies, and rolls back on failure. If your board is not configured yet, run /speckit-project-init. You are ready when doctor --project passes.

With User Manual selected, initialise the manual once on the target branch before the first feature: run /speckit-user-manual-init, approve its module map and commit User-Manual/ there. The script init names this step in next, and start warns MANUAL_NOT_INITIALIZED while User-Manual/manual.yml is missing. Without it, each feature stops at Manual Update or Execute for its own module-map decision and creates its own manual, and those PRs conflict.

The installed evidence gate, .github/workflows/sanduq-workflow-gates.yml, runs on GitHub-hosted runners by default: the CI selection in .specify/workflow.yml starts as policy: hosted-allowed with linux: [ubuntu-latest], so the rendered job has runs-on: ubuntu-latest. To run it on your own runners, record the selection before install.py --apply (or reinstall after changing it):

python .specify/extensions/workflow/scripts/workflow.py ci --policy self-hosted-required --linux self-hosted,<label> --system-packages preinstalled --python preinstalled

Under self-hosted-required the command drops each GitHub-hosted platform you did not name (the default windows: [windows-latest]) and lists it under dropped_hosted_platforms; add --windows self-hosted,<label> to keep a Windows job on your own runner.

Never edit the rendered workflow file by hand. The selection and self-hosted-required's recorded exceptions are in where your CI actually runs.

First prompt

Claude Code
/speckit-workflow-scope 412 Assess refund approval using our project policy and continue through implementation. Stop before PR creation.
Codex
$speckit-workflow-scope 412 Assess refund approval using our project policy and continue through implementation. Stop before PR creation.

What you will see

User commands and dispatcher-owned delivery stages

You start workflow.scope 412. Scope posts any open questions on the issue. You answer them on GitHub, then run workflow.clarify. The dispatcher runs specification, planning, task generation, analysis, implementation, verification, review and documentation. When evidence is current, the feature is ready. workflow.finalize opens or updates one pull request.

At implementation start, a live progress report opens at specs/412-refund-approval/workflow/progress/index.html. workflow.continue resumes an interrupted run from its checkpoint. It never skips a blocking check.

The sequence diagram shows the claim, the host's work and the receipt check. The worked lifecycle walks through every stage.

Dispatcher and host command handoffs

Optional delivery paths

Independent QA and manual selections

QA and manual selection are independent. Selected QA adds readiness analysis and a walkthrough after checks. A selected manual adds gap analysis and affected-page updates. Selecting neither keeps the core stages. Editable decision flow.

Choice Path
Core executor Core task generation and implementation
SuperSpec installed SuperSpec generates tasks and executes; no second core executor runs
Superpowers Bridge installed Continuation goes to the current owner; no extra executor runs
Questions unresolved Pause for answers on GitHub, then run Clarify
Required check stale or failed Finalize is blocked until the evidence is repaired
PR Generate --no-pr Documents only; no remote PR work

State and recovery

Feature checkpoint states and blocked evidence

A ready feature moves through implementation and verified documentation to a pull request. Open questions or stale evidence block it until you fix them. Editable state diagram · status and recovery commands.

Next step

Who enforces dependencies

Workflow's installer adds Scope, Project, PR and Illustrate, plus Assure and User Manual when you select them. It pins each version in dependencies.json and keeps a newer compatible version if you already have one. Spec Kit itself does not enforce requires.extensions.

Limits

  • Merge and deployment need your explicit authorization. Finalize stops at the pull request.
  • Workflow disables the extension hooks it owns and runs those commands as stages instead. Do not re-enable them by hand. Run /speckit-workflow-reconcile to repair the wiring.
  • Installing a package does not enable its process. Init does.
  • Context protection relies on the host's measurements. When none are available, the run continues and records that the measurement was unavailable.
  • Receipts are self-asserted: each stage writes its own receipt into checkpoint.json, a local JSON file anyone with the checkout can edit, and the delegation ledger's tamper markers only catch accidental edits. The CI gate checks that receipts are present, passing and current; with the default advisory mode it warns and does not block the PR. Set ci.gate.mode: required once the first feature has passed, and treat the PR review as the control. See SECURITY.md.
  • Since Workflow 2.1.0 every save appends the hash of each receipt it changed to specs/<feature>/workflow/receipt-log.jsonl, committed with the checkpoint. The gate refuses a receipt that is not the one the dispatcher last logged (RECEIPT_EDITED_OUTSIDE_DISPATCHER) and a PR that changes or drops log entries already merged on the base branch. A save that finds a hand-edited receipt logs it as an outside-edit instead of adopting it. Someone who also writes a matching log line by hand still gets through; the gate result lists every entry the PR added (receipt_log.added) for the reviewer.

Clone this wiki locally