The 30-file tree moves under atlas as its third rung (D-243), ten verbs
fronting it. Each verb restates its module's options so `--help` describes
something; tooling/test_planet_router.py hands every declared option to the
module's own argparse and fails on drift, and now runs in make test-tooling.
The 2026-09-02 half of this move had converted the top-level imports and the
repo roots. Finishing it found what the half-move left:
- Lazy in-function imports, and all of sol_data/, still named siblings bare.
They resolved only through sys.path.insert hacks, so under reach the first
globe render in generate, batch or sol-import would have raised
ModuleNotFoundError. Qualified; the hacks are gone.
- 247 print() calls and a stdout progress writer that fired once per 8 KB
block. Report verbs (audit, quality) write through console.out, progress
through console.event, and download progress is throttled to 10% steps
so a job log is not tens of thousands of lines.
- Every error exit raises ReachError with a fix.
Two checks that could not fail:
- batch --verify-determinism printed a warning and exited 0 on a mismatch.
- import-provinces exited 0 with errors > 0.
Both now raise. The 271-body bake is only safe to re-run because the first
one holds.
sol-import --body is action="append" in the module but the router took one
value, so --body GJ0d --body GJ0e kept one. Now repeatable, and _flags repeats
list options.
test_conformance walked one level, so a nested group was reported as a verb
missing @command and its ten verbs were never checked. It recurses now;
proven by stripping @command from `planet quality` and watching it fail.
Stray PNGs from the 2026-09-03 runaway router-test run are parked in
.cache/t1288-stray-pngs/, not committed. Their reliefmaps differ from HEAD
while the heightmap regenerated byte-identical — filed as T-1291.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Twelve scripts retired, three domains registered. `reach` now covers nine.
generate: `generate-brands` and `generate-corporations` were the second and
third copies of the same 24-line build-if-missing-then-exec bash `tooling/atlas`
carried, so they collapsed into `core.process.cargo_binary` rather than being
ported. `import_economics` shelled out to the first of those, so it now calls
that helper — `generated_brands.toml` comes back byte-identical, and the stamp
registry swaps the retired wrapper for `core/process.py`.
pr: `watchlist-diff` derives its watched set from `generator_sources.py` instead
of restating it, so it cannot drift from the stamp check.
dev: the environment scripts split decision from performing, per D-263's
guarded-exec rule. `godot_plan()` and `worktree_plan()` decide what would
happen; `install_godot()`, `install_rust()` and `setup_worktree()` do it.
`tooling/test_environment.py` pins the version pin, both override precedences,
the already-current skip, the platform refusal and both worktree refusals —
none of them performed. `make setup` now installs reach first, since the
targets that install rust and godot are reach verbs.
Two live bugs found while porting:
- The clerk read its decision index from `decisions/README.md`, a path that
stopped existing when the DQR tree moved to `governance/`. Every clerk agent
has been grepping blind; its prompt pointed at the same dead directory.
- The conformance exec-check matched any `x.system()` regardless of receiver,
so `platform.system()` read as `os.system()`. Narrowed and re-proved against
a real mutant.
`process.run` gains `input=`, `timeout=` and a `ProcessTimeout` subclass so a
killed run stays distinguishable from a verdict. The pre-push hook no longer
merges the clerk's stderr into its stdout — under streaming the last merged
line is a JSONL event, which would read as an unrecognised verdict and block.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>