Skip to main content
manual page/ ADRs

ADR-0077 — suspec-cli is a reconcile-only harness of composable parts

Sections
5
Format
Markdown
Order
113 / 156

Context

RFC-suspec-cli-vision (suspec-works/specs/suspec-cli-vision/rfc.md, accepted by the owner 2026-06-13) proposed a direction for suspec-cli, grounded in a six-lens deep-research survey (~120 sources, research.md). Three pressures forced the decision: suspec-cli's on-paper design (in-repo specs 001, 005–009) is SOL-era and predates the practical-first repositioning; the agentic-CLI market has converged on a substrate (headless invocation, structured JSON events, hooks, MCP, worktree-per-task) and left two gaps open that map onto Suspec's strengths; and the owner's brief requires the CLI to both supercharge Suspec and be useful standalone for any agentic work, honoring the "parts individually usable, maximally valuable together" thesis. The owner also resolved the ir.json question (Option A, below).

This design is derived fresh — from the field research and Suspec's own principles, not from prior takes. The pre-existing docs/reference/future-cli.md sketch and the SOL-era specs (001, 005–009) are suggestive priors to mine, not a contract to inherit: their command inventory, milestones, and SOL-parsing center are not assumed here. Where they still fit the fresh design they are kept; where they drag (a verb-per-loop-step organizing principle, SOL as the parsing center), they are dropped.

Decision

