From 4faaa5246b9f3b9e3f70bba69ebd241d02f7395c Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sun, 26 Apr 2026 21:37:29 -0400 Subject: [PATCH] fix(journal): make record_moment mandatory, not a "nice to have" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../services/journal_pipeline.py | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/fabledassistant/services/journal_pipeline.py b/src/fabledassistant/services/journal_pipeline.py index f50a9c1..0fa658c 100644 --- a/src/fabledassistant/services/journal_pipeline.py +++ b/src/fabledassistant/services/journal_pipeline.py @@ -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)