Skip to content

Telos and Migrate skills still write to the legacy per-topic TELOS files, so the #2117 fix leaves the main write paths re-splitting TELOS #2291

Description

@mefsnef

Version

LifeOS 7.40.4 (latest release, 2026-08-14). The files below are byte-identical on main as of 2026-10-07.

What is broken

TELOS.md is the single source of truth (README, GenerateTelosSummary.ts:41), and #2117 fixed the onboarding interview to say so. The two other skills that write TELOS content were not touched, and both still route real content into the legacy per-topic files:

  • Telos skill. SKILL.md and Workflows/Update.md present the per-topic files as the write targets and give TELOS.md as one option among 18. UpdateTelos.ts appends to whichever file it is given and auto-creates any allowlisted file that does not exist. It has no path that maps a legacy name to a TELOS.md section.
  • Migrate skill. MigrateScan.ts classifies imported material into TELOS/GOALS.md, TELOS/WISDOM.md, TELOS/BELIEFS.md and the rest, and MigrateApprove.ts appends there. TELOS.md is not a possible target.

On a fresh install, the installer scaffolds 9 legacy sample stubs next to TELOS.md, so every /Telos or /Migrate write lands in a stub while TELOS.md stays template. From there the readers disagree, which is the family of issues #1477, #1960 and #2117. A user who migrates their content into TELOS.md gets split again by the next Telos or Migrate write.

Two smaller inconsistencies on the same surface:

  • skills/Telos/SKILL.md:194 lists LEARNED.md as a valid file, but UpdateTelos.ts allows LESSONS.md and rejects LEARNED.md.
  • Pulse's telosSectionOrFile (LIFEOS/PULSE/Observability/observability.ts:2435 and the other callers) takes the TELOS.md section whenever it is non-empty. Sample text is non-empty, so on a split install Pulse can prefer the template over the real legacy content. That is the opposite of GenerateTelosSummary's hasRealContent rule. Not verified at runtime.

Where (file:line)

Writers that target legacy files:

  • skills/Telos/Tools/UpdateTelos.ts:62-67 (allowlist), :173 (writes TELOS_DIR/<filename>)
  • skills/Telos/Workflows/Update.md:116 ("Which file should it go in? (BOOKS.md, LESSONS.md, BELIEFS.md, etc.)"), :143 (example writes BOOKS.md)
  • skills/Telos/SKILL.md:174-175 (read .../TELOS/GOALS.md, .../BELIEFS.md)
  • LIFEOS/TOOLS/MigrateScan.ts:47-64 (target union), :103-124 (routing rules), with LIFEOS/TOOLS/MigrateApprove.ts appending to the target
  • skills/Migrate/SKILL.md:97-99, 123-124

Readers that say TELOS.md is canonical: USER/TELOS/README.md, LIFEOS/TOOLS/GenerateTelosSummary.ts:41, 123-129, skills/Interview/Workflows/ContextCheckin.md.

Repro on a clean tree

# Fresh scaffold of the shipped TELOS tree into a throwaway HOME
S=$(mktemp -d); mkdir -p $S/.claude/LIFEOS/USER
cp -R ~/.claude/skills/LifeOS/install/USER/TELOS $S/.claude/LIFEOS/USER/TELOS
T=$S/.claude/LIFEOS/USER/TELOS
md5 -q $T/TELOS.md > $S/before

# Add a goal the way skills/Telos/Workflows/Update.md instructs
HOME=$S bun ~/.claude/skills/LifeOS/install/skills/Telos/Tools/UpdateTelos.ts \
  "GOALS.md" "- **G9:** Ship the thing by 2026-12-31" "Added goal G9"

# Any allowlisted name that is not scaffolded is created as a new legacy file
HOME=$S bun ~/.claude/skills/LifeOS/install/skills/Telos/Tools/UpdateTelos.ts \
  "FRAMES.md" "- A frame" "Added frame"

rg -n 'G9' $T/GOALS.md          # the goal is here
rg -c 'G9' $T/TELOS.md          # and not here
[ "$(md5 -q $T/TELOS.md)" = "$(cat $S/before)" ] && echo "TELOS.md unchanged"
cat $T/FRAMES.md

Negative control

On unpatched 7.40.4 (shipped install copy, byte-identical to the live copy), the run above prints:

GOALS.md:25:- **G9:** Ship the thing by 2026-12-31
(no match for G9 in TELOS.md)
TELOS.md unchanged
# FRAMES
- A frame

The goal is written to the legacy GOALS.md, TELOS.md is byte-identical to before, and FRAMES.md, which the scaffold does not ship, now exists as a new legacy file.

How I hit it in practice: content written during setup on a 7.28.x install landed in MISSION.md, GOALS.md and the rest, while TELOS.md stayed template. That is the #2117 scenario. Checking why it would recur after migrating to TELOS.md led here.

Suggested fix

Untested, shape only:

  1. UpdateTelos.ts: map each legacy name to its TELOS.md H2 section (the LEGACY_FILE_TO_SECTION map in GenerateTelosSummary.ts already exists) and write there with --section. Keep the legacy filename as an accepted alias, so old instructions still land in the right place. Stop auto-creating legacy files.
  2. Telos/SKILL.md and Workflows/Update.md: name sections of TELOS.md as the targets, not files.
  3. MigrateScan.ts / MigrateApprove.ts: route TELOS/* targets to TELOS.md sections through the same map.
  4. Optionally, the shared resolver proposed in Where should TELOS content live? The docs and the tools disagree #1960, so the next reader or writer cannot pick its own precedence.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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