Skip to content

feat(pi): make Calm mode conversation-only in the Pi TUI - #1278

Closed
morris2spears wants to merge 13 commits into
kunchenguid:mainfrom
morris2spears:fm/firstmate-pi-clean-chat
Closed

feat(pi): make Calm mode conversation-only in the Pi TUI#1278
morris2spears wants to merge 13 commits into
kunchenguid:mainfrom
morris2spears:fm/firstmate-pi-clean-chat

Conversation

@morris2spears

@morris2spears morris2spears commented Jul 30, 2026

Copy link
Copy Markdown

Intent

The developer wanted Firstmate's Pi conversation view to be conversation-only by default: Calm mode should hide ordinary tool call/result rows and their shells, internal thinking, the Pi working/status row, and all Firstmate operational injected input (watcher, turn-end guard, away-supervisor, session-start), while preserving real typed captain prompts and Firstmate's captain-facing replies exactly. They required extending the existing single Calm owner in .pi/extensions/fm-calm.ts rather than adding a second presentation mechanism, persisting Calm as this home's default and applying it immediately on reload with correct redraw of prior transcript rows, keeping /calm as a reversible toggle, and adding no "Calm enabled" banner or other replacement UI clutter. Constraints: no brittle terminal-output scraping or global hide-everything patch, stay within supported Pi 0.82.x APIs scoped to trusted interactive TUI mode, degrade safely if an upstream API disappears, and keep the change presentation-only so message delivery, model context, and supervision are unchanged. They also asked for focused tests on visibility rules, persistence, reload/redraw, and preservation of real captain/assistant conversation, plus full test and type/lint runs, with docs limited to what the existing classification requires. During no-mistakes validation the developer resolved the open question under decision key calm-tool-errors: show actionable tool errors only (explicit tool-turn abort/provider errors needing a response) while keeping routine tool activity hidden, applying that exact fix to every affected review-gate finding via the gate's own response command without --yes, then continuing validation.

What Changed

  • Extended the existing Calm owner in .pi/extensions/fm-calm.ts with two new layout modules (fm-calm-tool-layout.ts, fm-calm-nonconversation-layout.ts) so Calm now hides routine tool call/result rows and their shells, internal thinking, the Pi working/status row, and injected Firstmate operational input (watcher, turn-end guard, away-supervisor, session-start), including their leading spacers, while real captain prompts and Firstmate replies render unchanged. Actionable tool errors (aborted/provider failures on an interrupted assistant turn) still surface, clamped to terminal width, and are shown once per assistant turn across adapter reloads.
  • Calm stays persisted per home and reapplies on reload with prior transcript rows redrawn; /calm remains a reversible toggle with no added banner or replacement UI, and missing upstream Pi APIs degrade to a no-op rather than failing.
  • Grew tests/fm-calm-pi-extension.test.sh to 11 focused cases (visibility rules, persistence, reload/redraw, non-conversation rows, operational follow-ups, adapter degradation, real-Pi tmux E2E), fixed a stale composer-readiness probe in tests/fm-pi-primary-live-e2e.test.sh that had been short-circuiting the live suite, refreshed docs/calm.md plus the feasibility notes, and dropped a leaked .pi-live-e2e.* scratch gitlink from the tree.

Risk Assessment

⚠️ Medium: The tmux race is properly fixed and I confirmed against Pi 0.82.1's source that the eight new seams and the children-wrapping approach do not break any Pi code path that depends on child identity, class, or extra methods - but 308 new lines patching undocumented internal seams and swapping transcript children is broad enough to warrant follow-up attention, with one substantiated cosmetic reload-edge defect.

Testing

