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).
- Organizing principle: capability engines, not a verb per loop-step. The design's spine is four reconcile-only capability engines — check (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).
- The Unix contract — every command is a well-behaved part.
--jsonoutput, meaningful exit codes (0 clean / 1 warnings / 2 error), stdout-for-data / stderr-for-messages, a--no-workspacefallback that degrades likegitoutside a repo, and asuspec-*PATH-plugin convention for extensions. This is what lets a command be adopted one at a time. Level: toolable. - Standalone primitives (Layer 1):
suspec worktree(one-worktree-per-task + per-worktree runtime-isolation config; interops withclaude --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).costandnotifyship assuspec-*PATH-plugins, not core (resolves RFC Q-004 — keep the core reconcile-only). Level: toolable. - 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. - 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.yamlinto the agent CLI's hooks); launch-envelope provenance onsuspec run; diff-vs-self-report reconciliation insuspec 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. - The IR is tool-internal — there is no Suspec
ir.jsonartifact (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--jsonfor interop. That is the whole of it: markdown stays the only Suspec artifact, adopters never create or see anir.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--jsonprojection); the parse structure is an implementation detail. - 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.
- 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 --worktreeas 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). - 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);suspecwith 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 + itsspec.ir.jsonreferences 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