From e68a520d4c47f89b26d5aaf615d9a89075387461 Mon Sep 17 00:00:00 2001 From: autonomic-bot Date: Wed, 27 May 2026 06:25:09 +0100 Subject: [PATCH] Fix watchdog false gate-ping: edge-trigger on NEW claimed-awaiting gate ids, baseline silently MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- cc-ci-plan/launch.sh | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/cc-ci-plan/launch.sh b/cc-ci-plan/launch.sh index 0957b6a..4b5c357 100755 --- a/cc-ci-plan/launch.sh +++ b/cc-ci-plan/launch.sh @@ -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