Skip to content

LifeOsSchema.md and the USER/ scaffold the installer ships describe two incompatible layouts #1720

Description

@catchingknives

LifeOS/install/LIFEOS/DOCUMENTATION/LifeOs/LifeOsSchema.md calls itself "The canonical shape of the USER directory in LifeOS" and says it "Applies to: LIFEOS/USER/ in every LifeOS installation". The scaffold the installer actually copies contradicts it on naming, on directory placement, and on the frontmatter contract, and the runtime code sides with the installer while naming the schema as its spec.

Everything below is checkable from a clean checkout with ls and grep. Paths and line numbers are repo-relative, pinned to tag v7.1.1; section 5 also references v6.0.5, the last tag that shipped the page manifests. Paths starting LIFEOS/USER/... are quoted runtime values, as installed.

1. The two layouts

LifeOS/Tools/ScaffoldUser.ts line 48 is the source of truth for what a new user gets: const templateUser = join(skillRoot, "install", "USER");.

LifeOsSchema.md (Status: Draft v1.0, 2026-04-16, frontmatter version: 1.0.4) LifeOS/install/USER/
Naming (§2) "PascalCase, always. No underscores, no ALL_CAPS, no kebab-case", example PrincipalIdentity.md, "not PRINCIPAL_IDENTITY.md" 23 of 24 root entries are ALL_CAPS; PRINCIPAL/PRINCIPAL_IDENTITY.md ships verbatim
Health (§4, §8) Health/ at USER root, a domain sibling of Telos/ TELOS/HEALTH/
Finances (§4) Finances/ at USER root TELOS/FINANCES/
Business (§4) Business/ at USER root WORK/YOUR_COMPANIES/

Frontmatter contract (§3 requires category, kind, publish, review_cadence, last_updated on every .md):

cd LifeOS/install/USER
find . -name '*.md' | wc -l                             # 87
grep -rl '^category:'        --include='*.md' . | wc -l # 0
grep -rl '^publish:'         --include='*.md' . | wc -l # 0
grep -rl '^interview_phase:' --include='*.md' . | wc -l # 0
grep -rl '^kind:'            --include='*.md' . | wc -l # 7
grep -rl '^review_cadence:'  --include='*.md' . | wc -l # 7
grep -rl '^last_updated:'    --include='*.md' . | wc -l # 19

Two of the five required fields (category, publish) are on zero shipped files; the other three reach at most 19 of 87. All 7 files carrying kind: carry kind: metric, which is not one of the four kinds §5 defines.

2. The runtime hardcodes the installer layout, in a change dated after the schema

LifeOS/install/LIFEOS/PULSE/Observability/observability.ts lines 1069 to 1074:

const TELOS_DIR = join(USER_DIR, "TELOS")
// Post-2026-05-01 USER/ restructure: HEALTH and FINANCES live under TELOS/;
// BUSINESS data lives under WORK/YOUR_COMPANIES/; PROJECTS flattened to a top-level file.
const HEALTH_DIR = join(USER_DIR, "TELOS", "HEALTH")
const FINANCES_DIR = join(USER_DIR, "TELOS", "FINANCES")
const BUSINESS_DIR = join(USER_DIR, "WORK", "YOUR_COMPANIES")

The restructure this comment records postdates the schema draft. So this is not drift the spec predates. It is a change the spec was never updated for and never retired over.

3. The one consumer that cites the schema is written for the other layout

LifeOS/install/LIFEOS/PULSE/modules/user-index.ts line 18 declares Spec: LIFEOS/DOCUMENTATION/LifeOs/LifeOsSchema.md. Line 129 then reads // Remove once all USER/ files are migrated to the new schema., above ROOT_FALLBACK (line 132) and TELOS_FALLBACK (line 153): hardcoded category/kind/publish maps keyed on ALL_CAPS filenames (PRINCIPAL_IDENTITY.md, WRITINGSTYLE.md, FOOD_PREFERENCES.md, and so on), with inferFallback() matching parts[0] === "TELOS" at line 189. Since the scaffold emits no files carrying category: or publish: (and the 7 files carrying only kind: bypass the fallback into category unknown, per the !meta.category && !meta.kind trigger at line 327), the fallback tables are not a migration aid. They are the live code path for 80 of the 87 files a fresh install scaffolds.

4. Schema-shaped templates ship, and nothing installs them

LifeOS/install/LIFEOS/USER_TEMPLATES/ contains Beliefs.md, Books.md, Goals.md, Identity.md, Pronunciations.md: PascalCase, each carrying the full category / kind / publish / review_cadence frontmatter. Those five names are five of the six page ids the v6.0.5 manifests define (see §5). Per LifeOS/Workflows/Setup.md step 4.5, DeployCore.ts deploys this directory into the installed runtime and explicitly excludes USER, which ScaffoldUser.ts then fills from install/USER/. Nothing ever moves the schema-shaped files to the paths the manifests read.

The same directory has three names in the tree: LIFEOS/USER_TEMPLATES/ (the installed location, deployed from LifeOS/install/LIFEOS/USER_TEMPLATES/), LIFEOS/USER/_TEMPLATES/ (its own README, and LifeOS/install/LIFEOS/PULSE/Tools/ReleaseAudit.ts lines 87 and 100), and skills/_LIFEOS/RELEASE_TEMPLATES/USER/ (see §6).

