framework: prove the wrapper guard both ways, and resolve its wrappers relatively
ci/woodpecker/pr/ci Pipeline failed

Two defects found by running the guard rather than reading it.

1. The guard resolved its sibling wrappers through a hardcoded
   $HOME/.config/mosaic/tools/git. On a host with no installed mosaic home — a
   CI container, a bare checkout — every wrapper lookup missed, `[ -x ]` failed,
   and the guard fell through allowing the raw API write it exists to block. It
   failed OPEN, silently, in exactly the environment least likely to notice.
   It now resolves relative to its own path, so it names the wrappers from the
   install it was launched from, with $HOME as the fallback.

2. There was no test. Adding one surfaced the guard's other sharp edge
   immediately: it matches the literal text of the Bash command, so a harness
   that embeds a blocked pattern inline trips the guard on itself rather than on
   the fixture. That is the correct fail-closed posture and it is now recorded in
   the test's own comments, because the next person will hit it too.

test-wrapper-guard.sh asserts twelve fixtures and asserts the ALLOWED cases as
hard as the blocked ones. A guard that over-blocks gets routed around and a guard
that under-blocks is decoration; only pinning both edges keeps it useful. It is
hermetic — no network, no credentials, no repository — so it joins the CI
sanitization step directly rather than the exclusions file.
This commit is contained in:
Hermes Agent
2026-08-12 16:54:18 -05:00
parent e3a0ee87b3
commit 96609bdade
3 changed files with 83 additions and 1 deletions
+5
View File
@@ -56,6 +56,11 @@ steps:
# and sandboxes a throwaway git repo, so it resolves no real credentials and
# joins CI directly rather than the exclusions file.
- bash packages/mosaic/framework/tools/git/test-issue-close-fail-closed.sh
# Hermetic behavioural regression for the PreToolUse wrapper guard: proves
# it still blocks the three mistakes AND still lets reads, unwrapped
# endpoints and ordinary commands through. Both directions are asserted —
# a guard that over-blocks gets routed around, which fails just as hard.
- bash packages/mosaic/framework/tools/git/test-wrapper-guard.sh
# Blocking gate (#791): a framework upgrade must never write or delete an
# operator-owned path. The HARD GATE proves an unanticipated operator sentinel