docs(decisions): the commands/ survey — measured, classified, decided (#525) - #589
Merged
Conversation
…#525) ADR 0003: the #525 survey. commands/ is 13,552 lines (0.65x the engine, was 1.34x at filing) — 40.5% shared report assembly, 36.7% gate orchestration whose policy is engine-side, 13.9% glue, 5.3% CLI-only rendering, 31% of the layer prose. Ten decision-bearing paths named (_run_backtest's successors first); in every money case the deciding comparison lives in a compute module. Zero near-duplicate render paths across CLI/web/MCP. Decision: the shape stays; the one mechanical gap (the thinness AST pin does not scan keel/mcp) filed as #588.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #525.
A survey, not a refactor — the deliverable is numbers and a recorded decision. Lives as ADR 0003 (
docs/decisions/0003-commands-layer-survey.md), mirroring 0001's Context/Options/Decision/Consequences shape (0002 is in flight on its own branch; this takes the next number).Headline numbers
The issue's premise dissolved before the survey ran: #541 (PR #554) deleted the TUI and console-only layers (24,709 → 13,552 lines, +297/−23,448 with tests), and the engine grew in the same window. Restating the issue's table on
main@ 16725c1:Role split (the issue's checklist item 1)
A line-level AST attribution: 1,016 render / 3,734 assembly+service / 1,292 click bodies / 3,320 helpers — and 4,190 lines (31%) of headers, docstrings and imports. The layer is substantially prose: the explanatory surface the issue's "case that this is fine" describes.
Decision paths named (item 2)
_run_backtest(#335) no longer exists — the #390 C4 service extraction split it intoresolve_rule_backtest+backtest_resolved+run_rule_backtest, core instrategy.backtest. Ten further decision-bearing paths are named in the ADR with file:line and, crucially, where each one's policy lives: in every money case the deciding comparison (can_promote,transition,screen_asset,build_verdict,sizing.size) is in a compute module; commands/ holds sequencing and refusal wording. Two deliberate display-side mirrors (status._rail11_status, doctor's ATR banding) carry inline arguments for why they are not policy.Duplication quantified (item 3)
Traced report by report across CLI/web/MCP: zero near-duplicate render paths remain. Each load-bearing report is one shared core plus thin format projections (12–77 lines) — status (
gather_status→render_human/status_payload, the web even imports_human_age), doctor (gather_findings→ CLI lines / MCP JSON), purification (enginebuild_report→ text / JSON), insights (build_*→ CLI renders / web payloads). The historic duplication was real — the TUI — and #554 deleted 11,103 lines of it.Test parity (item 3b)
tests/commands/: 11,031 lines, 527 test functions — more than any engine area's suite — plustest_service_parity.py(CLI-vs-service byte-equality pins) andtest_console_thinness.py(AST scan: no compute imports/calls, Decimal display-only, no broker construction outside seams).The decision (item 4)
C — nothing moves. Move-to-engine is refused on the evidence (the policy is already engine-side; what would move is sequencing and explanation, and the parity tests pin the sequence against the CLI a human runs). Unification is moot (nothing left to unify). The shape is recorded as standing rules + four re-opening triggers. The one actionable gap found — the thinness pin scans
keel/web/*.pybut notkeel/mcp/*.py(8 thin handlers, vacuously green today) — is filed as #588, a pin extension, not a refactor.Deviations
docs/presentations/se.md(the raiser, §3/§9.2) is not on main — it lives on the unmergedworktree-docs-se-presentationbranch, so no pointer was added there (it would conflict on that branch's merge). The ADR cites it in its header the same way ADR 0002 cites §9.6.docs-526-sqlite-adrbranch).uv run pytest -q: 4355 passed, 3 skipped.