Skip to content
This repository was archived by the owner on Aug 25, 2026. It is now read-only.

fix(herdr): adopt upstream reliability while preserving fork contracts - #77

Merged
JTInventory merged 28 commits into
mainfrom
fm/firstmate-herdr-upstream-adopt-0725
Jul 26, 2026
Merged

JTInventory merged 28 commits into
mainfrom
fm/firstmate-herdr-upstream-adopt-0725

Conversation

@JTInventory

Copy link
Copy Markdown
Owner

Intent

Adopt owner kunchenguid/firstmate Herdr reliability onto JTInventory/firstmate from fork/main while keeping Herdr as the backend and preserving JT readable tab labels and exact lifecycle identity. Include stale projection cleanup at session start, restart reclaim, parent grouping, optional presentation ordering and focus preservation, composer/send reliability, AFK hardening already on the path, and pinned real-Herdr CI coverage. Do not change the captain's local config/backend, dirty primary skills tree, OpenClaw or PR 475, and do not merge.

What Changed

  • Adopt upstream Herdr reliability for session cleanup, restart reclaim, parent grouping, optional presentation ordering, and focus preservation while retaining readable JT labels and exact lifecycle identity.
  • Harden Herdr spawning, teardown, configuration inheritance, AFK supervision, and composer submission against stale, busy, partial, and uncertain states.
  • Add pinned real-Herdr CI coverage, isolated test runners, lifecycle tests, and updated operator documentation.

Risk Assessment

⚠️ Medium: The final race fix is clean and intent-conformant, but the overall branch remains a broad Herdr lifecycle and CI adoption whose runtime confidence depends on the dedicated test stage.

Testing

The supplied baseline, read-only Herdr 0.7.4/protocol 16 smoke, real presentation and stale-cleanup lifecycle E2E, and full isolated behavior suite all passed; initial gate-worktree refusals were resolved using the supported test runner, no source changes or transient worktree artifacts remained, and no screenshot was produced because the end-user surface is terminal/Herdr lifecycle behavior represented by CLI transcripts.

Evidence: Herdr intent E2E summary

Concise reviewer-facing proof covering flat spawn, projection ordering, focus, restart reclaim, stale cleanup, composer/send, AFK, labels, and pinned CI.

