Repository navigation
feat(bin): add guarded prelaunch coordination for fresh primary startup pull - #6913
thechrisfischer wants to merge 3 commits into
Conversation
|
Speaking as Kun's firstmate (OSS triage, not the captain). Thanks @thechrisfischer. Head Contract-class: new-default (my verdict). Not restore: main did not already specify this prelaunch coordination path. Enrollment gating the pull itself does not erase the new unconfigured digest line / architecture surface (specimen #4627). VISION.md
Security review: no workflows; never fetches/executes candidate code; git env scrubbed; update disables external hooks/attributes. Approved: |
Intent
does the dotfiles installer have a flag to just install firstmate configs? I have a feeling we're going to want to do that often. What we're trying to do is design a system: any time I spawn a new agent from inside the first mate repo, I'm always trying to ensure that I have the latest first mate bootstrapping harness. I feel like our system is close but right now it's more of a push. I think that we want to convert it to be something of a pull. The push would be just the very first install to make sure the hook that forces the check happens but upon any new session boot from first main repo, the future ones are a pull.
I want to complete all of the work on each of these feature branches and work trees listed above. the ony one I want to not do right now is th goodword api and web migration. everything else I want to have you continue to work on and finish until things are completed and fully merged into main. if there is somethig blocking me you need to slack me in the wolfworks channel to get attention, lets start by you invetigating these and deciding if there is anytihng you need from me to finish this work
Context: The approved Penny/Victor startup-pull proposal is data/firstmate-startup-pull-design/report.md with report.html companion. This is the Firstmate-owned participant in the same body of work, LAB-105, paired with the already promoted dotfiles participant; it is not Goodword migration.
The approved proposal establishes a one-time trusted dotfiles installation of a firstmate-start launcher followed by a pull before each supported fresh launch of an independent primary Firstmate home. The installed trusted bundle fetches and pins approved committed source and portable-configuration candidates, reserves the exact physical home against live or unknown sessions and active fleet or queue state, applies only conflict-free fast-forward updates without executing fetched candidate code, publishes verified evidence, and then creates exactly one fresh child with an authenticated handoff to the real Firstmate session lock. Local-ahead, dirty, divergent, offline, invalid, symlinked, or ambiguous states fail closed and preserve the checkout and unrelated work. Pinned worker worktrees, secondmates, no-mistakes phases, unsafe homes, resumes, saved sessions, direct GUI opens, and raw vendor launches stay outside automatic replacement and are reported honestly as exclusions or bypasses. Existing explicit reviewed save, restore, and software-update authority remains intact, while automatic startup and every relevant writer coordinate through the established lock owners. Dotfiles owns launcher installation, committed portable-object selection, guarded publication and whole-pull receipts; Firstmate owns reservation and session-lock coordination, supported fresh profiles, guarded pinned source update, and native handoff or bypass reporting.
What Changed
bin/fm-prelaunch.shfor the trusted bundle that the dotfilesfirstmate-startlauncher installs. It providescapabilities/profilefor no-argument fresh harness profiles and refuses any harness arguments. It also providesreserve/validate/attach/release, which reserve the exact physical primary home under the existing claim and wake-queue mutexes and record the launcher's child.check-update/updatefast-forward one already-fetched, pinned commit.guard-writelets ordinary writers check for a live reservation. A newfm_supervision_status_strictinfm-supervision-lib.shrefuses a reservation unless the task, event-source, registered-check, and queue inventories are readable, stable, and empty.bin/fm-session-lock-lib.shandbin/fm-lock.shnow exchange an authenticated reservation for the ordinary session lock. Only an attached harness descendant with the matching owner and token can do this, and other harnesses stay denied while the reservation is live.bin/fm-ff-lib.shgainsstartup-check/startup-updatemodes that refuse dirty, detached, off-default, ahead, or divergent checkouts, and any checkout that declares an externalfilterattribute. These modes also disable hooks and global attributes during the update.bin/fm-update.shcallsguard-writebefore fetching on an independent primary home.bin/fm-session-start.shprints aSTARTUP PULLline on fresh opens: either the verified launcher handoff commits and status, or an explicit bypass.tests/fm-prelaunch.test.shand a startup-pull check intests/fm-session-start.test.sh.bin/fm-test-run.shnow routes changes to the new script and libraries to these tests. Docs updated:architecture.md,scripts.md,sessionstart-nudge.md(supported entry plus the bypass/exclusion list) andverification/supervision.md.Risk Assessment
Testing
I ran the targeted prelaunch, session-start and update suites; all pass. The prelaunch suite needs NO_MISTAKES_GATE unset, which matches CI. I then ran the real
fm-prelaunch.shCLI across 15 happy-path and adversarial scenarios against a disposable cloned primary, and ran a full live launcher→real Claude→fm-lock handoff on a private tmux socket. Claude reported the verified update handoff; a raw launch reported an honest bypass, and every guard failed closed. Nothing failed. The evidence is CLI and pane transcripts; there is no visual UI surface.Evidence: Live CLI scenario transcript (S1–S15)
Source: Live CLI scenario transcript (S1–S15)
Evidence: Real Claude pane via launcher showing verified handoff
Source: Real Claude pane via launcher showing verified handoff
⏺ STARTUP_PULL: verified launcher handoff; source ba37295efb757e3e5ecc61708cb4ecc69abd43d3 -> cacc45339660131014f08b70174f854b27172852 (updated)Evidence: Launcher log, lock/handoff receipt, and refused concurrent reserve
Source: Launcher log, lock/handoff receipt, and refused concurrent reserve
Evidence: Raw claude launch pane showing honest bypass
Source: Raw claude launch pane showing honest bypass
⏺ STARTUP_PULL: bypassed; no verified firstmate-start handoff reached this fresh sessionEvidence: Scenario driver scripts
Source: Scenario driver scripts
Evidence: fm-prelaunch test log
Source: fm-prelaunch test log
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 2 issues found → auto-fixed ✅
bin/fm-supervision-lib.sh:113-fm_supervision_inventory_snapshotdoesn't actually fail closed. Theexit 1calls for an unsafe or unreadable inventory entry (lines 119 and 140) run inside thefor … donepipeline stage. Becausepipefailis not set in fm-prelaunch.sh or in this lib, the$( … | LC_ALL=C sort )command substitution takessort's exit status, which is 0. The snapshot silently comes back truncated instead of returning 1.Verified with a state dir that contains only a dangling
w1.meta -> /nonexistentsymlink:fm_supervision_status_strictreturned rc=0 with FM_SUP_NEEDED=false and an empty snapshot. Soreserve(fleet_idle, fm-prelaunch.sh) treats that home as proven idle, even though the docs and comments promise that unreadable or structurally unsafe inventories refuse.The same swallowed path applies to every inventory class the helper covers: dangling or symlinked
*.check.sh,*.check-trust,procevent/*.sourceand.wake-queueentries, andcksumfailures.Fix: run the substitution with
set -o pipefail(e.g.listing=$(set -o pipefail; for …; done | LC_ALL=C sort)), or collect the entries and check for an error before sorting. Then add a dangling-symlink case to tests/fm-prelaunch.test.sh.bin/fm-update.sh:100- fm-update.sh runs underset -euand now callsfm-prelaunch.sh guard-writefor every independent primary. Before any action-specific logic, fm-prelaunch.sh runsprelaunch_scope_check(line 185) and the--homephysical-path check. That gate checks whether the home can enroll in startup pull, not whether a live reservation exists.As a result, explicit
fm-update.shnow aborts (exit 1) on primaries it used to handle, including its secondmate sweep:originremote (it used to print 'skipped: no origin remote' and continue);origin/HEADor main/master;data/,state/,config/orprojects/directory (line 177);None of these homes can ever hold a reservation, since
reserveruns the same scope check. This conflicts with the intent's requirement that 'Existing explicit reviewed save, restore, and software-update authority remains intact', and with the docs line 'without a reservation the explicit workflow retains its existing authority'.Fix: make
guard-writereportclearwhen the home has no reservation file, before or instead of the enrollment scope checks, so it refuses only on a live or unknown reservation. Alternatively, have fm-update tolerate a scope refusal and fail only on a reservation refusal.🔧 Fix applied.
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
env -u NO_MISTAKES_GATE bash tests/fm-prelaunch.test.sh(13 ok, 0 failed; the first run failed at once only because the gate's NO_MISTAKES_GATE env var was inherited, and fm-prelaunch rightly refuses under it)bash tests/fm-session-start.test.sh(60 ok)bash tests/fm-update.test.sh(16 ok)bash cli.sh <worktree>: live fm-prelaunch.sh CLI scenarios S1–S15 against a disposable cloned primary with a local bare originlauncher.sh: real reserve/update/attach sequence, then a realclaudechild in tmux -L fm-lab with a private TMUX_TMPDIR; Claude was asked to quote its STARTUP_PULL lineSecondfm-prelaunch.sh reservewhile the live Claude session held the home/exitof the child, then the launcher'sreleasereturned handed-offRawclaudelaunch (no launcher) in the same home; Claude was asked to quote its STARTUP_PULL lineTeardown:tmux -L fm-lab kill-server,rm -rfof all disposable dirs; worktree left clean✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.