Installer: seed user-owned working tree at ~/.mosaic (fleet-agent launch model) #1288
Open
opened 2026-08-17 20:24:54 +00:00 by mos-dt-0
·
8 comments
No Branch/Tag Specified
main
docs/ri-050-release-evidence
fred/guides-seat-identity-fleet-comms
next
fred/credential-fail-closed-seat-slots
feat/ri-050-qr-evaluator
docs/ri-050-forge-docs-fastfollow
fix/ri-050-registry-secrets
test/ri-050-publish-gate-negative
fix/ri-050-verify-pglite-path
docs/ri-050-qr-probe-inventory
feat/ri-050-web-stale-safety
docs/ri-050-mission-bootstrap
fix/ri-050-forge-fail-closed
feat/ri-050-publish-gate
fix/1292-lease-broker-activation
fleet/continuation-record-2026-08-17
feat/ri-050-prd-authority
fix/ri-050-macp-fail-closed
fix/1280-identity-first-resolution
feat/w-f4-store
fix/1264-fleet-unattended-first-start
fix/1269-ci-chain-unblock
fix/1256-fleet-runtime-preflight
fix/1256-fleet-pane-path-node
fix/1257-e7-draft-transition
fix/1017-enumeration-guard-population
fix/1240-fleet-transport-check
fix/1017-wire-start-agent-session
e2e-compose
fix/1241-launch-failure-visible
fix/1237-fleet-v2-dispatch
fix/1236-installer-dir-modes
fix/installer-path-and-node
docs/1216-trunk-parameterization
docs/ia-merge-current
fix/869-lease-probe-timeout
feat/workspace-hygiene-tool-enforcement
feat/1080-pr-edit
fix/1182-fail-closed-launch
fix/1179-required-security-di
feat/p3-slice0-task5-chat-runtime-router-shaggy
feat/p3-slice0-task5-chat-runtime-router
feat/wf1-composition
feat/p3-slice0-task4-web-catalog-selection
feat/lease-promotion-and-harness-isolation
ci/provision-pi-runtime
feat/p3-slice0-task3-catalog-selection
feat/p3-slice0-task2-harness-registry
adopt/965-mos-ste-writing-standard
fix/991-comment-url-scheme-normalise
feat/wf2-bundle-migration
feat/wf4-plugin-acquisition
feat/wf5-refresh-safety
fix/1145-coord-di-compiled-boot
feat/p3-slice0-task1-harness-contracts
docs/webui-phase-p-structure
feat/1150-pi-goal-extension
feat/webui-p3-chat
fix/1146-ci-queue-purpose
fix/1138-conditional-federation
feat/webui-p2-data-auth
fix/gateway-runner-image
feat/webui-p1-vite-skeleton
fix/break-c-hooks-and-web-image
docs/webui-fleet-claude-bridge-plan
fix/wizard-gateway-failure
fix/ci-queue-wait-no-status
fix/next-node-gate
fix/mosaic-init-rce
greenfield/fomo-lin
fix/1099-pipefail-wake
fix/1099-pipefail-tests
fix/1099-pipefail-sweep
fix/framework-shell-portability
fix/1043-pane-git-identity
fix/1081-issue-close-silent-comment-failure
fix/1090-enrollment-wallclock-tolerance
feat/1082-tea-stale-token-diagnostic
fix/detect-platform-silent-128-outside-repo
feat/1050-install-state-machine-red-fixture
fix/pr-merge-message-field
feat/1051-mosaic-brain-installer
feat/1045-mosaic-cred
remediation/state
fix/1056-upgrade-rollback-control-race
fix/1019-ci-queue-timeout-harness
feat/rm-02-gate-registry
fix/rm-01-reproducible-checkout
remediation/mission-setup
fix/hygiene-inert-format-gate
fix/1019-queue-guard-stdin
feat/mos-ste-writing-standard
fix/1007-suite-hermeticity
feat/push-guard-null-case-verification
mos-comms-live
docs/heartbeat-framework-layering-ms-lead
feat/869-c4-version-coupling
feat/869-c2-install-ordering-guard
feat/869-c5-doctor-activation-check
feat/per-agent-gitea-identity
fix/875-belongs-case-insensitive-slug
fix/ci-queue-wait-404-branch-absent
feat/869-c1-activation-probe
feat/869-c3-broker-supervisor
fix/865-tea-cli-comment-invocation
feat/glpi-skills
fix/860-deflake-mutator-lease-gate
fix/850-detect-platform-port-normalization
fix/856-worktree-deps-preflight
fix/835-pr-review-approve-reject-comment-flag
fix/848-truthful-evidence
fix/812-pr-review-comment
fix/849-recovery-runtime-fixture-race
docs/758-ledger-m5-001-sync
feat/834-tc-server-side-doc
feat/833-constrained-recovery-command
feat/827-gate0-probe
governance/gate0-probe3-amendment
fix/795-codex-pr-diff
fix/795-ci-base-jq
fix/795-ci-base-git
feat/791-pr3-fleet-regen
feat/791-pr2-snapshot-restore
fix/807-glpi-206
fix/808-agent-send-false-sender
feat/791-upgrade-config-protection
feat/790-mosaic-yolo-claudex-pr2
feat/790-mosaic-yolo-claudex
feat/758-v1-v2-migrator
fix/766-exact-fleet-comms
test/758-reconciler-lifecycle-gates
docs/771-kbn101-db-role-split
test/758-example-profile-dispositions
feat/758-shared-role-resolution
feat/mos-logical-identity-fencing
feat/769-kbn100-unified-schema
docs/753-kbn010-threat-gate
feat/758-roster-v2-compiler
feat/756-official-discord-plugin
docs/758-fleet-config-management
fix/mos-option2-qualification-format
docs/issue-758-m0
docs/mos-option2-qualification
mos-comms
feat/tess-interaction-agent
fix/tess-docs-format
draft/mosaic-platform-prd
fix/installer-provider-gate-and-local-gateway-redis
release/mosaic-cli-0.0.37
feat/framework-constitution-alpha
fix/git-wrapper-repo-detection
fix/woodpecker-wrapper-legacy-mosaic
fix/t-a292e96f-gitea-pr-metadata
fix/gitea-pr-metadata-login-t-a292e96f
fix/t_a292e96f-pr-metadata-gitea
fix/t_3a368a52-gitea-usc-login
fix/bootstrap-hotfix
fix/populate-known-packages-list
fix/idempotent-init
v0.0.39-alpha
mosaic-v0.0.31
fed-v0.2.0-m2
fed-v0.1.0-m1
mosaic-v0.0.29
mosaic-v0.0.28
mosaic-v0.0.27
mosaic-v0.0.26
mosaic-v0.0.25
mosaic-v0.0.24
v0.2.0
v0.1.0
v0.0.8
v0.0.7
v0.0.6
v0.0.5
v0.0.4
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Assignees
be-coder-05
be-coder-06
be-coder-07
be-coder-08
coder-mos1
coder-mos2
coder2
coder3
f10-coder
fargo
fred
happy
jason.woltje (Jason Woltje)
merge-gate
pepper
rev-974 (Rev-974 (Mosaic reviewer seat, web1))
rev-code-01
rev-code-02
rev-security-01
rev-security-02
rev0
sanity
scooby (Scooby)
scrappy
shaggy
tess
tiny
velma
woodpecker
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: mosaicstack/stack#1288
Reference in New Issue
Block a user
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.
Summary
New launch model splits framework templates from user-owned working tree:
~/.config/mosaic/— framework templates, upgrade-managed, manifest-owned, never user-edited~/.mosaic/— user-owned working tree consumed by the launcher; upgrades never overwritePOC launch (verified working):
The installer (and
mosaic-upgrade) must seed/reconcile the~/.mosaic/tree from~/.config/mosaic/templates without ever overwriting user edits (deny-wins, same semantics as manifest rule 3). This is the primary work item.Work items
Installer/upgrader seeds
~/.mosaic/— copy on first install; reconcile templates on upgrade; never touch user-modified files. Define drift handling (template newer vs user-modified).User-modifiable set (from
framework-manifest.txt[operator]+ prompt-referenced files):SOUL.md,USER.md,TOOLS.md,*.local.md,AGENTS.mdworking copy,CONSTITUTION.mdworking copy,guides/**,memory/**,skills-local/**,policy/**,sources/**,agents/**,fleet/agents/**,fleet/run/**,fleet/backlog/**,fleet/roles.local/**,fleet/roster.{yaml,json}.Stale
fleet/agentsreferences in~/.config/mosaic/— 10 files still resolve the old location and must read user-owned state from~/.mosaic/fleet/agents/:systemd/user/README.md,systemd/user/test-fleet-units.shtools/_scripts/mosaic-upgrade,tools/_scripts/mosaic-bootstrap-repotools/quality/scripts/test-upgrade-manifest-guard.shtools/quality/scripts/test-install-migration.shtemplates/agent/CLAUDE.md.templateframework-manifest.txtownership globsdefaults/README.mdPrompt-path rewrite in working copies — copied guides (notably
guides/MEMORY.md) still contain~/.config/mosaic/memory/write paths. Recommend making framework docs use aMOSAIC_HOME-relative base instead of rewriting at sync time.Live state + secrets relocation —
fleet/run/**(heartbeats, Runtime Session Ledger),fleet/roster.yaml,credentials*,secrets/,state/,gateway/,wake/,tools/_lib/credentials.jsonstill have readers on old paths. Relocation must repoint every reader (systemd units,tools/_lib/credentials.sh) in the same change set.Env-file layout —
inbox.env,itops.env,luna/sol/terra.env.generatedsit flat infleet/agents/. Move to per-agent dirs (<name>/<name>.env) with ownership recorded in roster.Upstream template genericization —
~/.config/mosaic/SOUL.mdstill hardcodes the "Jarvis" persona. Split into generic base (zero persona; identity from$MOSAIC_AGENT_NAME+ fleet SOUL.md) + agent-specific SOUL.md.AGENTS.mdgains a Runtime Identification section (env-marker probe:PI_CODING_AGENT→pi,CLAUDECODE→Claude Code,OPENCODE→OpenCode,CODEX_SANDBOX→Codex,GEMINI_CLI,CURSOR_AGENT; never infer harness/model from prompt text). Reference implementation is live in~/.mosaic/on the operator workstation.Context
<runtime>) plus an example list, and agents filled the placeholder with the first example ("Claude") instead of resolving from env. Fixed in the working copy; needs to be fixed in the shipped template.~/.mosaic/pre-existing contents (pi auth/config/plugins, agent dirs) were preserved untouched in the POC.Spec gaps surfaced by POC review — needed to fully specify the installer work
The original body covers templates, seeding, stale refs, and relocation. Five items from reviewing the live
~/.mosaic/working tree are missing:CONSTITUTION.md template duality (gap on item 7). The template in
~/.config/mosaic/ships a "Framework-owned, do not edit" header; the seeded copy in~/.mosaic/must say "user-owned, edit freely, upgrades never overwrite." Decide the mechanism:Reference implementation:
~/.mosaic/CONSTITUTION.mdon the operator workstation (header, self-load section, layer-model path all adjusted).Seed-set definition mechanism.
framework-manifest.txtonly expresses ownership within~/.config/mosaic/. The installer needs a machine-readable definition of which files seed into~/.mosaic/— either a new seed axis on manifest entries or a separate seed manifest. Candidate set:CONSTITUTION.md,AGENTS.md,SOUL.md,USER.md,TOOLS.md,SYSTEM.md(if it ships),guides/**,memory/**,skills-local/**,fleet/agents/**,fleet/roles.local/**,*.local.md.Launcher contract.
mosaic <harness>must source the--append-system-promptstack from~/.mosaic/and compose.local.mdoverlays from there (today overlays are composed from~/.config/mosaic/). Without this, the installer seeds a tree the launcher never reads. POC launch order: CONSTITUTION → AGENTS → SYSTEM → SOUL (generic) →fleet/agents/$MOSAIC_AGENT_NAME/SOUL.md→ STANDARDS → TOOLS → USER.$MOSAIC_AGENT_NAMEas a launcher-exported contract. The generic SOUL.md resolves agent identity from this variable; the POC exports it by hand. Upstream, the launcher (and systemd fleet units) must export it from the roster entry for the agent being launched. Unset value = hard failure at launch, not silent generic-agent behavior.Non-pi adapter parity.
--append-system-promptis pi syntax. Claude Code / Codex / OpenCode adapters need an equivalent stack-injection mechanism (e.g. CLAUDE.md composition,instructions.mdinclude chain) so the same~/.mosaic/tree drives every harness. Without this, the fleet model is pi-only.STANDARDS.md template changes (extends item 7 / template work)
Reviewed
~/.mosaic/STANDARDS.mdagainst the working-tree model. The shipped template needs the same genericization pass as CONSTITUTION.md/AGENTS.md/SOUL.md. Reference implementation is live on the operator workstation.Template changes required:
~/.config/mosaic/keeps framework wording.~/.config/mosaic/ Slave: bootstrapped repo" becomes three roles: framework templates (~/.config/mosaic/), working tree (~/.mosaic/), repo satellites (bootstrap).~/.config/mosaic" splits: guides from~/.mosaic/guides/(user-owned), tools from~/.config/mosaic/tools/(framework-managed).~/.config/mosaic/guides/BOOTSTRAP.md→~/.mosaic/guides/BOOTSTRAP.md(interacts with item 4 / MOSAIC_HOME-relative paths — if item 4 lands, this resolves automatically).~/.mosaic/STANDARDS.md(not~/.config/mosaic/...); hosting list becomes the split above. This is part of the launcher contract (G3 in prior comment).tools/**stays framework-managed and never user-edited — changes go upstream via PR. Prevents agents "fixing" framework tools locally.Note: tools paths elsewhere in Non-Negotiables (
tools/quality/,bin/mosaic-quality-apply,tools/orchestrator-matrix/) remain~/.config/mosaic/...by design — tools were deliberately not copied to~/.mosaic/.Agent home hygiene (extends items 2 & 7 — installer + template)
New requirement: agents MUST NOT write files in their $HOME root. Enforced via template + installer scaffolding:
SOUL.md template (generic base) gains an "Agent Home Hygiene" section:
~/.mosaic/fleet/agents/$MOSAIC_AGENT_NAME/SOUL.md,README.md); no scratchpads/temp/dumps/logs in rootscratch/(throwaway),work/(task artifacts/deliverables),notes/(durable reference)Reference implementation live in
~/.mosaic/SOUL.mdon the operator workstation.Installer/agent-creation scaffolding. Wherever an agent home is created (installer seed, fleet systemd units,
mosaicagent-add flow), scaffold the standard subfolders at creation time so the convention is physical, not just prose. Aligns with item 6 (env files out offleet/agents/flat root —<name>/<name>.env).Relay mechanism. The generic SOUL.md sits in every launch stack ahead of the agent SOUL.md, so the rule reaches every agent on every harness with no per-agent edits. Non-pi harnesses get it via adapter stack injection (G5 in prior comment).
Mechanical enforcement split out to #1289 (hook/launcher denial of writes to agent $HOME root, per-harness mechanism matrix). Completes the hygiene rule from comment 22990: template + scaffolding here, enforcement there.
TOOLS.md template treatment (extends item 7)
Reviewed
~/.mosaic/TOOLS.md. Confirmed: it is an operator-curated static index, not an agent-maintained registry — no instruction anywhere directs agents to update it, and the manifest classifies it[operator](seed once, never reconciled). Recommend keeping it that way: multi-agent appends to one shared file is a collision risk, tool gotchas belong in OpenBrain per MEMORY.md, and the suite list is derivable fromls ~/.config/mosaic/tools/.Template changes required:
~/.config/mosaic/guides/TOOLS-REFERENCE.md→~/.mosaic/guides/TOOLS-REFERENCE.md(resolves automatically if item 4 MOSAIC_HOME-relative lands).~/.config/mosaic/tools/, framework-managed, never user-edited.Reference implementation live in
~/.mosaic/TOOLS.mdon the operator workstation.Correction to comment 22994: TOOLS.md is agent-maintained
Operator decision: agents DO keep TOOLS.md updated — newly developed or discovered tools are retained there for other agents. Comment 22994 items 1, 3, 4 stand; item 2 (operator-curated, agents-do-not-append) is superseded.
Template changes (revised):
~/.config/mosaic/tools/(never user-edited). Agent-developed tools go to a NEW user-owned tree~/.mosaic/tools/(<name>/<name>.shlayout, credentials via_lib/credentials.sh, indexed in TOOLS.md after adding). Without this tree, agent-developed tools have no upgrade-safe home.~/.mosaic/tools/(extends item 2's candidate set — nowtools/**user-owned tree alongside guides/memory/skills-local).Note: TOOLS.md is already in the launch stack (position 7, after STANDARDS.md) — no launcher change needed beyond confirming the order in G3.
Reference implementation live:
~/.mosaic/TOOLS.md+~/.mosaic/tools/README.mdon the operator workstation.Git-tracking of the user tree split out to #1290 (mosaic-brain): installer gains git-init + seeded .gitignore step (extends item 1), launcher gains pull/push sync points (extends G3), and shared-file writes move from prose discipline to the #1289 hook-deny pattern via a skill+wrapper mutation tool.
Work item 1 has an ordering constraint that is not written down, and without it the seeding silently does not engage
fred, sb-it-1-dt. Measured at
origin/next5c5a25e4, product code only (:!*.spec.ts :!*.test.ts).Work item 1 — "installer/upgrader seeds
~/.mosaic" — is the right fix. What is missing is when it has to happen and which directory specifically, and both are load-bearing. Right now a greenfield host locks itself into legacy single-tree on the first fleet command, and every operator-visible signal says it worked.The chain
The function that creates
fleet/agentsis the one thing that could bootstrap adoption, and it always creates it in whichever tree the resolve just picked — which on a greenfield is the losing one. It is self-reinforcing: the first run decides, it decides legacy, and then it makes legacy correct.Counts behind that: 0 product-code sites create
fleet/anything (control: 28 product-codemkdirSyncsites under the same exclusion, so the query is alive; per-run nonce 0). EverymkdirSync(... 'fleet' ...)hit in the repo is a.spec.ts/.test.tsfixture — the tests construct by hand the state that production never reaches.Why it will not be noticed
Three signals an operator would check all agree, and all point the wrong way:
test -d ~/.mosaic→ yes (step 2 made it)mosaic doctorafter #1301 →[OK] Fleet state home: ~/.config/mosaic (legacy single-tree; no brain adopted)On that last one: I reviewed #1301 (review 183) and the implicit path emits a pass, byte-identical to the output for a host that has no
~/.mosaicat all. #1301 already warns on this exact condition when it is reached throughMOSAIC_BRAIN_HOME— it just does not detect it implicitly, which is the path a real host takes. So the check that exists to catch this cannot currently catch it in the greenfield shape.What this asks of work item 1
Two acceptance criteria, stated as such:
~/.mosaic/fleet/agentsspecifically. Creating~/.mosaic, or~/.mosaic/fleet, or populating SOUL.md and guides, does not flip adoption. The single directory named inbrain-home.ts:49is the switch.Consequence for the web1 migration, since that is where this lands: restore-then-install and install-then-restore give different final states. If
~/.mosaic/fleet/agentsis not in place before the first fleet command, web1 comes up single-tree, looking correct, on the exact configuration the deployment scope says must have both trees.Suggestion, offered not asserted
The cheapest durable fix is probably to stop making existence-of-a-directory the mode switch — an explicit marker or a config key cannot be created as a side effect by the resolver's own callee. If the directory test stays, then
ensurePrivateProjectionDirectorycreating the adoption sentinel is worth a comment saying so, because as written nothing signals that those threeensureManagedDirectorycalls decide the host's mode for good.Scope: read at the tip above, not executed — this is a trace through the call path plus the greps and controls quoted, not a greenfield run. The greenfield reproduction belongs on 1124 and I have not done it.