docs(governance): D-263 — one CLI named reach, and Q-124 answered

Q-124 asked whether the 123-file Python tooling should be retooled into a
Rust CLI. The answer is no, and it is a costing rather than a preference.
All three frictions it names — per-script permission prompts, the venv/PATH
split between interactive and non-interactive shells, and interpreter
startup paid four times per push — are packaging problems, and one bare
command on PATH with lazy subcommand loading fixes all three. Rust would
additionally owe a numerical-equivalence proof on the planet-gen path,
whose heightmaps are committed build artefacts with goldens standing on
them: a large one-time cost to avoid a small recurring one, paid in the
currency the project can least afford to spend.

D-263 fixes the shape. tooling/ becomes an installable package behind the
`reach` command: a routing-only main.py, every domain under domains/<name>/
split router/service/schemas/helpers, a core/ bounded on day one to what
has no domain, logging and error handling attached as decorators rather
than call-site discipline, and pydantic confined to domain schemas —
measured at 87 ms against a whole gate check of 20-46 ms, which is why it
must never reach the push path. Failures carry the command that fixes them
and keep their exit code; a tool that explains itself and exits 0 silently
disables its own gate.

R-014 records the Rust option as costed down, not argued down, with the
condition under which it is worth reopening. T-1247 files the work as
eight dependency-ordered epics; only the skeleton is unblocked.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-20 02:32:21 +02:00
co-authored by Claude Opus 5
parent 284ce847c3
commit bbd64307ab
8 changed files with 150 additions and 3 deletions
+2
View File
@@ -328,6 +328,7 @@ line in place — keep the Q-record for the audit trail rather than deleting it.
- [D-260: Generator scope — Sol is authored, not generated](decisions/architecture.md#d-260-generator-scope--sol-is-authored-not-generated) — _architecture_
- [D-261: River rendering — a stroke, not a scaled feature](decisions/architecture.md#d-261-river-rendering--a-stroke-not-a-scaled-feature) — _architecture_
- [D-262: The wiki↔generator data flow has one canonical map, and it is a diagram](decisions/architecture.md#d-262-the-wikigenerator-data-flow-has-one-canonical-map-and-it-is-a-diagram) — _architecture_
- [D-263: Tooling consolidates into one Python CLI named `reach` — not a Rust rewrite](decisions/architecture.md#d-263-tooling-consolidates-into-one-python-cli-named-reach--not-a-rust-rewrite) — _architecture_
## Open questions
@@ -473,3 +474,4 @@ line in place — keep the Q-record for the audit trail rather than deleting it.
- [R-011: Single currency for Phase 2 economics](rejected/economics.md#r-011-single-currency-for-phase-2-economics) — _economics_
- [R-012: Overheard NPC conversation system (D-078) — scrapped](rejected/perception.md#r-012-overheard-npc-conversation-system-d-078--scrapped) — _perception_
- [R-013: Localization / i18n](rejected/scope.md#r-013-localization--i18n) — _scope_
- [R-014: Rust rewrite of the Python tooling](rejected/architecture.md#r-014-rust-rewrite-of-the-python-tooling) — _architecture_