Skip to content

DeployCore merges LifeOS skills into pre-existing user skills without warning, disabling its own #1506

Description

@mygirleatsmayo

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

  1. 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.
  2. Install LifeOS v7.1.1 by the documented primary path: bun Tools/DetectEnv.ts, then ScanConflicts.ts, then DeployCore.ts --apply.
  3. 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:

  1. The boundary's own rule classifies my pre-existing third-party skills as LifeOS SYSTEM files.
  2. 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

  1. 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.
  2. 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.
  3. Report skips. DeployCore prints copied counts and no skipped-because-exists list, so a partial install looks identical to a clean one.
  4. 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.
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions