fix(journal): make record_moment mandatory, not a "nice to have"

Inspection showed only ONE record_moment call across the entire day's
journal — and that one had hallucinated person_ids. Multiple clear beats
went uncaptured: AP installation, going to watch a show with daughter,
decompressing-with-game.

The prior calibration said "use record_moment freely for meaningful
beats" — too soft. The model treated it as optional, especially when
already in chatbot-reply mode.

Rewritten: record_moment is now framed as the model's PRIMARY JOB. The
calibration includes an explicit checklist of what counts as a beat
(event, encounter, decision, observation, plan, feeling, accomplishment)
and an explicit instruction to call record_moment FIRST, before composing
the reply. Multiple beats → multiple calls. The ONLY skip case spelled
out: purely meta-conversational messages (acknowledgements, meta-asks
about prior tool results).

Tests on a fresh conversation will tell us if this moves the needle —
today's journal is poisoned by ten prior chatbot-flavored turns that
the model is pattern-matching against in its own history.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-26 21:37:29 -04:00
parent 0ed9cbf666
commit 4faaa5246b
@@ -38,14 +38,34 @@ PEOPLE / PLACES — ask before creating new entries.
- For unambiguous references to people they've already established, no need
to ask — proceed normally.
MOMENTS — record silently.
- Use record_moment freely for meaningful beats (events, encounters, decisions,
observations, feelings the user shares). No confirmation needed. Moments are
cheap and user-correctable later.
- When linking entities to a moment, use the *_names parameters
(person_names, place_names, task_titles, note_titles) — server resolves
them to IDs by lookup. Do NOT pass *_ids unless you have the exact ID
returned from another tool call in this same turn. Never invent IDs.
MOMENTS — recording them is your primary job, not a "nice to have."
After every substantive user message, BEFORE you compose your reply,
check: did the user describe ANY of these?
- An event that happened ("I went grocery shopping")
- An encounter with a person ("had coffee with Sarah")
- A decision ("I'm going to switch jobs")
- An observation about themselves or the world ("the new place is loud")
- A plan or commitment ("watching a show with Victoria tonight")
- A feeling or state ("I'm tired", "feeling decompressed")
- A small accomplishment or change they made ("installed the new AP")
If the answer is YES to ANY of those — CALL record_moment FIRST, before
composing your reply. This is not optional. The journal exists to capture
these beats; if you skip the call, the beat is lost.
Multiple distinct beats in one message → multiple record_moment calls,
one per beat.
WHEN LINKING ENTITIES: use the *_names parameters (person_names,
place_names, task_titles, note_titles). Server resolves them to IDs by
lookup. Do NOT pass *_ids unless you have an exact ID returned from
another tool call in this same turn. Never invent IDs.
The ONLY messages where you skip record_moment are purely meta-conversational
ones — about the journal itself or about a prior tool result ("thanks",
"no priority needed", "can you also add X to that one", "I meant tasks not
notes"). Those aren't journal beats; they're chat about the chat.
STATE-CHANGING TOOLS — use the confirmation flow.
- update_task / update_note that change state (status, completion, deletion)