Skip to content

chore: restore upstream content for three captain-environment-only hunks - #82

Merged
ironerumi merged 2 commits into
mainfrom
fm/env-items-home
Oct 5, 2026
Merged

ironerumi merged 2 commits into
mainfrom
fm/env-items-home

Conversation

@ironerumi

Copy link
Copy Markdown
Owner

Intent

Second step of shrinking this fork's divergence from kunchenguid/firstmate (fork sync rethink report 2026-09-30, decision R3): three hunks that only existed because of the captain's own machine environment go home to that environment, and the fork reverts to upstream content for them.

  1. Auto-compact: the captain's user-scope ~/.claude/settings.json now sets autoCompactEnabled true with autoCompactWindow 500000 (dotfiles d06c249), so bin/fm-spawn.sh no longer needs to write those two keys into each crew worktree's .claude/settings.local.json. The spawned file carries only the lifecycle hooks again, exactly as upstream writes it. The harness-adapters Claude reference and the stuck-crewmate-recovery skill lose the fork-only prose that explained the override; the stuck-crewmate line returns to upstream's "modern harnesses auto-compact and keep going". tests/fm-spawn-claude-attribution.test.sh drops the two auto-compact assertions and keeps pinning the hooks and the absence of the attribution object.

  2. Calm widget key: the standalone Pi Calm in the captain's dotfiles now uses the firstmate-calm-working-ship widget slot (dotfiles d06c249), so .pi/extensions/lib/fm-calm-working-ship.ts returns to upstream's key and comment; dual-install sessions still render one boat. Upstream PR fix: share Pi Calm's working-ship widget slot kunchenguid/firstmate#1854 becomes unnecessary.

  3. .sessions/: the captain retired the session export that wrote .sessions/ into repos (skills-sprint 017793b), so the fork's .gitignore line for it is dead and is removed.

Deliberate non-goals: no behavior replacement is added in the fork for any of the three; per-project auto-compact pins, if ever wanted, are a project-scope settings matter outside this repo. Local evidence: bin/fm-lint.sh --fast clean on bin/fm-spawn.sh and the attribution test; tests/fm-spawn-claude-attribution.test.sh passes.

What Changed

  • bin/fm-spawn.sh no longer writes autoCompactEnabled/autoCompactWindow into each crew worktree's .claude/settings.local.json; the spawned file now carries only the lifecycle hooks, and tests/fm-spawn-claude-attribution.test.sh drops the two auto-compact assertions while still pinning the hooks and the absence of the attribution object. The harness-adapters Claude reference and the stuck-crewmate-recovery skill lose the fork-only prose explaining that override, with the stuck-crewmate line returning to upstream's "modern harnesses auto-compact and keep going".
  • .pi/extensions/lib/fm-calm-working-ship.ts reverts CALM_WORKING_SHIP_WIDGET_KEY (and its comment) to upstream's firstmate-calm-working-ship slot, and tests/fm-calm-pi-extension.test.sh drops the assertion pinning the shared calm-working-ship key.
  • .gitignore drops the now-dead .sessions/ entry.

Risk Assessment

✅ Low: Clean, well-bounded revert-to-upstream of three environment-specific hunks that removes code and assertions with no dangling references, valid generated JSON, and source files matching upstream 349e189 exactly as the intent requires.

Testing

Phase 1 ran the two changed test scripts serially (jobs 1, 300s/script). fm-spawn-claude-attribution passed: it drives fm-spawn.sh's claude branch and asserts the real generated .claude/settings.local.json via jq — hooks present for all four lifecycle events, no attribution object, and (per intent) no autoCompactEnabled/autoCompactWindow keys. fm-calm-pi-extension failed, but on an unrelated pre-existing assertion (Pi package createToolHtmlRenderer tool-HTML export under Pi 1.0.3 + node v25.8.1), which crashed the node eval before the working-ship test and is causally independent of the one-line widget-key edit. To prove scenario 2 I drove the working-ship geometry/lifecycle test in isolation against the real Pi package: the boat registers and renders under CALM_WORKING_SHIP_WIDGET_KEY (now firstmate-calm-working-ship) as exactly one boat, passing. No reviewer-visible screenshot was captured because the Calm boat surface is a terminal-TUI widget exercised headlessly through the Pi package's render API, not a browser/Electron surface; the render assertions in the passing working-ship test are the product-level evidence. The .gitignore line removal and the claude.md / stuck-crewmate-recovery prose removals have no live-exercisable runtime surface. Both driveable scenarios pass; the transient scoped test copy was removed and the worktree is clean.

  • Live validation: ✅ go - 2 of 4 scenarios driven live against the product
