Skip to content

Port upstream batch 2: away-mode reliability (#54) + Claude ghost text (#59) - #3

Merged
augustomklee merged 1 commit into
mainfrom
port-upstream-batch-2
Jun 24, 2026
Merged

Port upstream batch 2: away-mode reliability (#54) + Claude ghost text (#59)#3
augustomklee merged 1 commit into
mainfrom
port-upstream-batch-2

Conversation

@augustomklee

Copy link
Copy Markdown
Owner

What

Second batch of the cherry-pick-and-port of upstream into this psmux/Windows fork: the two supervision-reliability fixes, hand-adapted (every tmux rewired to $FM_MUX; doc deltas folded into CLAUDE.md, not AGENTS.md).

New: bin/fm-tmux-lib.sh

One shared set of pane primitives - busy detection, border- and ghost-text-aware composer-empty detection, and a verified Enter-retry submit - sourced by both the away-mode daemon and fm-send.sh so the logic can't drift. Ported from upstream with tmux$FM_MUX; it sources fm-mux-lib.sh so it works standalone.

kunchenguid#54 (e4fbed5) — harden away-mode escalation delivery

  • Border-aware detection: strips the harness's box-drawing borders before deciding, so an idle bordered claude composer (│ > … │) reads empty, not pending. Root cause of incident afk-invx-i5, where away-mode deferred 100% of escalations for 9.5h.
  • Max-defer escape: anything buffered past FM_MAX_DEFER_SECS (default 300) gets one more flush; if delivery still can't be confirmed, a rate-limited wedge alarm fires (ERROR log + state/.subsuper-inject-wedged marker + status-line flash). The daemon can no longer silently wedge.
  • Verified submit via the shared primitive; fm-send.sh exits non-zero on a positively-confirmed swallow, so a steer that doesn't land is no longer silent.

kunchenguid#59 (3718fd0) — ignore Claude predicted-prompt ghost text

  • At the source: claude crewmates launch with CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false (per-launch env prefix in fm-spawn.sh, scoped to firstmate-launched agents; never the captain's global config).
  • Defense in depth: fm_tmux_strip_ghost drops dim/faint (SGR 2) runs from the captured cursor line, so ghost text never reads as pending input.

The fork kept its pane primitives inline in the daemon; this replaces them with the shared lib's fm_pane_is_busy / fm_pane_input_pending and routes the inject submit through fm_tmux_submit_core.

Tests

  • New tests/fm-composer-ghost.test.sh (ported, FM_MUX-pinned to the fake): dim-ghost stripping incl. SGR color payloads, dim-only/bordered composers read not-pending, real and colored text still pending. Passes 8/8 locally.
  • Not ported: upstream's additions to tests/fm-wake-queue.test.sh and its fm-peek escape-free test - they lean on the FM_HOME / FM_ROOT_OVERRIDE scaffolding introduced by the secondmate rewrite (feat: support persistent secondmates kunchenguid/firstmate#37), which this fork is not taking. The existing wake-queue suite is unchanged.
  • Note on local runs: tests/fm-wake-queue.test.sh aborts early on this Windows/MSYS dev machine at a background-process watcher timing test (watcher did not exit for first signal) - confirmed identical on unmodified main, so it is pre-existing and platform-related, not caused by this change. CI (Linux) runs the full suite.

Verification

  • bash -n passes on all touched scripts.
  • fm_tmux_strip_ghost validated directly: dim-only → empty, normal/bold/colored text preserved, bordered-dim → borders only (then stripped).
  • Zero raw tmux calls introduced (all routed through $FM_MUX).

Docs

CLAUDE.md (sections 2/4/8), README.md, and the afk SKILL.md updated for the shared lib, border/ghost-aware detection, the max-defer wedge alarm, and the new env knobs (FM_MAX_DEFER_SECS, FM_SEND_*, FM_INJECT_CONFIRM_*).

… Claude ghost text (kunchenguid#59)

Cherry-pick-and-port of two upstream supervision-reliability fixes, adapted to
this psmux/Windows fork (every tmux call rewired to $FM_MUX; doc deltas folded
into CLAUDE.md, not AGENTS.md).

New bin/fm-tmux-lib.sh: one shared set of pane primitives (busy detection,
border- and ghost-text-aware composer-empty detection, verified Enter-retry
submit), sourced by the away-mode daemon and fm-send.sh so the logic cannot
drift. Ported from upstream with tmux -> $FM_MUX; it sources fm-mux-lib.sh.

kunchenguid#54 (e4fbed5) - harden away-mode escalation delivery:
- Composer detection strips the harness's box-drawing borders before deciding,
  so an idle bordered claude composer reads empty, not pending (root cause of
  afk-invx-i5: away-mode deferred 100% of escalations for 9.5h).
- Max-defer escape: anything buffered past FM_MAX_DEFER_SECS (default 300) gets
  one more flush; if delivery still can't be confirmed, a rate-limited wedge
  alarm fires (ERROR log + state/.subsuper-inject-wedged marker + status-line
  flash). The daemon can no longer silently wedge forever.
- Verified submit via the shared primitive; fm-send.sh exits non-zero on a
  positively-confirmed swallow so a steer that doesn't land is no longer silent.

kunchenguid#59 (3718fd0) - ignore Claude predicted-prompt ghost text:
- Disable at the source: claude crewmates launch with
  CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false (per-launch env prefix in
  fm-spawn.sh, scoped to firstmate-launched agents; never the captain's config).
- Defense in depth: fm_tmux_strip_ghost drops dim/faint (SGR 2) runs from the
  captured cursor line, so ghost text never reads as pending input.

The fork kept its inline daemon pane primitives; this replaces them with the
shared lib's fm_pane_is_busy / fm_pane_input_pending and routes the inject submit
through fm_tmux_submit_core.

Tests: new tests/fm-composer-ghost.test.sh (ported, FM_MUX-pinned) - dim-ghost
stripping incl. SGR color payloads, dim-only/bordered composers read not-pending,
real and colored text still pending; passes 8/8 locally. Not ported: upstream's
additions to tests/fm-wake-queue.test.sh and the fm-peek escape-free test (they
lean on kunchenguid#37 FM_HOME / FM_ROOT_OVERRIDE scaffolding this fork is not taking); the
existing wake-queue suite is unchanged and remains CI-gated on Linux.

Docs: CLAUDE.md (sections 2/4/8), README.md, and afk SKILL.md updated for the
shared lib, border/ghost-aware detection, max-defer wedge alarm, and the new env
knobs (FM_MAX_DEFER_SECS, FM_SEND_*, FM_INJECT_CONFIRM_*).
@augustomklee
augustomklee merged commit 59b73d4 into main Jun 24, 2026
@augustomklee
augustomklee deleted the port-upstream-batch-2 branch June 24, 2026 14:40
augustomklee pushed a commit that referenced this pull request Jul 28, 2026
* docs: trim AGENTS.md redundancy (diet PR 3/3)

Consolidates five duplicated passages to a single owner each, per
data/agentsmd-diet-s2/report.md redundancy items c3-c7:

- Inheritable-config propagation mechanism: owned by section 3 (where
  the sweep runs); sections 4 and 7 keep compact references. Section 4
  retains its one genuinely unique fact (crew-harness inherit-vs-fallback
  semantics), just no longer restates the propagation mechanism itself.
- Landed-work definition: owned by section 7's ship-teardown detail
  (PR-containment mechanics, pr= discovery fallback); section 1's hard
  rule #3 keeps the rule plus a three-case summary and a pointer.
- Backend meta-field enumeration: owned by docs/configuration.md
  ("Runtime backend", already comprehensive including cmux) and each
  backend's own doc; AGENTS.md keeps only the fields common to every
  task plus a pointer.
- Dropped one redundant restatement of "silence is correct while
  waiting" in section 8.
- Worktree-tangle guard explanation: owned by section 8 (already the
  fuller, cross-referenced version); section 3's TANGLE bullet keeps
  the remediation action and points at section 8 for the why.

Also adds two captain-requested single-sentence rules: invoke bin/
scripts by absolute $FM_ROOT path after any cd away from the home, and
a backend spawn refusal must be surfaced to the captain rather than
silently worked around by switching backends.

AGENTS.md: 901 -> 889 lines, 112355 -> 108560 bytes.

* no-mistakes(review): Clarify post-cd bin invocation guidance

* no-mistakes(document): Sync AGENTS trim docs

* no-mistakes(lint): Fix Markdown line style
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