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

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>
This commit is contained in:
2026-04-11 20:56:55 -05:00
parent b2cbf898d7
commit 03a53c543a
5 changed files with 306 additions and 25 deletions

View File

@@ -222,12 +222,17 @@ sync_framework
mkdir -p "$TARGET_DIR/memory"
mkdir -p "$TARGET_DIR/credentials"
# Seed defaults — copy from defaults/ to framework root if not already present.
# These are user-editable files that ship with sensible defaults but should
# Seed defaults — copy framework contract files from defaults/ to framework
# root if not already present. These ship with sensible defaults but must
# never be overwritten once the user has customized them.
#
# This list must match the framework-contract whitelist in
# packages/mosaic/src/config/file-adapter.ts (FileConfigAdapter.syncFramework).
# SOUL.md and USER.md are intentionally NOT seeded here — they are generated
# by `mosaic init` from templates with user-supplied values.
DEFAULTS_DIR="$TARGET_DIR/defaults"
if [[ -d "$DEFAULTS_DIR" ]]; then
for default_file in AGENTS.md STANDARDS.md; do
for default_file in AGENTS.md STANDARDS.md TOOLS.md; do
if [[ -f "$DEFAULTS_DIR/$default_file" ]] && [[ ! -f "$TARGET_DIR/$default_file" ]]; then
cp "$DEFAULTS_DIR/$default_file" "$TARGET_DIR/$default_file"
ok "Seeded $default_file from defaults"