diff --git a/packages/mosaic/framework/framework-manifest.txt b/packages/mosaic/framework/framework-manifest.txt index 8c328cf3..99320075 100644 --- a/packages/mosaic/framework/framework-manifest.txt +++ b/packages/mosaic/framework/framework-manifest.txt @@ -35,6 +35,8 @@ CONTRIBUTING.md defaults/** examples/** guides/** +# Shipped framework subtree — canonical skills are upgrade-reconciled. +skills/** install.sh install.ps1 LICENSE @@ -67,6 +69,9 @@ policy/** memory/** sources/** credentials/** +# Operator-authored/customized skills live separately from canonical skills/ and +# must remain structurally unprunable even as skills/** is framework-owned. +skills-local/** # Secret-bearing operator file INSIDE the framework-owned tools/ subtree. # Listed explicitly so the deny-wins rule carves it out of tools/**. tools/_lib/credentials.json diff --git a/packages/mosaic/src/framework/manifest-parity.spec.ts b/packages/mosaic/src/framework/manifest-parity.spec.ts index f2915f69..cd06ac2d 100644 --- a/packages/mosaic/src/framework/manifest-parity.spec.ts +++ b/packages/mosaic/src/framework/manifest-parity.spec.ts @@ -78,6 +78,7 @@ const PROBE_PATHS = [ 'install.sh', 'framework-manifest.txt', 'guides/E2E-DELIVERY.md', + 'skills/mosaic-context-refresh/SKILL.md', 'tools/git/pr-create.sh', 'tools/_lib/manifest.sh', 'defaults/SOUL.md', @@ -97,6 +98,7 @@ const PROBE_PATHS = [ 'memory/note.md', 'sources/skills/x.md', 'credentials/c.json', + 'skills-local/custom/SKILL.md', 'tools/_lib/credentials.json', 'fleet/roster.yaml', 'fleet/roster.json', diff --git a/packages/mosaic/src/framework/manifest.spec.ts b/packages/mosaic/src/framework/manifest.spec.ts index bc5ab5a6..ec237cda 100644 --- a/packages/mosaic/src/framework/manifest.spec.ts +++ b/packages/mosaic/src/framework/manifest.spec.ts @@ -304,6 +304,11 @@ describe('manifest completeness against shipped framework tree', () => { expect(misclassified).toEqual([]); }); + it('shipped canonical skills are framework-owned while local skills are operator-owned', () => { + expect(resolveOwnership(manifest, 'skills/mosaic-context-refresh/SKILL.md')).toBe('framework'); + expect(resolveOwnership(manifest, 'skills-local/custom/SKILL.md')).toBe('operator'); + }); + it('the operator-owned surface from #791 resolves to operator', () => { const operatorPaths = [ 'agents/coder0.conf', @@ -313,6 +318,7 @@ describe('manifest completeness against shipped framework tree', () => { 'SOUL.local.md', 'USER.local.md', 'STANDARDS.local.md', + 'skills-local/custom/SKILL.md', 'tools/_lib/credentials.json', 'fleet/roster.yaml', 'fleet/roster.json',