feat!: unify mosaic CLI — native launcher, no bin/ directory
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful

BREAKING CHANGE: ~/.config/mosaic/bin/ is removed entirely.
The mosaic npm CLI is now the only executable.

## What changed

- **bin/ → deleted**: All scripts moved to tools/_scripts/ (internal)
- **mosaic-launch → deleted**: Launcher logic is native TypeScript
  in packages/cli/src/commands/launch.ts
- **mosaic.ps1 → deleted**: PowerShell launcher removed
- **Framework install.sh**: Complete rewrite with migration system
- **Version tracking**: .framework-version file (schema v2)
- **Migration v1→v2**: Auto-removes bin/, cleans old PATH entries
  from shell profiles

## Native TypeScript launcher (commands/launch.ts)

All runtime launch logic ported from bash:
- Runtime prompt builder (AGENTS.md + RUNTIME.md + USER.md + TOOLS.md)
- Mission context injection (reads .mosaic/orchestrator/mission.json)
- PRD status injection (scans docs/PRD.md)
- Pre-flight checks (MOSAIC_HOME, AGENTS.md, SOUL.md, runtime binary)
- Session lock management with signal cleanup
- Per-runtime launch: Claude, Codex, OpenCode, Pi
- Yolo mode flags per runtime
- Pi skill discovery + extension loading
- Framework management (init, doctor, sync, bootstrap) delegates
  to tools/_scripts/ bash implementations

## Installer

- tools/install.sh: detects framework by .framework-version or AGENTS.md
- Framework install.sh: migration system with schema versioning
- Forward-compatible: add migrations as numbered blocks
- No PATH manipulation for framework (npm bin is the only PATH entry)
This commit is contained in:
Jarvis
2026-04-02 19:23:44 -05:00
parent 04db8591af
commit 15830e2f2a
43 changed files with 724 additions and 1475 deletions

View File

@@ -114,10 +114,10 @@ version_lt() {
}
framework_version() {
# Read VERSION from the installed mosaic launcher
local mosaic_bin="$MOSAIC_HOME/bin/mosaic"
if [[ -f "$mosaic_bin" ]]; then
grep -m1 '^VERSION=' "$mosaic_bin" 2>/dev/null | cut -d'"' -f2 || true
# Read framework schema version stamp
local vf="$MOSAIC_HOME/.framework-version"
if [[ -f "$vf" ]]; then
cat "$vf" 2>/dev/null || true
fi
}
@@ -145,7 +145,7 @@ if [[ "$FLAG_FRAMEWORK" == "true" ]]; then
FRAMEWORK_CURRENT="$(framework_version)"
HAS_FRAMEWORK=false
[[ -d "$MOSAIC_HOME/bin" ]] && [[ -f "$MOSAIC_HOME/bin/mosaic" ]] && HAS_FRAMEWORK=true
[[ -f "$MOSAIC_HOME/AGENTS.md" ]] || [[ -f "$MOSAIC_HOME/.framework-version" ]] && HAS_FRAMEWORK=true
if [[ -n "$FRAMEWORK_CURRENT" ]]; then
dim " Installed: framework v${FRAMEWORK_CURRENT}"
@@ -202,13 +202,8 @@ if [[ "$FLAG_FRAMEWORK" == "true" ]]; then
ok "Framework installed"
echo ""
# Ensure framework bin is on PATH
FRAMEWORK_BIN="$MOSAIC_HOME/bin"
if [[ ":$PATH:" != *":$FRAMEWORK_BIN:"* ]]; then
warn "$FRAMEWORK_BIN is not on your PATH"
dim " The 'mosaic' launcher lives here. Add to your shell rc:"
dim " export PATH=\"$FRAMEWORK_BIN:\$PATH\""
fi
# Framework bin is no longer needed on PATH — the npm CLI delegates
# to mosaic-launch directly via its absolute path.
fi
fi
@@ -290,7 +285,6 @@ if [[ "$FLAG_CLI" == "true" ]]; then
# PATH check for npm prefix
if [[ ":$PATH:" != *":$PREFIX/bin:"* ]]; then
warn "$PREFIX/bin is not on your PATH"
dim " The 'mosaic' TUI/gateway CLI lives here (separate from the launcher)."
dim " Add to your shell rc: export PATH=\"$PREFIX/bin:\$PATH\""
fi
fi
@@ -303,28 +297,9 @@ fi
if [[ "$FLAG_CHECK" == "false" ]]; then
step "Summary"
echo " ${BOLD}Framework launcher:${RESET} $MOSAIC_HOME/bin/mosaic"
echo " ${DIM}mosaic claude, mosaic yolo claude, mosaic pi, mosaic doctor, …${RESET}"
echo " ${BOLD}mosaic:${RESET} $PREFIX/bin/mosaic"
dim " Framework data: $MOSAIC_HOME/"
echo ""
echo " ${BOLD}npm CLI (TUI):${RESET} $PREFIX/bin/mosaic"
echo " ${DIM}mosaic tui, mosaic login, mosaic wizard, mosaic update, …${RESET}"
echo ""
# Warn if there's a naming collision (both on PATH)
FRAMEWORK_BIN="$MOSAIC_HOME/bin"
if [[ ":$PATH:" == *":$FRAMEWORK_BIN:"* ]] && [[ ":$PATH:" == *":$PREFIX/bin:"* ]]; then
# Check which one wins
WHICH_MOSAIC="$(command -v mosaic 2>/dev/null || true)"
if [[ -n "$WHICH_MOSAIC" ]]; then
dim " Active 'mosaic' binary: $WHICH_MOSAIC"
if [[ "$WHICH_MOSAIC" == "$FRAMEWORK_BIN/mosaic" ]]; then
dim " (Framework launcher takes priority — this is correct)"
else
warn "npm CLI shadows the framework launcher!"
dim " Ensure $FRAMEWORK_BIN appears BEFORE $PREFIX/bin in your PATH."
fi
fi
fi
# First install guidance
if [[ ! -f "$MOSAIC_HOME/SOUL.md" ]]; then