fix(mosaic): seed TOOLS.md from defaults on install #458

Merged
jason.woltje merged 1 commits from fix/tools-md-seeding into main 2026-04-12 02:02:22 +00:00
Owner

Summary

Fixes mosaicstack/stack#457. ~/.config/mosaic/TOOLS.md was never created during a bootstrap install even though AGENTS.md declares it as mandatory reading at position 5 of the load order. A fresh 0.0.29 install left the file missing and the agent contract pointing at nothing.

Root cause

packages/mosaic/framework/install.sh lines 228-236 explicitly seed AGENTS.md STANDARDS.md from defaults/TOOLS.md was listed in PRESERVE_PATHS but never seeded in the first place.

While investigating I also found:

  1. The TS wizard's FileConfigAdapter.syncFramework (packages/mosaic/src/config/file-adapter.ts) was iterating every file under framework/defaults/, which meant on a fresh install it would silently seed defaults/SOUL.md (hardcoded "Jarvis") and defaults/USER.md (placeholder) into the user's mosaic home before the wizard's own identity stages ran.
  2. packages/mosaic/framework/templates/TOOLS.md.template still referenced ~/.config/mosaic/rails/git/... and ~/.config/mosaic/rails/codex/.... The rails/ tree was renamed to tools/ in the v1→v2 framework migration — so any user who did run mosaic init would end up with a TOOLS.md full of broken paths.
  3. preservePaths drift: install.sh preserves 8 paths across upgrades; file-adapter.ts was only preserving 4. This has been masked in production because the framework source tree has no root-level contract files — but the two code paths should agree regardless.

Fix

  • packages/mosaic/framework/install.sh — extend the explicit defaults-seed loop from AGENTS.md STANDARDS.md to AGENTS.md STANDARDS.md TOOLS.md.
  • packages/mosaic/src/config/file-adapter.ts — replace the greedy readdirSync(defaultsDir) loop with an exported DEFAULT_SEED_FILES = ['AGENTS.md', 'STANDARDS.md', 'TOOLS.md'] whitelist. Align preservePaths with the bash PRESERVE_PATHS list so both install paths have the same upgrade-preservation semantics.
  • packages/mosaic/framework/templates/TOOLS.md.template — replace rails/ with tools/.

Tests

Adds packages/mosaic/src/config/file-adapter.test.ts (5 tests, all green):

  • Seeds the three framework-contract files on a fresh mosaic home.
  • Does NOT seed SOUL.md/USER.md from defaults/ — wizard stages own those.
  • Does NOT seed README.md / AUDIT-*.md (framework-internal).
  • Preserves existing user contract files under keep mode, including AGENTS.md — this test plants a root-level AGENTS.md in the fixture's sourceDir to actually exercise syncDirectory's preserve path, not just the seed loop.
  • No-op when defaults/ directory is absent.

Test plan

  • Unit tests added and green (5/5)
  • pnpm --filter @mosaicstack/mosaic run typecheck green
  • pnpm --filter @mosaicstack/mosaic run lint green
  • pnpm --filter @mosaicstack/mosaic exec vitest run → 275/276 pass (the one failure, src/commands/uninstall.spec.ts:138, is a pre-existing EACCES issue on main and is unrelated to this change)
  • Repo-wide pnpm typecheck / pnpm lint / pnpm format:check green
  • Live smoke of bash framework/install.sh against a tmp MOSAIC_HOME — prints "Seeded TOOLS.md from defaults" and the file lands
  • Independent code review (no blockers; one must-fix on test fixture incorporated before commit)
  • CI green on PR
  • Merged and verified on main

Affected version

Ships in @mosaicstack/mosaic 0.0.30.

