Skip to content

feat(bin): enable claude's native prompt suggestion for secondmates#642

Open
LuckyB-UF wants to merge 9 commits into
kunchenguid:mainfrom
LuckyB-UF:fm/fm-sm-native-suggest-r1
Open

feat(bin): enable claude's native prompt suggestion for secondmates#642
LuckyB-UF wants to merge 9 commits into
kunchenguid:mainfrom
LuckyB-UF:fm/fm-sm-native-suggest-r1

Conversation

@LuckyB-UF

Copy link
Copy Markdown

Intent

Let claude SECONDMATE agents launch with the native predicted-next-prompt suggestion ENABLED so the captain sees it as in their own session, while ship/scout crewmates keep it DISABLED. fm-spawn.sh launch_template's claude case branches on kind as codex/pi already did; ship/scout stay byte-identical. Safety rests on the EXISTING one-owner fm_composer_strip_ghost, which every secondmate-reachable read already routes through. Review also surfaced a real send risk on zellij (plain-screen reader, content-diff submit could report a false success against rotating ghost text), so per captain decision zellij now refuses --secondmate exactly as orca and cmux do, and the docs were reconciled to that three-backend refusing set.

RESUMING AFTER A PUSH-ONLY FAILURE - this is a re-run of run 01KXNK1KVVHEXQG3SZJ6MB2SGT on the same branch, whose review, document and lint steps ALL COMPLETED CLEAN on this exact HEAD; test was skipped by captain decision. The only failure was the push step: the gate had fork_url=NULL so it pushed at upstream kunchenguid/firstmate, where the captain has no write access (403). The captain has now set fork_url=https://github.com/LuckyB-UF/firstmate.git, PRs still open against upstream. Review/document/lint/test are skipped by captain decision to avoid ~1h of redundant re-review on unchanged content.

DOCUMENT IN THE PR BODY that the test step was skipped and why: this machine's local env is red independently of this change - cloning the clean base commit and running the full suite there fails the same 2 deterministic tests (fm-backend-orca state-dir; fm-dispatch-select missing quota-axi) because the orca binary is absent locally, plus 2 full-suite flakes that pass in isolation on base and this branch. No coverage is lost: every affected suite passes locally (fm-spawn-dispatch-profile, fm-composer-ghost, fm-composer-lib, fm-secondmate-harness, fm-instruction-owners, fm-brief, fm-spawn-batch, fm-backend-zellij), fm-lint is clean, and GitHub CI runs the same suite in a clean env and still gates this PR.

What Changed

  • bin/fm-spawn.sh now branches its claude launch template on task kind, the same shape codex and pi already used: a secondmate launches without the CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false prefix so its captain-facing window shows the native predicted-next-prompt suggestion, while ship/scout crewmates keep the suggestion disabled and their launch command byte-identical. Safety rests on the existing single-owner fm_composer_strip_ghost, which every secondmate-reachable composer read already routes through.
  • The per-backend --secondmate refusals in fm-spawn.sh collapse into one case, and zellij joins orca and cmux in that refusing set, since its plain-screen reader cannot strip ghost styling and a content-diff submit could report false success against rotating ghost text. tests/fm-backend-zellij.test.sh pins that the refusal happens before any secondmate-home mutation.
  • Docs and comments reconcile to the three-backend refusing set (docs/configuration.md, docs/zellij-backend.md, docs/architecture.md, docs/herdr-backend.md, docs/tmux-backend.md, bin/fm-backend.sh, the harness-adapters skill), bin/fm-watch.sh notes why the paused-secondmate stale arm stays reachable, and tests/fm-spawn-dispatch-profile.test.sh plus tests/fm-composer-ghost.test.sh cover the kind split and the now load-bearing ghost-text extractor.

Note on the skipped test step

The test step was skipped by captain decision because this machine's local environment is red independently of this change: cloning the clean base commit and running the full suite there fails the same two deterministic tests (fm-backend-orca state-dir and fm-dispatch-select missing quota-axi, both because the orca binary is absent locally), plus two full-suite flakes that pass in isolation on both base and this branch. No coverage is lost — every affected suite passes locally (fm-spawn-dispatch-profile, fm-composer-ghost, fm-composer-lib, fm-secondmate-harness, fm-instruction-owners, fm-brief, fm-spawn-batch, fm-backend-zellij), fm-lint is clean, and GitHub CI runs the same suite in a clean environment and still gates this PR.

This is a re-run of an earlier pipeline run on this exact HEAD, whose review, document, and lint steps all completed clean; that run's only failure was the push step pushing at an upstream the captain has no write access to. Review, document, and lint are skipped here to avoid roughly an hour of redundant re-review on unchanged content.

Testing

  • ⏭️ Test - skipped

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⏭️ **Review** - skipped

Step was skipped.

⏭️ **Test** - skipped

Step was skipped.

⏭️ **Document** - skipped

Step was skipped.

⏭️ **Lint** - skipped

Step was skipped.

✅ **Push** - passed

✅ No issues found.

A secondmate is a captain-facing agent the captain reads and drives, so
its window should show claude's native predicted-next-prompt suggestion
exactly as the captain's own session does. A ship/scout crewmate is an
autonomous worker whose composer the captain never drives, so the ghost
text there has no reader to help and is pure classifier risk.

launch_template()'s claude case now branches on kind exactly as the codex
and pi cases already do: secondmate omits the
CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false prefix, ship/scout keep it.

Safety rests on the existing shared fm_composer_strip_ghost
(bin/fm-composer-lib.sh), the one fleet-wide ANSI-aware extractor of real
typed content. Audited every secondmate-reachable read path; all already
route through it, so no new stripping was added:
  - tmux: fm_tmux_composer_state strips ghost for content and keeps it for
    the structural bordered-shape read, per that lib's documented contract.
  - herdr: fm_backend_herdr_composer_state strips through the same owner.
  - fm-send: fm_backend_send_text_submit -> fm_tmux_submit_core ->
    fm_tmux_composer_state, so the submit check reads a ghost-only
    composer as empty rather than a swallowed Enter.
  - away-mode daemon: pane_input_pending -> fm_backend_composer_state ->
    the same per-backend owners.
  - agent liveness (fm_backend_{tmux,herdr}_agent_alive): reads the
    foreground process / agent state, never composer content, so ghost
    text cannot reach the verdict.
  - orca and cmux read a plain screen with no ANSI channel, but both
    refuse --secondmate spawns outright, so no secondmate can land on a
    reader that cannot strip ghost text.
  - zellij verifies submits by content diff and never reads composer
    emptiness, so ghost text is not read as pending.

Tests extend the existing suites rather than adding a runner:
fm-spawn-dispatch-profile pins the kind split (scout keeps the prefix,
secondmate omits it; the existing byte-identical assertion already pins
ship), and fm-composer-ghost's dim SGR 2 fixtures already pin the
classifier both ways through the real path - its header now records that
those guarantees became load-bearing for secondmates.

Skipped the optional kill-switch: the audit found complete coverage and
orca/cmux cannot host a secondmate, so a force-disable guard would add a
config surface, a doc entry, and a test for a hypothetical with no
uncovered path behind it.
@kunchenguid

kunchenguid commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Automated reminder: thanks for the PR! This branch currently has a merge conflict with the base branch.

When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again.

Noted for firstmate#642 at d8447ff6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants