Skip to content

fix(algorithm): read phase/progress/iteration from modern ISA frontmatter - #2122

Open
pai-scaffolde wants to merge 1 commit into
danielmiessler:mainfrom
pai-scaffolde:fix/r-read-modern-isa-frontmatter
Open

pai-scaffolde wants to merge 1 commit into
danielmiessler:mainfrom
pai-scaffolde:fix/r-read-modern-isa-frontmatter

Conversation

@pai-scaffolde

Copy link
Copy Markdown

Reproduced on a fresh LifeOS 7.40.4 install (macOS, Claude Code in the Claude desktop app); the fix was applied to that install and run there before filing.

Observed

Every session-start ACTIVE WORK block reported the same placeholder ISA line, whatever the ISA actually said:

  ⚡ Modern ISA frontmatter probe session
     2026-09-14 10:15 | Status: climbing
     ISA: ISA (UNKNOWN, 0/0)

Note Status: climbing on the line above — the dir-level reader already understands phase:, the ISA summary right under it does not.

Separately, bun LIFEOS/TOOLS/Reflect.ts --session … --slug … --reflection … with no --iteration always wrote "iteration":1, including for ISAs the rewind hook had already bumped to 2, 3, 4.

Root cause

Both readers parse only the legacy ISA frontmatter keys. Modern ISAs carry phase:, progress: and iteration:; id:, status: and verification_summary: are the pre-rename keys.

hooks/LoadContext.hook.ts builds the isa summary from id: / status: / verification_summary: alone, so all three matches miss and the hardcoded defaults 'ISA', 'UNKNOWN', '0/0' print instead. The dir-level status reader ~50 lines above already has the phase: fallback; this block was never given one.

LIFEOS/TOOLS/Reflect.ts defaults iteration to the literal 1 when --iteration is absent. The ISA is the thing that actually tracks the iteration count, and nothing read it, so the reflection corpus silently recorded every rewound session as a first pass.

Fix

LoadContext.hook.ts: add phase: and progress: fallbacks to the ISA summary and fall back to the WORK directory slug for the id. Legacy keys still win when present, so old ISAs render exactly as before. progress: has its whitespace stripped so 3 / 7 and 3/7 both render 3/7.

Reflect.ts: add isaIteration(slug), which reads iteration: out of MEMORY/WORK/<slug>/ISA.md, and use it as the default. An explicit --iteration still wins; a missing or unparseable ISA still falls back to 1. The path is resolved through the module's existing LIFEOS constant (process.env.LIFEOS_DIR ?? join(homedir(), ".claude", "LIFEOS")) rather than a fresh homedir() join, so a relocated config dir keeps working.

How tested

Both files transpile: bun build --target=bun --no-bundle on each, exit 0.

LoadContext, against a throwaway HOME holding one WORK dir whose ISA.md frontmatter is phase: climbing / progress: "3/7" / iteration: 4, with a SessionStart payload on stdin:

$ env -u LIFEOS_DIR HOME=$TMP/home bun hooks/LoadContext.hook.ts \
    <<< '{"session_id":"probe-session-0001","hook_event_name":"SessionStart","source":"startup"}'

before:  ISA: ISA (UNKNOWN, 0/0)
after:   ISA: modern-isa-probe (climbing, 3/7)

Reflect, same fixture, --dry-run so nothing is appended:

$ LIFEOS_DIR=$TMP/home/.claude/LIFEOS bun LIFEOS/TOOLS/Reflect.ts \
    --session probe-session-0001 --slug 20260914-101500_modern-isa-probe \
    --reflection probe --dry-run

before, no --iteration:      "iteration":1
after,  no --iteration:      "iteration":4
after,  --iteration 9:       "iteration":9
after,  --slug no-such-slug: "iteration":1

On the live install the same change produced ISA: install-closeout-upstream (climbing, 3/12) in place of ISA: ISA (UNKNOWN, 0/0), and Reflect --dry-run reported "iteration":3 matching that ISA's frontmatter.

Repro on a clean tree: create LIFEOS/MEMORY/WORK/<YYYYMMDD-HHMMSS>-slug/ISA.md with a title plus phase: climbing, progress: "3/7", iteration: 4 in the frontmatter, then run the two commands above against that tree.

🤖 Generated with Claude Code

…tter

Two readers still parse only the legacy ISA frontmatter keys. The
session-start ACTIVE WORK block printed "ISA: ISA (UNKNOWN, 0/0)" for
every current ISA, and a reflection written without --iteration always
recorded iteration 1 even after the rewind hook had bumped the ISA.

Modern ISAs carry phase:, progress: and iteration:; id:, status: and
verification_summary: are the legacy keys. LoadContext now falls back to
phase:/progress: (and to the directory slug for the id), and Reflect.ts
reads iteration: from MEMORY/WORK/<slug>/ISA.md as the default. Legacy
keys still win when present, and an explicit --iteration still wins.

Reflect.ts resolves the ISA through the file's existing LIFEOS constant,
so LIFEOS_DIR keeps working.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant