Skip to content

fix(afk): hard-cap away-mode escalation re-injection - #2390

Open
baksoy wants to merge 1 commit into
kunchenguid:mainfrom
baksoy:fm/wedge-reinject-cap
Open

fix(afk): hard-cap away-mode escalation re-injection#2390
baksoy wants to merge 1 commit into
kunchenguid:mainfrom
baksoy:fm/wedge-reinject-cap

Conversation

@baksoy

@baksoy baksoy commented Aug 14, 2026

Copy link
Copy Markdown

What

Hard-cap the away-mode sub-supervisor's escalation re-injection so a submit-confirmation false-negative degrades to a single wedge alarm instead of an all-night re-injection loop.

Why

On claude+herdr, an escalation digest can land and start a real turn while the idle composer is briefly misread as still holding text (pending). Housekeeping's per-tick batch flush then re-injected the same digest every tick indefinitely — an overnight (~10h) re-injection loop.

How

  • Re-injection is bounded per buffered content (content-addressed via md5 of the buffer): the initial flush attempt plus at most one max-defer escape flush. When that escape still cannot confirm, the existing wedge alarm fires exactly once for that content, then the daemon holds without re-injecting or re-alarming it.
  • The cap bounds retry count only — the buffered escalation stays durable in state/.subsuper-escalations for return catch-up, so nothing is lost after queue publication.
  • The cap is per buffered content, never a permanent mute: a genuinely distinct escalation re-arms and raises its own single alarm, and any positively confirmed delivery clears the cap markers so normal injection resumes.
  • Backend-independent: the cap lives in state files (.subsuper-inject-failed, .subsuper-inject-capped), not any pane surface. The only backend-specific bit (the tmux status-line flash) is unchanged.
  • The two new markers join the delivery-artifact cleanup/backup paths in fm-afk-start.sh, fm-afk-return.sh, and fm-afk-launch.sh so a stale cap cannot leak across away-mode sessions.

Tests

Two portable regression tests added to tests/fm-daemon.test.sh, asserting through the executable interface:

  • Persistent submit non-confirmation → bounded injection (≤ 2), exactly one alarm, a durable preserved buffer, and the wedge marker present.
  • Content driven to capped → a distinct escalation re-arms and a confirmed healthy flush clears all cap markers.

Docs

  • Daemon header reliability model extended.
  • New "Bounded re-injection" section in docs/wedge-alarm.md (the one authoritative owner), with the docs/configuration.md cross-reference updated to match.

Validated through the no-mistakes pipeline (rebase, review, test, document, lint all green).

A submit-confirmation false-negative (the digest lands and starts a real
turn while the idle composer is briefly misread as still holding text)
made housekeeping's per-tick batch flush re-inject the same digest every
tick indefinitely - an overnight ~10h re-injection loop.

Bound re-injection per buffered content: the initial flush attempt plus
at most one max-defer escape flush, which raises the wedge alarm exactly
once and then CAPS that content so no later tick re-injects or re-alarms
it. The cap bounds retry count only - the buffer stays durable for return
catch-up, so nothing is lost after queue publication. The cap is per
buffered content (content-addressed markers), never a permanent mute: a
distinct escalation re-arms it, and any positively confirmed delivery
clears it and resumes normal injection. Backend-independent (state files,
not any pane surface).

Cap markers join the delivery-artifact family cleared/snapshotted by the
afk enter, return, and launch paths so a stale cap cannot leak across
away-mode sessions. Adds a portable regression test driving persistent
non-confirmation, asserting bounded injection (<= 2), a single alarm, a
durable buffer, cap re-arm on new content, and marker clearing on a
confirmed flush.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant