Skip to content

SessionStart dynamic context is empty by construction: LoadContext reads three sources nothing ever writes #1712

Description

@jacobo-ortiz

Version: v7.1.1

The defect

hooks/LoadContext.hook.ts builds its <system-reminder> from three dynamic sources. On this install all three are empty by construction, so the hook takes its empty branch and emits only:

✅ LifeOS session ready...

28 bytes. Exit code 0, no warning. Not even the ⏭️ Skipped … (disabled) line, because the features are enabled; their data sources are simply never written.

Repro

echo '{"session_id":"probe"}' | bun ~/.claude/hooks/LoadContext.hook.ts | wc -c
# 28

The three sources, and who writes them

  1. LIFEOS/MEMORY/WISDOM/FRAMES/ is read by loadWisdomFrames() in hooks/lib/learning-readback.ts, which scans *.md for ### <name> [CRYSTAL: N%] headers. LIFEOS/TOOLS/WisdomFrameUpdater.ts exists and would produce these, but nothing invokes it: no hook registration, no cron entry, no other script references it outside documentation. On my install, git log --all --diff-filter=A -- 'LIFEOS/MEMORY/WISDOM/FRAMES/*.md' is empty. No frame has ever existed.

  2. LIFEOS/MEMORY/RELATIONSHIP/YYYY-MM/YYYY-MM-DD.md is read for today and yesterday only. Nothing in the tree writes these files. They appear only when the assistant happens to write one by hand mid-session, which is sporadic, so the today-or-yesterday window almost never hits even when files exist. Mine has 8 files across 5 months.

  3. LIFEOS/MEMORY/STATE/progress/ is written only by LIFEOS/TOOLS/SessionProgress.ts, a manual CLI whose invocation LoadContext itself prints as a hint. Where the user has never run it, the directory does not exist.

The 2026-07-10 change that made this total

The code documents it at hooks/LoadContext.hook.ts:426:

// 2026-07-10 directive: keep ONLY the Wisdom Frames — the actionable
// behavioral guidance. Dropped the self-rating wall (Performance Signals,
// Complaint Clusters, Recent Learning Signals, Recent Failure Patterns): it was
// negative session-start priming and the biggest single one-time context block.

Dropping that wall is defensible on its own terms. The side effect is that the one source left standing is the only one with no producer, so the block went to zero. Measured on my install: 45 of 45 sessions before that change emitted over 200 bytes; 60 of 60 after emitted the 28-byte stub.

Why nothing caught it

LIFEOS/TOOLS/MemoryHealthCheck.ts reported "overall":"ok" for 60 consecutive runs across the same period. Every one of its checks asserts that a file or a hook registration exists; none asserts that a hook produces output. Presence is not delivery.

Suggested direction

Two independent fixes:

  1. Either schedule the wisdom-frame generator and create the directories at install time, or drop the sources that have no producer. Right now there is a reader with no writer, which is invisible precisely because the empty branch looks like success.

  2. Add a health check that asserts delivery. Comparing the hook's output length against a floor would have caught this on day one.

For what it is worth, I pointed the dynamic block at LIFEOS/MEMORY/WORK/<slug>/ISA.md instead, which is the one corpus written on every substantive run, and read back decisions and open claims from the last 72 hours. That took the block from 28 bytes to about 2.4 KB of genuinely useful continuity, at roughly 690 tokens. Happy to send a PR if that shape is interesting.

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