Ran the focused Calm suite (tests/fm-calm-pi-extension.test.sh, 11 cases green, including its real-Pi tmux E2E coverage of visibility rules, persistence, reload/redraw, and conversation preservation); tests/fm-pi-primary-types.test.sh skips here because tsc is not installed. Since passing tests alone would not show the captain-facing surface, I additionally drove a live Pi 0.82.1 TUI in tmux over a transcript containing every row class the intent names and captured the actual rendered pane in four states, producing a side-by-side screenshot and rendered HTML: Calm on shows only captain prompts and Firstmate replies while thinking, tool rows, routine tool failures, all injected operational input, user bash, branch and compaction rows and the Working row are hidden with no replacement banner; /calm restores every one of them and a second /calm re-hides them with prior rows redrawn; quit-and-relaunch keeps Calm on and redraws conversation-only. A captain message that merely quotes the operational marker stays visible, confirming genuine typed prompts are untouched. I did not re-run the opt-in credentialed live E2E (round 1 already ran it green after its probe fix, and it costs real provider credits); I did fix the artifact that run left behind - its scratch lab directory had been committed as a gitlink - by removing it and gitignoring the path. Worktree is otherwise clean.

  • Evidence: Side-by-side screenshot of the live Pi TUI: Calm on, Calm off, Calm re-enabled, after relaunch (local file: /var/folders/z5/m852gsm10ts0cd8hmbk2jjcw0000gn/T/no-mistakes-evidence/01KYR5N3KGY3V99JX0YB1QB74Q/calm-mode-panes.png)
