4.1 KiB
4.1 KiB
Issue #824 — Mosaic skill CLI and Claude bridge auto-sync
Objective
Deliver mosaic skill register|unregister|list plus install/upgrade reconciliation of every canonical ~/.config/mosaic/skills/* entry into ~/.claude/skills/, without clobbering runtime-owned files or directories.
Scope and constraints
- Issue: mosaic skill management CLI — register/unregister + symlink-bridge auto-sync on install/upgrade (mosaicstack/stack#824)
- Branch:
feat/824-mosaic-skill-cli - M1 runtime: Claude Code only.
- Pi/Codex parity is documentation-only; no non-Claude bridge implementation.
- Do not author the downstream
mosaic-context-refreshskill. - Workers do not modify
docs/TASKS.md, merge, close #824, or touchmain. - TDD is mandatory and red-first; filesystem tests use temporary directories only.
- Budget: no explicit token cap supplied; use a focused single-worker implementation with no new dependencies.
Requirements mapping
- Register creates the canonical Claude symlink and is idempotent.
- Names are untrusted: reject empty/escaping/absolute/separator/
../leading-dash names before filesystem mutation, with clear CLI stderr and nonzero status. - Register repairs only Mosaic-owned dangling symlinks and refuses foreign files, directories, and symlinks.
- Unregister removes only symlinks pointing inside the canonical Mosaic skills root and is idempotent when absent.
- List reports registered, dangling, foreign, and canonical-but-unregistered skills.
- Install and upgrade generically reconcile all canonical skills after framework sync/re-seed, continuing past foreign conflicts without clobbering them.
- User/developer documentation describes commands, status meanings, security boundaries, and Claude-only M1 scope.
Plan
- Add co-located failing Vitest coverage for all filesystem behaviors and auto-sync.
- Run the focused spec and record the expected RED failure.
- Commit the red contract as
test(#824): .... - Implement the skill bridge and Commander command registration.
- Wire reconciliation into wizard finalize and
mosaic updatere-seed, preserving non-clobber behavior. - Update canonical docs and sitemap if navigation changes.
- Run focused tests, package tests, typecheck, lint, and formatting.
- Commit implementation/docs as
feat(#824): ..., queue-guard, push, open PR withCloses #824., fire completion event, and notify the coordinator.
Progress
- 2026-07-17: Loaded mission/delivery/TDD/documentation rails, issue #824, active mission state, and relevant installer/update paths.
- 2026-07-17: Confirmed
mosaic updateinvokesframework/install.shwithMOSAIC_SYNC_ONLY=1; that path exits before existing post-install skill linking, leaving newly present canonical skills unregistered. - 2026-07-17: Coordinator addendum classified the user-supplied skill name and runtime symlink target as a path-traversal/symlink-injection surface. Expanded the initial red contract to reject traversal before mutation, preserve every foreign entry, and unregister Mosaic-owned links only.
Tests and evidence
- RED environment attempt:
pnpm --filter @mosaicstack/mosaic exec vitest run src/commands/skill.spec.tsinitially could not locate Vitest because this fresh worktree had no dependencies. - Dependency setup:
pnpm install --frozen-lockfile --store-dir /home/hermes/.local/share/pnpm/storesucceeded. The explicit store was required because machine pnpm config incorrectly resolves the default store under/root. - RED verified: focused Vitest suite failed with
Failed to load url ./skill.js ... Does the file exist?, proving the skill bridge API/implementation is absent before production code.
Risks
- Symlink replacement must use
lstatsemantics so dangling links are detectable without following them. - Link ownership must be determined lexically/canonically against the canonical skills root without following a foreign destination through an attacker-controlled path.
- Auto-sync must continue across conflicts while never deleting real files/directories or foreign symlinks.
- Claude Code discovers filesystem skills at session launch/reload boundaries; bridge creation makes a later
/reload-skillsor new session able to discover the skill, but cannot mutate an already-cached in-process registry by itself.