feat(fm-spawn): load project .claude/skills for pi crewmates#422
Open
blazingbunny wants to merge 4 commits into
Open
feat(fm-spawn): load project .claude/skills for pi crewmates#422blazingbunny wants to merge 4 commits into
blazingbunny wants to merge 4 commits into
Conversation
Pi does not auto-discover project skills (it ignores .claude/skills and .pi/skills at the project root) but accepts --skill <dir>. Thread --skill <worktree>/.claude/skills into the pi crewmate/scout launch template only, when the resolved worktree actually has a .claude/skills directory. Empty for non-pi harnesses, skill-less projects, and pi secondmates, so all other launch paths stay byte-identical. Adds tests/fm-spawn-piskill.test.sh pinning the four cases: pi crewmate with dir gets --skill, pi crewmate without dir omits it, codex/claude crewmates never get it, and pi --secondmate never gets it.
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 firstmate's pi crewmates load their project's own skills at launch by threading --skill /.claude/skills into the pi crewmate/scout launch template in bin/fm-spawn.sh, only when the worktree has a .claude/skills directory, leaving non-pi harnesses, skill-less projects, and pi secondmates unaffected
What Changed
bin/fm-spawn.shnow threads a--skill <worktree>/.claude/skillsflag into the pi crewmate/scout launch template (via a new__PISKILL__token), but only when the harness is pi, the task is not a secondmate, and the worktree actually has a.claude/skillsdirectory — so pi crewmates load their project's own skills at launch since pi does not auto-discover them. Non-pi harnesses, skill-less worktrees, and pi secondmates get nothing.docs/configuration.mdand theharness-adaptersskill, noting pi ignores.claude/skills/.pi/skillsat the project root but accepts--skill <dir>.tests/fm-spawn-piskill.test.sh(4 behavior tests) plus shared helpers intests/lib.sh, and hardened existing tool-detection tests (bootstrap, session-start, backlog-handoff, secondmate-lifecycle) against host environment leakage.Risk Assessment
✅ Low: The change is minimal, tightly guarded (harness/kind/dir checks), leaves all other harnesses and secondmates byte-identical, uses the same safe shell_quote + pattern-substitution idiom as existing flags, and is covered by four targeted behavior tests.
Testing
The configured full e2e suite passed as baseline; I additionally ran the new pi-skill behavior test plus every other test touched by the change (backlog-handoff, bootstrap, secondmate-lifecycle-e2e, session-start) and all pass. To show the intent working the way a firstmate operator would experience it, I captured the actual launch command pi is handed via a fake-tmux capture harness: a pi crewmate whose worktree has .claude/skills getspi --skill '<abs>/.claude/skills' -e ..., a pi crewmate without the dir stays byte-identical to the old template, and both a codex crewmate (dir present) and a pi secondmate (dir present in home) receive no --skill flag. Round 1's generic exit-1 failure no longer reproduces and was addressed by the final commit hardening tool-detection tests against host env leakage.Evidence: Captured pi/codex/secondmate launch commands across four scenarios
=== pi crewmate, worktree HAS .claude/skills === pi --skill '<wt>/.claude/skills' -e '<...>.pi-ext.ts' "$(cat '<brief>')" === pi crewmate, NO .claude/skills === pi -e '<...>.pi-ext.ts' "$(cat '<brief>')" === codex crewmate, HAS .claude/skills (no --skill) === codex --dangerously-bypass-approvals-and-sandbox ... "$(cat '<brief>')" === pi SECONDMATE, home HAS .claude/skills (no --skill) === ... pi -e '<...>fm-primary-turnend-guard.ts' -e '<...>fm-primary-pi-watch.ts' "$(cat '<charter>')"Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
bin/fm-spawn.sh:1028- In this repo, .claude/skills is a symlink to .agents/skills (firstmate's internal operational skills, all marked metadata.internal=true). Because pwd -P resolves the symlink, a pi crewmate/scout spawned on a firstmate-on-itself worktree will now auto-load firstmate's own internal skills (harness-adapters, secondmate-provisioning, etc.) via --skill. This is within the literal 'load the project's own skills' intent and is benign (skills are only surfaced, not forced), but it's a non-obvious consequence specific to this self-pooled repo. No action needed unless you want firstmate-repo tasks excluded.🔧 **Test** - 1 issue found → auto-fixed ✅
command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"🔧 Fix: test: harden tool-detection tests against host env leakage
✅ Re-checked - no issues remain.
command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"bash tests/fm-spawn-piskill.test.sh(4 behavior tests, all pass)bash tests/fm-backlog-handoff.test.sh(pass)bash tests/fm-bootstrap.test.sh(pass)bash tests/fm-secondmate-lifecycle-e2e.test.sh(pass)bash tests/fm-session-start.test.sh(pass)Manual launch-command capture harness printing the real pi/codex/secondmate launch strings for all four scenarios✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.