ok - AFK daemon survives harness process-group reap and stops on return
ok - AFK launch fails closed when the durable away flag cannot be created
ok - AFK launch is idempotent and return clears the away flag
ok - AFK launch forwards the resolved Herdr supervisor target and backend
ok - AFK refresh fails closed when the durable away flag cannot be written
ok - AFK return retains the away flag when identity verification fails
ok - AFK return retains the away flag when a live daemon record is missing
ok - AFK return retains the away flag when a stale daemon record remains live
ok - AFK status keeps a live unverified daemon visible
ok - AFK return fails closed when the durable away flag cannot be removed
ok - AFK transition lock rejects an invalid state path promptly
ok - AFK transition lock distinguishes I/O failure from contention
ok - AFK transition lock handoff preserves contention return code
ok - AFK transition lock bounds contention retries
ok - AFK transition lock preserves a replacement daemon and away flag
ok - AFK return clears the away flag after confirmed daemon absence
ok - AFK return retains the away flag when TERM does not stop the daemon
ok - real Herdr lab: flag-off spawn retains the Stage 1 Herdr command sequence with zero ordering calls
ok - real Herdr lab: every projected create, task-tab create, seeded prune, and move preserves active workspace and tab
ok - real Herdr lab: bounded lock contention warns and falls back flat without projection or focus drift
ok - real Herdr lab: concurrent primary workers form one stable contiguous block without active workspace/tab drift
ok - real Herdr lab: primary and two secondmate homes each own a top-level contiguous child block
ok - real Herdr lab: concurrent primary/A/B spawns preserve parent order and exact focus
ok - real Herdr lab: Hi Bit and Wheelhouse-style same-identity restarts reclaim one nested space with exact focus and idempotence
ok - real Herdr lab: secondmate restart binding and reclaim stay isolated to the exact child home and parent
ok - real Herdr lab: concurrent cross-home recoveries replace exact husks under one session lock with no focus drift
ok - real Herdr lab: multi-home exact-pane teardowns restore captain focus without workspace close authority
ok - real Herdr lab: missing, renamed, and duplicate tokens trigger zero destructive or adoptive calls, and live duplicate risk refuses launch
ok - fm_backend_herdr_composer_state: a bare '❯' composer row reads empty
ok - fm_backend_herdr_composer_state: the ghost placeholder text reads empty, not pending
ok - fm_backend_herdr_composer_state: real composer text reads pending
ok - fm_backend_herdr_composer_state: a slash-command popup's argument-hint placeholder still reads pending (the incident fix)
ok - fm_backend_herdr_composer_state: reports unknown when the pane cannot be captured
ok - fm_backend_herdr_composer_state: reports unknown for bare shell prompts with no composer row
ok - fm_backend_herdr_composer_state: a native idle Pi separator composer reads empty
ok - fm_backend_herdr_composer_state: real Pi composer text remains pending
ok - fm_backend_herdr_composer_state: an incomplete lower Pi separator cannot inherit a stale empty row
ok - fm_backend_herdr_composer_state: Pi separators never authorize working, non-Pi, unreadable, or over-tall targets
ok - fm_backend_herdr_composer_state: a real-claude unbordered '❯' prompt row (no border box in view) reads empty
ok - fm_backend_herdr_composer_state: a real-claude unbordered '❯ <text>' prompt row reads pending
ok - fm_backend_herdr_composer_state: a live unbordered prompt row below a stale bordered decorative box still wins (not misread as the box's own row)
ok - fm_backend_herdr_composer_state: claude's dim prompt-suggestion ghost (the overnight wedge shape) reads empty
ok - fm_backend_herdr_composer_state: real typed text on the same claude prompt row still reads pending
ok - fm_backend_herdr_composer_state: grok's dark-truecolor placeholder (the TRUECOLOR gap) reads empty
ok - fm_backend_herdr_composer_state: grok's real bright typed input still reads pending
ok - fm_backend_herdr_composer_state: a real-codex unbordered '›' prompt row reads empty
ok - fm_backend_herdr_composer_state: a faint real-codex ghost suggestion reads empty
ok - fm_backend_herdr_composer_state: non-faint codex prompt text still reads pending
ok - fm_backend_herdr_send_text_submit: applies the herdr minimum confirmation budget before polling agent-state
ok - fm_backend_herdr_send_text_submit: reports 'empty' once agent_status reports working after one Enter, without ever reading the composer
ok - fm_backend_herdr_send_text_submit: reports 'pending' when agent_status never reports working after retried Enters (swallowed)
ok - fm_backend_herdr_send_text_submit: a slash-command popup's placeholder fill on Enter #1 never flips agent_status to working, so it does not short-circuit as submitted; Enter #2 is retried and lands it
ok - fm_backend_herdr_send_text_submit: a post-Enter blocked state confirms delivery without retrying into the prompt
ok - fm_backend_herdr_send_text_submit: preexisting busy plus pending composer confirms accepted queue delivery
ok - fm_backend_herdr_send_text_submit: busy autocomplete retries before accepting exact queued text
ok - fm_backend_herdr_send_text_submit: idle pending text is never acknowledged as sent
ok - fm_backend_herdr_send_text_submit: failed Enter transport is never accepted as queued
ok - fm_backend_herdr_send_text_submit: confirms submission via native agent-state alone, immune to a codex-style dynamic idle-tip composer that would have misread as 'pending' under the old composer-based confirmation
ok - fm_backend_herdr_composer_state: a faint real-codex dynamic idle-tip composer row reads empty
ok - fm_backend_herdr_send_text_submit: a slow transition landing on a later sample within one Enter's budget is confirmed WITHOUT sending a needless extra Enter
ok - fm_backend_herdr_send_text_submit: reports 'send-failed' when the literal send-text call itself errors
ok - fm_backend_herdr_send_text_submit: reports 'unknown' when the post-Enter agent-get read fails (never retries past an unreadable target)
ok - fm_backend_herdr_send_text_submit: unknown baseline verifies composer and retries autocomplete safely
ok - fm_backend_herdr_send_text_submit: pending unknown state never retries Enter
ok - fm_backend_herdr_submit_enter: idle swallowed text is never falsely acknowledged
ok - fm_backend_herdr_submit_enter: failed final Enter is never acknowledged
ok - fm_backend_herdr_submit_enter: mismatched and unreadable composer content is never submitted
ok - fm_backend_herdr_submit_enter: an idle empty composer is unconfirmed and never submitted
ok - fm_backend_herdr_submit_enter: empty composer needs submit-active proof
ok - fm_backend_herdr_submit_enter: pending text requires current idle proof
ok - fm_backend_herdr_submit_enter: unreadable final confirmation is never promoted to success
ok - AFK nonterminal working:+merged keeps wedge aging and re-escalates at bound
ok - real named lab reproduced the exact restored one-tab one-pane childless no-agent shell shape
ok - real named lab cleanup closes only the exact stale pane and preserves exact focus
ok - real named lab cleanup is idempotent and leaves the default fleet session to the teardown tripwire
evidence: herdr=0.7.4 protocol=16 default-session-tripwire=armed
ok - Herdr installer pins exact version, asset, checksum, and protocol floor
ok - CI wires pinned installers into a required serial Herdr lane
ok - task labels: ship/crew, scout, and secondmate map to Crew, Scout, and 2nd
All 79 behavior tests passed
Evidence: Full behavior suite

Complete transcript from the supported isolated behavior runner, including real Herdr presentation and cleanup E2E.

ok: PR target repo jtinventory/firstmate verified
tmux 3.4
ok - gate refusal helper covers marker, empty marker, path backstop, and normal session
ok - spawn, send, and teardown refuse both gate signals before lifecycle work
ok - tracked gate-refusal wiring and trusted no-mistakes config are present
# all fm-gate-refuse tests passed
Running 79 behavior tests with 4 parallel job(s)
START: tests/fm-afk-inject-e2e.test.sh (TMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-afk-inject-e2e/tmp GOTMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-afk-inject-e2e/gotmp)
START: tests/fm-afk-inject-herdr-e2e.test.sh (TMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-afk-inject-herdr-e2e/tmp GOTMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-afk-inject-herdr-e2e/gotmp)
START: tests/fm-afk-launch.test.sh (TMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-afk-launch/tmp GOTMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-afk-launch/gotmp)
START: tests/fm-backend-herdr-presentation-e2e.test.sh (TMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-backend-herdr-presentation-e2e/tmp GOTMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-backend-herdr-presentation-e2e/gotmp)
PASS: tests/fm-afk-inject-e2e.test.sh
ok - Scenario A: partial input defers injection; digest arrives clean after idle
ok - Scenario B: swallowed Enter produces exactly one clean digest
ok - Scenario C: a normal captain status injects exactly one clean single-line sentinel digest
all e2e injection tests passed
PASS: tests/fm-afk-inject-herdr-e2e.test.sh
skip: set FM_HERDR_SMOKE=1 to opt into the real Herdr AFK e2e
PASS: tests/fm-afk-launch.test.sh
ok - AFK daemon survives harness process-group reap and stops on return
ok - AFK launch fails closed when the durable away flag cannot be created
ok - AFK launch is idempotent and return clears the away flag
ok - AFK launch forwards the resolved Herdr supervisor target and backend
ok - AFK refresh fails closed when the durable away flag cannot be written
ok - AFK return retains the away flag when identity verification fails
ok - AFK return retains the away flag when a live daemon record is missing
ok - AFK return retains the away flag when a stale daemon record remains live
ok - AFK status keeps a live unverified daemon visible
ok - AFK return fails closed when the durable away flag cannot be removed
ok - AFK transition lock rejects an invalid state path promptly
ok - AFK transition lock distinguishes I/O failure from contention
ok - AFK transition lock handoff preserves contention return code
ok - AFK transition lock bounds contention retries
ok - AFK transition lock preserves a replacement daemon and away flag
ok - AFK return clears the away flag after confirmed daemon absence
ok - AFK return retains the away flag when TERM does not stop the daemon
all fm-afk-launch tests passed
PASS: tests/fm-backend-herdr-presentation-e2e.test.sh
ok - real Herdr lab: flag-off spawn retains the Stage 1 Herdr command sequence with zero ordering calls
ok - real Herdr lab: every projected create, task-tab create, seeded prune, and move preserves active workspace and tab
warning: herdr presentation cleanup could not verify the exact pane; refusing focus-unsafe pane close
ok - real Herdr lab: active seeded-tab pruning refuses the exact pane and preserves exact focus
ok - real Herdr lab: bounded lock contention warns and falls back flat without projection or focus drift
ok - real Herdr lab: concurrent primary workers form one stable contiguous block without active workspace/tab drift
ok - real Herdr lab: forced workspace.move failure leaves a successful worker in default order with a warning and no cleanup
ok - real Herdr lab: concurrent post-create abort cleanup stays serialized with exact focus restoration
ok - real Herdr lab: Treehouse commands and metadata shape are byte-identical except for Herdr container IDs
ok - real Herdr lab: exact task-pane close restores the exact captain workspace/tab after Herdr's raw focus steal
ok - real Herdr lab: concurrent projected cleanup is serialized and leaves active workspace/tab unchanged
ok - real Herdr lab: three repeated concurrent create/order/cleanup waves have zero active workspace or tab drift
ok - real Herdr lab: primary presentation opt-in inherits into real secondmate homes
ok - real Herdr lab: primary and two secondmate homes each own a top-level contiguous child block
ok - real Herdr lab: concurrent primary/A/B spawns preserve parent order and exact focus
ok - real Herdr lab: session lock contention from a secondmate home falls back flat with no journal
ok - real Herdr lab: Hi Bit and Wheelhouse-style same-identity restarts reclaim one nested space with exact focus and idempotence
ok - real Herdr lab: secondmate restart binding and reclaim stay isolated to the exact child home and parent
ok - real Herdr lab: concurrent cross-home recoveries replace exact husks under one session lock with no focus drift
ok - real Herdr lab: legacy projection labels and flat secondmate tabs are left unmigrated
ok - real Herdr lab: multi-home exact-pane teardowns restore captain focus without workspace close authority
warning: no exact herdr presentation token match for missing1; leaving any stale space untouched and spawning flat
warning: no exact herdr presentation token match for renamed1; leaving any stale space untouched and spawning flat
warning: 2 exact herdr presentation token matches for duplicate1 are quarantined; inspecting only for duplicate-agent risk
warning: quarantined herdr presentation for duplicate1 is dead or agent-free; exact bound reclaim may proceed, otherwise spawning flat
warning: 2 exact herdr presentation token matches for duplicate1 are quarantined; inspecting only for duplicate-agent risk
error: quarantined herdr presentation for duplicate1 has a live pane; refusing duplicate launch
ok - real Herdr lab: missing, renamed, and duplicate tokens trigger zero destructive or adoptive calls, and live duplicate risk refuses launch
ok - real Herdr lab validation completed on Herdr 0.7.4 with the default-session tripwire intact
START: tests/fm-backend-herdr-prune-safety-e2e.test.sh (TMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-backend-herdr-prune-safety-e2e/tmp GOTMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-backend-herdr-prune-safety-e2e/gotmp)
START: tests/fm-backend-herdr-respawn-idem-e2e.test.sh (TMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-backend-herdr-respawn-idem-e2e/tmp GOTMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-backend-herdr-respawn-idem-e2e/gotmp)
START: tests/fm-backend-herdr-smoke.test.sh (TMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-backend-herdr-smoke/tmp GOTMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-backend-herdr-smoke/gotmp)
START: tests/fm-backend-herdr-workspace-per-home-e2e.test.sh (TMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-backend-herdr-workspace-per-home-e2e/tmp GOTMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhyt0/fm-backend-herdr-workspace-per-home-e2e/gotmp)
PASS: tests/fm-backend-herdr-prune-safety-e2e.test.sh
skip: set FM_HERDR_E2E=1 to run the real prune-safety Herdr lab e2e
PASS: tests/fm-backend-herdr-respawn-idem-e2e.test.sh
skip: set FM_HERDR_E2E=1 to run the real respawn-idempotency Herdr lab e2e
PASS: tests/fm-backend-herdr-smoke.test.sh
skip: set FM_HERDR_SMOKE=1 to opt into the real Herdr smoke
PASS: tests/fm-backend-herdr-workspace-per-home-e2e.test.sh
skip: set FM_HERDR_E2E=1 to run the real workspace-per-home Herdr lab e2e
START: tests/fm-backend-herdr.test.sh (TMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G/fm-behavior-tests.Mlhy

... [82902 bytes truncated] ...


ok - a stale pane sitting on a terminal status is surfaced (queue + exit)
ok - declared pause is absorbed, re-surfaces once after cadence, throttles duplicates, then clears on resume
ok - paused+parked run is absorbed as an external wait, not a wedge
ok - provably-working non-terminal stale is absorbed on first sight, then wedge-escalated past the threshold
ok - a not-provably-working non-terminal stale is surfaced immediately (never left to wait out the timer)
ok - matching non-terminal stale suppressors repair missing or corrupt stale-since timers
ok - triage log capping handles wc byte counts with leading spaces
ok - a heartbeat with no captain-relevant change is absorbed and backs off the cadence
ok - heartbeat backstop fail-safe surfaces a captain-relevant status the per-wake path missed
ok - the liveness beacon stays fresh while the watcher absorbs benign wakes (fm-guard never false-alarms)
ok - with .afk present the watcher reverts to one-shot so the daemon owns triage (no double-triage)
PASS: tests/fm-watcher-lock.test.sh
ok - simultaneous watcher starts leave exactly one live process
ok - killed watcher stale lock is reclaimed
ok - live watcher lock with stale heartbeat is actionable
ok - guard banner leads when down with pending wakes (re-arm-after-drain) and stays silent when fresh+live
ok - concurrent fm_lock_try_acquire yields exactly one winner
ok - dead-pid stale lock is reclaimed by a single acquirer
ok - concurrent stale-lock steal yields exactly one winner
ok - live steal mutex is not reclaimed
ok - live-held lock is not stolen
ok - live-held lock with matching pid identity is not stolen
ok - live-held lock with mismatched pid identity is reclaimed
ok - live-held legacy identity remains protected during migration
ok - expired live-held legacy identity is reclaimed
ok - matching expired legacy watcher identity is migrated before expiry recovery
ok - live-held lock without pid identity remains live-held
ok - zombie follower lock is reclaimed using its stored process identity
ok - legacy zombie follower lock is reclaimed without new metadata
ok - fallback process identity includes stable process-group and command data
ok - fallback start identity accepts and distinguishes prior formats
ok - detach cleanup rejects legacy start tokens
ok - detached spawn waits for the target after exec
ok - detached spawn cleans the launcher after pid-file timeout
ok - detached spawn cleans the target after exec timeout
ok - legacy follower locks without home scope fail closed
ok - watcher health rejects a zombie lock owner
ok - watcher health rejects an unpinned legacy lock
ok - empty mid-acquire lock keeps a minimum grace
ok - late original claimant cannot claim a recreated lock
ok - paused mid-acquire claimant backs off to active stealer
ok - watch restart refuses to signal a reused pid
ok - plain arm recovers from a reused-pid stale watcher lock
ok - watcher self-evicts when the lock pid no longer names it
ok - arm attaches to a live fresh watcher and exits only when that cycle ends
ok - arm migrates and attaches to a live legacy watcher lock
ok - arm rejects an unverified legacy watcher lock
ok - arm starts+confirms a fresh watcher on a clean lock and self-heals a dead-pid lock (never healthy off a dead pid)
ok - arm stands down on HUP while the detached watcher keeps its lock and beacon
ok - watcher survives SIGTERM of the arm's entire process group
ok - a healthy cycle keeps one attach waiter and duplicate arms exit without stacking
ok - restart hands off the follower slot without stacking waiters
ok - process start identity distinguishes same-second processes
ok - arm propagates an immediate watcher wake before confirmation
ok - arm attaches to a peer watcher after child stands down and exits when peer dies
ok - arm reports FAILED and exits non-zero when no fresh watcher can be confirmed
PASS: tests/fm-x-mode.test.sh
ok - fm-x-poll is a hard no-op without a token (inert default)
ok - fm-x-poll treats an explicitly empty env token as configured
ok - fm-x-poll stays silent on HTTP 204 (the common case)
ok - fm-x-poll lets an explicitly empty relay env override .env
ok - fm-x-poll surfaces auth/config errors once and clears on recovery
ok - fm-x-poll stashes the question and prints the compact marker
ok - fm-x-poll preserves in_reply_to conversation context in the inbox
ok - fm-x-poll reports inbox commit failures without emitting a mention wake
ok - fm-x-poll requires a non-empty question before waking
ok - fm-x-poll rejects an unsafe request_id (path-traversal guard)
ok - fm-x-reply posts a request-bound answer and echoes only the request_id
ok - fm-x-reply accepts the reply via --text-file and stdin (safe, unexpanded)
ok - fm-x-reply exits non-zero on a non-2xx relay response
ok - fm-x-reply cleans up auth header temp files on interrupted posts
ok - fm-x-reply rejects missing arguments with a usage error
ok - fm-x-reply --help makes image support discoverable
ok - fm-x-reply rejects whitespace-only reply text
ok - fm-x-reply dry-run records the would-be reply and never posts
ok - fm-x-reply dry-run works without a token
ok - fm-x-reply honors FMX_DRY_RUN from .env
ok - fm-x-reply lets an explicitly empty dry-run env override .env
ok - fm-x-reply dry-run fails when it cannot record the preview
ok - fmx_split_thread: word-boundary, within-limit, numbered, lossless, capped
ok - fm-x-reply keeps a concise reply as a single unnumbered tweet
ok - fm-x-reply auto-splits a long reply into a numbered thread (texts[])
ok - fm-x-reply clamps a below-floor max to 50 characters
ok - fm-x-reply posts a thread payload (texts[]) to the relay
ok - fm-x-reply --image posts an image object on answer
ok - fm-x-reply streams large image payloads outside curl argv
ok - fm-x-reply dry-run records compact image metadata for threaded replies
ok - fm-x-reply cleans image and payload temp files
ok - fm-x-reply --image rejects missing and unsupported image paths clearly
ok - fm-x-reply --image rejects oversized files before encoding
ok - fm-x-reply --followup posts to /connector/followup with the same request-bound body
ok - fm-x-reply --followup --image posts an image object
ok - fm-x-reply --followup is accepted in any position and leaves the answer path default
ok - fm-x-reply --followup dry-run marks the endpoint without changing the answer path
ok - fm-x-reply --followup auto-splits a long follow-up into a marked thread
ok - fm-x-reply followup dry-run keeps endpoint marker and compact image metadata
ok - fm-x-dismiss posts a request-bound dismiss and echoes only the request_id
ok - fm-x-dismiss dry-run records the would-be body and never posts
ok - fm-x-dismiss dry-run works without a token
ok - fm-x-dismiss exits non-zero on a non-2xx relay response
ok - fm-x-dismiss exits non-zero on a transport failure
ok - fm-x-dismiss rejects an unsafe request_id (path-traversal guard)
ok - fm-x-dismiss rejects missing or extra arguments with a usage error
ok - fm-x-link records and refreshes the X-request link without disturbing meta
ok - meta rewrites are independent of TMPDIR
ok - fm-x-link rejects unsafe ids, missing meta, and missing arguments
ok - fm-x-followup --check reports postable / not-linked correctly
ok - fm-x-followup --check prunes a link past the 24h window
ok - fm-x-followup posts the follow-up and clears the link on success
ok - fm-x-followup --image forwards the attachment through fm-x-reply --followup
ok - fm-x-followup keeps the link when the post fails
ok - fm-x-followup skips silently and clears the link past the 24h window
ok - fm-x-followup is a no-op for a task with no X link
ok - fm-x-followup dry-run records the follow-up and clears the link
ok - fm-x-followup rejects malformed invocations
ok - bootstrap activates X mode from an .env token, idempotently
ok - bootstrap reports missing X-mode dependencies before arming
ok - bootstrap does not report X mode on when activation artifacts cannot be written
ok - bootstrap is inert without a non-empty .env token (non-X users unaffected)
ok - bootstrap cleans up X artifacts on opt-out and is silent once off
ok - bootstrap reports failed X artifact cleanup on opt-out
All 79 behavior tests passed
Evidence: Real Herdr read-only smoke

ok - real Herdr smoke: client protocol 16 and live server verified (read-only)

ok - real Herdr smoke: client protocol 16 and live server verified (read-only)
- Outcome: 🔧 1 issue found → auto-fixed ✅ across 2 runs (42m58s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 7 issues found → auto-fixed (11) ✅
  • 🚨 .github/workflows/ci.yml:163 - The required “pinned real-Herdr CI coverage” is not enforced. This lane runs real-herdr-gated without enabling FM_HERDR_E2E or FM_HERDR_SMOKE; several mapped scripts therefore exit successfully as opt-in skips, while --fail-on-gate-skip &#39;herdr not found&#39; rejects only that exact skip reason. The lane can pass without exercising substantial real-Herdr coverage.
  • 🚨 tests/fm-afk-inject-herdr-e2e.test.sh:39 - The AFK Herdr E2E now enters its readiness loop before provisioning the lab, sourcing the backend, or creating the pane. Variables including PANE_ID, CONTAINER, and TARGET are consequently unset, so enabling this test causes a timeout or immediate failure. Restore the removed provisioning and task-creation setup before this loop.
  • 🚨 bin/fm-session-start.sh:274 - The required “stale projection cleanup at session start” is only wired into the new fm-session-start.sh wrapper, but the authoritative startup instructions still direct operators to run fm-bootstrap.sh and fm-lock.sh separately, and no executable call site invokes this wrapper. Following the documented lifecycle therefore bypasses cleanup. Make the wrapper the documented entrypoint or integrate cleanup into the established locked startup path.
  • 🚨 bin/backends/herdr.sh:2133 - The required “composer/send reliability” remains incomplete for the mandated Herdr backend. When the baseline composer is busy, queued OpenCode submission can intentionally leave text visible; this branch retries and then returns pending instead of recognizing the accepted queue operation. The repository's adapter documentation also labels this as a known Herdr gap.
  • 🚨 bin/fm-spawn.sh:249 - The new abort trap no longer cleans up flat-Herdr panes. A pane is created before later fallible operations, but abort cleanup is armed only for Orca projections; failures such as workspace resolution leave an untracked live pane, and a retry can create a duplicate lifecycle endpoint. This contradicts the required exact lifecycle identity.
  • 🚨 bin/backends/herdr.sh:2149 - Herdr kill now reports success when target preparation fails and suppresses all pane close failures without confirming that the pane disappeared. Teardown trusts this success and can remove lifecycle state while the agent remains live. Propagate close/preparation failures and confirm absence before returning success.
  • ⚠️ bin/backends/herdr.sh:1538 - After a successful replacement-tab creation, missing IDs cause reclaim to return flat fallback without rolling back any known new pane or failing closed when the mutation cannot be identified. A partial Herdr response can therefore leave an extra shell/tab and block exact reclaim. Roll back known resources, and return the documented post-mutation uncertainty result when identity is unavailable.

🔧 Fix: Harden Herdr lifecycle and real-CI coverage
10 issues (8 errors, 2 warnings) still open:

  • 🚨 .github/workflows/ci.yml:167 - The required “pinned real-Herdr CI coverage” is still unenforced. This passes skip: to a runner that searches for skip: $token, producing the impossible pattern skip: skip:; ordinary gated skips therefore remain successful. Add explicit fail-on-any-skip behavior and use it here.
  • 🚨 tests/fm-install-herdr.test.sh:81 - The portable suite includes this contract test, but it still requires the removed --fail-on-gate-skip &#39;herdr not found&#39; workflow text. The portable CI job will fail deterministically. Update the assertion to the corrected any-skip contract.
  • 🚨 bin/backends/herdr.sh:2152 - The required composer/send reliability is incomplete for busy slash-command submission. A first Enter can fill an autocomplete placeholder while leaving the composer pending, but every busy-baseline pending state is now reported as delivered, so the necessary second Enter is never sent. Distinguish queue acceptance from autocomplete before returning success.
  • 🚨 bin/backends/herdr.sh:2140 - An Enter transport failure is suppressed. With a busy baseline, the unchanged pending composer is then treated as successful delivery, causing callers to discard or acknowledge a message that was never submitted. Return unknown or send-failed when fm_backend_herdr_send_key fails.
  • 🚨 bin/backends/herdr.sh:2169 - An already-absent pane makes pane close fail, so teardown refuses to remove stale metadata and its worktree even though the requested endpoint is already gone. Confirm a dead pane as idempotent success before attempting close; continue failing closed on unknown state.
  • 🚨 bin/backends/herdr.sh:1539 - The required exact lifecycle identity is violated when focus restoration fails after replacement creation. This early return runs before rollback, leaving the known new pane alive while reclaim refuses the launch. Attempt exact rollback before returning the focus error.
  • 🚨 AGENTS.md:84 - The authoritative layout says config/secondmate-harness may contain harness, model, and effort tokens, but the resolver strips all whitespace and treats the result as one harness name; section 4 instead defines a separate secondmate-profile.json. Following line 84 therefore breaks secondmate launch. Restore the single-name format and separate profile entry.
  • 🚨 .agents/skills/secondmate-provisioning/SKILL.md:73 - The changed skill promises that mid-session fm-config-push.sh publishes and sends a CONFIG_REREAD instruction, but that script only propagates files and prints its report; it never calls fm_config_send_reread_nudge. Running secondmates keep stale configuration. Either wire the promised locked generation-and-delivery path or correct the claimed behavior.
  • ⚠️ .agents/skills/harness-adapters/SKILL.md:140 - The mandatory adapter reference still labels busy-queued Herdr submission a known gap, while this target implements it. The AFK skill and architecture documentation repeat the stale boundary, which can lead supervising agents to make incorrect recovery decisions. Align these references with the final send contract.
  • ⚠️ bin/backends/herdr.sh:210 - The Herdr adapter has grown to roughly 2,700 lines and now combines projection journals, ordering/focus, reclaim, composer parsing, events, and core lifecycle operations. Extract the cohesive presentation-projection subsystem into a sourced helper to reduce cross-feature coupling without changing behavior.

🔧 Fix: Harden Herdr lifecycle, delivery, and CI contracts
8 issues (5 errors, 3 warnings) still open:

  • 🚨 bin/fm-teardown.sh:810 - Projected teardown suppresses pane-close or focus-lock failure, then deletes task metadata and reports success. This can leave a live pane untracked and contradicts the required “exact lifecycle identity”; preserve state and fail teardown unless exact pane absence is confirmed.
  • 🚨 bin/backends/herdr.sh:1199 - After tab create succeeds, partial IDs or later husk-removal verification failures return without exposing or rolling back the new endpoint. The spawn abort trap therefore cannot remove it, contradicting required “exact lifecycle identity.”
  • 🚨 bin/backends/herdr.sh:1207 - Flat restart reclaim closes restored husk tabs directly without checking whether the tab is active or restoring the prior focus. Herdr may move the captain to another tab, contradicting required “focus preservation.”
  • 🚨 bin/backends/herdr.sh:2182 - Busy-queue acceptance relies on the one-time pre-loop status. After an autocomplete retry, the original turn can become idle; a swallowed later Enter that leaves the exact text visible is still reported delivered, contradicting required “composer/send reliability.” Require contemporaneous busy-state proof for each retry.
  • 🚨 bin/fm-config-inherit-lib.sh:171 - The changed documentation promises guarded propagation of data/captain-shared.md, but this compatibility entry point explicitly performs config-only propagation. Operators are subsequently told to trim local captain preferences to pointers that may not exist; implement the promised shared-file contract or remove those instructions.
  • ⚠️ bin/fm-test-run.sh:138 - This isolated, credential-free real-Herdr marker/send E2E is classified as live-harness-optin, so neither portable CI nor the required Herdr lane executes it. Move it into real-herdr-gated to complete the required “pinned real-Herdr CI coverage” for this production send path.
  • ⚠️ AGENTS.md:154 - The authoritative inheritance instructions omit config/herdr-presentation-spaces, and later say config-push is only for cases where reread nudges are unnecessary even though it now sends CONFIG_REREAD. Align these instructions with the implemented allowlist and delivery behavior.
  • ⚠️ bin/fm-config-push.sh:25 - CLI help says nonzero status is limited to propagation errors, but the new path also exits nonzero when CONFIG_REREAD publication or delivery fails. Update the exit-status contract so operators diagnose the correct failure.

🔧 Fix: Harden Herdr lifecycle, inheritance, and CI
9 issues (7 errors, 2 warnings) still open:

  • 🚨 bin/backends/herdr.sh:1249 - Post-create rollback failures are suppressed with || true. If close or absence confirmation fails, create_task returns without exposing the new IDs, so spawn cannot clean up the endpoint. This still contradicts required “exact lifecycle identity.”
  • 🚨 bin/backends/herdr.sh:1125 - Restart reclaim refuses to replace a restored husk when that husk is the active tab. Since Herdr restores the previously focused tab, relaunching that task can fail until the captain manually changes focus, contradicting required “restart reclaim” and “focus preservation.”
  • 🚨 bin/backends/herdr.sh:655 - Teardown ignores the focus-preserving close result and succeeds whenever the pane is dead. If close succeeds but exact focus restoration fails, the failure is silently discarded, contradicting required “focus preservation.”
  • 🚨 bin/fm-teardown.sh:763 - Projected teardown returns and resets the worktree before acquiring the presentation lock or confirming pane absence. A later close refusal preserves metadata but leaves it pointing to a destroyed worktree, contradicting required “exact lifecycle identity.”
  • 🚨 bin/fm-teardown.sh:835 - A presentation journal with incomplete or mismatched metadata bypasses the confirmed-close path, then suppresses generic kill failure. Metadata is subsequently deleted even if the pane survives, contradicting required “exact lifecycle identity.”
  • 🚨 bin/fm-spawn.sh:837 - Secondmate launch still calls config-only propagation, although the changed operator contract says launch also converges data/captain-shared.md. Fresh and recovery launches can start without the authoritative shared preferences.
  • 🚨 bin/backends/herdr.sh:2224 - After typing text, an unreadable native status returns unknown before Enter is sent; fm-send.sh treats that verdict as success. This leaves messages unsubmitted and deterministically breaks the newly gated plain-shell marker E2E, contradicting required “composer/send reliability” and “pinned real-Herdr CI coverage.”
  • ⚠️ bin/fm-config-inherit-lib.sh:266 - Callers pass the active data directory as a fourth argument, but this helper ignores it and hardcodes $src_home/data. With FM_DATA_OVERRIDE, bootstrap can propagate stale or unintended captain-shared.md content; accept and use the explicit source-data directory.
  • ⚠️ bin/fm-test-run.sh:815 - --fail-on-any-gate-skip only checks the first non-empty output line. A test that prints a diagnostic before skip: ... can exit successfully and leave the required lane green; scan every line beginning with skip:.

🔧 Fix: Harden Herdr recovery, teardown, and inheritance contracts
5 issues (4 errors, 1 warning) still open:

  • 🚨 bin/backends/herdr.sh:2256 - An unreadable native baseline sends one Enter and immediately returns unknown, bypassing composer inspection and retries. Because fm-send.sh treats unknown as success, autocomplete can consume that Enter while leaving the request unsubmitted, contradicting required “composer/send reliability.”
  • 🚨 bin/fm-spawn.sh:269 - Failed focus-preserving rollback falls back to generic Herdr kill and suppresses its result. This can close the captain’s active replacement tab without restoring focus, or leave a failed-to-close pane alive with no durable identity, contradicting required “focus preservation” and “exact lifecycle identity.”
  • 🚨 bin/backends/herdr.sh:1278 - When tab create mutates successfully but returns neither ID and follow-up discovery fails or is ambiguous, abort cleanup emits no identity or uncertainty record. Spawn therefore exits while the new endpoint may remain untracked, still contradicting required “exact lifecycle identity.”
  • 🚨 bin/fm-teardown.sh:798 - Flat Herdr teardown and presentation journals with incomplete endpoint metadata use generic kill without the presentation lock or focus snapshot/restore. Closing a non-active last pane can move the captain to another workspace and race presentation mutations, contradicting required “focus preservation.”
  • ⚠️ bin/fm-teardown.sh:826 - Journal retirement occurs after the fallible worktree return. If pane closure succeeds but worktree return fails, retry can no longer revalidate the now-dead endpoint, so it deletes metadata while retaining the journal; future same-ID projection launches then fall back flat until manual cleanup.

🔧 Fix: Harden Herdr send and lifecycle uncertainty handling
3 errors still open:

  • 🚨 bin/backends/herdr.sh:1266 - Flat tab create returns immediately on any nonzero CLI result. Herdr may accept the mutation before a transport failure, but this path records neither an exact cleanup target nor durable uncertainty, so a retry can create a duplicate endpoint. This contradicts the required “exact lifecycle identity”; capture the result and persist workspace/label uncertainty whenever rollback cannot be proved.
  • 🚨 bin/backends/herdr.sh:2271 - For a pending composer, contemporaneous native state unknown falls through and sends Enter again. If the first Enter already queued the message while leaving its text visible, retries can submit it twice. This contradicts required “composer/send reliability”; retry only explicit autocomplete and return unknown for pending text unless current state positively proves busy.
  • 🚨 bin/fm-teardown.sh:821 - Forced secondmate teardown ignores failures from cleanup_firstmate_home_children; recursive cleanup at line 662 does the same. Because the script does not use set -e, it continues deleting parent state after an unconfirmed child-pane close, leaving a live child untracked. This contradicts required “exact lifecycle identity”; propagate both failures before deleting any parent home or metadata.

🔧 Fix: Harden Herdr mutation and teardown failure handling
2 errors still open:

  • 🚨 bin/backends/herdr.sh:1285 - After a failed tab create returns no response IDs, this path promotes a unique same-label tab from a later listing into rollback authority. Because readable labels are non-unique and external Herdr actions do not share this lock, Firstmate can close a foreign tab. This contradicts required “exact lifecycle identity”; use only response-derived identity and otherwise persist session/workspace/label uncertainty.
  • 🚨 bin/backends/herdr.sh:2287 - The wildcard maps both current idle and unreadable states to unknown. For a swallowed Enter, exact text remains pending and current idle proves it was not accepted as a busy queue, but fm-send.sh treats unknown as success and acknowledges the unsent message. This contradicts required “composer/send reliability”; return pending for current idle and reserve unknown for unreadable state.

🔧 Fix: Enforce Herdr identity and truthful pending verdicts
1 error still open:

  • 🚨 bin/backends/herdr.sh:2275 - The required “composer/send reliability” is still violated. The changed idle) printf &#39;pending&#39; branch sends marked Codex secondmate traffic into fm-send.sh’s final-Enter fallback, but Herdr’s dispatcher calls an undefined fm_backend_herdr_submit_enter. Under set -eu, the send exits 127 without submitting the message. Implement the Herdr primitive with the expected verdict contract or prevent this fallback from dispatching to Herdr.

🔧 Fix: Implement truthful Herdr final Enter submission
2 errors still open:

  • 🚨 bin/backends/herdr.sh:2317 - The required “composer/send reliability” is contradicted when final confirmation becomes unreadable. This helper returns unknown, but fm-send.sh rejects only pending and send-failed; because this fallback starts from positively pending text, a swallowed final Enter can therefore be falsely acknowledged. Treat unknown as unconfirmed failure on this final-after-pending path.
  • 🚨 bin/backends/herdr.sh:2295 - The required “composer/send reliability” is contradicted because the delayed fallback sends Enter before verifying that the composer still contains expected_text. During the preceding settle delay, the text can be consumed or replaced, causing unrelated human input to be submitted and reported successful. Preflight exact composer ownership before Enter; handle empty, mismatched, and unreadable states without submitting foreign text.

🔧 Fix: Harden Herdr final Enter ownership verification
2 errors still open:

  • 🚨 bin/backends/herdr.sh:2296 - The required “composer/send reliability” is contradicted because an empty preflight is promoted to confirmed delivery without this helper sending Enter or observing a submit-active state. During the settle delay, a user clear or TUI reset is indistinguishable from successful submission. Return unknown unless delivery has independent confirmation.
  • 🚨 bin/backends/herdr.sh:2302 - The required “composer/send reliability” is contradicted because exact pending text still receives another Enter when the native baseline is unknown. The actual state may be a busy queue that accepted a prior attempt, so this can duplicate submission—the pending/unknown condition earlier logic deliberately refuses to retry. Send only with affirmative idle proof; otherwise return unknown without transport.

🔧 Fix: Require idle proof for Herdr final Enter
1 error still open:

  • 🚨 bin/backends/herdr.sh:2294 - The required “composer/send reliability” is still contradicted. The changed hunk samples baseline before capturing composer ownership, then later trusts that earlier idle result. If the pane becomes busy while the composer is being read, another Enter is sent and can duplicate a submission accepted by the previous attempt. Capture exact pending ownership first, then obtain affirmative idle proof immediately before Enter.

🔧 Fix: Order Herdr ownership before idle proof
✅ Re-checked - no issues remain.

🔧 **Test** - 1 issue found → auto-fixed ✅
  • 🚨 tests failed with exit code 1
  • bash bin/fm-run-behavior-tests.sh

🔧 Fix: Restore flat Herdr spawning without presentation locks
✅ Re-checked - no issues remain.

  • bash bin/fm-run-behavior-tests.sh
  • Pipeline-provided baseline: bash bin/fm-run-behavior-tests.sh (passed)
  • FM_HERDR_SMOKE=1 bash tests/fm-backend-herdr-smoke.test.sh
  • Initial direct tests/fm-backend-herdr-presentation-e2e.test.sh attempts were safely refused because this is a gate worktree; retried successfully through the repository-supported isolated runner
  • env -u TMUX -u TMUX_PANE FM_TEST_JOBS=4 TMPDIR=/tmp/no-mistakes-evidence/01KYDB8XPV3F2D278AE5W3264G bash bin/fm-run-behavior-tests.sh
  • git status --short && git diff --name-only && git diff --cached --name-only
🔧 **Document** - 1 issue found → auto-fixed ✅
  • 🚨 tests/fm-backend-herdr.test.sh:3001 - Captain, the focused Herdr suite still fails its explicit metadata-matched fm-send --key routing assertion. Fixing executable behavior is outside this documentation-only task.

🔧 Fix: Isolate Herdr routing test from gate refusal
✅ Re-checked - no issues remain.

🔧 **Lint** - 1 issue found → auto-fixed ✅
  • ⚠️ linter found issues (exit code 1)

🔧 Fix: Remove unused Herdr lint variables
✅ Re-checked - no issues remain.

✅ **Push** - passed

✅ No issues found.

kunchenguid and others added 28 commits July 25, 2026 17:45
* feat(herdr): add optional presentation spaces

* no-mistakes(review): Harden Herdr projection creation and spawn serialization

* no-mistakes(review): Captain, disarm Herdr cleanup before launch submission

* no-mistakes(test): Correct stale Orca metadata failure fixture

* no-mistakes(document): Document Herdr presentation projection accurately
…nguid#790)

* feat(herdr): order presentation worker spaces

* fix(herdr): preserve focus during projected cleanup

* no-mistakes(review): Serialize Herdr cleanup and protect active seeded tabs

* no-mistakes(review): Serialize Herdr aborts with guarded focus regressions

* no-mistakes(review): Fall back flat when Herdr serialization is unavailable

* no-mistakes(test): Stabilize watcher startup and AFK handoff tests

* no-mistakes(document): Correct Herdr ordering and focus documentation
…uid#821)

* feat(herdr): correct all-home child presentation topology

Inherit the presentation opt-in to secondmate homes, label new projected
spaces with the approved corner format, insert each child under its owning
parent under one session-scoped lock, and keep flat non-destructive fallback.

* no-mistakes(review): Exclude secondmates from Herdr presentation projection

* no-mistakes(review): Harden shared Herdr locks and ambiguous child ordering

* no-mistakes(review): Use adjacency-only Herdr child ownership

* no-mistakes(review): Reject foreign legacy projections safely

* no-mistakes(review): Validate Herdr session sockets before projection

* no-mistakes(test): Fix Herdr teardown fixture session socket metadata

* fix(herdr): canonicalize presentation lock socket paths

Always resolve the session socket parent directory so symlink parents
such as /tmp -> /private/tmp cannot split the shared cross-home lock
identity. Refuse relative socket paths. Clarify lock-unavailable warnings.

* no-mistakes(test): Fix Bash-compatible GitLab merge request URL parsing

* no-mistakes(document): Document all-home Herdr child topology

* no-mistakes(lint): Quote fallback provenance string for ShellCheck
* feat: add required pinned Herdr CI lane

Install exact Herdr 0.7.4 and Treehouse 2.0.1 with official assets and
SHA-256 pins, run the real-herdr-gated family serially through
fm-test-run with hard-fail on herdr-not-found, and keep portable
Behavior free of claimed Herdr coverage.

* no-mistakes(document): Consolidate real-Herdr CI documentation ownership

* no-mistakes: apply CI fixes

* no-mistakes: apply CI fixes

* no-mistakes: apply CI fixes
…id#967)

* fix(herdr): reclaim resumed task projections safely

* no-mistakes(review): Enforce safe Herdr reclaim close boundaries

* no-mistakes(document): docs: clarify Herdr restart projection contract
* Clean stale Herdr projections at session start

* no-mistakes(document): Document stale Herdr session-start projection cleanup

* no-mistakes(review): Enforce locked exact Herdr projection cleanup

* no-mistakes(review): Fail closed on unverified session lock ownership

* no-mistakes(review): Serialize session lock acquisition atomically

* no-mistakes(document): Align session-start and Herdr cleanup documentation

* no-mistakes(document): Generalize lock-refusal diagnostics

* no-mistakes(lint): Avoid reserved keyword in concurrency test

* no-mistakes: apply CI fixes

* no-mistakes: apply CI fixes
…nchenguid#775)

* fix(send): treat opencode busy-queued composer state as submitted

When fm-send sends a message to a BUSY opencode crewmate on the tmux
backend, opencode accepts the Enter and queues the message for the next
turn, but leaves the typed text visible in the composer row.  The
submit-verification loop sees a pending composer, exhausts retries, and
reports a false "Enter swallowed" failure while the message is actually
delivered.

Fix: after Enter retries are exhausted and the composer still shows
pending, check fm_pane_is_busy.  If the pane is busy (agent mid-turn,
footer shows "esc interrupt"), the harness queued the message, so
return "empty" (accepted).  On an idle pane, keep returning "pending"
(genuine swallow detection preserved).

Regression tests cover four scenarios:
- busy pane + pending composer -> empty (message queued)
- idle pane + pending composer -> pending (genuine swallow)
- busy pane + composer clears on first Enter -> empty
- idle pane + composer clears on first Enter -> empty (existing path)

* docs: document busy-queued Enter exception across backend docs and skills

Add explanatory comments and backend documentation for the
busy-queued Enter fix (opencode 1.18.4 accepts Enter mid-turn
but keeps typed text in composer until the turn ends):

- bin/fm-tmux-lib.sh: document the busy-aware fallback in the
  file header and above fm_tmux_submit_enter_core
- .agents/skills/afk/SKILL.md: daemon-facing policy note
- .agents/skills/harness-adapters/SKILL.md: harness-specific fact
- docs/tmux-backend.md: submit-acknowledgement section with the
  busy-queue exception
- docs/herdr-backend.md: record the known gap
- docs/architecture.md: cross-reference in the daemon section

* test(tmux): fix SC2181 and make busy-submit test executable
* fix(supervision): verb-aware captain relevance, AFK wedge, head-bound state

Stop free-text tokens like "merged" from promoting nonterminal working: lines
to captain-relevant, so AFK no longer permanently suppresses idle recovery.
Defend wedge aging independently for nonterminal progress verbs, bind
no-mistakes current-state attribution to code identity (not branch alone),
and mark setup-complete as nonterminal in the ship brief scaffold.

* no-mistakes(review): Enforce nonterminal suppression and head-bound run attribution

* no-mistakes(document): Document current-code-bound run attribution

* no-mistakes(test): Wait for stable Herdr shell readiness

* no-mistakes(test): Make Herdr and watcher readiness tests deterministic

* no-mistakes(test): Make tmux capture and watcher lifecycle deterministic

* no-mistakes(document): Document corrected supervision contracts
…#809)

* Send literal config reread after inherited config push

When declared inherited config changes under an already-running secondmate,
build a per-home instruction from validated destination post-write bytes and
deliver it on the routed secondmate path. Unchanged config sends nothing;
ABSENT represents removal; captain-shared is never inlined. Covers mid-session
config-push and the locked bootstrap convergence path without hardening spawn
against deliberate runtime choice.

* no-mistakes(review): Fix config reread framing, partial propagation, and respawn order

* no-mistakes(review): Send config rereads via durable single-line pointers

* no-mistakes(review): Make failed config rereads retryable

* no-mistakes(review): Make config reread retries generation-safe

* no-mistakes(review): Make config rereads durable and ordered

* no-mistakes(review): Drain retries, bound history, preserve detect-only read-only mode

* no-mistakes(review): Retain write retries and quarantine stale respawn generations

* no-mistakes(review): Preserve exact config reread retries and delivery order

* no-mistakes(review): Preserve exact retry bytes and bounded quarantine pruning

* no-mistakes(document): Consolidated config-reread documentation
@JTInventory
JTInventory merged commit 4fbe587 into main Jul 26, 2026
6 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants