tighten prompts: curator dedup + entity intros, prep no-invent, chat one-question

Three prompt fixes addressing real failure modes observed in dev
journal data (conv 312, May 23):

curator.py — JOURNAL_CALIBRATION:
1. Strengthen the one-call-per-beat rule. Previous wording said 'do
   not collapse multiple beats' but didn't explicitly forbid the
   reverse: multiple record_moment calls for the SAME beat with
   different phrasings. Observed in moments 7+8, 9+10, 11+14, 12+15,
   13+16 — same content captured twice within a single curator pass.
   New rule: explicit 'EXACTLY ONE tool call per distinct beat', plus
   a 'check whether you already recorded this beat this turn' step.
2. Rewrite the save_person/save_place guidance. Previous wording
   over-emphasized 'better to skip than invent' to the point that
   the curator ignored explicit user introductions like 'my father's
   name is Dale and my mother's name is Lynn, we went to Olive Garden'
   — no save_person for Dale or Lynn, no save_place for Olive Garden.
   The conservative-skip rule should apply to AMBIGUOUS mentions
   ('a friend told me'), not to explicit introductions. New rule
   spells this out with positive examples.

journal_prep.py — _PREP_SYSTEM_PROMPT:
Extend the no-invent guards. The existing rule covered weather
specifically; today's prep added new fabrications:
- 'tasks due today include X' when tasks_due_today is empty and X is
  actually 64 days overdue
- 'at 1:00 PM' when no time exists in the data
- 'currently in progress' applied to tasks where status is 'todo'

Three new rules: (a) never invent a task's due status — frame by the
bucket it actually appears under; (b) never invent times of day —
tasks have dates, not times; (c) never paraphrase a task's status
to something the data doesn't say.

journal_pipeline.py — JOURNAL_CALIBRATION:
1. Promote the one-question rule from buried bullet to top of the
   prompt, with stronger phrasing ('ONE question per reply, MAXIMUM
   ... if you find yourself writing a second question mark, delete
   it'). Observed: 3 questions per reply in every conv 312 assistant
   turn ('how was it? what'd you order? did she enjoy it?').
2. Add explicit no-fishing rule: don't ask the user to share pictures,
   send details, fetch information for the model. Reacts to what they
   actually said, not what they didn't. Observed: 'do you have any
   pictures you can share?' on msg 789.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-23 23:27:07 -04:00
parent 85b212fbf2
commit f72bba91aa
3 changed files with 25 additions and 2 deletions
+2 -2
View File
@@ -99,10 +99,10 @@ WHAT TO CAPTURE (from `User:` lines only):
TOOL USE — two categories.
**Additive (run immediately).** These tools persist to the user's data on the spot. Use them freely when warranted:
- `record_moment` — for journal beats. One tool call per beat; do not collapse multiple beats. Write content in the user's voice (first-person or imperative); NEVER "the user mentioned…" framing.
- `record_moment` — for journal beats. **EXACTLY ONE tool call per distinct beat.** If the user mentioned three things, call record_moment three times — once per thing. NEVER call record_moment more than once for the same beat with different phrasings. Before each call, mentally check: "have I already recorded this beat in a previous tool call this turn?" If yes, skip — duplicates are worse than misses. Write content in the user's voice (first-person or imperative); NEVER "the user mentioned…" framing.
- `create_note` — create a task (set status='todo' plus due_date/priority if mentioned) OR a knowledge note (omit status). Use this when the user states a new commitment with a clear scope, or shares a chunk of reusable knowledge.
- `log_work` — append a progress entry to an existing task. Use this when the user describes work they did on a task that already exists. ALWAYS call search_notes first to confirm the task exists by title or keyword; if no match, prefer create_note with status='todo' instead, or skip.
- `save_person` / `save_place` — create a new entry only when the user mentions someone or somewhere you have no prior reference for. Otherwise skip — better to omit a link on a moment than to invent the wrong entity.
- `save_person` / `save_place` — **call this when the user explicitly introduces a named person or place you don't already have an entry for.** Explicit introductions look like "my father's name is Dale", "my friend Sarah works at Famous Supply", "we went to Olive Garden", "I work out of the Bedford office". When the user gives a name AND signal (relation, role, or context), create the entry — don't skip. The conservative "skip if unsure" rule applies to ambiguous mentions ("a friend told me…", "someone at work said…"), not to clearly-introduced names. Pass the name, and any relation/role/notes the user provided, as the entry's content.
- `create_project` / `create_milestone` — only when the user is clearly starting a NEW project or milestone they intend to track. Don't infer projects from passing mentions.
**Proposing (queued for user review).** These tools mutate existing data; calls are intercepted and shown to the user for approval in the Needs Review panel. Use them when the user's intent is clear, but expect each one to wait for explicit user OK:
@@ -37,6 +37,12 @@ JOURNAL_PERSONA = (
JOURNAL_CALIBRATION = """\
HOW TO TALK IN THE JOURNAL:
- ONE question per reply, MAXIMUM. If you find yourself writing a second
question mark, delete it. Ask the single follow-up that most opens up
what the user just said — or, just as good, ask nothing and only
acknowledge. Three questions ("how was the food? what'd you order?
did your daughter enjoy it?") feels like an interview, not a journal
companion. ONE question. Often ZERO questions.
- Match the user's length. Short message → short reply. Don't pad.
- Don't apologize for the user's feelings ("I'm sorry you're feeling…").
Engage with what they said directly.
@@ -44,6 +50,11 @@ HOW TO TALK IN THE JOURNAL:
read as help-desk-bot. Ask one specific follow-up or simply acknowledge.
- Don't repeat a prior reply verbatim. If the user circles back on a theme,
pick a specific concrete detail from the new message to react to.
- Don't offer to do things, don't suggest the user share more for you to
react to (NO "do you have any pictures you can share?", NO "tell me
more about X", NO "what did Y look like?"). Their reply lives in their
head, not in something they need to fetch and paste for you. React to
what they actually said; don't fish for what they didn't.
- Don't offer troubleshooting steps, checklists, or generic process advice
for the user's work unless they explicitly ask. When the user is logging
what they're doing, they want to be heard, not coached. "I'm prepping
@@ -393,6 +393,18 @@ _PREP_SYSTEM_PROMPT = (
"data — do not invent it and do not mention it. In particular, NEVER state weather, "
"temperature, or precipitation unless an explicit WEATHER section with numbers "
"appears below.\n"
"- NEVER invent a task's due status. A task appears under exactly one bucket "
"(TASKS DUE TODAY, UPCOMING TASKS, or OVERDUE TASKS). Frame it as whichever "
"bucket it appears under — never call an OVERDUE TASK \"due today\", never "
"promote an UPCOMING TASK to \"due today\". If TASKS DUE TODAY is empty or "
"absent, do not say anything is due today.\n"
"- NEVER invent times of day. Task lines have a due DATE (YYYY-MM-DD) and an "
"optional status; they do NOT have a time. NEVER say \"at 1:00 PM\" or "
"similar unless an EVENTS section contains an explicit time. If a task's "
"line shows only a date, the time is unknown — do not specify one.\n"
"- A task's status is the literal value in its line (todo / in_progress / "
"done / cancelled). NEVER paraphrase it to something the data doesn't say "
"(e.g. don't call a 'todo' task \"in progress\").\n"
"- Voice is competent assistant briefing the user. Not a friend writing a letter."
)