mosaic [yolo] pi launched Pi with ['--no-skills'] whenever MOSAIC_PI_SKILL_MODE
was unset — which is the default on every shell, systemd unit, and launcher. Result: Pi loaded zero Mosaic skills, so fleet workers never saw the ~/.config/mosaic/tools/
wrappers and routinely improvised raw tmux send-keys / tea / gh. (Pi's own
RUNTIME.md claimed skills "load natively" — direct contradiction of the launcher default.)
Root-cause investigation (Step-1 verdict): TOOLS.md is injected into Pi's prompt
(PR #554 already raised its salience); the remaining gap is that skills never load.
Fix
buildPiSkillArgs() now force-loads a small fleet-critical skill set on every Pi
launch, regardless of mode. An explicit --skill <dir> overrides --no-skills for that
path, so we surface the must-use toolkit without the ~100-skill context bloat of MOSAIC_PI_SKILL_MODE=all.
DEFAULT_PI_FORCE_SKILLS = ['mosaic-tools']; forcedPiSkillArgs() maps each to --skill <MOSAIC_HOME>/skills/<name>, existsSync-guarded → a complete no-op until the
skill is synced (safe to merge before the skill lands).
Merged into all three return paths (none / all / discover); all dedups via mergeSkillArgs() so a discovered skill isn't double-loaded.
Override with MOSAIC_PI_FORCE_SKILLS (colon-separated; empty string disables).
claude / codex / opencode paths untouched.
Also in this PR
runtime/pi/RUNTIME.md — reconcile the "skills load natively" drift with the real
default-off + force-load + MOSAIC_PI_SKILL_MODE behavior.
templates/agent/** — fix stale ~/.config/mosaic/rails/ → tools/ (60 occurrences
across 12 scaffold templates; rails/ no longer exists). Mechanical, toolkit-path-only; quality-rails repo refs untouched.
Companion PR (required for runtime effect)
The mosaic-tools skill ships in mosaicstack/agent-skills#1. This launcher PR is inert
(existsSync no-op) until that skill is synced.
prettier --check on CI-matched files ✅ (.md.template files aren't in CI's glob)
New deterministic unit coverage for buildPiSkillArgs (none/all/discover/no-disk/dedup)
and piForceSkillNames (unset vs empty-string-disable vs colon-list parsing).
Independent code review performed (APPROVE-WITH-NITS); both raised points remediated
(guarantee forced skills under all + dedup; empty-string-disable test).
Follow-up (NOT auto-applied)
Live fleet sessions need mosaic-sync-skills (to pull mosaic-tools) and a launcher
upgrade to pick this up. Do not auto-reseed running sessions — coordinate via Mos.
## Problem
`mosaic [yolo] pi` launched Pi with `['--no-skills']` whenever `MOSAIC_PI_SKILL_MODE`
was unset — which is the default on every shell, systemd unit, and launcher. Result:
**Pi loaded zero Mosaic skills**, so fleet workers never saw the `~/.config/mosaic/tools/`
wrappers and routinely improvised raw `tmux send-keys` / `tea` / `gh`. (Pi's own
RUNTIME.md claimed skills "load natively" — direct contradiction of the launcher default.)
Root-cause investigation (Step-1 verdict): TOOLS.md **is** injected into Pi's prompt
(PR #554 already raised its salience); the *remaining* gap is that skills never load.
## Fix
`buildPiSkillArgs()` now force-loads a small **fleet-critical** skill set on every Pi
launch, regardless of mode. An explicit `--skill <dir>` overrides `--no-skills` for that
path, so we surface the must-use toolkit **without** the ~100-skill context bloat of
`MOSAIC_PI_SKILL_MODE=all`.
- `DEFAULT_PI_FORCE_SKILLS = ['mosaic-tools']`; `forcedPiSkillArgs()` maps each to
`--skill <MOSAIC_HOME>/skills/<name>`, **existsSync-guarded** → a complete no-op until the
skill is synced (safe to merge before the skill lands).
- Merged into all three return paths (`none` / `all` / `discover`); `all` dedups via
`mergeSkillArgs()` so a discovered skill isn't double-loaded.
- Override with `MOSAIC_PI_FORCE_SKILLS` (colon-separated; empty string disables).
- `claude` / `codex` / `opencode` paths untouched.
### Also in this PR
- **`runtime/pi/RUNTIME.md`** — reconcile the "skills load natively" drift with the real
default-off + force-load + `MOSAIC_PI_SKILL_MODE` behavior.
- **`templates/agent/**`** — fix stale `~/.config/mosaic/rails/` → `tools/` (60 occurrences
across 12 scaffold templates; `rails/` no longer exists). Mechanical, toolkit-path-only;
`quality-rails` repo refs untouched.
## Companion PR (required for runtime effect)
The `mosaic-tools` skill ships in **mosaicstack/agent-skills#1**. This launcher PR is inert
(existsSync no-op) until that skill is synced.
## Verification
- `pnpm typecheck` (turbo, 41/41) ✅ · `pnpm lint` ✅ · `pnpm test` 302 passed (33 files) ✅
- `prettier --check` on CI-matched files ✅ (`.md.template` files aren't in CI's glob)
- New deterministic unit coverage for `buildPiSkillArgs` (none/all/discover/no-disk/dedup)
and `piForceSkillNames` (unset vs empty-string-disable vs colon-list parsing).
- Independent code review performed (APPROVE-WITH-NITS); both raised points remediated
(guarantee forced skills under `all` + dedup; empty-string-disable test).
## Follow-up (NOT auto-applied)
Live fleet sessions need `mosaic-sync-skills` (to pull `mosaic-tools`) **and** a launcher
upgrade to pick this up. Do **not** auto-reseed running sessions — coordinate via Mos.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Pi workers launched via `mosaic [yolo] pi` never loaded any skill because
buildPiSkillArgs emitted `--no-skills` whenever MOSAIC_PI_SKILL_MODE was
unset (the default everywhere), so maintained `~/.config/mosaic/tools/`
wrappers stayed invisible and workers improvised raw `tmux send-keys` /
`tea` / `gh`. An explicit `--skill` overrides `--no-skills` for that path,
so we now force-load a small fleet-critical set (default: `mosaic-tools`)
on every Pi launch regardless of mode — no full-catalog context bloat.
- launch.ts: add DEFAULT_PI_FORCE_SKILLS + forcedPiSkillArgs(); merge into
every buildPiSkillArgs() return path (existsSync-guarded → no-op until the
skill is synced). Override via MOSAIC_PI_FORCE_SKILLS (colon-separated;
empty string disables).
- launch.spec.ts: deterministic 4th-param injection + force-load coverage.
- runtime/pi/RUNTIME.md: reconcile the "skills load natively" drift with the
real default-off + force-load + MOSAIC_PI_SKILL_MODE behavior.
- templates/agent/**: fix stale `~/.config/mosaic/rails/` → `tools/` (60
occurrences across 12 scaffold templates; `rails/` no longer exists).
Companion skill `mosaic-tools` ships in mosaic/agent-skills.
Follow-up (NOT auto-applied): live fleet needs `mosaic-sync-skills` +
launcher upgrade to pick up the new skill on running sessions.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QoYiBeKNh3BiYtAJS5Z587
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
mosaic [yolo] pilaunched Pi with['--no-skills']wheneverMOSAIC_PI_SKILL_MODEwas unset — which is the default on every shell, systemd unit, and launcher. Result:
Pi loaded zero Mosaic skills, so fleet workers never saw the
~/.config/mosaic/tools/wrappers and routinely improvised raw
tmux send-keys/tea/gh. (Pi's ownRUNTIME.md claimed skills "load natively" — direct contradiction of the launcher default.)
Root-cause investigation (Step-1 verdict): TOOLS.md is injected into Pi's prompt
(PR #554 already raised its salience); the remaining gap is that skills never load.
Fix
buildPiSkillArgs()now force-loads a small fleet-critical skill set on every Pilaunch, regardless of mode. An explicit
--skill <dir>overrides--no-skillsfor thatpath, so we surface the must-use toolkit without the ~100-skill context bloat of
MOSAIC_PI_SKILL_MODE=all.DEFAULT_PI_FORCE_SKILLS = ['mosaic-tools'];forcedPiSkillArgs()maps each to--skill <MOSAIC_HOME>/skills/<name>, existsSync-guarded → a complete no-op until theskill is synced (safe to merge before the skill lands).
none/all/discover);alldedups viamergeSkillArgs()so a discovered skill isn't double-loaded.MOSAIC_PI_FORCE_SKILLS(colon-separated; empty string disables).claude/codex/opencodepaths untouched.Also in this PR
runtime/pi/RUNTIME.md— reconcile the "skills load natively" drift with the realdefault-off + force-load +
MOSAIC_PI_SKILL_MODEbehavior.templates/agent/**— fix stale~/.config/mosaic/rails/→tools/(60 occurrencesacross 12 scaffold templates;
rails/no longer exists). Mechanical, toolkit-path-only;quality-railsrepo refs untouched.Companion PR (required for runtime effect)
The
mosaic-toolsskill ships in mosaicstack/agent-skills#1. This launcher PR is inert(existsSync no-op) until that skill is synced.
Verification
pnpm typecheck(turbo, 41/41) ✅ ·pnpm lint✅ ·pnpm test302 passed (33 files) ✅prettier --checkon CI-matched files ✅ (.md.templatefiles aren't in CI's glob)buildPiSkillArgs(none/all/discover/no-disk/dedup)and
piForceSkillNames(unset vs empty-string-disable vs colon-list parsing).(guarantee forced skills under
all+ dedup; empty-string-disable test).Follow-up (NOT auto-applied)
Live fleet sessions need
mosaic-sync-skills(to pullmosaic-tools) and a launcherupgrade to pick this up. Do not auto-reseed running sessions — coordinate via Mos.
🤖 Generated with Claude Code