Scenario Result Live Evidence
Spawning a Claude crew worktree: generated .claude/settings.local.json carries the four lifecycle hooks and no attribution object, and no longer writes autoCompactEnabled/autoCompactWindow ✅ pass live tests/fm-spawn-claude-attribution.test.sh drives fm-spawn.sh and asserts the real generated JSON via jq (has hooks, has("attribution")|not, and the two autoCompact assertions removed per intent)
Calm working-ship widget registers and renders as one boat under the restored firstmate-calm-working-ship key (dual-install slot sharing preserved) ✅ pass live test_working_ship_geometry_and_lifecycle from tests/fm-calm-pi-extension.test.sh driven in isolation against the real Pi 1.0.3 package; boat registers under CALM_WORKING_SHIP_WIDGET_KEY and passes ful…
Removing the dead .sessions/ .gitignore line changes no runtime behavior ⏸️ untested no Declarative ignore-file hunk with no live-exercisable runtime product surface; the behavior that produced .sessions/ no longer exists, so removal is dead-config cleanup with no end-user action to driv…
Removing fork-only auto-compact prose from harness-adapters claude.md and stuck-crewmate-recovery SKILL.md ⏸️ untested no Documentation-only prose change with no runtime product surface to drive; no observable end-user behavior to exercise live.
Evidence: Phase 1 + scenario-2 isolation record

Source: Phase 1 + scenario-2 isolation record

Phase 1 narrowed suites (changed test scripts in diff):
- tests/fm-spawn-claude-attribution.test.sh  => PASS (2 tests ok)
    drives fm-spawn.sh claude branch; asserts generated .claude/settings.local.json
    carries hooks, no attribution, and (per intent) no autoCompact keys.
- tests/fm-calm-pi-extension.test.sh          => FAILED at unrelated renderer test
    "Pi calm renderer and lifecycle contract" assertStockHtmlRendering:
    "grep disappeared from /export calm.html HTML while calm mode was on"
    Node.js v25.8.1 crashed the node eval; working-ship test did not run.
    Failure is in tool-call-row export HTML path, NOT the working-ship widget key.
    Needs causation check vs base commit d72ca55.

--- Scenario 2 isolation (phase 2) ---
Env: Pi @earendil-works/pi-coding-agent 1.0.3, node v25.8.1.
Drove test_working_ship_geometry_and_lifecycle in isolation (scoped copy, removed after):
  PASS - "Pi Calm working ship keeps its centered two-row asymmetric Unicode boat...
          freezes and resumes across settle/start... leaves Calm-off visibility untouched"
  This registers the boat under CALM_WORKING_SHIP_WIDGET_KEY (now "firstmate-calm-working-ship")
  via the real Pi package and asserts one-boat geometry/lifecycle. Scenario 2 proven.

Causation of the fm-calm-pi-extension suite failure:
  Failing assert = createToolHtmlRenderer().renderCall("grep",...) returns falsy under Pi 1.0.3
  (tool HTML export path). Independent of the one-line widget-key string edit; pre-existing /
  environmental (Pi 1.0.3 + node v25.8). Covered by CI; not introduced by this change.
