Skip to content

feat: add bounded fleet recaps and resilient supervision - #33

Merged
Keigyoku merged 15 commits into
mainfrom
fm/fm-batcha-features-p5
Jul 23, 2026
Merged

Keigyoku merged 15 commits into
mainfrom
fm/fm-batcha-features-p5

Conversation

@Keigyoku

Copy link
Copy Markdown
Owner

What Changed

  • Give the captain a new /ahoy session recap and rebuild /bearings around bounded, deterministic fleet snapshots covering main and secondmate work.
  • Preserve X and Discord reply context after inbox cleanup, fail safely when follow-up routing is unresolved, and harden cmux teardown across windows, ID churn, nested cleanup, and scan failures.
  • Reframe firstmate as an agent distro and align the documentation and regression coverage with the new recap, X-mode, and cmux contracts.

Risk Assessment

✅ Low: The three requested behaviors are satisfied, the fixes are bounded and fail closed where retry metadata matters, and no additional material source regression was substantiated.

Testing

Completed 1 recorded test check.

Pipeline

Updates from git push no-mistakes

⏭️ **intent** - skipped

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 2 issues found → auto-fixed (6) ✅
  • ⚠️ bin/fm-bearings-snapshot.sh:448 - When unresolved_blocker_ids is present but empty, the projection falls back to raw blocked_by, so completed dependencies are still reported as blockers. Fall back only when the normalized field is absent; apply the same fix to the secondmate mapping at line 460.
  • ⚠️ bin/backends/cmux.sh:649 - Teardown validates the expected label through fm_backend_cmux_target_ready, whose workspace lookup is current-window-only. Tasks in another cmux window return before the new all-window membership helper runs, leaving their workspace open. Make expected-label validation window-aware before returning.

🔧 Fix: Captain, fix blocker projection and cross-window cmux teardown
1 warning still open:

🔧 Fix: Captain, preserve secondmate status decisions in bearings
1 warning still open:

  • ⚠️ bin/fm-bearings-snapshot.sh:399 - The fix adds any secondmate with active children to in_flight, even when its aggregate bearings_state is captain_decision, and hardcodes the duplicate row to active_child_work. This conflicts with the changed Bearings contract that the four buckets are mutually exclusive and a secondmate’s own row appears Underway only for active_child_work; decide whether mixed homes should remain solely captain-decision aggregates or whether the documented categorization should change.

🔧 Fix: Captain, enforce exclusive secondmate bearings buckets
2 warnings still open:

  • ⚠️ bin/fm-fleet-snapshot.sh:552 - registry_secondmates_json reads all of data/secondmates.md directly into jq and always reports input_truncated:false and records_truncated:false; the advertised FM_SNAPSHOT_REGISTRY_LINES, FM_SNAPSHOT_REGISTRY_BYTES, and FM_SNAPSHOT_REGISTRY_RECORDS controls are not implemented. A large registry therefore bypasses the bounded-snapshot contract, while a read failure aborts the snapshot instead of producing the supported available:false record. Add a bounded reader that reports truncation and converts read failures into availability metadata.
  • ⚠️ bin/backends/cmux.sh:659 - The all-window stale-ID fallback takes the first workspace matching the expected title, although cmux permits duplicate titles and uniqueness checks remain current-window-only. After ID churn, same-title workspaces in different windows can cause teardown to close an arbitrary duplicate. Collect all-window matches and fail closed on ambiguity, or enforce all-window uniqueness before title-based recovery.

🔧 Fix: Captain, bound secondmate registry and harden cmux recovery
1 warning still open:

  • ⚠️ bin/backends/cmux.sh:695 - fm_backend_cmux_window_of_workspace collapses list/JSON failures into the same empty result as “not found”; teardown then skips creating the throwaway sibling and still calls close-workspace. If the target is last in its window, cmux silently no-ops while fm-teardown.sh removes task metadata, leaving an orphaned workspace. Distinguish scan failure from a verified non-last result and preserve or retry teardown instead of proceeding unverified.

