DeployCore merges LifeOS skills into pre-existing user skills without warning, disabling its own
Version: LifeOS v7.1.1
OS: macOS 26.5.1 (APFS, case-insensitive, the macOS default)
Harness: Claude Code
bun: 1.3.14
Install path: primary AI-native path per INSTALL.md (bun Tools/DeployCore.ts --apply)
Summary
DeployCore drops the skill library loose into ~/.claude/skills/ with copy-if-missing. If you already keep skills there, LifeOS merges its directories into yours wherever the names collide case-insensitively. It skips SKILL.md, which honors never-overwrite but leaves its own skill without an entry point. The result is a LifeOS skill the harness can't see, and a user skill full of files they didn't install.
Nothing in the output says so. ScanConflicts passes clean.
Reproduction
- On macOS (default case-insensitive APFS), keep pre-existing skills at
~/.claude/skills/research/ and ~/.claude/skills/cmux/. Lowercase, third-party, each with its own SKILL.md.
- Install LifeOS v7.1.1 by the documented primary path:
bun Tools/DetectEnv.ts, then ScanConflicts.ts, then DeployCore.ts --apply.
- Look inside
~/.claude/skills/research/ and ~/.claude/skills/cmux/.
LifeOS v7.1.1 ships install/skills/Research/ and install/skills/CMUX/. On a case-insensitive filesystem, those resolve to the same directories as my custom research/ and manaflow's cmux/.
Expected
One of:
- The install catches the collision and stops, or asks.
ScanConflicts reports it. It's the designated pre-flight, and it passed clean here.
- User-owned skills live in a namespace LifeOS won't enter.
Actual
DeployCore reports blockers: [], failures: [], skillsCopied: 909, exit 0. Underneath:
- LifeOS wrote 30 of its files into two skill directories I own (makes me grateful for version control!)
research/ received Workflows/, Templates/, MigrationNotes.md, QuickReference.md, SourceRoutingProtocol.md, UrlVerificationProtocol.md.
cmux/ received DESIGN.md, ISA.md, Tools/cmux.ts, Workflows/{AgentRace,BootTeam,Fleet,Monitor}.md. That list matches the contents of install/skills/CMUX/ exactly.
- LifeOS skipped both
SKILL.md files, so its Research and CMUX skills never became discoverable. Research is missing from the harness skill list while roughly 12 shipped LifeOS descriptions route to it ("NOT FOR general research (use Research)"). Those references dangle.
Each skill now has two owners. My SKILL.md sits on top of LifeOS workflows it never references, and LifeOS's workflows sit under a SKILL.md that never routes to them.
I version-control my skills, so git measured this precisely: 0 tracked files modified, 0 deleted, 30 untracked additions inside tracked directories. Never-overwrite protected the contents of my files. It didn't keep LifeOS out of my directories.
Root cause
SystemUserBoundary states the ownership model:
~/.claude/skills/<name>/** where <name> does NOT start with _ → SYSTEM
LifeOS claims every non-underscore directory in ~/.claude/skills/ as its own SYSTEM zone. Per Skills__SkillSystem, _ALLCAPS is the only user-owned skill namespace. So the model has no category for a skill that lives in ~/.claude/skills/, belongs to me, and didn't come from LifeOS—which describes most existing Claude Code machines.
The copier is doing exactly what the architecture tells it to. Two things follow:
- The boundary's own rule classifies my pre-existing third-party skills as LifeOS SYSTEM files.
copyMissing is the only guard left standing. SystemUserBoundary records that the write-time runtime guard hook came out in the 2026-05-06 security simplification, so nothing enforces the boundary at write time.
INSTALL.md never mentions that LifeOS claims ~/.claude/skills/, or that _ALLCAPS is the only protected namespace.
Related: install/skills/CMUX/ uses ALLCAPS with no leading underscore, which matches neither form Skills__SkillSystem permits (public TitleCase, private _ALLCAPS).
Suggested fixes
- Have
ScanConflicts compare shipped skill names against existing entries in skillsDir, case-insensitively, and report every collision. It already owns the read-only pre-flight, and today it reports only lifeosSkillPresent.
- Stop
DeployCore from merging into a directory it didn't create. Treat a skipped SKILL.md as a blocker, because that single condition is what produces the undiscoverable skill.
- Report skips.
DeployCore prints copied counts and no skipped-because-exists list, so a partial install looks identical to a clean one.
- Document the namespace claim in
INSTALL.md. Say that LifeOS deploys loose into ~/.claude/skills/, and that _ALLCAPS alone is protected. Then users with existing skills can decide before step 4 instead of finding out afterward.
- Rename
CMUX to _CMUX or Cmux to match the documented convention.
This is the silent-degradation pattern from #1461. A state-scoped health check would flag a skill directory with no SKILL.md.
DeployCore merges LifeOS skills into pre-existing user skills without warning, disabling its own
Version: LifeOS v7.1.1
OS: macOS 26.5.1 (APFS, case-insensitive, the macOS default)
Harness: Claude Code
bun: 1.3.14
Install path: primary AI-native path per
INSTALL.md(bun Tools/DeployCore.ts --apply)Summary
DeployCoredrops the skill library loose into~/.claude/skills/with copy-if-missing. If you already keep skills there, LifeOS merges its directories into yours wherever the names collide case-insensitively. It skipsSKILL.md, which honors never-overwrite but leaves its own skill without an entry point. The result is a LifeOS skill the harness can't see, and a user skill full of files they didn't install.Nothing in the output says so.
ScanConflictspasses clean.Reproduction
~/.claude/skills/research/and~/.claude/skills/cmux/. Lowercase, third-party, each with its ownSKILL.md.bun Tools/DetectEnv.ts, thenScanConflicts.ts, thenDeployCore.ts --apply.~/.claude/skills/research/and~/.claude/skills/cmux/.LifeOS v7.1.1 ships
install/skills/Research/andinstall/skills/CMUX/. On a case-insensitive filesystem, those resolve to the same directories as my customresearch/and manaflow'scmux/.Expected
One of:
ScanConflictsreports it. It's the designated pre-flight, and it passed clean here.Actual
DeployCorereportsblockers: [],failures: [],skillsCopied: 909, exit 0. Underneath:research/receivedWorkflows/,Templates/,MigrationNotes.md,QuickReference.md,SourceRoutingProtocol.md,UrlVerificationProtocol.md.cmux/receivedDESIGN.md,ISA.md,Tools/cmux.ts,Workflows/{AgentRace,BootTeam,Fleet,Monitor}.md. That list matches the contents ofinstall/skills/CMUX/exactly.SKILL.mdfiles, so itsResearchandCMUXskills never became discoverable.Researchis missing from the harness skill list while roughly 12 shipped LifeOS descriptions route to it ("NOT FOR general research (use Research)"). Those references dangle.Each skill now has two owners. My
SKILL.mdsits on top of LifeOS workflows it never references, and LifeOS's workflows sit under aSKILL.mdthat never routes to them.I version-control my skills, so git measured this precisely:
0tracked files modified,0deleted, 30 untracked additions inside tracked directories. Never-overwrite protected the contents of my files. It didn't keep LifeOS out of my directories.Root cause
SystemUserBoundarystates the ownership model:LifeOS claims every non-underscore directory in
~/.claude/skills/as its own SYSTEM zone. PerSkills__SkillSystem,_ALLCAPSis the only user-owned skill namespace. So the model has no category for a skill that lives in~/.claude/skills/, belongs to me, and didn't come from LifeOS—which describes most existing Claude Code machines.The copier is doing exactly what the architecture tells it to. Two things follow:
copyMissingis the only guard left standing.SystemUserBoundaryrecords that the write-time runtime guard hook came out in the 2026-05-06 security simplification, so nothing enforces the boundary at write time.INSTALL.mdnever mentions that LifeOS claims~/.claude/skills/, or that_ALLCAPSis the only protected namespace.Related:
install/skills/CMUX/uses ALLCAPS with no leading underscore, which matches neither formSkills__SkillSystempermits (publicTitleCase, private_ALLCAPS).Suggested fixes
ScanConflictscompare shipped skill names against existing entries inskillsDir, case-insensitively, and report every collision. It already owns the read-only pre-flight, and today it reports onlylifeosSkillPresent.DeployCorefrom merging into a directory it didn't create. Treat a skippedSKILL.mdas a blocker, because that single condition is what produces the undiscoverable skill.DeployCoreprintscopiedcounts and no skipped-because-exists list, so a partial install looks identical to a clean one.INSTALL.md. Say that LifeOS deploys loose into~/.claude/skills/, and that_ALLCAPSalone is protected. Then users with existing skills can decide before step 4 instead of finding out afterward.CMUXto_CMUXorCmuxto match the documented convention.This is the silent-degradation pattern from #1461. A state-scoped health check would flag a skill directory with no
SKILL.md.