## Summary Fixes mosaicstack/stack#457. `~/.config/mosaic/TOOLS.md` was never created during a bootstrap install even though `AGENTS.md` declares it as mandatory reading at position 5 of the load order. A fresh 0.0.29 install left the file missing and the agent contract pointing at nothing. ## Root cause `packages/mosaic/framework/install.sh` lines 228-236 explicitly seed `AGENTS.md STANDARDS.md` from `defaults/` — `TOOLS.md` was listed in `PRESERVE_PATHS` but never seeded in the first place. While investigating I also found: 1. The TS wizard's `FileConfigAdapter.syncFramework` (packages/mosaic/src/config/file-adapter.ts) was iterating *every* file under `framework/defaults/`, which meant on a fresh install it would silently seed `defaults/SOUL.md` (hardcoded "Jarvis") and `defaults/USER.md` (placeholder) into the user's mosaic home before the wizard's own identity stages ran. 2. `packages/mosaic/framework/templates/TOOLS.md.template` still referenced `~/.config/mosaic/rails/git/...` and `~/.config/mosaic/rails/codex/...`. The `rails/` tree was renamed to `tools/` in the v1→v2 framework migration — so any user who did run `mosaic init` would end up with a `TOOLS.md` full of broken paths. 3. `preservePaths` drift: `install.sh` preserves 8 paths across upgrades; `file-adapter.ts` was only preserving 4. This has been masked in production because the framework source tree has no root-level contract files — but the two code paths should agree regardless. ## Fix - `packages/mosaic/framework/install.sh` — extend the explicit defaults-seed loop from `AGENTS.md STANDARDS.md` to `AGENTS.md STANDARDS.md TOOLS.md`. - `packages/mosaic/src/config/file-adapter.ts` — replace the greedy `readdirSync(defaultsDir)` loop with an exported `DEFAULT_SEED_FILES = ['AGENTS.md', 'STANDARDS.md', 'TOOLS.md']` whitelist. Align `preservePaths` with the bash `PRESERVE_PATHS` list so both install paths have the same upgrade-preservation semantics. - `packages/mosaic/framework/templates/TOOLS.md.template` — replace `rails/` with `tools/`. ## Tests Adds `packages/mosaic/src/config/file-adapter.test.ts` (5 tests, all green): - Seeds the three framework-contract files on a fresh mosaic home. - Does NOT seed `SOUL.md`/`USER.md` from `defaults/` — wizard stages own those. - Does NOT seed `README.md` / `AUDIT-*.md` (framework-internal). - Preserves existing user contract files under `keep` mode, including `AGENTS.md` — this test plants a root-level `AGENTS.md` in the fixture's `sourceDir` to actually exercise `syncDirectory`'s preserve path, not just the seed loop. - No-op when `defaults/` directory is absent. ## Test plan - [x] Unit tests added and green (5/5) - [x] `pnpm --filter @mosaicstack/mosaic run typecheck` green - [x] `pnpm --filter @mosaicstack/mosaic run lint` green - [x] `pnpm --filter @mosaicstack/mosaic exec vitest run` → 275/276 pass (the one failure, `src/commands/uninstall.spec.ts:138`, is a pre-existing EACCES issue on main and is unrelated to this change) - [x] Repo-wide `pnpm typecheck` / `pnpm lint` / `pnpm format:check` green - [x] Live smoke of `bash framework/install.sh` against a tmp MOSAIC_HOME — prints "Seeded TOOLS.md from defaults" and the file lands - [x] Independent code review (no blockers; one must-fix on test fixture incorporated before commit) - [ ] CI green on PR - [ ] Merged and verified on main ## Affected version Ships in `@mosaicstack/mosaic` 0.0.30.
jason.woltje added 1 commit 2026-04-12 01:58:06 +00:00
fix(mosaic): seed TOOLS.md from defaults on install
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
03a53c543a
Closes #457.

The bash framework installer only seeded AGENTS.md and STANDARDS.md from
defaults/, even though TOOLS.md is listed in PRESERVE_PATHS and AGENTS.md
declares it as mandatory reading at position 5 of the load order. A fresh
bootstrap install therefore left ~/.config/mosaic/TOOLS.md missing and the
agent contract pointing at a non-existent file.

Fixes:

- packages/mosaic/framework/install.sh — extend the explicit defaults-seed
  loop from "AGENTS.md STANDARDS.md" to "AGENTS.md STANDARDS.md TOOLS.md".
- packages/mosaic/src/config/file-adapter.ts — replace the greedy
  readdirSync loop in syncFramework with an exported DEFAULT_SEED_FILES
  whitelist, so the TS wizard no longer silently seeds the Jarvis-flavored
  defaults/SOUL.md, placeholder defaults/USER.md, or internal
  README.md/AUDIT-*.md into the mosaic home. Also align preservePaths with
  the bash PRESERVE_PATHS list (AGENTS.md, STANDARDS.md, sources, and
  credentials were previously missing) so both install paths have the
  same upgrade-preservation semantics.
- packages/mosaic/framework/templates/TOOLS.md.template — replace stale
  ~/.config/mosaic/rails/ references with ~/.config/mosaic/tools/. The
  rails/ tree was renamed to tools/ in the v1→v2 framework migration.

Tests:

- packages/mosaic/src/config/file-adapter.test.ts (new, 5 tests): pins
  the whitelist, asserts SOUL.md/USER.md/README.md/AUDIT-*.md are not
  seeded, verifies existing user contract files (including AGENTS.md)
  survive a keep-mode sync, and asserts a no-op when defaults/ is absent.

Baselines: mosaic typecheck / lint green. Full mosaic vitest 275/276 —
the one failure (src/commands/uninstall.spec.ts:138) is a pre-existing
EACCES issue on main and is unrelated to this change. Repo-wide
typecheck / lint / format:check green. Live smoke of
`bash framework/install.sh` against a tmp MOSAIC_HOME confirms the
installer now prints "Seeded TOOLS.md from defaults" and the file lands.

Ships in @mosaicstack/mosaic 0.0.30.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
jason.woltje merged commit c3f810bbd1 into main 2026-04-12 02:02:22 +00:00
jason.woltje deleted branch fix/tools-md-seeding 2026-04-12 02:02:22 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#458