Fix watchdog false gate-ping: edge-trigger on NEW claimed-awaiting gate ids, baseline silently

The Adversary got a spurious "gate CLAIMED" ping: STATUS.md keeps historical
"Gate: Mn — CLAIMED, awaiting Adversary" lines after they PASS, and on watchdog restart the
first observation pinged on those already-passed lines. Now track the SET of gate ids on
CLAIMED-awaiting lines and ping only when an id NEWLY appears vs the prior observation, after a
silent baseline. A gate passing (line kept) or evidence edits don't re-ping; restart re-baselines
without pinging. Verified: watchdog restart no longer pings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 06:25:09 +01:00
parent 649b90b586
commit e68a520d4c

View File

@ -123,18 +123,33 @@ ping_session() {
# Edge-triggered handoff signalling: the moment one loop produces the artifact the other is
# waiting on, ping the waiting loop so it wakes immediately instead of idling out its sleep.
# Reads the loops' local working clones (same host) for the fastest signal; the pinged loop
# still pulls the real state on wake. Edge-triggered (hash compare) so it pings once per change.
_wd_last_gate=""; _wd_last_review=""
# still pulls the real state on wake.
#
# IMPORTANT: STATUS.md keeps *historical* gate lines ("Gate: Mn — CLAIMED, awaiting Adversary")
# even after they PASS (the Builder appends "→ Mn PASS"). So we cannot ping on the mere presence
# of "CLAIMED". We track the set of gates that are **claimed-and-awaiting but NOT yet PASS** (by
# gate id), and ping the Adversary ONLY when a gate *newly enters* that set — never on the
# watchdog's first observation (baseline), never when a line is merely edited or marked PASS.
_wd_awaiting="" # current set of unverified-claimed gate ids (newline-separated)
_wd_baselined="" # set once the first observation has established a baseline (no ping then)
_wd_last_review=""
handoff_check() {
local sf="$BUILDER_DIR/STATUS.md" rf="$ADV_DIR/REVIEW.md" cur
# Builder -> Adversary: a milestone gate is CLAIMED and awaiting verification.
local sf="$BUILDER_DIR/STATUS.md" rf="$ADV_DIR/REVIEW.md" cur now added
# Builder -> Adversary: a gate newly CLAIMED & awaiting verification (and not already PASS).
if [[ -f "$sf" ]]; then
cur="$(grep -iE 'Gate:.*CLAIMED' "$sf" 2>/dev/null | sort -u | md5sum | awk '{print $1}')"
if grep -qiE 'Gate:.*CLAIMED' "$sf" 2>/dev/null && [[ "$cur" != "$_wd_last_gate" ]]; then
log "handoff: Builder CLAIMED a gate -> pinging Adversary"
ping_session "$ADV_SESSION" "watchdog ping: the Builder has CLAIMED a milestone gate in STATUS.md and is awaiting your verification. Pull and verify it now — don't idle."
# gate ids appearing on any "CLAIMED … awaiting" line. We ping only when an id NEWLY appears
# vs the previous observation, so: a new claim pings; a gate passing (its line is kept, not
# removed) does not re-ping; editing evidence does not ping; watchdog restart re-baselines silently.
now="$(grep -iE 'CLAIMED.*awaiting' "$sf" 2>/dev/null \
| grep -oiE 'M[0-9]+(\.[0-9]+)?' | tr '[:lower:]' '[:upper:]' | sort -u)"
if [[ -n "$_wd_baselined" ]]; then
added="$(comm -13 <(printf '%s\n' "$_wd_awaiting" | sort -u) <(printf '%s\n' "$now" | sort -u) | grep -vE '^$' || true)"
if [[ -n "$added" ]]; then
log "handoff: gate(s) newly awaiting verification: $(echo $added) -> pinging Adversary"
ping_session "$ADV_SESSION" "watchdog ping: the Builder has CLAIMED milestone gate(s) [$(echo $added)] in STATUS.md and is awaiting your verification. Pull and verify now."
fi
fi
_wd_last_gate="$cur"
_wd_awaiting="$now"; _wd_baselined=1
fi
# Adversary -> Builder: REVIEW.md changed (a verdict/PASS/FAIL or a new finding).
if [[ -f "$rf" ]]; then
@ -142,7 +157,7 @@ handoff_check() {
if [[ -n "$cur" && "$cur" != "$_wd_last_review" ]]; then
[[ -n "$_wd_last_review" ]] && {
log "handoff: REVIEW.md changed -> pinging Builder"
ping_session "$BUILDER_SESSION" "watchdog ping: the Adversary updated REVIEW.md (a verdict or finding). Pull and act now — if it PASSes your gate, proceed; if it's a finding, address it. Don't idle."
ping_session "$BUILDER_SESSION" "watchdog ping: the Adversary updated REVIEW.md (a verdict or finding). Pull and act now — if it PASSes your gate, proceed; if it's a finding, address it."
}
_wd_last_review="$cur"
fi