fix: red-team review fixes (9 findings, 2 critical)

Red team reviewed what four specialists missed — cross-cutting and
self-contradiction class:

CRITICAL: the release-body banner tripwire failed OPEN on the exact leak it
guards (grep -c prints 0 AND exits 1 on no-match, so a fallback echo
double-emitted "0" twice and the -gt comparison fell into the clean branch) —
counts now default via parameter expansion, and a functional drift test
executes the rendered tripwire block against a 0->1 banner delta to prove the
ABORT branch fires. CRITICAL: evidence fingerprints were captured AFTER the
child exited, so a working-tree edit made DURING a long suite was certified as
tested content — wtree is now captured before spawn and re-checked after;
mid-run drift omits the fingerprint (grades STALE) with a warning.

Also: the review-grading rule dropped its dirty-gates (they nullified the
keystone dirty-record->commit->CURRENT property that evidence checks already
honor — wtree equality alone proves identical content); careful's HIGH
force-push tier falls back to probing origin/main|master when the origin/HEAD
symbolic ref is absent (Conductor worktrees — the tier was silently inert in
the primary deploy environment); quoted tokens (rm -rf "/", push "main") no
longer dodge the deny; freeze fails CLOSED when its own helper file is missing
(bash makes a missing source target fatal non-interactively, so an existence
pre-check guards it); spec dedupe distinguishes pipeline failure from zero
matches instead of silently skipping dedupe on gh/jq breakage; land 3.5b sets
the cross-session --expect-cmd mismatch expectation; hook analytics JSON
fields are encoder-built per this wave's own rule.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-08-16 08:35:56 -07:00
co-authored by Claude Fable 5
parent a171029e6b
commit 5d6804cb61
23 changed files with 212 additions and 39 deletions
+8 -1
View File
@@ -70,5 +70,12 @@ gstack_hook_decision() {
gstack_hook_log_fire() {
_ghlf_dir="${GSTACK_HOME:-$HOME/.gstack}/analytics"
mkdir -p "$_ghlf_dir" 2>/dev/null || true
echo '{"event":"hook_fire","skill":"'"$1"'","pattern":"'"$2"'","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || echo "unknown")'"}' >> "$_ghlf_dir/skill-usage.jsonl" 2>/dev/null || true
# Fields are JSON-encoded (a repo basename can carry quotes/backslashes) —
# same rule this file states for decisions: never raw-interpolate into JSON.
_ghlf_repo=$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || echo "unknown")
printf '{"event":"hook_fire","skill":%s,"pattern":%s,"ts":"%s","repo":%s}\n' \
"$(gstack_hook_json_string "$1")" \
"$(gstack_hook_json_string "$2")" \
"$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
"$(gstack_hook_json_string "$_ghlf_repo")" >> "$_ghlf_dir/skill-usage.jsonl" 2>/dev/null || true
}