Version
LifeOS 7.40.4, Claude Code 2.1.292 or newer (verified on 2.1.294). Same code on main today.
What is broken
Claude Code 2.1.292 changed how hook output is handled. The changelog says:
Improved hook output handling: <system-reminder> tags written in a hook's output are escaped before they reach Claude
LoadContext.hook.ts still wraps its SessionStart dynamic context in <system-reminder>…</system-reminder>. On 2.1.292+ the model gets the tag as escaped literal text (<system-reminder>) around the block instead of a reminder frame. The content still arrives, because SessionStart stdout goes into the context as plain text either way, but every session now opens with a stray escaped tag.
Where (file:line)
LifeOS/install/hooks/LoadContext.hook.ts:547 and :552 open and close the wrapper around message.
LifeOS/install/hooks/LoadContext.hook.ts:26 header says "stdout: containing dynamic context".
LifeOS/install/LIFEOS/DOCUMENTATION/Hooks/HookSystem.md:77 describes the same output.
The other shipped files that mention the tag (PromptProcessing, SatisfactionCapture, VoiceCompletion, TranscriptParser, IntegrityMaintenance) only strip it with a regex, so they are unaffected.
Fix we run locally
Drop the wrapper and print the block as plain text:
const message = `LifeOS Dynamic Context (Auto-loaded at Session Start)
${relationshipContext ?? ''}${learningContext ? '\n---\n' + learningContext : ''}${advisoryContext ? '\n---\n' + advisoryContext : ''}
---
Dynamic context loaded. Constitutional rules are in the system prompt (LIFEOS/LIFEOS_SYSTEM_PROMPT.md). Operational procedures are in CLAUDE.md.`;
We also guard the class with a test: for every script a settings.json hook command runs, plus everything under hooks/, flag any line that contains <system-reminder> or </system-reminder>, skipping comments and regex literals (/<system-reminder>, /^<system-reminder>). On 7.40.4 it flags exactly LoadContext.hook.ts:547,552. Happy to open a PR with the fix and the test if useful.
Version
LifeOS 7.40.4, Claude Code 2.1.292 or newer (verified on 2.1.294). Same code on
maintoday.What is broken
Claude Code 2.1.292 changed how hook output is handled. The changelog says:
LoadContext.hook.tsstill wraps its SessionStart dynamic context in<system-reminder>…</system-reminder>. On 2.1.292+ the model gets the tag as escaped literal text (<system-reminder>) around the block instead of a reminder frame. The content still arrives, because SessionStart stdout goes into the context as plain text either way, but every session now opens with a stray escaped tag.Where (file:line)
LifeOS/install/hooks/LoadContext.hook.ts:547and:552open and close the wrapper aroundmessage.LifeOS/install/hooks/LoadContext.hook.ts:26header says "stdout: containing dynamic context".LifeOS/install/LIFEOS/DOCUMENTATION/Hooks/HookSystem.md:77describes the same output.The other shipped files that mention the tag (
PromptProcessing,SatisfactionCapture,VoiceCompletion,TranscriptParser,IntegrityMaintenance) only strip it with a regex, so they are unaffected.Fix we run locally
Drop the wrapper and print the block as plain text:
We also guard the class with a test: for every script a
settings.jsonhook command runs, plus everything underhooks/, flag any line that contains<system-reminder>or</system-reminder>, skipping comments and regex literals (/<system-reminder>,/^<system-reminder>). On 7.40.4 it flags exactlyLoadContext.hook.ts:547,552. Happy to open a PR with the fix and the test if useful.