Date: 2026-07-09 Status: accepted Deciders: Thibault Souris (maintainer) Method: decision-loop — first build piece of the retro-documentation surface scoped in ADR-0013. Contract decided against the never-a-runtime and zero-LLM-gate invariants. Decision only; no code in this ADR.
Amendment (2026-07-10, before implementing
--mine). Reconciled--minewith the zero-LLM-tool invariant and ADR-0007: runward's--mineis deterministic (git archaeology) and makes no model call — the original "may use an agent/LLM" wording is corrected below. The LLM refinement of a candidate into an argued hypothesis lives in the harness (the operating agent), exactly like the advisory verify workflow; a model behind a port remains possible but runward bundles none.Amendment (2026-07-20, resume-existing audit). The Decision's inventory list described three capabilities ahead of the code; reconciled here rather than left as drift. Pinned versions and git churn are now implemented (ADR-0035, ADR-0036) — those claims are now true. "reported coverage" is withdrawn:
characterizedeliberately reads test presence and a file count, never a coverage figure — reading a coverage report would mean trusting a generated artifact the command never produced, against the "parse at rest" line. In the Surface,--yesand--dry-runare global flags (runward --dry-run characterize), not command options; the command's own options are--pathand--mine. Separately, the "two runs agree" promise now rests on deterministic ordering (every filesystem scan is sorted — ADR-0034, which also adds monorepo/workspace coverage), and--minenow mines across languages and groups by family (ADR-0038). None of these loosen the read-only / zero-LLM / operator-owns-the-gate contract; they fulfil it.
Context
ADR-0013 adopts retro-documentation as the transmission phase pointed backward and names runward characterize as the one genuinely new primitive: the read-only entry point that turns an undocumented system into the start of a governed mission. Today the brownfield entry mode is a workflow the agent reads (brownfield.md) with no CLI verb; "characterize before touching" is a manual instruction, not a tool.
Before writing code, the command's contract must be locked, because characterize is the highest-temptation surface in runward: it is the one place an agent reads a real codebase, and the pull is to let it conclude — to emit "here is your architecture / here are your decisions / here is your compliance posture" as fact. That would put an LLM's judgment on the path to the gate and make runward an oracle. The contract exists to make that impossible by construction, not by good intentions.
Decision
runward characterize is a read-only command that produces the raw material of a brownfield mission: a factual inventory plus candidate decisions, all explicitly unvalidated. It reads artifacts at rest and writes only into runward/ — never into .git/, never the user's source, and it never executes the user's system.
Two layers, sharply separated:
- Deterministic inventory (default, zero-LLM). Parses artifacts at rest: repo tree, dependency manifests and lockfiles (pinned versions), entrypoints, CI/workflow config, container/deploy files, test presence and reported coverage, and the shape of
git log(age, churn, authors — counts, not interpretation). Emitsrunward/characterization.md: a factual inventory with aconfidence: highheader, no opinions, no why. Reproducible — two runs on the same commit agree. - Candidate ADR-mining (opt-in,
--mine). Only under an explicit flag, and deterministic — runward makes no model call. It reads git history and the inventory at rest to propose candidate structural decisions (the stack/language choice, containerization, the CI pipeline, notable dependency families) and writes onlyrunward/adr/DRAFT-*.mdfiles, each withstatus: hypothesis, the evidence pointers (file paths, first-seen dates) that suggest a decision, and an explicitwhy: UNKNOWN — needs operatorfield. Turning a candidate into an argued hypothesis, and supplying the why, is the harness/agent's job downstream (per ADR-0007), never runward's. It writes nothing else and touches no manifest.
The contract's hard lines:
- Read-only, never a runtime.
characterizeopens files; it does not install, build, run, or instrument the target. No network to the target, no execution of its code. - Zero-LLM, no model call. The whole command is deterministic: the inventory is pure parsing, and
--mineis git archaeology. runward calls no model and bundles none — the LLM refinement of candidates lives in the harness (ADR-0007's advisory posture), strictly upstream of any gate, and even there its only output is DRAFT hypotheses the operator must ratify. - Nothing it emits can pass the gate. DRAFT ADRs carry
status: hypothesis;check --strict(per ADR-0013's lifecycle) requiresstatus: accepted+ a human-written why + a trigger.characterizeproduces material for the operator to ratify, never a conformance verdict. - Facts are labelled facts; guesses are labelled guesses.
characterization.mdisconfidence: high(mechanical). DRAFT ADRs are hypotheses with provenance. No output is ever presented as original design intent or as compliance. - Idempotent and non-destructive. Re-running refreshes
characterization.mdand adds/updates DRAFTs; it never overwrites an operator-ratified ADR (status: accepted) or any mission state.
Surface: runward characterize [--path <dir>] [--mine] [--yes] [--dry-run]. Exit codes follow the house convention: 0 inventory produced, 2 no repo/target found. --mine never changes the exit code (advisory). Default (no --mine) is deterministic and offline.
Alternatives discarded
- Let
characterizerun or instrument the system to observe real behavior. Violates never-a-runtime and would require executing untrusted code. Characterization tests that do run belong to the operator in their own harness (brownfield workflow), not to a runward command. Rejected. - Emit ADRs directly (no DRAFT state), or auto-accept mined decisions. Launders a hypothesis into a validated fact and lets an LLM's guess satisfy the gate. Rejected — it breaks operator-owns-the-gate (ADR-0013).
- Put the mining in the default path (no opt-in flag). Makes every
characterizean LLM call and blurs the deterministic/advisory line. Rejected — the deterministic inventory must stand alone, offline and reproducible. - One combined artifact (inventory + decisions in one file). Confuses
confidence: highfacts withhypothesisguesses. Rejected — separatecharacterization.md(facts) fromadr/DRAFT-*.md(hypotheses).
Consequences
- Positive. The named-but-untooled entry mode becomes a real, safe primitive; the operator gets the raw material of a brownfield mission in one read-only pass; the deterministic inventory is useful on its own (offline, no keys), and the advisory layer accelerates ADR reconstruction without ever asserting truth.
- Negative, accepted. A useful
--minerun depends on an agent whose proposals are fallible — surfaced honestly ashypothesis/why: UNKNOWN, never smoothed over. The command does not finish the retro-doc; it starts it (the operator must ratify, and prove autonomy — ADR-0013's caveat). - On other boundaries. A new
src/commands/characterize.ts; arunward/characterization.mdconvention and aDRAFT-*.mdADR shape;init/doctorunaffected; the deterministic gate and its zero-LLM invariant untouched (this command sits entirely upstream of it).
Reevaluation trigger (mandatory, dated)
Reopen if --mine proposals are trusted without ratification in practice (operators promoting DRAFTs unread), or if the deterministic inventory is asked to make judgments beyond parsing. At that point, add friction to DRAFT promotion (an explicit per-ADR confirm) or narrow the inventory, rather than let characterize drift toward asserting conclusions.
Trigger set on: 2026-07-09 · Watched via: field use of characterize --mine and any DRAFT promoted without an operator-written why.
References
- ADR-0013 — the retro-documentation decision and the ADR
hypothesis → acceptedlifecycle this command feeds. - ADR-0001 — the deterministic gate
characterizesits upstream of. docs/retro-documentation.md— the capability brief, confidence model, and anti-overclaim guardrails.templates/workflows/brownfield.md,docs/when-to-use.md— the documented entry mode this command tools.