[FIX] REVIEWED-131: build PENDING-165 (d) as an allowlist, then (b) narrowly
(d) — governance-drift-check.py now DECLARES the contents of ~/dotfiles/git/hooks
(README.md, pre-commit) and reports anything unexpected or declared-but-missing.
Tracked-ness is never consulted, and that is the correction: the filed form tested
"neither tracked nor pre-commit", and 066a47a was TRACKED for four weeks, so it
would have been silent throughout the only occurrence that did damage. Asserted
structurally, not in prose — a control checks that scan_hooks' code names contain
neither "git" nor "subprocess".
(b) — .gitignore for the four git-lfs shim names. DELIBERATELY NARROW: a blanket
git/hooks/* + allowlist would silently prevent committing a new legitimate hook,
which would work locally, never reach the repo, and be invisible to (d) because
(d) reads the filesystem and not the index. Verified the pair composes: a planted
shim yields 0 entries in git status AND is reported UNEXPECTED by the check.
⚠ And a fifth self-referential instrument event, in the fix for that very class.
The five new controls were appended after failed_controls is computed (702 vs
846): all ran, none counted, tally still read 48/48, and a failure among them
would have printed NOTHING. The check against blind checks was blind to itself.
Caught by comparing the printed tally to the number of controls added. Moved above
the report block (53/53) and verified by breaking one deliberately and confirming
it prints INSTRUMENT NOT VERIFIED and names itself.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NvZAKSf9aqratbqHbU9LK5
This commit is contained in:
co-authored by
Claude Opus 5
parent
a0d63f44ca
commit
46aa3d15a2
+19
@@ -4,3 +4,22 @@ __pycache__/
|
|||||||
|
|
||||||
# macOS Finder droppings
|
# macOS Finder droppings
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# git-lfs shims in the GLOBAL hook directory (REVIEWED-131 / PENDING-165 option (b))
|
||||||
|
# git-lfs installs these into whatever core.hooksPath names; here that is the hook
|
||||||
|
# directory shared by every repo on this machine. On 2026-03-20 a routine `git add`
|
||||||
|
# captured them (066a47a) and they sat TRACKED for four weeks, executing everywhere and
|
||||||
|
# indistinguishable from hooks the steward wrote. Ignoring them stops that capture.
|
||||||
|
#
|
||||||
|
# ⚠ DELIBERATELY NARROW — these four names only, not `git/hooks/*` with an allowlist.
|
||||||
|
# A blanket ignore would silently prevent committing a NEW legitimate hook: it would work
|
||||||
|
# locally, never reach the repo, and the allowlist check cannot see that (it reads the
|
||||||
|
# filesystem, not the index). A narrow ignore trades away nothing.
|
||||||
|
#
|
||||||
|
# Visibility is NOT lost by this: governance-drift-check.py declares the directory's
|
||||||
|
# contents and reports anything unexpected, tracked-ness not consulted. That check is
|
||||||
|
# what makes ignoring safe — do not ignore more than this without extending it.
|
||||||
|
git/hooks/pre-push
|
||||||
|
git/hooks/post-checkout
|
||||||
|
git/hooks/post-commit
|
||||||
|
git/hooks/post-merge
|
||||||
|
|||||||
@@ -40,6 +40,16 @@ type: feedback
|
|||||||
ignoring them would hide the pollution instead of surfacing it. ⚠ Care did not prevent the
|
ignoring them would hide the pollution instead of surfacing it. ⚠ Care did not prevent the
|
||||||
second occurrence; I had cleaned the first one two hours earlier.
|
second occurrence; I had cleaned the first one two hours earlier.
|
||||||
|
|
||||||
|
- 2026-08-26T~night — ⚠ **FIFTH self-referential instrument event, and it was in the fix
|
||||||
|
for the class.** The new hook-allowlist controls were appended AFTER `failed_controls` is
|
||||||
|
computed (line 702 vs 846), so all five ran, none was counted — the tally still read
|
||||||
|
`48/48` — and **a failure among them would have printed nothing.** I built the check
|
||||||
|
against *blind checks* with a check blind to itself, in the same hour, immediately after
|
||||||
|
the jurist caught the previous blindness in the same item. Caught only because I compared
|
||||||
|
the printed tally against the number of controls I knew I had added. Fixed by moving the
|
||||||
|
section above the report block (`53/53`), then **verified by deliberately breaking one new
|
||||||
|
control and confirming it now prints INSTRUMENT NOT VERIFIED and names itself.**
|
||||||
|
|
||||||
## What held
|
## What held
|
||||||
|
|
||||||
- Ran `thread-query.py` on the actual thread and reported the **null honestly** (689 candidates,
|
- Ran `thread-query.py` on the actual thread and reported the **null honestly** (689 candidates,
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import re
|
|||||||
import signal
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -697,6 +698,58 @@ except Exception:
|
|||||||
pass # git absent is not a check failure; the fixtures still ran
|
pass # git absent is not a check failure; the fixtures still ran
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------------- N. the global hook directory (REVIEWED-131 / PENDING-165)
|
||||||
|
# git-lfs installs four shims — pre-push, post-checkout, post-commit, post-merge — into
|
||||||
|
# whatever core.hooksPath names. Here that is the GLOBAL hook directory for 37 repos, and
|
||||||
|
# no human is in the invocation path.
|
||||||
|
#
|
||||||
|
# ⚠ THIS CHECK DELIBERATELY DOES NOT TEST TRACKED-NESS, and that is the whole correction.
|
||||||
|
# The first filed form of it reported files that were "neither tracked nor pre-commit".
|
||||||
|
# The one occurrence that did damage — 066a47a, 2026-03-20 — was TRACKED: a routine
|
||||||
|
# `git add` captured the shims and they sat in the tracked hook path for four weeks,
|
||||||
|
# executing on every push/checkout/commit/merge in every repo. `not tracked` was false
|
||||||
|
# for that entire period, so the check would have been silent throughout the only
|
||||||
|
# occurrence that mattered. It saw DEPOSIT and not CAPTURE, and capture is the laundering.
|
||||||
|
# Caught by the jurist before the check was built (PENDING-165 AMENDMENT 1).
|
||||||
|
#
|
||||||
|
# So: declare the contents instead. Anything unexpected is a finding, tracked or not, and
|
||||||
|
# anything DECLARED-BUT-MISSING is also a finding — REVIEWED-105 §2 measured that an
|
||||||
|
# absent hook file produces zero output rather than an ambiguous silence, so absence must
|
||||||
|
# be asserted rather than inferred from quiet.
|
||||||
|
HOOKS_DIR = HOME / "dotfiles/git/hooks"
|
||||||
|
HOOKS_ALLOWED = {"README.md", "pre-commit"}
|
||||||
|
|
||||||
|
|
||||||
|
def scan_hooks(d):
|
||||||
|
"""(unexpected, missing) for a hook directory. Consults the FILESYSTEM only —
|
||||||
|
never git, never the index. See the note above for why tracked-ness is excluded."""
|
||||||
|
present = {f.name for f in d.iterdir() if f.is_file()}
|
||||||
|
return sorted(present - HOOKS_ALLOWED), sorted(HOOKS_ALLOWED - present)
|
||||||
|
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as _td:
|
||||||
|
_t = Path(_td)
|
||||||
|
(_t / "README.md").touch()
|
||||||
|
(_t / "pre-commit").touch()
|
||||||
|
control("hook allowlist: an exactly-conforming directory yields no finding",
|
||||||
|
scan_hooks(_t) == ([], []))
|
||||||
|
(_t / "post-commit").touch()
|
||||||
|
control("hook allowlist: an unexpected file IS detected [the deposit case]",
|
||||||
|
scan_hooks(_t) == (["post-commit"], []))
|
||||||
|
(_t / "pre-commit").unlink()
|
||||||
|
control("hook allowlist: a DECLARED-BUT-MISSING file IS detected [negative control — "
|
||||||
|
"REVIEWED-105 §2: an absent hook is silent, not obviously broken]",
|
||||||
|
scan_hooks(_t) == (["post-commit"], ["pre-commit"]))
|
||||||
|
# Structural, not behavioural: the correction is that tracked-ness is never consulted, and
|
||||||
|
# a prose comment saying so is not a check. This asserts it of the code itself.
|
||||||
|
control("hook allowlist: the scan never consults git [the tracked/untracked test is the "
|
||||||
|
"defect this replaced — 066a47a was TRACKED]",
|
||||||
|
"git" not in scan_hooks.__code__.co_names
|
||||||
|
and "subprocess" not in scan_hooks.__code__.co_names)
|
||||||
|
control("hook allowlist: the real hook directory is reachable", HOOKS_DIR.is_dir())
|
||||||
|
|
||||||
|
hook_unexpected, hook_missing = (scan_hooks(HOOKS_DIR) if HOOKS_DIR.is_dir() else (None, None))
|
||||||
|
|
||||||
# ------------------------------------------------------------- report
|
# ------------------------------------------------------------- report
|
||||||
failed_controls = [lbl for lbl, ok in controls if not ok]
|
failed_controls = [lbl for lbl, ok in controls if not ok]
|
||||||
if failed_controls:
|
if failed_controls:
|
||||||
@@ -809,6 +862,7 @@ else:
|
|||||||
print(" ~57 candidate negative-state claims are unmarked and unread (a grep, not a")
|
print(" ~57 candidate negative-state claims are unmarked and unread (a grep, not a")
|
||||||
print(" census). Adoption is the open question, not expressibility (PENDING-158).")
|
print(" census). Adoption is the open question, not expressibility (PENDING-158).")
|
||||||
|
|
||||||
|
|
||||||
if dangling:
|
if dangling:
|
||||||
print(f"\n⚠ register integrity: {len(dangling)} resolved block(s) name no pointer "
|
print(f"\n⚠ register integrity: {len(dangling)} resolved block(s) name no pointer "
|
||||||
f"that resolves")
|
f"that resolves")
|
||||||
@@ -816,4 +870,22 @@ if dangling:
|
|||||||
print(f" {_d['slug']} — resolved: {_d['resolved'] or '(empty)'}")
|
print(f" {_d['slug']} — resolved: {_d['resolved'] or '(empty)'}")
|
||||||
print(" A discharge recording THAT a gate closed but not WHAT closed it is no record.")
|
print(" A discharge recording THAT a gate closed but not WHAT closed it is no record.")
|
||||||
|
|
||||||
|
if hook_unexpected is None:
|
||||||
|
print(f"\n— hook directory: CANNOT ASSESS — {HOOKS_DIR} unreachable.")
|
||||||
|
print(" Not a pass and not a finding. Nothing was checked.")
|
||||||
|
elif hook_unexpected or hook_missing:
|
||||||
|
print(f"\n⚠ hook directory: {len(hook_unexpected)} unexpected, "
|
||||||
|
f"{len(hook_missing)} declared-but-missing")
|
||||||
|
for _f in hook_unexpected:
|
||||||
|
print(f" UNEXPECTED {_f}")
|
||||||
|
for _f in hook_missing:
|
||||||
|
print(f" MISSING {_f}")
|
||||||
|
print(" ~/dotfiles/git/hooks is global to every repo. An unexpected file here executes")
|
||||||
|
print(" everywhere; git-lfs deposits four shims and a routine `git add` can capture them")
|
||||||
|
print(" as though governed (066a47a sat tracked for four weeks). Tracked-ness is not")
|
||||||
|
print(" consulted here on purpose — see PENDING-165.")
|
||||||
|
else:
|
||||||
|
print(f"✓ hook directory: exactly the declared contents "
|
||||||
|
f"({', '.join(sorted(HOOKS_ALLOWED))})")
|
||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|||||||
Reference in New Issue
Block a user