Evidence: Rendered HTML of the same four terminal panes (color-preserving)
<!doctype html><meta charset="utf-8">
<title>Firstmate Pi Calm mode - real TUI panes</title>
<style>
 body{background:#12151c;color:#dcdfe4;font-family:-apple-system,Segoe UI,sans-serif;margin:24px}
 h1{font-size:20px;margin:0 0 4px}
 .lede{color:#96a0b5;font-size:13px;margin:0 0 20px;max-width:1100px;line-height:1.5}
 .grid{display:grid;grid-template-columns:1fr 1fr;gap:18px}
 section{background:#0b0e14;border:1px solid #232a36;border-radius:10px;padding:14px 16px}
 h2{font-size:14px;margin:0 0 2px;color:#e5c07b}
 .cap{margin:0 0 10px;font-size:12px;color:#8b94a7}
 pre{margin:0;font-family:SFMono-Regular,Menlo,monospace;font-size:11px;line-height:1.32;
     white-space:pre;overflow-x:auto;color:#dcdfe4}
</style>
<h1>Firstmate Pi Calm mode - captured from a live Pi 0.82.1 TUI</h1>
<p class="lede">Same resumed Pi session, same terminal, real <code>pi</code> process driven in tmux.
The transcript contains a captain prompt, internal thinking, routine tool calls and results, a routine
tool failure, injected Firstmate operational input (session-start, watcher, turn-end-guard,
away-supervisor), a user bash row, branch and compaction summaries, and Firstmate's replies.
Calm is this home's persisted default; <code>/calm</code> toggles it both ways.</p>
<div class="grid">
<section><h2>Calm ON (default for this home)</h2><p class='cap'>Conversation only: captain prompts + Firstmate replies. No thinking, no tool rows, no operational injections, no Working row, no Calm banner.</p><pre>
 pi v0.82.1
 escape interrupt · ctrl+c/ctrl+d clear/exit · / commands · ! bash · ctrl+o more
 Press ctrl+o to show full startup help and loaded resources.

 Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.

[Extensions]
  fm-calm.ts



 Captain: get the crew started on the login bug.


 Firstmate: crewmate 2 is on the login bug; I will report when its PR lands.


 Captain quote: FIRSTMATE_OP: v1 watcher: I typed this myself, keep it visible.



 Captain: now push it.


 Error

 Session compacted 1 time

 Warning: No models available. Use /login to log into a provider via OAuth or API key. See:
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/providers.md
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/models.md

 Warning: tmux extended-keys-format is xterm. Pi works best with csi-u. Add `set -g extended-keys-format csi-u` to
 ~/.tmux.conf and restart tmux.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
/var/folders/z5/m852gsm10ts0cd8hmbk2jjcw0000gn/T/calm-evidence.cbbYhm/project (main)
↑4 ↓4 0.0%/0 (auto)                                                                                              unknown</pre></section>
<section><h2>Calm OFF (after /calm)</h2><p class='cap'>Everything Pi normally renders comes back: tool calls, routine output and failures, injected operational input, user bash, branch/compaction rows.</p><pre>
 pi v0.82.1
 escape interrupt · ctrl+c/ctrl+d clear/exit · / commands · ! bash · ctrl+o more
 Press ctrl+o to show full startup help and loaded resources.

 Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.

[Extensions]
  fm-calm.ts



 [compaction]

 Compacted from 1,234 tokens (ctrl+o to expand)



 Captain: get the crew started on the login bug.


 INTERNAL REASONING the captain should never see


 $ ls crew-notes.txt

 ROUTINE TOOL OUTPUT crew-notes.txt


 MORE INTERNAL REASONING


 read missing.txt

 ROUTINE TOOL FAILURE no such file



 ⁣FIRSTMATE_OP: v1 watcher: crewmate 2 finished; check its PR.



 ⁣FIRSTMATE_OP: v1 turn-end-guard: TURN WOULD END BLIND - supervision is off.



 ⁣FIRSTMATE_OP: v1 away-supervisor: Supervisor escalate (1 event(s)): done: rollout


────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 $ printf USER_BASH_COMMAND

 USER_BASH_OUTPUT

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


 [branch]

 Branch summary (ctrl+o to expand)


 Firstmate: crewmate 2 is on the login bug; I will report when its PR lands.


 Captain quote: FIRSTMATE_OP: v1 watcher: I typed this myself, keep it visible.



 Captain: now push it.



 $ git push

 Error


 Session compacted 1 time

 Warning: No models available. Use /login to log into a provider via OAuth or API key. See:
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/providers.md
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/models.md

 Warning: tmux extended-keys-format is xterm. Pi works best with csi-u. Add `set -g extended-keys-format csi-u` to
 ~/.tmux.conf and restart tmux.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
/var/folders/z5/m852gsm10ts0cd8hmbk2jjcw0000gn/T/calm-evidence.cbbYhm/project (main)
↑4 ↓4 0.0%/0 (auto)                                                                                              unknown</pre></section>
<section><h2>Calm re-enabled (second /calm)</h2><p class='cap'>Prior transcript rows are redrawn at zero height again - no restart needed.</p><pre>
 pi v0.82.1
 escape interrupt · ctrl+c/ctrl+d clear/exit · / commands · ! bash · ctrl+o more
 Press ctrl+o to show full startup help and loaded resources.

 Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.

[Extensions]
  fm-calm.ts



 Captain: get the crew started on the login bug.


 Firstmate: crewmate 2 is on the login bug; I will report when its PR lands.


 Captain quote: FIRSTMATE_OP: v1 watcher: I typed this myself, keep it visible.



 Captain: now push it.


 Error

 Session compacted 1 time

 Warning: No models available. Use /login to log into a provider via OAuth or API key. See:
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/providers.md
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/models.md

 Warning: tmux extended-keys-format is xterm. Pi works best with csi-u. Add `set -g extended-keys-format csi-u` to
 ~/.tmux.conf and restart tmux.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
/var/folders/z5/m852gsm10ts0cd8hmbk2jjcw0000gn/T/calm-evidence.cbbYhm/project (main)
↑4 ↓4 0.0%/0 (auto)                                                                                              unknown</pre></section>
<section><h2>After /quit + relaunch</h2><p class='cap'>Calm persisted on disk, applied immediately on reload; the resumed transcript redraws conversation-only.</p><pre>
 pi v0.82.1
 escape interrupt · ctrl+c/ctrl+d clear/exit · / commands · ! bash · ctrl+o more
 Press ctrl+o to show full startup help and loaded resources.

 Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.

[Extensions]
  fm-calm.ts



 Captain: get the crew started on the login bug.


 Firstmate: crewmate 2 is on the login bug; I will report when its PR lands.


 Captain quote: FIRSTMATE_OP: v1 watcher: I typed this myself, keep it visible.



 Captain: now push it.


 Error

 Session compacted 1 time

 Warning: No models available. Use /login to log into a provider via OAuth or API key. See:
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/providers.md
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/models.md

 Warning: tmux extended-keys-format is xterm. Pi works best with csi-u. Add `set -g extended-keys-format csi-u` to
 ~/.tmux.conf and restart tmux.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
/var/folders/z5/m852gsm10ts0cd8hmbk2jjcw0000gn/T/calm-evidence.cbbYhm/project (main)
↑4 ↓4 0.0%/0 (auto)                                                                                              unknown</pre></section>
</div>
Evidence: Raw tmux pane capture - Calm ON (conversation only)

 pi v0.82.1
 escape interrupt · ctrl+c/ctrl+d clear/exit · / commands · ! bash · ctrl+o more
 Press ctrl+o to show full startup help and loaded resources.

 Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.

[Extensions]
  fm-calm.ts



 Captain: get the crew started on the login bug.


 Firstmate: crewmate 2 is on the login bug; I will report when its PR lands.


 Captain quote: FIRSTMATE_OP: v1 watcher: I typed this myself, keep it visible.



 Captain: now push it.


 Error

 Session compacted 1 time

 Warning: No models available. Use /login to log into a provider via OAuth or API key. See:
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/providers.md
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/models.md

 Warning: tmux extended-keys-format is xterm. Pi works best with csi-u. Add `set -g extended-keys-format csi-u` to
 ~/.tmux.conf and restart tmux.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
/var/folders/z5/m852gsm10ts0cd8hmbk2jjcw0000gn/T/calm-evidence.cbbYhm/project (main)
↑4 ↓4 0.0%/0 (auto)                                                                                              unknown
Evidence: Raw tmux pane capture - Calm OFF (everything restored)

 pi v0.82.1
 escape interrupt · ctrl+c/ctrl+d clear/exit · / commands · ! bash · ctrl+o more
 Press ctrl+o to show full startup help and loaded resources.

 Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.

[Extensions]
  fm-calm.ts



 [compaction]

 Compacted from 1,234 tokens (ctrl+o to expand)



 Captain: get the crew started on the login bug.


 INTERNAL REASONING the captain should never see


 $ ls crew-notes.txt

 ROUTINE TOOL OUTPUT crew-notes.txt


 MORE INTERNAL REASONING


 read missing.txt

 ROUTINE TOOL FAILURE no such file



 ⁣FIRSTMATE_OP: v1 watcher: crewmate 2 finished; check its PR.



 ⁣FIRSTMATE_OP: v1 turn-end-guard: TURN WOULD END BLIND - supervision is off.



 ⁣FIRSTMATE_OP: v1 away-supervisor: Supervisor escalate (1 event(s)): done: rollout


────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 $ printf USER_BASH_COMMAND

 USER_BASH_OUTPUT

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────


 [branch]

 Branch summary (ctrl+o to expand)


 Firstmate: crewmate 2 is on the login bug; I will report when its PR lands.


 Captain quote: FIRSTMATE_OP: v1 watcher: I typed this myself, keep it visible.



 Captain: now push it.



 $ git push

 Error


 Session compacted 1 time

 Warning: No models available. Use /login to log into a provider via OAuth or API key. See:
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/providers.md
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/models.md

 Warning: tmux extended-keys-format is xterm. Pi works best with csi-u. Add `set -g extended-keys-format csi-u` to
 ~/.tmux.conf and restart tmux.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
/var/folders/z5/m852gsm10ts0cd8hmbk2jjcw0000gn/T/calm-evidence.cbbYhm/project (main)
↑4 ↓4 0.0%/0 (auto)                                                                                              unknown
Evidence: Raw tmux pane capture - Calm re-enabled by a second /calm

 pi v0.82.1
 escape interrupt · ctrl+c/ctrl+d clear/exit · / commands · ! bash · ctrl+o more
 Press ctrl+o to show full startup help and loaded resources.

 Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.

[Extensions]
  fm-calm.ts



 Captain: get the crew started on the login bug.


 Firstmate: crewmate 2 is on the login bug; I will report when its PR lands.


 Captain quote: FIRSTMATE_OP: v1 watcher: I typed this myself, keep it visible.



 Captain: now push it.


 Error

 Session compacted 1 time

 Warning: No models available. Use /login to log into a provider via OAuth or API key. See:
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/providers.md
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/models.md

 Warning: tmux extended-keys-format is xterm. Pi works best with csi-u. Add `set -g extended-keys-format csi-u` to
 ~/.tmux.conf and restart tmux.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
/var/folders/z5/m852gsm10ts0cd8hmbk2jjcw0000gn/T/calm-evidence.cbbYhm/project (main)
↑4 ↓4 0.0%/0 (auto)                                                                                              unknown
Evidence: Raw tmux pane capture - after /quit and relaunch (Calm persisted on)

 pi v0.82.1
 escape interrupt · ctrl+c/ctrl+d clear/exit · / commands · ! bash · ctrl+o more
 Press ctrl+o to show full startup help and loaded resources.

 Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.

[Extensions]
  fm-calm.ts



 Captain: get the crew started on the login bug.


 Firstmate: crewmate 2 is on the login bug; I will report when its PR lands.


 Captain quote: FIRSTMATE_OP: v1 watcher: I typed this myself, keep it visible.



 Captain: now push it.


 Error

 Session compacted 1 time

 Warning: No models available. Use /login to log into a provider via OAuth or API key. See:
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/providers.md
   /opt/homebrew/lib/node_modules/@earendil-works/pi-coding-agent/docs/models.md

 Warning: tmux extended-keys-format is xterm. Pi works best with csi-u. Add `set -g extended-keys-format csi-u` to
 ~/.tmux.conf and restart tmux.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
/var/folders/z5/m852gsm10ts0cd8hmbk2jjcw0000gn/T/calm-evidence.cbbYhm/project (main)
↑4 ↓4 0.0%/0 (auto)                                                                                              unknown
Evidence: Row-visibility matrix measured from the live panes
marker calm-on calm-off re-enabled after-restart
session-start: Run bin 0 0 0 0
watcher: crewmate 2 0 1 0 0
turn-end-guard: TURN WOULD END BLIND 0 1 0 0
away-supervisor: Supervisor escalate 0 1 0 0
INTERNAL REASONING 0 2 0 0
ROUTINE TOOL OUTPUT 0 1 0 0
ROUTINE TOOL FAILURE 0 1 0 0
ls crew-notes.txt 0 1 0 0
USER_BASH_OUTPUT 0 1 0 0
[branch] 0 1 0 0
[compaction] 0 1 0 0
Captain: get the crew 1 1 1 1
Captain: now push it. 1 1 1 1
Captain quote: FIRSTMATE_OP 1 1 1 1
Firstmate: crewmate 2 is on the login bug 1 1 1 1
- Outcome: 🔧 1 issue found → auto-fixed ✅ across 2 runs (25m42s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 1 info
  • ⚠️ tests/fm-calm-pi-extension.test.sh:1792 - The e2e helpers no longer kill the prior tmux session (or wait for Pi to exit) before creating a new one with the same name; they only sleep 0.2 after sending /quit. Since the file runs under set -u without -e, a slow Pi exit makes tmux new-session -s fm-calm-e2e fail non-fatally and every following capture-pane/send-keys targets the OLD, dying session. In run_followup_case (9 sequential invocations) the stale pane still contains followup-e2e.ts, so the readiness loop breaks immediately and the /followup-e2e &lt;label&gt; keys are typed into the exiting session, yielding a confusing timeout failure - or, for the generic asserts, a pass against the previous case's transcript. Same pattern at lines 1918, 2074, 2398 and 2673. Additionally, the Calm-persistence restart at line 2671 replaced wait_for_text &#34;PI_EXIT=0&#34; with sleep 0.2, dropping the clean-exit assertion the previous code made. Fix: before each new-session, either restore tmux kill-session -t &#34;$TMUX_SESSION&#34; 2&gt;/dev/null || true or poll tmux has-session until the prior session is gone.
  • ℹ️ docs/calm.md:9 - The rewritten operator doc states what Calm removes but no longer discloses what still renders. !bash rows (BashExecutionComponent), skill-invocation rows, compaction/branch summaries, cache-miss notices and unrelated custom entries have no adapter and remain fully visible - the previous version of this file said so explicitly, and docs/calm-mode-feasibility.md still documents it in its taxonomy table's last row. Re-adding one sentence keeps the operator-facing doc from implying a stricter conversation-only guarantee than the implementation makes.
  • ℹ️ tests/fm-calm-pi-extension.test.sh:38 - mkdir -p &#34;$TMP_ROOT&#34; and FM_TEST_CLEANUP_DIRS+=(&#34;$TMP_ROOT&#34;) are redundant: fm_test_tmproot already creates the directory via mktemp -d and registers it for EXIT cleanup (tests/lib.sh:69-77), so this double-registers the same path. Only the cp of fm-operational-input.sh into $TMP_ROOT is actually needed here.

🔧 Fix: hide remaining non-conversation Calm rows; fix tmux e2e race
1 info still open:

  • ℹ️ .pi/extensions/lib/fm-calm-nonconversation-layout.ts:233 - The leading-spacer wrapper captures rowHides at mount time (const rowHides = calmHidesRow(row) on line 231), so the wrapper closes over the closure belonging to whichever module instance was live when the row was mounted. Pi re-evaluates the extension modules on every reload while the surviving prototype wrappers keep the registry object - which is exactly why the tool-error turn scope is registry-held - but a spacer wrapper created before a reload keeps calling the OLD module's calmPresentationHides, and only the NEW module's setCalmPresentation is updated by fm-calm.ts. Concrete path: Calm on, a compaction summary (or branch summary / skill block) already rendered, extensions reload (session_start reason "reload"), then /calm off - the summary row reappears (its prototype patch reads the registry-updated patch.hides) but its leading blank line stays suppressed; the reverse order leaves a stray blank line where a hidden row used to be, which is the gaplessness this feature asserts elsewhere. Impact is one stray/missing blank line, not lost content. Fix: resolve the policy lazily inside the wrapper, e.g. calmConditionalRow(spacer, () =&gt; calmHidesRow(row)?.() ?? false), since calmHidesRow reads the shared symbol-keyed map and is always current.
🔧 **Test** - 1 issue found → auto-fixed ✅
  • ⚠️ tests/fm-pi-primary-live-e2e.test.sh:298 - tests/fm-pi-primary-live-e2e.test.sh failed immediately with "Pi did not reach its ready composer": its readiness probe waited for "(openai-codex)" in the composer footer, which Pi 0.82.x no longer prints (the footer shows "gpt-5.6-sol • low"). The probe predates this branch, so the branch's new Calm working-row suppression assertion on the credentialed provider path had never actually executed. Fixed by pinning the probe to the model id; the suite then passed end-to-end.
  • bash tests/fm-calm-pi-extension.test.sh - all 11 focused Calm cases (visibility rules, persistence, reload/redraw, adapter degradation, tmux TUI E2E) pass
  • FM_PI_LIVE_E2E=1 bash tests/fm-pi-primary-live-e2e.test.sh - failed on a stale composer-readiness probe, fixed the probe, re-ran: ok - Pi 0.82.1 live E2E covered native Calm working suppression, Ahoy first/later messages, legacy transcripts, near misses, and watcher continuity
  • bash tests/fm-documentation-audiences.test.sh - doc classification for the changed docs/calm.md, docs/configuration.md, README.md
  • bash tests/fm-pi-primary-types.test.sh - reports skip: tsc not found in this environment (typecheck is the type/lint phase's concern, not run here)
  • Manual TUI evidence A: drove real pi 0.82.1 in tmux over a replayed session containing a captain prompt, thinking, bash tool call/result, all five encoded operational inputs, a user bash row, a compaction summary and Firstmate replies; captured the viewport with Calm on (home default) and again after /calm, and read back the persisted config/calm value (on -> off)
  • Manual TUI evidence B: drove real pi with a deterministic faux provider to compare a routine failing tool turn (stays hidden) against an escape-interrupted tool turn (surfaces Operation aborted) with Calm on

🔧 Fix: fix stale Pi composer readiness probe in live e2e
✅ Re-checked - no issues remain.

  • bash tests/fm-calm-pi-extension.test.sh - all 11 focused cases pass, including the real-Pi tmux E2E cases for rendering, persistence, reload/redraw, non-conversation rows, operational follow-ups, and adapter degradation
  • bash tests/fm-pi-primary-types.test.sh - skips on this box (no tsc installed); typecheck is owned by the lint phase
  • Manual end-user demo: launched a real pi 0.82.1 in tmux (PI_OFFLINE=1, project-scoped fm-calm.ts, FM_HOME with config/calm=on) resuming a session transcript containing a captain prompt, internal thinking, routine tool calls/results, a routine tool failure, session-start/watcher/turn-end-guard/away-supervisor injected input, a user bash row, branch and compaction summaries, a captain message that quotes the operational marker, and Firstmate replies
  • Captured the rendered pane with tmux capture-pane -e -p -S -300 at four points: Calm on by default, after /calm (off), after a second /calm (re-enabled), and after /quit plus relaunch
  • Rendered the ANSI captures to HTML and screenshotted with headless Chrome for reviewer-visible visual evidence
  • Verified $FM_HOME/config/calm flipped to off then back to on across the two /calm toggles and stayed on across relaunch
  • git rm --cached .pi-live-e2e.19827/project plus a .pi-live-e2e.* gitignore entry to remove the leaked live-e2e scratch gitlink committed by the previous round
✅ **Document** - passed

✅ No issues found.

⚠️ **Lint** - 1 warning
  • ⚠️ linter found issues (exit code 127)
✅ **Push** - passed

✅ No issues found.

morris2spears and others added 13 commits July 29, 2026 14:56
…e-inbox bridge (#1)

* feat: add Telegram mode - two-way captain phone chat through the phone-inbox bridge

Inert until a home opts in via the gitignored config/telegram-mode flag.
Bootstrap then arms a byte-validated tg-watch.check.sh identity shim and a
30s cadence config, exactly the X-mode contract; the watcher dispatches the
trusted bin/fm-tg-poll.sh, which surfaces pending phone-inbox note ids
(never bodies, never text-derived filename slugs) as tg-message wakes with
durable offer markers, pruning and a 30-minute re-offer. The fmtg-respond
skill owns claim/classify/act/reply through the phone-inbox durable bridge,
with fm-tg-link.sh and fm-tg-followup.sh carrying milestone and final
follow-ups under a local cap and window. Reversible lifecycle actions only:
destructive, irreversible, and security-sensitive actions still require the
captain in a trusted session. No firstmate-side code reads the bot token.

* no-mistakes(review): fix telegram poll dedupe dir, cadence block, doc drift

* no-mistakes(document): document telegram mode in stale doc owners

* no-mistakes(review): clear tg follow-up link on counter write failure

* no-mistakes(document): document tg follow-up link-clear fallback and opt-out behavior

* test: use the sanctioned /dev/null source directive in the tg suite

The lint meta-contract pins the exact set of interop tests allowed a
'# shellcheck source=bin/' directive; test files that source production
libs use 'source=/dev/null', the same idiom as the X security and
turn-end guard suites.
@morris2spears morris2spears changed the title feat(pi): make Calm mode a conversation-only Pi transcript feat(pi): make Calm mode conversation-only in the Pi TUI Jul 30, 2026
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