From 06b243d8eb7ca7ec9960f27368cd54baf73e6d31 Mon Sep 17 00:00:00 2001 From: burakgizlice Date: Wed, 29 Jul 2026 12:42:40 +0300 Subject: [PATCH] fix(herdr): add blocked-transition confirm delay to suppress transient OpenCode false alarms Herdr's agent-status change events can report 'blocked' when the OpenCode TUI briefly shows an input prompt between tool calls. The agent is actually working - it has just finished one tool call and is about to start the next - but the transient 'blocked' edge was treated as actionable immediately, producing a firehose of stale wake notifications. The existing per-pane dedupe marker prevents re-escalating the same blocked edge, but OpenCode cycles through working -> blocked -> working -> blocked on every tool call, so each new blocked transition is a fresh edge that re-escalates. Fix: add a re-check step in fm_backend_herdr_apply_transition. When a blocked transition arrives, wait 3 seconds (FM_BACKEND_HERDR_BLOCKED_CONFIRM_DELAY), then re-query the live agent status via herdr's agent.get API. If the agent has already resumed 'working' (or gone 'idle'/'done'), absorb the transition silently. If the agent is still 'blocked', escalate as before. This also handles long-running commands (e.g. 'sleep 600') correctly: herdr reports 'working' during command execution, so no blocked transition is emitted in the first place. A real wedge (permission dialog, stuck prompt, interactive menu) persists far longer than the 3-second delay, so genuine escalations are only delayed by 3 seconds. Also adds a git-identity rule to the crewmate brief scaffold (fm-brief.sh rule 8) so workers never invent an agent identity for commits. They must use the global git config (user.name/user.email) instead. --- bin/backends/herdr.sh | 31 ++++++++++++++++++++++++++++++- bin/fm-brief.sh | 8 ++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/bin/backends/herdr.sh b/bin/backends/herdr.sh index 3a28daaa33..193cb054a3 100644 --- a/bin/backends/herdr.sh +++ b/bin/backends/herdr.sh @@ -2189,6 +2189,16 @@ fm_backend_herdr_busy_state() { # FM_BACKEND_HERDR_SUBMIT_POLLS=${FM_BACKEND_HERDR_SUBMIT_POLLS:-6} FM_BACKEND_HERDR_SUBMIT_MIN_SLEEP=${FM_BACKEND_HERDR_SUBMIT_MIN_SLEEP:-0.6} +# FM_BACKEND_HERDR_BLOCKED_CONFIRM_DELAY (default 3): seconds to wait before +# re-checking a `blocked` transition. herdr can emit transient `blocked` events +# when the OpenCode TUI shows a brief input prompt between tool calls; the +# re-check queries the live agent status and absorbs the transition if the +# agent has already resumed `working`. This also covers long-running commands +# (e.g. `sleep 600`) where herdr correctly reports `working` during execution. +# A real wedge (permission dialog, stuck prompt) persists far longer than this +# delay, so genuine escalations are only delayed by this many seconds. +FM_BACKEND_HERDR_BLOCKED_CONFIRM_DELAY=${FM_BACKEND_HERDR_BLOCKED_CONFIRM_DELAY:-3} + fm_backend_herdr_submit_confirm_budget() { # awk -v b="${1:-0}" -v m="$FM_BACKEND_HERDR_SUBMIT_MIN_SLEEP" 'BEGIN { b += 0 @@ -2383,7 +2393,7 @@ fm_backend_herdr_escalation_marker() { # # with no output. reconstructs the window (":") for # the marker key, matching the watcher's own key scheme. fm_backend_herdr_apply_transition() { # - local state=$1 session=$2 record=$3 pane_id to action window marker + local state=$1 session=$2 record=$3 pane_id to action window marker current_status pane_id=$(fm_transition_pane_id "$record") [ -n "$pane_id" ] || return 1 to=$(fm_transition_to_status "$record") @@ -2393,6 +2403,25 @@ fm_backend_herdr_apply_transition() { # case "$action" in actionable) if [ ! -e "$marker" ]; then + # Re-check: herdr can emit transient `blocked` transitions when the + # OpenCode TUI shows a brief input prompt between tool calls. Wait a + # short time, then re-query the live agent status. If the agent has + # already resumed `working` (or gone `idle`/`done`), absorb the + # transition instead of escalating a false alarm. This also covers + # long-running commands (e.g. `sleep 600`) where herdr reports + # `working` during command execution. A real wedge (permission dialog, + # stuck prompt) persists far longer than the confirm delay, so genuine + # escalations are only delayed by that many seconds. + # Set FM_BACKEND_HERDR_BLOCKED_CONFIRM_DELAY=0 to skip the re-check + # (used by tests that lack a live herdr server). + if [ "${FM_BACKEND_HERDR_BLOCKED_CONFIRM_DELAY:-3}" != "0" ]; then + sleep "$FM_BACKEND_HERDR_BLOCKED_CONFIRM_DELAY" + current_status=$(fm_backend_herdr_agent_status_raw "$session" "$pane_id") + if [ -n "$current_status" ] && [ "$current_status" != "blocked" ]; then + command -v triage_log >/dev/null 2>&1 && triage_log "absorbed transient blocked transition (agent now $current_status): $window" + return 1 + fi + fi printf '%s' "$record" return 0 fi diff --git a/bin/fm-brief.sh b/bin/fm-brief.sh index 00ea34ddab..87912aa4ee 100755 --- a/bin/fm-brief.sh +++ b/bin/fm-brief.sh @@ -262,6 +262,10 @@ The report is the only thing that survives, so anything worth keeping must be in 7. Never stop, restart, or update the shared \`no-mistakes\` daemon - it is one instance serving every lane/home, so restarting it kills other lanes' in-flight pipeline runs. On ANY no-mistakes daemon error, append \`blocked: {the daemon error}\` and stop; only firstmate manages the daemon. +8. Use the existing global git identity for every commit. Never set \`user.name\`, \`user.email\`, + \`GIT_AUTHOR_NAME\`, \`GIT_AUTHOR_EMAIL\`, \`GIT_COMMITTER_NAME\`, or \`GIT_COMMITTER_EMAIL\` + to invent an agent identity. The captain's global git config already has the correct author; + do not override it. # Definition of done Write your findings to \`$DATA/$ID/report.md\`. @@ -374,6 +378,10 @@ $RULE1 7. Never stop, restart, or update the shared \`no-mistakes\` daemon - it is one instance serving every lane/home, so restarting it kills other lanes' in-flight pipeline runs. On ANY no-mistakes daemon error, append \`blocked: {the daemon error}\` and stop; only firstmate manages the daemon. +8. Use the existing global git identity for every commit. Never set \`user.name\`, \`user.email\`, + \`GIT_AUTHOR_NAME\`, \`GIT_AUTHOR_EMAIL\`, \`GIT_COMMITTER_NAME\`, or \`GIT_COMMITTER_EMAIL\` + to invent an agent identity. The captain's global git config already has the correct author; + do not override it. # Project memory If \`AGENTS.md\` or \`CLAUDE.md\` already exists, or if this task produced durable project-intrinsic knowledge, run \`$FM_ROOT/bin/fm-ensure-agents-md.sh .\` in the worktree.