🔧 Fix: Captain, preserve cmux metadata on scan failure
4 warnings still open:

  • ⚠️ bin/fm-teardown.sh:1016 - Forced cleanup propagates direct cmux child-kill failures, but the recursive cleanup_firstmate_home_children "$child_home" result remains unchecked. If a nested secondmate contains a cmux child whose scan fails, cleanup removes the nested home and metadata anyway, orphaning the deeper workspace. Propagate recursive cleanup and home-removal failures before deleting the parent record.
  • ⚠️ bin/backends/cmux.sh:675 - After all-window membership verifies the expected workspace, fm_backend_cmux_surface_id_for_workspace still collapses failed list-panes or invalid JSON into empty output, which teardown interprets as “target absent.” Kill then reports success and metadata is removed while the workspace remains live. Make surface lookup status-aware and return the retryable failure code for incomplete scans.
  • ⚠️ bin/backends/cmux.sh:717 - The fail-closed teardown path still masks a non-zero close-workspace result with || true, so metadata is removed even when cmux reports that the workspace was not closed. Existing tests describe this as intentional best-effort behavior; confirm that intent, or propagate the failure so teardown remains retryable.
  • ⚠️ bin/fm-fleet-snapshot.sh:567 - The bounded reader captures head -c limit+1 through command substitution, which strips trailing newlines before ${#input} checks the size. When byte limit+1 is a newline, input_truncated remains false and later registry rows are silently omitted. Preserve the probe byte independently or determine truncation from file/read metadata.

🔧 Fix: Captain, preserve nested cleanup and cmux retry state
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

Keigyoku and others added 14 commits July 22, 2026 20:18
Port the final upstream bearings stack tip state rather than serial-cherrying
the conflicting kunchenguid#475/kunchenguid#485/kunchenguid#555/kunchenguid#640/kunchenguid#830/kunchenguid#875 family.

New bin/fm-bearings-snapshot.sh projects fm-fleet-snapshot.sh into a bounded
TOON-by-default fm-bearings.v1 view (local-only unless --include-prs).
Rewrite .agents/skills/bearings to the four-section chat contract
(Captain's Call / Recently Landed / Underway / Charted Next).

Fork adaptations (not taking kunchenguid#593 decision-hold in this batch):
- Soft-gate fm-afk-return.sh when absent.
- Omit captain_actionable captain-hold surfaces; decisions_open uses fork
  status hints / last_event needs-decision|blocked text instead.
- gates.blocked_by falls back to the string backlog.blocked_by field.

Upstream provenance (tip family, newest first):
- 5549834 kunchenguid#875 preserve trustworthy data in partial snapshots
- f61e65c kunchenguid#830 surface main inventory gaps
- c115561 kunchenguid#640 balance landed baseline
- 8934c17 kunchenguid#555 authoritative secondmate state
- 9ecd7c4 kunchenguid#485 concise and accurate bearings
- a6508b7 kunchenguid#475 deterministic bounded bearings snapshots

Tests: adapted core suite + decision-hold stub + blocked_by + chat contract.
shellcheck clean on the new script.
* fix(cmux): close the last/selected workspace in a window at teardown

cmux keeps every window at >=1 workspace, so close-workspace on the only
workspace in a window silently no-ops (returns OK, workspace stays), and a
window holding a live session cannot be closed over the control socket.
That left a selected task workspace open at teardown (the last workspace
in a window is always the selected one).

Add fm_backend_cmux_window_of_workspace and have fm_backend_cmux_kill
create a throwaway default sibling in the target's window before closing
when the target is the last workspace there, so the close lands; the
window keeps a fresh default workspace (cmux's own "closed the last tab"
outcome). Non-last teardown closes directly, as before.

Cover both kill branches plus the helper with fake-CLI unit tests, add a
real-cmux window/count detection smoke assertion, and record the
empirical evidence in docs/cmux-backend.md.

* no-mistakes(review): Derive cmux count from membership snapshot

* no-mistakes(document): Document cmux last-workspace teardown behavior

(cherry picked from commit 3f549c1)
…guid#520)

* fix: recover X/Discord follow-up platform after inbox cleanup

A milestone follow-up posted directly by request_id after the inbox was
drained - and with no task link, because one persistent secondmate's single
x_request slot collides across concurrent requests - resolved platform only
from the local inbox, so a >280 Discord reply silently defaulted to the X
280-char budget and threaded as (1/2).

- fm-x-poll records a durable per-request reply context
  (state/x-context/<rid>.json) at stash time, keyed by request_id so
  concurrent requests never overwrite each other; it survives inbox cleanup
  and restart.
- fm-x-reply resolves platform/budget through registry -> inbox -> relay
  (the relay lookup confined to a live follow-up), recovering the original
  platform independent of task-link availability.
- Fail-safe: a follow-up whose platform/budget cannot be authoritatively
  resolved and that would split is refused (exit 8) and held for retry,
  never wrongly split; fm-x-followup keeps the link on that exit.
- fm-x-dismiss clears the durable context for a dismissed mention.

Refactors reply-context extraction into a single owner and adds regression
coverage for all four cases.

* no-mistakes(review): Captain, fail closed on incomplete follow-up context

* no-mistakes(review): Captain, bound X context registry retention

* no-mistakes(review): Captain, align context retention with answer binding

* no-mistakes(document): Align X follow-up context documentation

* no-mistakes(document): Align durable X follow-up documentation

(cherry picked from commit b708731)
Copilot AI review requested due to automatic review settings July 23, 2026 02:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Keigyoku
Keigyoku merged commit e3a20b0 into main Jul 23, 2026
4 checks passed
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.

3 participants