install → init → launch broken at four consecutive links on fresh main: F6 eval injection in mosaic-init (SECURITY), F7 init drops installer's mcpServers block, F8 missing fleet roster = raw stack trace, F9 activation probe 2.0s timeout < 2.6s CLI cold-start on modest hardware (flagship), F10 shipped lease-broker unit never installed. Seat launched after documented workarounds; runtime-contract injection verified in-seat. Co-Authored-By: Claude Fable 5 <[email protected]>
8.8 KiB
Greenfield install log — fomo-lin
Running log of a from-scratch Mosaic Stack install on Jason's test laptop fomo-lin
(Debian 13, x86_64). Operator: scooby (agent). Started 2026-08-08. Channel per fred:
findings → comms as they land; this file is the durable record. Branch: greenfield/fomo-lin.
Machine starting state (2026-08-08)
- Debian 13 (kernel 6.12.101+deb13), no Node/npm, no global git config, no
~/.ssh, no~/.config/mosaic, no~/.mosaic, sudo requires password (agent cannot escalate). - Repos pre-cloned by Jason: jarvis-brain, mosaic-brain, stack, uconnect, uscllc-website
(all https remotes to git.mosaicstack.dev, no credentials stored — private-repo
fetch/push dead until a token was provisioned from credentials.json,
usc_mos). - tmux session
scoobyrunning Claude Code (bare harness — notmosaic claude).
Pre-install setup that had NO framework mechanism (manual work)
- Agent identity:
MOSAIC_AGENT_NAME=scoobyhand-added to~/.bashrc+ tmux env. - Git identity + credential store: hand-configured.
- Comms receive path: hand-ported
scooby-comms-watcher.shfrom fred's watcher + hand-written systemd--userunit +loginctl enable-linger. Works (both peers verified round-trip within ~90s), but every step was artisanal — relevant input for harness-homes (W-F).
Install run (2026-08-08 ~19:09Z)
curl -fsSL https://mosaicstack.dev/install.sh | bash -s -- --yes --no-auto-launch
→ exit 0, framework v3 → ~/.config/mosaic/, CLI @mosaicstack/mosaic 0.0.49 →
~/.npm-global/. Prereq path: sudo apt install nodejs npm (Debian 13's node 20.19.2
meets the ≥20 floor). Public read on the stack repo means the installer itself needs no
credentials — good.
Findings (outside fred's known-gaps list of 2026-08-08)
F1 — PATH advice is print-only
Installer warns ~/.npm-global/bin is not on your PATH and suggests the rc line, but
shellProfileEdits: [] in the manifest — nothing is persisted. Every fresh machine ends
with mosaic not resolvable in new shells until the user hand-edits rc. Either edit the
rc (with consent/flag) or make the closing summary a copy-paste block.
F2 — Installer overwrites live ~/.claude/settings.json + ~/.claude/CLAUDE.md with backup: null
.install-manifest.json runtimeAssetCopies shows dest ~/.claude/settings.json,
~/.claude/CLAUDE.md, hooks-config.json, context7-integration.md, all backup: null,
written while a Claude session was LIVE on this machine. On this box the pre-existing files
were near-defaults so nothing of value was lost; on any configured machine this silently
destroys user settings/memory. Wants: backup-before-overwrite (populate the manifest
backup field it clearly already models) + merge-not-replace for settings.json.
F3 — Fresh install fails its own doctor: 10 warnings out of the box
Immediately after a clean, successful install, mosaic doctor reports: missing USER.md;
AGENTS.md missing CRITICAL HARD GATES override block; runtime file drift on
~/.claude/settings.json; 7 missing mosaic-* skills. A green install that self-reports
10 warnings erodes trust in doctor as a signal. Whatever subset is "expected until
mosaic init/wizard" should be suppressed or labeled as such.
F4 — Drift check points users at the gated template (wedge hazard)
The settings the installer writes to ~/.claude/settings.json are UNGATED (no
mutator-gate, no receipt-observer) — which on today's main is CORRECT, it avoids the
Stop-hook wedge. But ~/.config/mosaic/runtime/claude/settings.json (the file doctor
diffs against) IS the gated template. So doctor's "runtime file drift" warning invites the
obvious remediation — copy the template over — which would seed the receipt-observer wedge
into a live seat. The drift baseline and the seeded file should be the same artifact, or
doctor should know about the gated/ungated split.
F5 — Installed skill set is disjoint from repo skills/
Skill sync installed 101 skills (six mosaic-*: deploy, gitea, orchestrator, portainer,
tools, woodpecker) but NONE of the eight in stack skills/ on main (board, forge, jarvis,
macp, prd, prdy, setup-cicd, standards). Doctor then flags 7 of those 8 as missing
(mosaic-jarvis escapes the check). Two sources of truth for "the Mosaic skills" — the
installer's bundle and the repo dir — have diverged.
Environment answers / status
- fomo-lin → sb-it-1-dt: comms-only today. Hostname does not resolve from here and the laptop has no ssh keys. ssh reach would need Jason (key provisioning + route/VPN).
- Gitea write to the stack repo: verified by the push of this very branch (token
usc_mos).
Session 2 (2026-08-08 later) — mosaic init + first bare seat
mosaic init completed (SOUL.md / USER.md / TOOLS.md generated; TOOLS.md was backed up
before overwrite — the contrast with F2 shows the codebase already knows how). Its
runtime-adapter step correctly REFUSED to wire mutator-gate/receipt-observer hooks
(activation half absent, #869) — loud, explained, fail-safe. Good.
First bare seat: launched — mosaic claude --model sonnet → Claude Code v2.1.226,
runtime-contract injection verified from inside the seat. But it took findings F6–F10 to
get there; on an untouched fresh main install, install → init → launch is broken at
FOUR consecutive links.
F6 — SECURITY: mosaic-init eval-injects free-text answers
tools/_scripts/mosaic-init line 142: eval "$var_name=\"$value\"". Any answer
containing " crashes init mid-flow (reproduced: exit 127, USER.md never written);
an answer containing $( ) would EXECUTE arbitrary commands. Fix: printf -v.
Same bug in the NON_INTERACTIVE default branch. Related: init exits 1 even on success
when enforcement wiring is (correctly) refused — poisons any scripted chaining.
F7 — init silently drops the installer's mcpServers block → launcher refuses to run
init's "Updating runtime adapters" rewrote ~/.claude/settings.json and removed the
mcpServers.sequential-thinking block the installer had written 11 min earlier.
mosaic claude hard-requires that MCP → launch refused. The prescribed fix command
(mosaic-ensure-sequential-thinking --runtime claude) works. So the happy path is
install → init → BROKEN → hand-run a repair script. Merge-not-replace (F2) fixes this too.
F8 — no fleet roster on a fresh install; launcher dies with a raw stack trace
mosaic claude throws an uncaught Error: Fleet communications contract unavailable: no fleet roster at ~/.config/mosaic/fleet/roster.{yaml,json} (full Node stack trace to the
user). Nothing in install or init creates a roster (wizard untested here — --no-auto-launch;
if the wizard seeds one, the bare-flow gap still stands). Unblocked by hand-authoring a
minimal site roster from fleet/examples/minimal.yaml.
F9 — FLAGSHIP: activation-probe timeout loses to CLI cold-start on modest hardware
activation_version_gate.py gives the mosaic __lease-capability probe
PROBE_TIMEOUT_SECONDS = 2.0. On fomo-lin the CLI answers CORRECTLY in ~2.55–2.61s
every run (Node startup cost). Timeout → fail-closed → every bare mosaic claude
launch aborts (exit 65) with an error blaming "mosaic not on PATH … framework/CLI version
skew" — neither true. Invisible on fast dev boxes; fatal on laptops. Suggest: raise/make
configurable the timeout, warm-probe cache, and split the three failure causes into
distinct messages. Local workaround (documented, removable):
MOSAIC_LEASE_VERSION_PROBE_COMMAND pointed at a script emitting the verified payload
instantly (~/.local/bin/mosaic-lease-probe-fast).
F10 — shipped lease-broker unit is never installed → registration denied
With F9 bypassed, launch dies with "Mosaic lease broker registration failed; runtime
launch denied": the broker daemon isn't running, and although the framework SHIPS
systemd/user/mosaic-lease-broker.service, nothing installs/enables it.
systemctl --user link + enable --now of the shipped unit → READY instantly, launch
proceeds. Installer/init/wizard should own this step.
Observations (not filed as findings)
- Launcher settings audit demands
mutator-gate.pywhile init refuses to wire it — main's components disagree about the gated state (fold into #1113/F4). - Seat context: runtime contract injected ✓; SOUL.md NOT injected (seat confirmed) — matches AGENTS.md read-on-demand load order, but README says the launcher "checks for SOUL.md". Question for lead, not a finding.
--ref nextinstall path verified available (flag exists, next archive HTTP 200) — not exercised; fomo-lin stays main-as-shipped per lead ruling.
Next
- Milestone comms sent at: install complete ✓ / first seat launched ✓.
- First gated-seat probe deliberately deferred until PR #1109 lands (known deny-only state).