Backstop exposes a repository-oriented CLI, YAML artifacts, JSON-capable output, and process exit codes. A runtime integration must invoke the pinned binary from the intended working directory and propagate blocking exits. That proves operability; artifact order and role separation require additional harness behavior.
Reference
What exact interface or behavior do I need?
Deterministic product truth, presented without changing its owner.
Compatibility
A harness can invoke Backstop, but operability alone does not preserve artifact ordering, review separation, or enforcement of a blocking verdict.
Invocation proves that the binary runs. A trustworthy integration separately proves that the harness preserves lifecycle order and stops on failure.
Runtime-neutral does not mean runtime-guaranteed. Backstop cannot make a harness respect a result it chooses to discard.
Artifact schema catalog
| Artifact type | Schema path version | Document version | Schema ID | Title | Source |
|---|---|---|---|---|---|
| base | base | 1.1.0 | backstop-artifact-base-v1 | Backstop Base Artifact Schema v1 | artifacts/base/schema.json |
| adr | v1 | 1.0.0 | backstop-adr-v1 | Backstop ADR Schema v1 | artifacts/adr/v1/schema.json |
| adr | v2 | 2.0.0 | backstop-adr-v2 | Backstop ADR Schema v2 | artifacts/adr/v2/schema.json |
| backstop-yml | v1 | not-declared | backstop-yml-v1 | Backstop Project Manifest Schema v1 | artifacts/backstop-yml/v1/schema.json |
| bundle | v1 | 1.0.0 | backstop-bundle-v1 | Backstop Context Bundle Schema v1 | artifacts/bundle/v1/schema.json |
| bundle | v2 | 2.0.0 | backstop-bundle-v2 | Backstop Context Bundle Schema v2 | artifacts/bundle/v2/schema.json |
| capability | v1 | 1.0.0 | backstop-capability-v1 | Backstop Capability Schema v1 | artifacts/capability/v1/schema.json |
| directive | v1 | 1.0.0 | backstop-directive-v1 | Backstop Directive Schema v1 | artifacts/directive/v1/schema.json |
| issue | v1 | 1.1.0 | backstop-issue-v1 | Backstop Issue Schema v1 | artifacts/issue/v1/schema.json |
| plan | v1 | 1.0.0 | backstop-plan-v1 | Backstop Plan Schema v1 | artifacts/plan/v1/schema.json |
| spec | v1 | 1.1.0 | backstop-spec-v1 | Backstop Implementation Spec Schema v1 | artifacts/spec/v1/schema.json |
Artifact schemas live under artifacts/<kind>/v1/schema.json. The CLI reserves IDs, scaffolds valid records, validates references and state, and excludes terminal historical artifacts where policy declares that behavior.
Configuration
The repository root contains backstop.yml. Its project, packs, and enforcement.policy fields declare versioned standards and policy levels. The lock under .backstop/ binds resolved pack bytes.
CLI conventions
Backstop commands return 0 for success, 1 for blocking violations or broken promises, and 2 for configuration failure. The global --json flag selects structured output where supported, while backstop commands provides machine-readable command discovery.
Troubleshooting
backstop doctor diagnoses configuration discovery and loading, Git repository state, installed packs, build identity, toolchain execution, engine-tool availability, and artifact layout. A failing check returns 1; an unknown check identifier is a configuration error.
Gate
backstop gate evaluates changed files by default. backstop gate --file <path> bounds verification explicitly, while backstop gate --all runs the repository-wide kill chain. Exit zero means every blocking step passed; a nonzero exit is a verdict to preserve, not suppress.
Pack commands
Use backstop pack install, backstop pack list, backstop pack update, and backstop pack relock to manage declared versions and resolved locks. Inspect findings before accepting an update.
Pack artifact
A pack declares identity, version, claims, engines, fixtures, tools, applicability, and findings. Commands are direct argv contracts; tool pins are trust declarations rather than installers.
Path-filter diagnostics
When an engine receives explicit changed-file arguments, do not assume a slash-bearing include or exclude pattern behaves as it does during directory traversal. Use pack check and pack test to surface path-scope advisories, preserve production-relative fixture paths, and prefer a slash-free single-segment pattern only when it retains the intended scope.
Artifact lifecycle and closure
Status is a declared field. Authors set it. It is not inferred from git or CI. Per-noun status vocabularies are defined in their owning artifact schemas (issue, spec, bundle, and plan). Directive, ADR, and Capability schemas carry separate status fields. This section is the machine: legal moves, what must be true, what starts being enforced, and what that move enables.
Live states
- Bundle
idea→exploring→defined→ready- Spec
draft→ready-for-implementation→implemented- Issue
open→ready→in-progress
blocked waits on named work- Plan
draft→ready→implementing→completed
Terminal states distinguish delivered or implemented work from replacement, cancellation, deprecation, and obsolescence. Successor fields are required where the schema names one.
Feature work uses bundle → spec → plan. Bounded work uses issue → plan. Both tracks meet at a plan. Each spec has exactly one plan. An issue does not get a spec. Product code is not written until a plan is ready.
Bundles progress through idea, exploring, defined, and ready.
Coupled states
- Feature
- bundle
ready→ specready-for-implementation→ planready→ plancompleted→ specimplemented
bundledeliveredis declared separately - Bounded
- issue
ready→ planready→ plancompleted→ issueclosedviadelivered_by
delivered_by requires a completed PLAN-ISSUE-NNN. Spec implemented is declared; it is not inferred from the plan. A delivered bundle cited by a non-implemented spec fails the gate.
Issue
Live: open → ready → in-progress. blocked waits on named work.
| State | Before you can enter it | Validator / gate | Enables |
|---|---|---|---|
open | Scaffolded issue, Problem section | Schema only. Requirements and claims are optional. | Issue exists but cannot produce a plan |
ready | Requirements, claims, verification, implementation, and contracts | Full spec-parity traceability. | Plan creation |
in-progress | Same rigor as ready | Same. | Plan implementation or issue close-out |
blocked | Same rigor as ready, plus blocked_by | Same, plus the blocker must be named. | Work remains open with a named blocker |
closed | ## Resolution, and exactly one close pointer unless the issue carries its own requirements and claims | Close traceability. | No further issue work |
Closing an issue requires a ## Resolution section and at most one traceability field: delivered_by names a completed plan, while resolved-by names a direct typed artifact reference, commit SHA, or pull-request URL when no plan lineage applies.
delivered_by and resolved-by on the same close is illegal. replaced requires replaced-by. obsoleted requires obsoleted-by. canceled is abandoned work.
Spec
Live: draft → ready-for-implementation → implemented.
| State | Before you can enter it | Validator / gate | Enables |
|---|---|---|---|
draft | Spec exists from a bundle; required live-work shape | Spec schema/completeness | Authoring |
ready-for-implementation | Requirements, claims, verification, implementation, contracts complete; review/validation passed | Full live-work completeness/traceability | Plan creation |
implemented | Work delivered through its plan | Delivery/closure requirements | No further implementation work |
Terminals: replaced, canceled, deprecated, obsoleted. Retired specs are exempt from live-work completeness.
Bundle
Live: idea → exploring → defined → ready. Success terminal: delivered.
The user drives promotion. Do not self-promote.
| State | Before you can enter it | Validator / gate | Enables |
|---|---|---|---|
idea | Named bundle | Identity and maturity enum. | Bundle exists but cannot produce a spec |
exploring | Real open questions, unresolved | Same. | Exploration |
defined | problem.summary, problem.user_story, solution.approach, requirements[], and sections Current Thinking, Draft Requirements, Draft Design Decisions, Spec Seeds, Version History | Maturity gates. Placeholders are illegal. | Promotion to ready |
ready | Everything defined requires, plus problem.success_criteria and solution.assumptions | Same, tighter. | Spec generation |
delivered | The work shipped. requirements[] still required. | Success terminal. | No further bundle work |
Terminals without delivery: replaced, canceled, deprecated. replaced requires replaced-by.
Plan
Live: draft → ready → implementing → completed.
draft, ready, and implementing are the same shape to the validator: phases, tasks, tests before implementation, every source claim mapped. Terminal plans (replaced, canceled, obsoleted) are exempt from phase and task completeness.
| State | Before you can enter it | Validator / gate | Enables |
|---|---|---|---|
draft | Source is an issue or a spec. Phases and tasks are present. | Plan schema and completeness. | Authoring |
ready | Same shape. Reviewer has passed. | Same. | Implementation |
implementing | An implementer is executing it. | Same. | Plan execution |
completed | The work was delivered. Mandated tests exist. | Validator may accept a completed plan whose mandated tests are missing. The gate does not. | Source artifact close-out |
Issue-sourced (PLAN-ISSUE-NNN): permits delivered_by on that issue. Spec-sourced (PLAN-SPEC-NNN): permits setting the spec to implemented. Bundle delivered is a separate declared status. Spec and bundle status are not inferred from the plan.
replaced requires replaced-by. obsoleted requires obsoleted-by.
Directive, ADR, and Capability each carry their own status vocabularies in their artifact schemas. They are not paths into implementation.
Source traceability
A gate result is useful evidence only when its command, prerequisites, and captured artifact are named.
A literal Liquid-shaped {{ ... }} expression is currently interpreted as an undeclared recipe parameter and rejected before any write; ISSUE-182 tracks the missing literal-escape capability.
Linux CI exposed a contracts-pack fixture false negative, and commit f8b3846fe5d4c2bc6465efc6eb5e4594e1b591da repaired it with checked-in before-and-after evidence.
Durable references use repository paths, immutable commits, or published versions. Execution evidence includes the exact command and prerequisites; observation evidence identifies its checked-in artifact and provenance.
CLI command catalog
| Command | Path | Description | Flags |
|---|---|---|---|
| artifact | artifact | Artifact lifecycle commands | --json |
| new | artifact new | Scaffold a new artifact | --json --slug --source |
| validate | artifact validate | Validate artifacts against schemas | --adr --all --bundle --directive --issue --json --plan --spec |
| baseline | baseline | Baseline cache and artifact commands | --json |
| generate | baseline generate | Generate baseline JSON from full-scope gate | --json |
| pull | baseline pull | Fetch latest successful main baseline artifact | --json |
| commands | commands | List all available commands for agent discovery | --help --json --json |
| doctor | doctor | Diagnose a backstop setup, including the conditions that make other commands refuse | --check --json |
| gate | gate | Run full verification gate | --all --base --file --json --json-out --pack-sandbox |
| init | init | Take a project from nothing to a first gated run | --ci --json --no-baseline --no-git --no-gitignore --no-observe --no-packs --no-sdlc --no-toolchain --only --pack --scaffold |
| pack | pack | Enforcement content commands | --json |
| add | pack add | Add an enforcement pack to the project | --json --version |
| check | pack check | Validate pack manifest and constraints | --format --json |
| install | pack install | Restore packs from backstop.lock | --cache --json |
| list | pack list | List installed enforcement packs | --json |
| new | pack new | Scaffold a new enforcement pack | --json --language --slug --type |
| relock | pack relock | Refresh a local pack's lock entry after editing it in place | --json |
| remove | pack remove | Remove an enforcement pack from the project | --json |
| test | pack test | Run full pack validation including fixture execution | --format --json |
| update | pack update | Update a pack to the latest compatible minor/patch version | --acknowledge --json |
| upgrade | pack upgrade | Upgrade a pack to a new major version | --json |
| recipe | recipe | Recipe adoption commands | --json |
| apply | recipe apply | Apply a pinned recipe from an installed pack | --json --param |
| version | version | Print version and schema cohort information | --json |
| waiver | waiver | Inspect backstop waivers (read-only) | --json |
| list | waiver list | List active, expiring-soon, and unused/dangling waivers | --json |
The command families cover initialization, diagnosis, gates, packs, artifacts, recipes, baselines, waivers, version reporting, and command discovery. Use --help on the pinned release for exact flags and --json where a command exposes structured output.