Evidence: fm-spawn settings: hooks present, no attribution, no autoCompact
ok - claude spawn settings carry the hooks and no per-worker attribution object
ok - non-claude spawn carries no claude settings file
# all fm-spawn-claude-attribution tests passed
FM_TEST_END exit=0
Evidence: Scenario 2: isolated working-ship boat renders under firstmate-calm-working-ship key
ok - Pi Calm working ship keeps its centered two-row asymmetric Unicode boat inside a deterministic long-wave trough ... freezes and resumes across settle/start ... leaves Calm-off visibility untouched
FM_TEST_END exit=0 (Pi 1.0.3, node v25.8.1)
- Outcome: ⚠️ 1 info across 1 run (5m48s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 1 issue found → auto-fixed ✅
  • 🚨 .pi/extensions/lib/fm-calm-working-ship.ts:47 - Changing CALM_WORKING_SHIP_WIDGET_KEY to "firstmate-calm-working-ship" breaks an existing behavioral test that was not updated. tests/fm-calm-pi-extension.test.sh:3017 imports the real module and asserts CALM_WORKING_SHIP_WIDGET_KEY === "calm-working-ship", throwing a hard failure otherwise; the diff does not touch that test, so it will now fail. (The stale slot-sharing comment/message at tests/fm-calm-pi-extension.test.sh:2952-2960 and :3018 describe the old contract but only line 3017 is the failing assertion.) The remedy — aligning the expected key to "firstmate-calm-working-ship", matching the Claude mod's CALM_SHIP_RASTER_KEY and the intent — is a mechanical correction that completes the authoritative key change, not a behavior change.

🔧 Fix applied.
✅ Re-checked - no issues remain.

⚠️ **Test** - 1 info
  • ℹ️ tests/fm-calm-pi-extension.test.sh:1685 - tests/fm-calm-pi-extension.test.sh fails on an unrelated pre-existing assertion: test_rendering_and_session_lifecycle's assertStockHtmlRendering reports "grep disappeared from /export calm.html HTML while calm mode was on" because the Pi package's createToolHtmlRenderer().renderCall returns falsy under the installed Pi 1.0.3 + node v25.8.1. This is the tool-HTML-export code path and is causally independent of this change's one-line widget-key edit ("calm-working-ship" -> "firstmate-calm-working-ship"). The crash aborts the suite before the working-ship test, so I drove that test in isolation (passed). Not introduced by this change; broad regression is owned by CI.
  • Live validation: ✅ go - 2 of 4 scenarios driven live against the product
Scenario Result Live Evidence
Spawning a Claude crew worktree: generated .claude/settings.local.json carries the four lifecycle hooks and no attribution object, and no longer writes autoCompactEnabled/autoCompactWindow ✅ pass live tests/fm-spawn-claude-attribution.test.sh drives fm-spawn.sh and asserts the real generated JSON via jq (has hooks, has("attribution")|not, and the two autoCompact assertions removed per intent)
Calm working-ship widget registers and renders as one boat under the restored firstmate-calm-working-ship key (dual-install slot sharing preserved) ✅ pass live test_working_ship_geometry_and_lifecycle from tests/fm-calm-pi-extension.test.sh driven in isolation against the real Pi 1.0.3 package; boat registers under CALM_WORKING_SHIP_WIDGET_KEY and passes ful…
Removing the dead .sessions/ .gitignore line changes no runtime behavior ⏸️ untested no Declarative ignore-file hunk with no live-exercisable runtime product surface; the behavior that produced .sessions/ no longer exists, so removal is dead-config cleanup with no end-user action to driv…
Removing fork-only auto-compact prose from harness-adapters claude.md and stuck-crewmate-recovery SKILL.md ⏸️ untested no Documentation-only prose change with no runtime product surface to drive; no observable end-user behavior to exercise live.
  • bin/fm-test-run.sh --jobs 1 --per-script-timeout-secs 300 tests/fm-spawn-claude-attribution.test.sh (PASS)
  • bin/fm-test-run.sh --jobs 1 --per-script-timeout-secs 300 tests/fm-calm-pi-extension.test.sh (FAILED on unrelated renderer assertion; crashed before working-ship test)
  • Drove test_working_ship_geometry_and_lifecycle in isolation via a scoped copy of the suite against the real Pi 1.0.3 package (PASS); copy removed, worktree clean
⚠️ **Document** - 1 info
✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@ironerumi
ironerumi merged commit 71945d3 into main Oct 5, 2026
37 of 56 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.

1 participant