Commit Graph
2 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 5 338644b409 refactor(tooling): T-1286 — generate, pr and dev become reach domains
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>
2026-09-02 17:00:46 +02:00
jpmschweitzerandClaude Opus 5 3b211a5450 feat(config): T-1279 — a detached failure reaches its caller
The non-negotiable from D-263, pointed at its worst hiding place: a foreground
command that swallows a failure at least does it in front of someone, while a
background runner that reports "started" and loses the failure does it where
nothing is watching.

Testing the two timing cases the ticket names — fails before the parent exits,
fails long after — needs a command slow enough to tell them apart, and every
verb in reach finishes in milliseconds. So `reach dev selftest` exists: emits
progress for N seconds, then optionally fails with a chosen code. A genuine
diagnostic rather than a test hook, in the dev domain the map already planned,
and the only way to answer "does streaming work here, can I tail it, does a
failure survive detach" by observation instead of argument.

The slow case is the one that proves the design. --detach returned in 75ms
while the child ran six seconds, so the parent was demonstrably gone long
before the child failed — and wait still relayed exit 7. That is the half of
the recording path only this case reaches, and why T-1277 moved completion
recording into the child.

Also pinned: --detach exits 0 for starting and SAYS "not succeeded" in words,
which the test asserts on rather than trusting the code to be read correctly;
a failed job nobody waited on shows as failed in jobs list; and every event a
detached job emits carries its job id.

Closed T-1278's open gap in passing — jobs log --follow had never run against a
genuinely long job because none existed. It now has: attached mid-flight,
streamed the remaining steps live, and caught the final verdict after the job
ended.

Proven to fail by making effective_exit_code always return 0 — the trap itself.
Both timing cases failed by name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 17:14:23 +02:00