Files
stack/docs/scratchpads/791-upgrade-config-protection.md
Hermes Agent 87e21fd933 docs(791): Phase-1 design for upgrade config protection
Design-only planning artifact for #791. Traces the wipe mechanism
(install.sh:199 rsync --delete gated by PRESERVE_PATHS denylist) and
specifies the ratified (b)+(a)+(d) fix: framework-owned manifest allow-list
with fail-safe unknown=>operator default and manifest-scoped prune, a
transactional pre-update snapshot with mosaic restore, and a projection-only
mosaic fleet regen recovery path. No implementation changes.

Refs #791

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 15:14:50 -05:00

3.1 KiB

Scratchpad — #791 Upgrade config protection (ms-791 worker lane)

Lane: web1:ms-791 → reports to MS-LEAD (web1:mosaic-100). Do NOT contact Jason/Mos directly. Worktree: /home/hermes/agent-work/stack-agents-dir-791, branch feat/791-upgrade-config-protection off origin/main 9745bc3f (verified exact head).

Mission prompt (verbatim intent)

Protect operator-owned config under ~/.config/mosaic from framework-upgrade wipes. Ratified combination (Mos-approved, do NOT re-litigate): (b) strict ownership separation [PRIMARY] + (a) transactional pre-update snapshot [safety net] + (d) regeneration-from-SSOT [recovery]. (c) periodic timer DEFERRED. HARD GATE: unit test that an upgrade run touches NO path outside the manifest. Design-first: write design doc, send to MS-LEAD, WAIT for confirmation before impl.

Session 1 (2026-07-16) — Phase 1 design

Evidence gathered (wipe mechanism, file/line)

  • mosaic updateupdate-checker.ts:509 buildReseedCommandbash install.sh (MOSAIC_SYNC_ONLY=1, MOSAIC_INSTALL_MODE=keep).
  • Wipe = packages/mosaic/framework/install.sh:199 rsync -a --delete + PRESERVE_PATHS denylist (install.sh:47). cp-fallback install.sh:223 find ... -exec rm -rf.
  • Denylist gaps → WIPED: agents/*.conf, policy/*.md, *.local.md, harvester/SOP, tools/_lib/credentials.json.
  • Stale comment update-checker.ts:492 claims *.local preserved — PRESERVE_PATHS has no such entry.
  • TS path file-adapter.ts:157file-ops.ts:66 syncDirectory = non-destructive copy-overlay, BUT its preserve list (file-adapter.ts:164) already DRIFTED from install.sh (missing fleet/backlog, fleet/roles.local). Evidence for single shared manifest SSOT.
  • Existing snapshot (install.sh:76) = /tmp, crash-trap only, deleted on success → inadequate; no mosaic restore.
  • fleet-reconciler.ts:93,234 already has regenerate-projections-from-roster phase separate from lifecycle → mosaic fleet regen = thin projection-only wrapper (no restart), no FCM-M4/M5 preemption.

Design decisions

  • (b) Invert to allow-list: shared framework/framework-manifest.json (framework globs + operatorReserved carve-outs); resolve per-path, deny-wins; UNKNOWN ⇒ operator (fail-safe). Mechanism: drop --delete; non-deleting bulk copy + explicit manifest-scoped prune pass (iterate framework globs only → operator/unknown structurally unreachable). Pure prune-planner fn for tests.
  • (a) Snapshot to ~/.local/state/mosaic/backups/pre-update-<ts>/ 0700/0600, retention N=5, post-sync verify+restore, mosaic restore --list/--from. No secret values in output.
  • (d) mosaic fleet regen projection-only, preview-first, never restart.
  • HARD GATE test includes a deliberately-unanticipated operator path to prove fail-safe default.
  • PR split: PR1 manifest+guard (root fix, ships alone) → PR2 snapshot/restore (secrev) → PR3 regen+docs. PR2/PR3 depend on PR1.

Status

Design doc written: docs/design/791-upgrade-config-protection.md. Sent to MS-LEAD. WAITING for confirmation before Phase 2 implementation. No impl started.