Files
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

155 lines
6.1 KiB
Python

#!/usr/bin/env python3
"""The `reach dev` environment decisions, exercised without performing them (T-1286).
`install-godot`, `install-rust` and `worktree-setup` were the three scripts the
CLI port stood to gain least from and risked most on. Nothing about them can be
checked by running them: a passing test would download a 60 MB archive, mutate
`~/bin`, or leave a git worktree behind. So the port split each one into a pure
decision (`godot_plan`, `worktree_plan`) and a thin performing half, and this
file pins the decisions.
That split is the whole claim of the port, which is why it gets a test rather
than a manual `--plan` run: an installer that cannot be tested has to be
trusted instead, and trusting an installer is how a working environment becomes
an unreproducible one.
Run: python3 tooling/test_environment.py
"""
from __future__ import annotations
import os
import sys
import tempfile
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO_ROOT))
from tooling.core.errors import ReachError # noqa: E402
from tooling.domains.dev import environment # noqa: E402
def test_plan_names_the_pinned_version(failures: list[str]) -> None:
"""The default plan targets DEFAULT_GODOT_VERSION and builds a real URL."""
plan = environment.godot_plan()
if plan.wanted != environment.DEFAULT_GODOT_VERSION:
failures.append(
f"godot_plan() wanted {plan.wanted}, expected the pinned "
f"{environment.DEFAULT_GODOT_VERSION}"
)
if plan.wanted not in plan.url or plan.filename not in plan.url:
failures.append(f"the URL does not carry version and filename: {plan.url}")
if not plan.url.startswith("https://"):
failures.append(f"the download URL is not https: {plan.url}")
def test_explicit_version_overrides_the_pin(failures: list[str]) -> None:
plan = environment.godot_plan("4.9")
if plan.wanted != "4.9" or "4.9-stable" not in plan.url:
failures.append(f"an explicit version did not reach the URL: {plan.url}")
def test_env_var_overrides_the_pin(failures: list[str]) -> None:
"""GODOT_VERSION is how make setup passes the version through."""
before = os.environ.get("GODOT_VERSION")
os.environ["GODOT_VERSION"] = "4.7"
try:
if environment.godot_plan().wanted != "4.7":
failures.append("GODOT_VERSION was ignored by godot_plan()")
# An explicit argument still wins over the environment.
if environment.godot_plan("4.8").wanted != "4.8":
failures.append("an explicit version lost to GODOT_VERSION")
finally:
if before is None:
del os.environ["GODOT_VERSION"]
else:
os.environ["GODOT_VERSION"] = before
def test_already_current_is_decided_not_performed(failures: list[str]) -> None:
"""already_current compares installed against wanted — the skip decision."""
real = environment.godot_plan()
same = type(real)(
wanted="4.6", installed="4.6", platform_tag=real.platform_tag,
url=real.url, filename=real.filename,
)
differs = type(real)(
wanted="4.6", installed="4.5", platform_tag=real.platform_tag,
url=real.url, filename=real.filename,
)
absent = type(real)(
wanted="4.6", installed=None, platform_tag=real.platform_tag,
url=real.url, filename=real.filename,
)
if not same.already_current:
failures.append("a matching installed version was not treated as current")
if differs.already_current:
failures.append("a mismatched version was treated as current — install skipped")
if absent.already_current:
failures.append("a missing install was treated as current — install skipped")
def test_unsupported_platform_names_a_remedy(failures: list[str]) -> None:
"""An unknown platform must fail loudly, not build a URL that 404s."""
saved = dict(environment.PLATFORMS)
environment.PLATFORMS.clear()
try:
environment.godot_plan()
failures.append("an unsupported platform produced a plan instead of an error")
except ReachError as exc:
if not exc.fix:
failures.append("the unsupported-platform error carries no fix")
finally:
environment.PLATFORMS.update(saved)
def test_worktree_plan_targets_the_convention(failures: list[str]) -> None:
"""D-221: worktrees live at <root>/.worktrees/<branch>."""
target = environment.worktree_plan("some-unused-branch-name")
expected = environment.config.repo_root() / ".worktrees" / "some-unused-branch-name"
if target != expected:
failures.append(f"worktree_plan gave {target}, expected {expected}")
def test_worktree_plan_refuses_an_existing_tree(failures: list[str]) -> None:
"""Silently reusing a directory is how two branches share one tree."""
root = environment.config.repo_root()
with tempfile.TemporaryDirectory(dir=root / ".worktrees") as existing:
name = Path(existing).name
try:
environment.worktree_plan(name)
failures.append("worktree_plan accepted a branch whose directory exists")
except ReachError as exc:
if not exc.fix:
failures.append("the existing-worktree error carries no fix")
def main() -> int:
# .worktrees/ must exist for the collision test to place a directory in it.
(environment.config.repo_root() / ".worktrees").mkdir(exist_ok=True)
failures: list[str] = []
test_plan_names_the_pinned_version(failures)
test_explicit_version_overrides_the_pin(failures)
test_env_var_overrides_the_pin(failures)
test_already_current_is_decided_not_performed(failures)
test_unsupported_platform_names_a_remedy(failures)
test_worktree_plan_targets_the_convention(failures)
test_worktree_plan_refuses_an_existing_tree(failures)
if failures:
print("test_environment: FAIL", file=sys.stderr)
for failure in failures:
print(f" - {failure}", file=sys.stderr)
return 1
print(
"test_environment: OK — version pin, overrides, skip decision, "
"platform refusal and worktree placement, none of them performed"
)
return 0
if __name__ == "__main__":
sys.exit(main())