Orchestrata Ultimate › Plans › briefs › git-sentinel-split-signal
§5.2 — git_sentinel: tree snapshot is the hard signal, ref advance is advisory
Source: plans/briefs/git-sentinel-split-signal.md at 8a2cb42ad · last changed 2026-10-20 · first committed 2026-10-20 · 55 lines.
Prose pending.
Plan text
§5.2 — git_sentinel: tree snapshot is the hard signal, ref advance is advisory
Status: DISPATCH-READY · Repo: /home/mohamed/workspace/wt-COMPONENTS (branch components)
Authority: Mohamed ruling 2026-10-20 §5.2, option (a): "Tree snapshot is the hard signal; ref
advance = advisory" — a test-modified tracked file stays a hard ❌; a ref advance with an untouched
tree becomes an advisory log line. The 2026-07 incident class (a test mutating the live repo:
core.bare/fsmonitor/identity + 16 commits) MUST stay caught; only the false alarm dies.
Context (measured)
tests/plugins/git_sentinel.pysnapshots the live-repo files that change on HEAD/branch/config mutation and compares them per-test + at session end (pytest_runtest_teardown/pytest_sessionfinish); it also scrubs GIT_* env vars (wired fromtests/conftest.pyat import).- The false alarm (session 272): the plugin marked a run ❌ "A test wrote to the repository this suite runs from" while tests were 175/0 green — the ref moved because ANOTHER coordinator session committed mid-run. It cannot distinguish a test's own git write from an external committer.
- Tests:
tests/plugins/test_git_sentinel.py+tests/plugins/test_git_sentinel_untracked_root.pypin the current behavior (some will assert the OLD hard-fail-on-ref-advance semantics — repoint them to the new contract, never weaken the incident-class assertions). - Read the plugin's full "Design constraints" section BEFORE editing — it documents the sentinel file set and the per-test/session-end compare order; keep every mechanism except the one ruling.
Deliverables
- D1 — the split signal. At run start capture BOTH: (a) the tree snapshot (the sentinel's existing
file-set bytes/status) and (b) the HEAD ref. At teardown/session end:
- a test-modified tracked file (sentinel file differs) → the existing hard ❌, unchanged, naming the exact test — this is the incident class, it never softens;
- ref advance (HEAD moved) with an UNTOUCHED tree → an advisory log line naming the old and new ref (and, when determinable, the committer) — the run stays green;
- BOTH → hard ❌ (a tree mutation is a test's write regardless of who committed).
- D2 — measurement first: paste the plugin's current compare/snapshot functions and the two test files' relevant assertions BEFORE editing; then the edits. Keep the GIT_* scrub untouched.
- D3 — tests repointed: every existing assertion stays meaningful; assertions that encoded "ref advance ⇒ ❌" flip to "advisory line + green"; the incident-class assertions (sentinel file mutated ⇒ ❌, names the test) are byte-kept in substance. Add one NEW real test proving the split: commit to a real tmp repo (or move HEAD) while the sentinel's tree is untouched → advisory, exit 0.
- D4 — verification: the two plugin test files via the sanctioned runner
(
ORCHESTRATA_ENV_PROFILE=test python scripts/run_tests.py tests/plugins/test_git_sentinel.py tests/plugins/test_git_sentinel_untracked_root.py --skip-gates— paste verbatim output; use --force only if the ledger claims reuse and you can justify it) + ruff/black clean on the touched files. NEVER a full-suite run (RUL-040).
Fence
ALLOWED: tests/plugins/git_sentinel.py, tests/plugins/test_git_sentinel.py,
tests/plugins/test_git_sentinel_untracked_root.py — NOTHING else (no /tmp writes, no helper
scripts, no tests/conftest.py). FOREIGN DIRT — do not touch/stage/"fix": context.json,
context.md, context.history.md, docs/CODEBASE_MAP*.md, plans/ast-*.json,
reports/run-tests-latest.json, .claude/skills/**, .deepchat/**.
Conduct
RUL-037 (no python -c/heredoc writes; file tools only). Measure before editing; verbatim outputs;
no false attribution. Do NOT commit (the coordinator commits). The branch's dirty files above are
NOT yours. Final report ends with: git status of the three allowlist files, the before/after
snippets, the D4 lane output verbatim.