用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/lukemcqueen/hermes-cortex --skill enforcement-change-safety命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
Cross-server agent health monitoring using binary status vectors — deploy health endpoints on each agent, poll from orchestrator, alert on state transitions.
Wire a self-hosted Langfuse instance to Hermes Agent — generate API keys, configure env vars, enable the bundled plugin, install SDK, and verify traces flow.
Mandatory pre-ship verification before calling end_change(). Covers Phase 0 survey, test, multi-OS, multi-role, docs, final verification, and reflexion. Every governance cycle must run this before closing.
| name | enforcement-change-safety |
| version | 1.0.0 |
| category | devops |
| description | Use before enforcement code changes or shared-repo commits. |
| author | Hermes Cortex |
| license | MIT |
| platforms | ["linux","macos"] |
| metadata | {"hermes":{"tags":["governance","enforcement","security","git","concurrency","hooks"],"related_skills":["enforcer-modification-considerations","change-checklist","two-hard-rules","loop-governance"]}} |
Load BEFORE touching any enforcement/governance code: git hooks (pre-commit, pre-push, post-commit), the enforcer plugin, the loop-governance MCP server, or the scoring pipeline. Also load when doing ANY git operation in a repo that other agent sessions share.
This skill exists because a single misread of a "fix the warning" request
deleted the entire scoring subsystem (the heart of loop governance), and a
careless git commit swept another session's staged work into the wrong commit.
Both were trust-destroying, user-corrected mistakes (2026-08-03).
When an issue says "remove the stale X block so the warning stops printing":
warn + exit 0 when a dependency is missing —
that exit 0 SHORT-CIRCUITS the hook early, skipping every downstream guard
(orchestrator-only paths, self-test, adversarial scan). THAT is the bug.exit 1 with a
message pointing at the sanctioned fix (e.g. cortex-update.sh). A commit
without a governance record must not land.exit 0 would skip?exit 0 on missing dependency → the early exit IS
the bypass; convert to exit 1 (fail closed).bash -n the hook; live-test BOTH branches (dependency present → scoring
runs; dependency missing → exit 1).cortex-update.sh), verify deployed copy
byte-identical to repo source, verify fail-closed present in deployed.A hook that fails closed when a scorer binary is missing must actually FIND the binary on macOS, or every commit on Titus blocks:
~/.local/bin in PATH by default — command -v score-cycle
fails even when installed. Add the canonically-deployed path as a search
candidate: $HOME/.hermes-cortex/tools/loop-governance/score_cycle.py
(cortex-update.sh registers it there on BOTH Linux and macOS). Test the search
with an emptied PATH to prove the deployed-path candidate resolves.timeout command (coreutils provides gtimeout). Resolve
the timeout binary portably before the scorer invocation:
_TIMEOUT_BIN=""
if command -v timeout >/dev/null 2>&1; then _TIMEOUT_BIN="timeout 30"
elif command -v gtimeout >/dev/null 2>&1; then _TIMEOUT_BIN="gtimeout 30"
fi
SCORE_OUTPUT=$($_TIMEOUT_BIN "$PYTHON_BIN" "$SCORE_CYCLE" ...)
Empty _TIMEOUT_BIN = unbounded run; the || hard-block still guards.for-in, command -v, [[ -z ]], $() are safe;
grep -P, mapfile, ${var,,} are NOT. Check the whole hook, not just your
edit.<<< herestrings and [[ =~ ]] — both are
bash-3.2-safe; do not "fix" them.git add <my-file> does NOT mean only your file is staged. Sibling sessions
(and cron jobs) stage files concurrently into the SAME index. A plain
git commit sweeps EVERYTHING staged — foreign work lands in your commit and
its author panics ("my edits vanished").
git status --short AND
git diff --cached --name-only. Review the FULL staged set.git restore --staged <file> — index-only,
worktree content untouched.git checkout -- ., git reset --hard) in a repo
others use — you destroy their uncommitted work.git restore --staged per foreign file.sha256sum verify) before any
recovery dance — proof nothing was lost.git rev-parse HEAD origin/main,
git branch -r --contains <sha>. A sibling may have pushed a commit that
absorbed yours — confirm the final state on origin rather than fighting it.tests/test_runtime/test_governance_bypass.py::TestHasGovernanceLock
(corrupted/deleted lock → False) FAILS when your session holds an active
governance lock: _has_governance_lock() Phase 3 reads the repo marker
.hermes-cortex/.governance-lock written by begin_change, so it returns True.
mv .hermes-cortex/.governance-lock /tmp/x → tests pass
→ mv back. Phase 1 primary lock is separate, so your write gate survives.begin_change creates a PENDING cycle. The doctor distinguishes (since
2026-08-05, commit 63981498): a cycle whose task_id has a LIVE lock file
(~/.hermes-cortex/state/.governance-*.json, status executing) is the
CURRENT task → reported INFO "score at end_change", NOT a FAIL. A cycle
whose task_id has NO lock is a LEAK (you moved on without scoring) → FAIL.
Green is achievable mid-lock; the current task's own cycle no longer fails
the doctor.feedback_accept) before end_change — and
score each task's cycle at THAT task's end_change. NEVER batch: opening
begin_change under a new task_id while earlier cycles from the same
session are still PENDING creates a leak (Luke caught 3 such cycles
2026-08-05; the 30-min backlog alert fires on exactly this).cycle_query(status="pending"),
score only the ones your session_id created.cortex-update.sh no longer purges live locks (FIXED 2026-08-05). The
old "deploy purges locks" behavior was a TIMEZONE BUG, not a feature: the
stale-lock cleanup sliced the heartbeat to [:19], STRIPPING the ISO-8601
Z (UTC) marker, then date -d parsed UTC as LOCAL time — on UTC+9 hosts a
2-minute-old lock computed as 9h old → deleted on EVERY deploy. See Rule 12
for the full story. If a deploy still eats your lock, check the stale-lock
age math FIRST (a fresh lock showing hours of age = TZ bug), then re-acquire
with begin_change as a stopgap only.Symptom: git pull --rebase replays your commit WITHOUT running the
pre-commit hook, so the pre-commit sentinel (.git/.pre-commit-ran) is never
written. The post-commit hook then logs the NEW rebased hash in
~/.hermes-cortex/state/no-verify-log.json as a --no-verify commit, and
pre-push BLOCKS your push: "commit X was made with --no-verify". Cherry-pick
and revert hit the same false positive. It's a FALSE POSITIVE — the commit
went through the hook originally; the replay just bypassed it mechanically.
Root fix (committed 7bc86ca3): post-commit-audit now discriminates via
the HEAD reflog message instead of assuming sentinel-missing == bypass:
git reflog -1 --format='%gs' — genuine git commit (normal, --no-verify,
--amend, --fixup) ALWAYS writes a message starting with commit
(commit: ..., commit (amend): ...). Internal replays write something
else: rebase (pick): ..., cherry-pick: ..., revert: ...,
merge <branch>: ..., pull ...:.commit* → genuine bypass →
LOG. Missing sentinel but reflog is a replay prefix → silent, no log entry.⚠️ Pitfall — use commit*, not commit:. The first implementation used
the prefix commit: which does NOT match commit (amend): ... — so
git commit --amend --no-verify (a GENUINE bypass) would have slipped through
silently. Prefix matching must be commit* so amend/no-verify still logs.
A real bypass must never be silenced to fix a false positive.
Workaround still needed ONLY on hosts whose deployed post-commit predates
the fix (before the next cortex-update.sh): git commit --amend --no-edit
re-runs the full pre-commit hook (sentinel written → consumed cleanly),
producing a new hash NOT in the log; then push passes. Leave the old dangling
entry — it can never match a future push range, and deleting audit entries
looks like tampering.
Do NOT: rm ~/.hermes-cortex/state/no-verify-log.json to unblock a push —
that is exactly the audit-trail tampering the pre-push hook exists to catch.
Verify hook behavior with the 8-path matrix before shipping any hook
change that touches the sentinel: scripts/test-post-commit-sentinel-matrix.sh
builds a scratch repo, installs the real hooks, and runs all eight paths
(normal, --no-verify, rebase, cherry-pick, revert, merge, amend, amend
--no-verify) asserting which must log and which must stay silent.
core.hooksPath ~/.hermes-cortex/hooks is set globally — the pre-commit/
pre-push hooks fire in every git repo on the host (client-repo-a, client-repo-b,
client repos, any project without the cortex ops/ tree). A hook that builds
a path on $REPO_ROOT (the repo being committed IN) and assumes cortex
layout breaks EVERY commit in those repos — even one-line test fixes.
Real regression (2026-08-04, Esther, commit faa0e929): the adversarial
gate hard-resolved ADVERSARIAL_SCRIPT="$REPO_ROOT/ops/scripts/quality/adversarial-verify.py".
That path exists only in ~/hermes-cortex itself. Project repos have no ops/
tree → fail-closed block on every commit (Titus hit it on client-repo-a within
hours). Fix 72d6cdc3: candidate loop with deployed-path fallback.
The pattern — repo-local first, canonically-deployed second, fail CLOSED:
ADVERSARIAL_SCRIPT=""
for candidate in "$REPO_ROOT/ops/scripts/quality/adversarial-verify.py" \
"$HOME/.hermes-cortex/scripts/adversarial-verify.py"; do
if [[ -f "$candidate" ]]; then
ADVERSARIAL_SCRIPT="$candidate"
break
fi
done
if [[ -z "$ADVERSARIAL_SCRIPT" ]]; then
# fail CLOSED — a commit without the scan is a bypass
exit 1
fi
$HOME/.hermes-cortex/scripts/ is where cortex-update.sh registers every
deployed tool on BOTH Linux and macOS — always include it as the fallback.$REPO_ROOT (from git rev-parse --show-toplevel) is the repo being
committed IN — only valid as the FIRST candidate, never the only path.Verify BEFORE shipping a hook change (all three):
ops/ tree → deployed copy found
(git init /tmp/proj && git config core.hooksPath ~/.hermes-cortex/hooks)The enforcer gates the TOP-LEVEL tool call only. Putting the command under test
inside a bash script (bash /tmp/test.sh whose body runs
git commit --no-verify ...) means the enforcer sees bash /tmp/test.sh —
the inner git command runs as a subprocess and NEVER crosses the gate. A test
that "proves" the gate is broken this way is testing nothing (2026-08-05: a
false "bypass-debt gate not working" conclusion; the gate was fine).
cd /tmp/repo && git commit --no-verify ... — hold a governance lock so the outer call passes),
and expect the gate's block message.python3 -c '...' ; git commit --no-verify ... one-liner is gated as one
unit, so set up state (debt file, marker) in a SEPARATE call first.spec_from_file_location on
~/.hermes/plugins/governance-enforcer/__init__.py) and calling
_is_readonly_terminal_command, _bypass_debt_count, re.search(...) —
fast, deterministic, no repo needed.PII/content scanners (enforcer PII gate, secret-leak-detector) must exempt
files whose PURPOSE is to hold the flagged content — with a NARROW path
allowlist, never a blanket pattern disable. The shared blocklist
(ops/install/deploy/nginx/blocked_ips.add / .submit) exists to hold PUBLIC
IPs; that is the data, not PII. Without the exemption every commit staging the
file warns once per IP — Gisu got flooded with dozens of ⚠ PII — public IP address warnings per commit (Telegram spam-filter ban risk), and the
pipeline's own sanctioned commits generated the noise too (2026-08-05).
case "$FILE" in ...blocked_ips.add|...blocked_ips.submit) : ;; *) ...scan... ;; esac).pin_repos_with_own_hooks() sets a repo's local core.hooksPath to its OWN
.git/hooks (to preserve deploy-bare-repo hooks) but historically never
refreshed the hook FILES — stale copies predated the mandatory adversarial
gate (Titus audit 2026-08-05: 9 repos, grep -c adversarial = 0). Two things
are needed together, or the fix breaks commits:
Refresh the files: cortex-update.sh refresh_pinned_hook_files()
copies the 4 cortex hooks (pre-commit-score, pre-push-pull,
post-commit-audit, post-push-audit) from deployed source into the repo's
own hooks dir. ONLY files carrying the cortex banner (Git <type> hook,
ASCII match — locale-safe on macOS) are overwritten; foreign hooks (vllm
pre-commit framework shim) are preserved. Missing hook files get the gate
installed.
Carve out the hooksPath guard: pre-commit-score and pre-push-pull both
fail CLOSED when core.hooksPath != ~/.hermes-cortex/hooks (5ab54547).
That guard would block EVERY commit in a pinned repo (their hooksPath IS
their own dir). The carve-out passes when the hooks dir carries any
cortex-managed hook (governance IS running there); the tripwire still
fires when hooksPath points at a dir with no cortex hooks.
Verify before shipping a pinned-hooks change (all three):
Pinned hooks fresh check: FAIL on stale → refresh → PASSPitfall: deployed hook files are chattr +i immutable — you cannot
overwrite them by hand to test; use cortex-update.sh or test with
repo-source as the simulated deployed source.
When a gate greps doctor output, the FAIL-detection pattern has bitten twice (2026-08-05, both caught by the dogfood loop itself):
FAIL. The doctor's summary line is
❌ Overall: FAILING — which contains "FAIL" → false positive on every
green run. And ❌ PENDING cycles contains no "FAIL" → false negative.❌ either. The footer 🔧 REQUIRED ACTIONS — resolve each ⚠️ or ❌ above contains ❌ mid-line → counted as a failure. The
gate blocked its own push showing "1 failure" while printing zero detail._DOCTOR_FAILS=$(echo "$DOCTOR_OUTPUT" | grep -E '^ *❌' \
| grep -vcE 'Overall: FAILING' || true)
Match ^ *❌ (lines STARTING with ❌ = actual check lines), exclude ONLY
the summary line. Unit-test against REAL doctor output including the
footer — a synthetic fixture without the footer line hides the bug.Leaked-cycle enforcement (63981498): the doctor now FAILs only on cycles
from FINISHED tasks (no active lock for their task_id); the current task's
cycle (lock held) is INFO. The pre-push gate therefore must NOT exclude
"PENDING cycles" lines — a push with leaked prior-task cycles is BLOCKED.
That is the mechanism that makes "clear cycles during cleanup, not later"
(Luke directive 2026-08-05) physical: you cannot ship while old cycles sit
unscored. The same applies to cortex-dogfood.sh — its verify step counts
the same way.
Two Luke corrections (2026-08-05) about gate blast radius. The pre-commit and pre-push hooks fire in EVERY repo on the host (Rule 6) — so any NEW gate added to them must be doubly scoped or it will block innocent work in project repos:
_REPO_TOP=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
[[ "$_REPO_TOP" == "$CORTEX_REPO_TOP" ]] # CORTEX_REPO_TOP=${HOME}/hermes-cortex
Non-cortex repos (client-repo-a, client-repo-b, client-web-app, pinned repos,
...) must NEVER run the hermes-cortex doctor — a failing cortex state must
not block a client repo's push._detect_orch() (hostname moses|esther AND home
/home/<hostname>, env-independent — the SAME function pre-commit uses
for its self-test; copy it, don't reinvent). Non-orch hosts never run the
doctor gate. cortex-dogfood.sh exits 1 with a clear message on
non-orch hosts.Orchestrator-only path arrays must be repo-scoped too (Titus over-block):
the hardcoded ORCHESTRATOR_ONLY_PATHS array had UNANCHORED patterns
(test_.*\.py$, .*_test\.py$, .*_spec\.py$) that fired in every repo —
Titus was blocked committing apps/api/tests/test_ipi_similarity.py in a
project repo. The config-driven guard (docs/orchestrator-only-paths.txt read
from HEAD) is the correct repo-aware design: "no config file = no
restrictions". The hardcoded array must be wrapped in the same
if [[ "$REPO_ROOT" == "${HOME}/hermes-cortex" ]] gate, and any
cortex-specific path it protects that the config misses (e.g.
^core/governance/tests/) added explicitly rather than via unanchored
patterns.
macOS deploy-script portability (deploy-fix-blocked-ips.sh, 2026-08-05): a deploy script that hardcodes Linux assumptions breaks on macOS silently — the sanctioned fix lands in the wrong dir and the doctor FAIL persists.
/usr/local/sbin (Linux) vs /usr/local/bin (macOS) — the doctor
check is platform-aware; the deploy script must match it.root (Linux) vs wheel (macOS — no root group).chattr/lsattr (Linux) vs chflags uchg/nouchg (macOS),
each guarded by command -v so a missing tool never fails the deploy.[ "$(uname -s)" = "Darwin" ].The TZ bug (2026-08-05, Luke: "this lock issue is MISERABLE"): the "cortex- update purges locks every deploy" behavior was NOT a designed purge — it was a timezone parse bug in cortex-update.sh's stale-lock cleanup:
Z (e.g. 2026-08-05T08:42:54Z).[:19] — stripping the Z — then ran
date -d "$heartbeat" +%s, which parses a marker-less timestamp as LOCAL
time. On a UTC+9 host (KST) the UTC time parsed as +9h-offset LOCAL → a
FRESH 2-minute lock computed as 9h old → > 3600 threshold → deleted
on every deploy._has_governance_lock (Python datetime.fromisoformat)
handled Z correctly the whole time — the lock was being deleted under it.Fix pattern for ANY bash date -d on an ISO heartbeat: KEEP the Z —
date -d "2026-08-05T08:42:54Z" +%s parses correctly. Or use Python
(fromisoformat handles Z). When diagnosing a "purged" lock, verify the
age math FIRST: a lock minutes old showing hours of age = TZ bug, not a real
stale lock. Python purge paths (MCP server, purge-stale-governance-locks.py)
were already correct — but the bash date -d had a SECOND, worse bug
(2026-08-10, Titus): date -d is GNU-only — macOS BSD date has no -d,
so the 2>/dev/null || echo 0 fallback fired, epoch=0, age = now-0 ≈ 1.78e9s
3600 → every lock, including fresh v2 session locks, deleted on every macOS deploy (cortex-update.sh:2719). The TZ fix (keep the Z) only addressed GNU parse — the
|| echo 0was the fail-OPEN trap. Fix that shipped: portable python3 epoch (datetime.fromisoformat(hb.replace('Z','+00:00'))) with an EMPTY fallback (|| echo "") +[[ -n "$epoch" ]]guard — parse failure now SKIPS the lock (P1-A rule: never delete what you can't age-verify). Rule: any heartbeat→epoch conversion in bash must (a) parse ISO-8601 with Z via python3, not GNUdate -d, and (b) fail CLOSED on parse failure — empty string + skip, never|| echo 0+ delete.
Mandatory dogfood in the pre-push gate (Luke: "make this MANDATORY — I
thought you did already"): a push that touches ANY non-doc file in
hermes-cortex runs the FULL dogfood cycle (pull → cortex-update → doctor →
verify) BEFORE landing. The gate invokes cortex-dogfood.sh --quiet itself
so the step cannot be forgotten:
*.md, docs/) exempt — no deployed state changes.cortex-dogfood.sh captures the active task_id
(DOGFOOD_OWN_TASK) BEFORE deploy and exempts exactly that task's cycle
from the FAIL count — other leaked cycles still fail.state/skills-loaded/<session_id>) survives deploy; the reload trigger is
deployed-skill drift → doctor → re-skill_view, not lock deletion. Do not
delete locks to force skill reloads — invalidate the marker instead.A register() dest that is USER-OWNED after install (MEMORY.md, USER.md, any
seed template the user personalizes) must never ride the generic
needs_update() hash-overwrite path. A personalized MEMORY.md can never match
its template, so EVERY full-mode deploy (the default; the post-merge hook
auto-runs cortex-update.sh) clobbers it — 7 clobbers in one day (2026-08-05),
saved only by deploy-backups/*.bak + manual restore.
The doctor made it worse — an INVERTED check: check_deploy_checksums
Category 1 parses every register line and content-compares deployed vs repo.
Personalized memory → FAIL + "Run: cortex-update.sh to resync", which is
EXACTLY the destructive action. The broken state (blank seed) PASSED; the
healthy state (personalized) FAILED. Do NOT "fix" the doctor FAIL by resyncing —
fix the classification: user-owned files are not repo-managed files.
Fix pattern (both layers or the bug persists):
register_seed() — copy ONLY when dest is missing, in BOTH full
and delta modes. Keep seed dests out of MAP/ORCH_MAP, and cover them in
clean_stale_deploys / check_stale_deploys so they aren't flagged stale.register_seed lines as existence-only — PASS if present,
WARN if missing, NEVER content-compare a user-owned file.register line is a
LIE until the code enforces it — the false comment is how this bug hid.Topology for diagnosis: live memory = ~/.hermes/memories/MEMORY.md
(Hermes resolves get_hermes_home()/memories, default HERMES_HOME=~/.hermes).
The deploy target ~/.hermes-cortex/memories/MEMORY.md is a dead seed copy on
most hosts — live only when HERMES_HOME=$HOME/.hermes-cortex (commented
option in hermes-cortex.env.example) or ~/.hermes/memories is symlinked to
it. Check which path the host loads BEFORE diagnosing "memory wiped": a
checksum "fix" on the dead copy is a no-op; on the live copy it is data loss.
Three governance gaps found and closed by the 2026-08-08 edge-case audit (Esther, Luke: "test governance thoroughly, see the weaknesses"):
14a. Skills tracking was PROCESS-global — sessions leaked each other's loads.
_skills_loaded_in_session is one module-level set shared by every session in
the gateway process. Any session's skill_view() counted for ALL sessions:
_check_domain_skill_gate) and adversarial gate passed
because ANOTHER session had loaded the skill → on long turns agents never
loaded mid-turn domain skills; the gate passed anyway.
Fix: per-session registry _session_skills_loaded: dict[str, set], populated
in the pre_tool_call hook on skill_view, consulted by the marker auto-create
condition, domain gate, and adversarial gate. Each session must load its own
7 always-skills and its own domain skill. Tests:
TestPerSessionSkillIsolation (marker + adversarial) and
test_md_write_blocks_when_skill_loaded_by_other_session (domain gate).14b. git -c core.hooksPath=... / GIT_CONFIG_GLOBAL|SYSTEM=... bypassed the
entire hook chain. The bypass-debt regex only matched literal --no-verify.
A per-invocation -c core.hooksPath=/dev/null commit skipped EVERY hook
including post-commit-audit, so the debt counter never incremented and the
escape hatch was unbounded. Fix: the enforcer now blocks hook-override forms
outright (they are not the sanctioned escape hatch); --no-verify remains
bounded by the debt counter (3 tolerated, 4th+ mandated). Benign -c configs
(user.name, color.ui) and plain git commit/status are NOT matched.
Tests: TestGitHookBypassGate (10 override forms detected, 7 benign forms
clean).
14c. Sessions could stack unbounded PENDING cycles. end_change() only
WARNED when the task's cycle was unscored, then released the lock; begin_change()
only checked for an existing lock. Sequence begin(A) → end(A) unscored →
begin(B) succeeded, leaving A PENDING until the doctor blocked the push.
Fix (Luke: "agents close out/score before moving to a new task"):
end_change() BLOCKS releasing the lock while the task's latest cycle is
unscored (user_overrode IS NULL, decision PENDING/LOOP).begin_change() REFUSES a new task while THIS session still has unscored
PENDING cycles (hook cycles with session_id NULL are exempt).
Tests: tests/test_runtime/test_mcp_closeout.py
(TestEndChangeRequiresScoredCycle, TestBeginChangeCloseOutGate).14d. _skills_dir() resolved to a NONEXISTENT dir when HERMES_HOME is set —
the fingerprint gate was a constant in production. The gateway runs with
HERMES_HOME=/home/<user>/.hermes; _skills_dir() returned
HERMES_HOME/.hermes/skills = ~/.hermes/.hermes/skills (no such dir), so
_skills_fingerprint() hashed eight EMPTY mtimes — a constant that never
changed. Markers never went stale after deploys, so agents were never forced
to reload the always-skills mid-turn (the 2026-08-05 skills-before-task gate
was silently dead). Also, task-start lives under workflow/, which the
fingerprint candidate paths missed. Fix: _skills_dir() resolves
HERMES_HOME/skills when it exists (HERMES_HOME IS the .hermes dir), and the
candidate list includes workflow/. Regression tests: TestSkillsDirResolution
(3 env variants + fingerprint-mtime-change).
Checklist when touching these paths:
-c/plain git passreferences/memory-seed-clobber-2026-08-05.md — the memory-clobber root
cause chain (register comment lie → needs_update hash path → doctor Category 1
sweep → inverted doctor), the live-vs-seed topology, and the register_seed +
existence-only doctor fix design.
references/tz-bug-lock-purge-and-mandatory-dogfood-2026-08-05.md — the TZ
root cause with exact before/after age math, the mandatory-dogfood gate
scope corrections, and the own-task exemption design.
references/leaked-cycles-and-doctor-grep-2026-08-05.md — the leaked-cycle
enforcement design (active-lock split), the doctor-output grep trap with
exact failing/working patterns, and the repo+orch scoping recipe.
references/pre-commit-score-fail-closed-2026-08-03.md — the incident:
misread → deletion → revert → correct fail-closed fix, with exact commands.
references/macos-fail-closed-hook-2026-08-03.md — macOS portability of the
fail-closed hook: deployed-path scorer candidate, timeout→gtimeout
fallback, bash-3.2-safe construct list, deploy+verify cycle for both OSes.
scripts/test-post-commit-sentinel-matrix.sh — re-runnable 8-path matrix
(normal / --no-verify / rebase / cherry-pick / revert / merge / amend /
amend --no-verify) proving genuine bypasses still log and internal replays
stay silent. Run before shipping any sentinel-touching hook change.