fix(code-health): --staged/--commit run the ratchet from the judged snapshot

F20 (andrexibiza): in --staged/--commit mode the guard jobs ran inside the
snapshot root with the snapshot's git env, but the health job ran in the real
worktree. Its source was pinned to the index tree, yet its engine and policy were
not: Measurer reads scripts/ci/profile_scope_patterns.json from the repo it runs
in, so with an identical `git write-tree`, editing only the unstaged P05
path_regex turned PS-P05 / exit 1 into "ok" / exit 0 and back.

The health job now runs like every other job: cwd = the snapshot root with the
snapshot env, so `python -m scripts.code_health` imports the snapshot's own engine
and reads the snapshot's policy files and ruff pin. The ruff job resolves its pin
from the same root. Unstaged edits to the policy file or the engine no longer move
the verdict, and they stay untouched in the worktree; plain runs are unchanged
(root is the worktree).
This commit is contained in:
Teknium
2026-10-04 17:39:11 -07:00
parent f98585d5cc
commit f8501a9328
2 changed files with 38 additions and 3 deletions

View File

@@ -122,13 +122,15 @@ def _jobs(names: list[str], base: str | None, head: str | None,
if name in _GUARDS:
jobs[name] = _Job([sys.executable, *_GUARDS[name]], root, env)
elif name == "ruff":
jobs[name] = _Job([*resolve_ruff(REPO), "check", "."], root, env)
jobs[name] = _Job([*resolve_ruff(root), "check", "."], root, env)
else:
# The ratchet reads both sides from git: real repo, judged against the head tree.
# The ratchet reads both sides from git. It runs from `root` like every other job, so
# in a snapshot its engine, rules and policy files (profile_scope_patterns.json, the
# ruff pin) are the judged artifact's own, never unstaged working-tree bytes.
health = [sys.executable, "-m", "scripts.code_health"]
health += ["--base", base] if base else []
health += ["--head", head] if head else []
jobs[name] = _Job(health)
jobs[name] = _Job(health, root, env)
return jobs

View File

@@ -114,6 +114,39 @@ def _ratchet_repo(tmp_path: Path, switch: str | None = None) -> tuple[Path, str]
return repo, _git(repo, "rev-parse", "HEAD")
# --- F20: the staged/commit health verdict comes from the judged artifact only -----------------
@pytest.mark.parametrize("unstaged", [
# the policy file read by the PS-P05 rule, narrowed so it no longer covers pkg/
("scripts/ci/profile_scope_patterns.json", lambda t: t.replace('"id": "P05",', '"id": "P05",\n'
' "path_regex": "^nowhere/",')),
# the engine itself, edited to exempt pkg/ from PS-P05
("scripts/code_health/config.py", lambda t: t.replace(
'exclude=SINGLE_PROFILE, pattern_id="P05"',
'exclude=SINGLE_PROFILE + ("pkg/*",), pattern_id="P05"')),
])
def test_staged_health_ignores_unstaged_policy_and_engine(tmp_path, unstaged):
repo = _engine_repo(tmp_path)
_write(repo, {"pkg/c.py": _ENV_COPY})
_git(repo, "add", "--", "pkg/c.py")
tree = _git(repo, "write-tree")
first = _check(repo, "--staged", "--only", "health", "--base", "HEAD")
assert first.returncode == 1 and "PS-P05" in first.stdout, first.stdout + first.stderr
rel, edit = unstaged
original = (repo / rel).read_text(encoding="utf-8")
edited = edit(original)
assert edited != original
(repo / rel).write_text(edited, encoding="utf-8")
again = _check(repo, "--staged", "--only", "health", "--base", "HEAD")
assert again.returncode == 1 and "PS-P05" in again.stdout, again.stdout + again.stderr
# the judged artifact and the user's unstaged work are both untouched
assert _git(repo, "write-tree") == tree
assert (repo / rel).read_text(encoding="utf-8") == edited
assert _git(repo, "diff", "--name-only") == rel
# --- F22: selectors are validated before anything runs ----------------------------------------