5. The page manifests were dropped from the payload, and three of six never resolved

LifeOS/install/LIFEOS/PULSE/pages/ shipped six *.manifest.toml files through v6.0.5 and is absent from v7.0.0 and v7.1.1, while the code that consumes it still ships there: lib/manifest-loader.ts, Tools/ValidateManifests.ts, and adapters/prompts/. So on a clean v7.1.1 install the page system has no manifests at all. Please confirm whether dropping pages/ from the payload was intentional, whether manifests are meant to be generated at setup, or whether they are simply missing.

Independently of that: resolving the v6.0.5 manifests' sourceGlobs (runtime LIFEOS/USER/... paths) against the v7.1.1 scaffold in LifeOS/install/USER/:

manifest sourceGlobs resolves
books LIFEOS/USER/Books.md nothing (scaffold has TELOS/BOOKS.md)
health LIFEOS/USER/Health/README.md, LIFEOS/USER/Health/*.md nothing (scaffold has TELOS/HEALTH/)
pronunciations LIFEOS/USER/PRINCIPAL/PRONUNCIATIONS.json, LIFEOS/USER/Pronunciations.md nothing (scaffold has PRINCIPAL/PRONUNCIATIONS.md)
beliefs LIFEOS/USER/Beliefs.md, LIFEOS/USER/TELOS/TELOS.md 1 of 2
goals, identity ok

The same globs fail against the v6.0.5 scaffold's own layout, so this predates the payload drop.

6. The documented template path cannot exist in a release

Schema §14: "Templates live in skills/_LIFEOS/RELEASE_TEMPLATES/USER/. Shipped with every LifeOS release. This is the scaffold a new LifeOS user starts with."

skills/_LIFEOS/ is not in the tree, and by policy cannot be: LifeOS/install/LIFEOS/DOCUMENTATION/Tools/Containment.md line 94 states "the release pipeline deletes all skills/_*/ wholesale". grep -rn 'skills/_LIFEOS/RELEASE_TEMPLATES' LifeOS/install/LIFEOS/DOCUMENTATION/ returns 11 hits across 5 docs:

  • LifeOs/LifeOsSchema.md lines 13, 239, 241, 244
  • LifeosSystemArchitecture.md lines 384, 442, 445
  • Config/ConfigSystem.md lines 42, 86
  • Pulse/PulseSystem.md line 115
  • Work/WorkSystem.md line 180

7. A third layout, plus two integrations described but not wired

LifeOS/install/skills/Daemon/Tools/DaemonAggregator.ts lines 45 to 56 hardcode USER/PROJECTS/PROJECTS.md, USER/PRINCIPAL_IDENTITY.md at root, USER/SKILLCUSTOMIZATIONS/, and USER/FINANCES, USER/HEALTH, USER/BUSINESS at root in ALL_CAPS. None of those paths exist in the scaffold, and none match the schema either. Schema line 172 says this file "replaces its hardcoded file list with a scan" driven by publish:; it never reads publish. Schema line 195 says InterviewScan.ts "reads user-index.json instead of scanning files directly"; LifeOS/install/LIFEOS/TOOLS/InterviewScan.ts contains no user-index reference.

The ask

Please declare the target layout. Everything else is mechanical once it is settled:

  • (A) The schema is the target. Then install/USER/ needs rebuilding in PascalCase with the frontmatter contract populated, USER_TEMPLATES needs scaffolding into USER/ where the manifests already point, the observability.ts constants move back to root, and the fallback tables in user-index.ts can be deleted as their own comment intends.
  • (B) The installer layout is the target. Then LifeOsSchema.md should be marked superseded or rewritten to describe ALL_CAPS with HEALTH and FINANCES under TELOS/, the manifest sourceGlobs need repointing when pages/ returns to the payload, and USER_TEMPLATES should be rewritten or removed.
  • (C) A migration is in flight. Then a status line in LifeOsSchema.md saying so is enough. Today the doc reads as current and normative.

Doc fixes that are safe either way, and that I will open a PR for on request:

  1. Replace skills/_LIFEOS/RELEASE_TEMPLATES/USER/ with LifeOS/install/USER/ in the 5 docs listed in §6. That path can never exist in a release.
  2. Settle on one name for the schema-shaped template directory (§4).
  3. State in LifeOsSchema.md which frontmatter convention is canonical for USER files: the §3 five-field contract, or pai-freshness-v1 (LifeOS/install/LIFEOS/DOCUMENTATION/Freshness/FreshnessSystem.md, library at LifeOS/install/LIFEOS/TOOLS/TelosFreshness.ts), which is the one with multiple consumers today.
  4. Decide the fate of PULSE/pages/ (§5): restore it to the payload or remove its consumers; if restored, add a CI check that every sourceGlobs entry resolves against a freshly scaffolded USER tree. That one check catches most of the above.

One caveat for whichever direction is chosen: LifeOS/install/LIFEOS/PULSE/lib/manifest-loader.ts line 92 resolves non-glob patterns with a literal existsSync, and the default macOS filesystem is case-insensitive. A path written in one casing against a tree in the other will appear to work locally and fail on a case-sensitive volume, so a casing change needs a deliberate two-step rename plus a case-sensitive CI run, not a rename in place.

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