fix(calm): gate loud thinking-field check to active hides and harden restore - #2643
Open
juangedaan wants to merge 6 commits into
Open
fix(calm): gate loud thinking-field check to active hides and harden restore#2643juangedaan wants to merge 6 commits into
juangedaan wants to merge 6 commits into
Conversation
…e on throw installCalmAssistantLayout verified updateContent exists but silently trusted the private hiddenThinkingLabel and hideThinkingBlock fields; a Pi upgrade that renamed either would silently regress the hidden-block gaps instead of failing loudly. The lastMessage restore also never ran when the original updateContent threw mid-render, making the original thinking content unrecoverable in the TUI; it now runs in a finally block. The geometry E2E's wait_for_geometry_transition only passed if a 10ms polling loop caught the transient reload banner before repaint. It now accepts the settled final text after a grace period instead of racing the banner. The five nested per-test helpers duplicating top-level machinery move to top-level, and two manual wait-until-absent loops reuse the new shared wait_for_geometry_absence helper.
…eload completion banner
… compatibility contract
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
The developer was working in the firstmate repo to implement four verified code-review findings on commit 6b0d21d with the smallest correct diffs: adding a loud existence check for the private Pi adapter fields hiddenThinkingLabel and hideThinkingBlock in .pi/extensions/lib/fm-calm-assistant-layout.ts, making the lastMessage restore robust if updateContent throws mid-render, removing a 10ms polling race in the geometry E2E test's reload-transition wait, and consolidating five nested duplicated shell test helpers into top-level ones. Explicit constraints included loading the firstmate-coding-guidelines skill first, following repo style (one sentence per line, plain dashes, shellcheck-clean scripts, colocated tests, no agent co-author), running the full test suite and shellcheck, and delivering through the no-mistakes validation pipeline to a PR without hand-fixing findings during a run. When the pipeline's reviewer flagged that the test fix relied on a fixed sleep, the developer (via the captain's decision) required a real positive post-reload synchronization signal that cannot match stale content, with a bounded timeout that fails loudly rather than passing vacuously. A later review finding led to a further decision to gate the field-existence check so it only throws when Calm is actively hiding thinking, keeping rendering unaffected for Calm-off and export paths, with updated comments, docs/calm.md, and tests proving both behaviors. Delivery was rerouted through a fork (juangedaan/firstmate) after push permission to the upstream repo was denied, with the goal of an open upstream PR with green CI.
What Changed
hiddenThinkingLabel/hideThinkingBlockfields and throws a named error if a Pi upgrade renames them — but only on renders where Calm is actively hiding thinking; Calm-off and stock export renders never read the fields and are unaffected.state.lastMessagerestoration was moved into afinallyblock so it survives anupdateContentthrow mid-render.start_geometry_pi,wait_for_geometry_text,wait_for_geometry_absence,assert_geometry_gap). A new colocated test covers the gated field check and the throw-path restore.The pipeline passed intent, rebase, test, document, lint, and push checks; review left two informational notes (a two-sentence doc line and a residual fixed settle sleep after the banner sync, an accepted flake-vs-staleness tradeoff).
Risk Assessment
✅ Low: Small, well-bounded change implementing four reviewed findings: the gated field check and try/finally restore are verified correct against the visibility module's semantics, the new fixture test covers all four behavior branches, the consolidated shell helpers are correctly parameterized with no dangling references, and shellcheck is clean — the only findings are a docs line-style nit and an acknowledged, loud-failing test-timing tradeoff.
Testing
Ran the two tests colocated with the change — the new field-check/restore unit test and the full hidden-block geometry E2E against real Pi 0.84.2 in tmux — both pass; captured the actual post-reload terminal viewport (completion banner + correct 2-row geometry, the end-user TUI surface) and a CLI transcript demonstrating the loud field-check error fires only while Calm actively hides thinking. The TUI evidence is a tmux capture-pane text transcript because the product surface is a terminal UI, so pane text is the rendered surface; no browser/pixel surface exists to screenshot.
Evidence: Post-/reload TUI viewport: persistent 'Reloaded ...' completion banner with correct 2-row hidden-block geometry
[skill] ahoy (ctrl+o to expand) CALM_GEOMETRY_FINAL - visible row one - visible row two Reloaded keybindings, extensions, skills, prompts, themes, and context filesEvidence: Gated field-check demo: loud error only while Calm hides thinking; Calm-off and export renders untouched
Calm ON (hiding thinking) -> throws loudly: Firstmate Calm requires AssistantMessageComponent.hiddenThinkingLabel and hideThinkingBlock Calm OFF -> renders normally, fields never read Stock export (Calm ON) -> renders normally, fields never readEvidence: Focused test run: both targeted tests pass against Pi 0.84.2
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
docs/calm.md:39- The added compatibility-contract line contains two sentences on a single line, breaking the one-sentence-per-line convention used throughout docs/calm.md (and stated as an explicit repo constraint). Split 'Renders with Calm presentation off and stock export renders never read those fields and are unaffected by the check.' onto its own line.tests/fm-calm-pi-extension.test.sh:2276- The post-reload geometry assertion still uses a fixed 2s settle sleep (GEOMETRY_RELOAD_SETTLE_SECONDS) after the completion-banner wait, then a single capture. This is a deliberate, commented grace period after a real positive sync signal, and an undersized sleep on a slow machine can only cause a loud failure (never a vacuous pass) — polling the gap instead would risk matching stale pre-reload content, which also shows the expected 2-row gap. Acceptable tradeoff; noting it as residual flake surface on slow CI.✅ **Test** - passed
✅ No issues found.
test_calm_assistant_layout_field_check_and_restore(new colocated test in tests/fm-calm-pi-extension.test.sh) via a focused runner — passestest_hidden_block_geometry_e2e(full TUI E2E in tmux against installed Pi 0.84.2, exercising the new reload completion-banner sync, the consolidated top-level geometry helpers, and both wait_for_geometry_absence call sites) — passesManual CLI demo: renamed private fields throw the named error only while Calm actively hides thinking; Calm-off and stock-export renders proceed untouchedCaptured the post-reload tmux viewport showing the persistent 'Reloaded ...' completion banner and the asserted 2-row gap between the collapsed skill row and CALM_GEOMETRY_FINAL✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.