feat(bin): add opt-in thin Pi crewmate launch via config/pi-crew-thin - #5
Merged
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
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
Make BB secondmate-spawned normal Pi ship and scout crewmates start with minimal context only when their home-local config/pi-crew-thin contains 1 or on. Preserve the existing no-extensions, workflow, and turn-end behavior while adding --no-skills plus absolute global background-terminals and pi-render-cache extension paths, leave Pi secondmate coordinators and all other homes unchanged, and cover the launch template with colocated tests. Do not start bug-bounty hunts or change hunt rules.
What Changed
bin/fm-spawn.shnow reads a home-localconfig/pi-crew-thin(value1oron, surrounding whitespace tolerated) and, for normal Pi ship and scout crewmates only, adds--no-skillsplus absolute-epaths for the globally installedbackground-terminalsandpi-render-cacheextensions to the Pi launch template; the--no-extensionsboundary, workflow extension, and turn-end behavior are unchanged, and the Pi secondmate coordinator template never honors the opt-in.pi_agent_dirhelper (PI_CODING_AGENT_DIRthen~/.pi/agent), the same root the workflow extension already used, and a relative root or a missing extension refuses the spawn with an actionable message before endpoint and metadata creation instead of leaving an orphaned pane.AGENTS.mdconfig inventory anddocs/configuration.md(local, gitignored, not inherited into secondmate homes), and extendedtests/fm-spawn-dispatch-profile.test.shwith six colocated cases covering the opt-in launch line, theonvalue, relocated-agent-dir resolution, the missing-extension refusal, a non-opt-in value, and the untouched Pi secondmate template.Risk Assessment
✅ Low: The change is well-bounded and default-off: with no config/pi-crew-thin file every existing launch path is byte-identical (pinned by new assert_not_contains guards in test_pi_threads_model_and_max_effort), the opt-in fails closed before endpoint and metadata creation, it reuses one shared pi_agent_dir resolver, and six colocated tests cover the positive, whitespace, relocated-agent-dir, missing-extension-refusal, non-opt-in-value, and secondmate-unchanged cases; the only gap is documentation ownership.
Testing
I ran the change's colocated suite
tests/fm-spawn-dispatch-profile.test.sh(all 34 cases pass, including the six new thin-Pi cases) and then demonstrated the intent the way an operator experiences it, by driving the real fm-spawn through a fake tmux pane that captures the literal command typed into a crewmate window: with noconfig/pi-crew-thinthe Pi ship launch is identical to the previous one, with1oronit gains--no-skillsand the two absolute global extension paths ahead of the preserved workflow and turn-end extensions for both ships and scouts, a Pi secondmate coordinator and a0value stay on their default templates, a missing pi-render-cache extension refuses with an actionable error and leaves no metadata or launched pane, and the flag is not inherited into a spawned secondmate home. No screenshot or rendered artifact applies — the change only affects the shell command firstmate types into a terminal pane, so the captured launch transcript is the actual end-user surface. The worktree was left clean.Evidence: Thin Pi crewmate launch transcript (7 operator scenarios, real fm-spawn)
Evidence: Manual demonstration script used to produce the transcript
Evidence: Default vs. thin Pi crewmate launch command (key excerpt)
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
bin/fm-spawn.sh:1724- bin/fm-spawn.sh:1724-1725 build the two thin-epaths with no existence check, unlike the sibling Pi preflightpi_dynamic_workflows_extension_path(bin/fm-spawn.sh:610-613) which refuses the spawn with an actionable message when the extension file is missing. On a home that sets config/pi-crew-thin=1 but does not have background-terminals or pi-render-cache installed at the assumed global paths, fm-spawn still reportsspawned <id> harness=piand sends a launch line referencing nonexistent files; pi either aborts (dead pane behind a live meta record) or silently starts without the extensions the opt-in promised, with no diagnostic either way. Whether both extensions should be hard requirements is a product decision (a home may deliberately have only one), so this needs the author's call rather than an automatic gate.bin/fm-spawn.sh:1722- TheHOME must be absoluterefusal at bin/fm-spawn.sh:1720-1723 runs after the pane is created and after state/<id>.meta is published (bin/fm-spawn.sh:1704) and afterORCA_ABORT_CLEANUP=0(bin/fm-spawn.sh:1709), sospawn_abort_cleanupcleans up nothing. With PI_CODING_AGENT_DIR or FM_PI_DYNAMIC_WORKFLOWS_EXTENSION pointing at a valid absolute workflow extension while HOME is relative or unset, the workflow preflight at :714 passes, the endpoint and meta are created, and the spawn then exits 1 at :1722 leaving an orphaned pane plus a task record that claims a launched task. The existing Pi preflight contract (pinned by test_pi_crewmate_missing_workflow_extension_refuses_before_endpoint) is to refuse before the endpoint; move this HOME validation and the path computation next toPI_THIN_FLAGS=$(pi_crew_thin_flags)at bin/fm-spawn.sh:715.bin/fm-spawn.sh:1725- The thin extension paths hardcode$HOME/.pi/agent/...(bin/fm-spawn.sh:1724-1725) while the sibling resolver for the workflow extension honors PI_CODING_AGENT_DIR (bin/fm-spawn.sh:601,agent_dir=${PI_CODING_AGENT_DIR:-${HOME:-}/.pi/agent}). On a home with a relocated Pi agent dir - a configuration this script already supports - the workflow extension resolves correctly under PI_CODING_AGENT_DIR while both thin-epaths point into an unused $HOME/.pi/agent tree, so the opt-in silently loads neither extension. Resolving both thin paths from the sameagent_dirthe workflow resolver uses keeps them absolute and global as the intent requires while staying consistent with the one existing owner of Pi's agent-dir location.bin/fm-spawn.sh:621- bin/fm-spawn.sh:621 reads the opt-in withvalue=$(<"$CONFIG/pi-crew-thin"), which strips only trailing newlines, then matches strictly against1|on. Every other value-style config reader in this repo normalizes whitespace first (fm_backlog_backend_valueat bin/fm-tasks-axi-lib.sh:58 andresolve_crewat bin/fm-harness.sh:82 both usetr -d '[:space:]'). A pi-crew-thin file written as1(trailing space), with a CRLF line ending, or with a leading blank/indent silently falls through to the default fat launch with no error, so an operator sees a normal Pi crewmate and no indication the opt-in was rejected. Use the sametr -d '[:space:]'read as the sibling config readers.AGENTS.md:72- AGENTS.md carries the canonical inventory of everyconfig/*key, including local, gitignored, non-inherited ones (see config/calm at AGENTS.md:72 and config/herdr-presentation-spaces at AGENTS.md:73), and docs/configuration.md documents the value-bearing ones. The newconfig/pi-crew-thinkey is documented only inside the fm-spawn.sh header comment (bin/fm-spawn.sh:141-144), so an operator reading the config inventory has no way to discover the opt-in or that it is deliberately not inherited into secondmate homes. Add one inventory line noting: LOCAL, gitignored, values 1|on, crewmate/scout only, not inherited.🔧 Fix: validate thin Pi opt-in before endpoint creation
1 warning still open:
docs/configuration.md:216- AGENTS.md:49 states the repo invariant that "docs/configuration.mdis the single owner of the top-level operational-home layout and configuration schemas; each producing script's header and help own exact child fields and mutation mechanics", and AGENTS.md:166 splits ownership sobin/fm-spawn.showns launch flags and fail-closed validation while docs/configuration.md owns the schema. Every other config/ key in the inventory follows this and has both an AGENTS.md line and a docs/configuration.md section: config/calm (docs/configuration.md:26), config/backlog-backend (:34), config/herdr-presentation-spaces (:86), config/wedge-alarm (:108), config/cmux-socket-password (:177). The new config/pi-crew-thin key has only the AGENTS.md:73 inventory line -grep -rn pi-crew-thinreturns zero hits under docs/. This matters concretely because docs/configuration.md:216 is the paragraph that describes the Pi-family crewmate/scout launch composition ("apply the same discovery boundary, explicitly load the installed pi-dynamic-workflows extensions/workflow.ts by absolute path, and fail before endpoint creation when that extension is unavailable"), and that description is now incomplete: it omits the opt-in that adds --no-skills and two more absolute -e extensions to that same launch, and omits the second fail-before-endpoint refusal the opt-in introduces (bin/fm-spawn.sh:650-657). Add a short section (or extend the paragraph at docs/configuration.md:216) covering: values 1 or on with surrounding whitespace tolerated, any other value or an absent file keeps the default launch, resolution under PI_CODING_AGENT_DIR then ~/.pi/agent, both extensions required so a missing one refuses before endpoint creation, crewmate/scout only and never the secondmate coordinator, and LOCAL/gitignored/not inherited.✅ **Test** - passed
✅ No issues found.
bash tests/fm-spawn-dispatch-profile.test.sh— full colocated suite (34 cases) including the six new thin-Pi cases: opt-in flags/extensions on a ship,onvalue with whitespace on a scout, resolution under a relocatedPI_CODING_AGENT_DIR, missing-extension refusal before endpoint creation, non-opt-in value keeping the default launch, and the untouched Pi secondmate templateManual end-to-end launch-command capture: ran the realbin/fm-spawn.shbehind a fake tmux that records the literal command sent withsend-keys -l, across 7 operator scenarios (default ship, thin ship, thin scout, Pi secondmate,pi-crew-thin=0, missing pi-render-cache, secondmate config inheritance) — script/tmp/no-mistakes-evidence/01KYYA2XPM798C26HDHEASBCMX/thin-pi-demo.shRefusal-safety check in the same manual run: asserted exit status 1, the actionablethin pi crewmate pi-render-cache extension is missing: …message, absence ofstate/<id>.meta, and an empty launch logInheritance check: spawned a Pi secondmate from a home withconfig/pi-crew-thin=1and inspected the secondmate home'sconfig/—crew-harnessinherited,pi-crew-thinabsentgit diff --name-only 1300bde c37db2f— confirmed only AGENTS.md, bin/fm-spawn.sh, and the colocated test changed (no hunt rules touched)git status --porcelain— worktree left clean, no transient test artifacts✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.