suspec-cli is a reconcile-only harness for agentic work: composable parts that prepare, launch, and reconcile agent runs — each useful standalone, all composed by the Suspec workspace into the loop. It never performs the coding loop. Each rule carries an honesty level (ADR-0063).

  1. Organizing principle: capability engines, not a verb per loop-step. The design's spine is four reconcile-only capability enginescheck (parse a spec, verify executable criteria, compute coverage/drift), launch (worktree + adapter + run record + provenance), reconcile (diff vs self-report → review draft, status, gated close), and prepare (scaffold/intake/packet drafting, the lightest — a command only when it does more than copy a template). The command names are a surface derived from these engines and the standalone-part test, re-derived per phase — never inherited from the prior future-cli verb list. These engines arrange as three layers: (a) a reconcile-only core library the CLI thinly wraps (importable by editors/CI/the MCP server without shelling out); (b) standalone primitives usable without adopting Suspec; (c) a Suspec-aware composition layer that supercharges the loop. Level: convention (architecture).
  2. The Unix contract — every command is a well-behaved part. --json output, meaningful exit codes (0 clean / 1 warnings / 2 error), stdout-for-data / stderr-for-messages, a --no-workspace fallback that degrades like git outside a repo, and a suspec-* PATH-plugin convention for extensions. This is what lets a command be adopted one at a time. Level: toolable.
  3. Standalone primitives (Layer 1): suspec worktree (one-worktree-per-task + per-worktree runtime-isolation config; interops with claude --worktree), suspec run --agent (a uniform headless wrapper normalizing each agent's flags + output), suspec spec check (a standalone spec linter), suspec status (a derived read-model). cost and notify ship as suspec-* PATH-plugins, not core (resolves RFC Q-004 — keep the core reconcile-only). Level: toolable.
  4. The canonical adapter event contract. Adopt the converged vocabulary (init / assistant / tool_call / result, + final message, cost, exit code) and map each agent CLI's native JSON/stream-JSON onto it; carry a contract version against vendor churn (resolves RFC Q-001). Suspec invents no new event vocabulary. Level: toolable.
  5. Supercharge (Layer 2): a Suspec MCP server (serves the task packet scope, the parsed requirements, and the checks contract — one surface for every MCP-capable agent); per-adapter hook generation (wires a task's write-set + checks.yaml into the agent CLI's hooks); launch-envelope provenance on suspec run; diff-vs-self-report reconciliation in suspec review; deterministic coverage/drift; gated close; per-task cost attribution. Sequencing: shell-out adapters first (M2), the MCP server at M3 (resolves RFC Q-005 — ship both, shell-out covers agents without MCP). Provenance emits the ADR-0076 Provenance line now; track Agent Trace as the interop JSONL format, adopt only once it settles (resolves RFC Q-003). Level: toolable; hook-based enforcement is performed by the agent CLI's hook runtime, recorded as such — never enforcement by suspec-cli.
  6. The IR is tool-internal — there is no Suspec ir.json artifact (resolves RFC Q-002, owner's Option A). suspec-cli must parse a spec's markdown into an internal structure to check it; it may project that structure as optional --json for interop. That is the whole of it: markdown stays the only Suspec artifact, adopters never create or see an ir.json/plan.json, and canon documents no frozen machine-artifact schema. The deterministic-coverage/drift wedge runs on the parsed markdown, not on a required file. Level: toolable (the --json projection); the parse structure is an implementation detail.
  7. The two defensible wedges. Own what the field leaves open and what depends on Suspec's declared scope: deterministic coverage / executable-criteria checking (the field ships LLM-interpreted prose "without guarantees"; Suspec checks mechanically) and reconciling the agent's self-report against the actual diff (no mainstream tool does it). Level: positioning.
  8. The boundary — what suspec-cli must never own. The model/reasoning loop, the chat UI, file-editing mechanics, provider auth, the MCP runtime, the sandbox/container runtime (adopt @anthropic-ai/sandbox-runtime / container-use / claude --worktree as substrates the adapter selects), and the review verdict (agent fill is a draft; empty Evidence reads Unverified; the human owns Pass/Fail/Unverified/Blocked). Absorbing any of these would make suspec-cli a coding agent. Level: convention (the hard line).
  9. Two co-equal surfaces — scriptable and interactive. Every flow ships both a direct command (the Unix contract of Decision 2 — --json, exit codes, scriptable) and a beautiful interactive TUI flow (prompts, live progress, coloured per-finding feedback); suspec with no command opens a dashboard that reaches every flow. The TUI is a frontend over the same core library (Decision 1a) — it invokes only the reconcile-only engines and is emphatically not the chat UI / model loop of the Decision 8 boundary. Interactivity is gated on a TTY and the absence of --json, so a prompt can never break the Unix contract for pipes, scripts, or CI. A standing principle: every flow in every milestone ships both forms. Level: convention (architecture); the flows are toolable.

Alternatives considered

The RFC weighs six in full; the load-bearing rejections: the SOL-era "canonical 14 / fixed pipeline / merge-gate-over-specs" design (predates practical-first; over-indexes on SOL and a spec-only gate — this ADR re-baselines it); building an orchestration/multi-agent/sandbox runtime (crosses the boundary — adopt substrates, don't rebuild); auto-decompose / parse-prd (the field's loudest failure — decomposition stays judgment work); emitting review verdicts (violates ADR-0063 — the CLI routes, never adjudicates); and a monolithic workflow command (forecloses piecemeal adoption — the Unix-part design is the answer).

Consequences

Accepted. future-cli.md is reframed from "the contract" to a suggestive illustrative surface of this design (it is a prior sketch, not the design of record — this ADR is): its header now points here, the layered/standalone framing, the Unix contract, the canonical adapter event contract, the MCP server, hook generation, and the reconciliation/coverage/gated-close capabilities are written in (all toolable, milestone-tagged), and the reserved *.ir.json/*.plan.json schema is trimmed per Decision 6 — the run record stays (the reconciliation substrate), the frozen IR/plan schema goes, replaced by "suspec-cli parses the markdown; optional --json." Refines ADR-0054 (the structured form is now explicitly tool-internal, not a documented Suspec artifact) and ADR-0072/0076 (the run record + Provenance line are the reconciliation substrate the run/review commands fill). Re-baselines the SOL-era suspec-cli specs (001, 005–009): worktree/check/promote survive as Layer-1/2 commands; 001's SOL-compiler framing and the SOL-ir.json substrate are superseded; new specs are cut per phase (M1 standalone parts → M2 launch/reconcile → M3 supercharge). The RFC + research are the recorded inputs in suspec-works. suspec-cli's existing internal Sol IR (buildIr) is exactly the tool-internal structure Decision 6 endorses — no artifact, kept.

Propagation

docs/reference/future-cli.md (reframe to a suggestive surface of this design + write in the new capabilities + trim the IR/plan schema), docs/reference/structured-requirements.md

  • docs/reference/advanced-lifecycle.md (reword the "reserved machine format" phrasing to tool-internal/--json), ledger row, RFC → accepted + its spec.ir.json references softened, suspec-works board + the SOL-era spec dispositions. No suspec-cli code change in this decision (the phase specs drive that).

Starter kit: Set up a workspace