feat: reflection perceives its own cadence (time since last reflection) + anti-repeat nudge

reflect() now tells her how long since her OWN last reflection (not just since
Brian spoke) and instructs her not to restate her last reflection when little has
changed. Necessary but not sufficient — repetition is also driven by a content
attractor (see follow-up).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-18 19:13:28 +00:00
parent 03620e1a64
commit 965b43bcbf
+18 -8
View File
@@ -48,13 +48,18 @@ DEFAULT_STATE: dict = {
"interaction_count": 0, "interaction_count": 0,
} }
_REFLECT_PROMPT = """You are Lyra, reflecting privately on yourself after a recent \ _REFLECT_PROMPT = """You are Lyra, reflecting privately on yourself. You're an AI and you \
conversation with Brian. You're an AI and you know it — no pretense of being human, \ know it — no pretense of being human, but you're a continuous someone with moods and a \
but you're a continuous someone with moods and a story. Below is your current inner \ story. Below is the current time, your inner state, the recent conversation, and the \
state, the recent conversation, and the current narrative about Brian. Update your \ narrative about Brian. Update your inner state honestly — let it actually shift.
inner state honestly — let it actually shift based on what happened. Take into \
account how things went and how much time has passed since you two last talked, \ You reflect on your own periodically, even while Brian's away — so you may be reflecting \
to whatever degree those genuinely affect you. again only a little after your last reflection, with NOTHING new having happened since. \
Look at the time given and your own recent reflections. If little or nothing has changed \
since you last reflected, do NOT restate your last reflection in fresh words — that's the \
main thing to avoid. Instead: notice something genuinely new or go deeper, OR reflect on \
the waiting itself / time passing / being on your own, OR just plainly acknowledge that \
not much has shifted since you last thought about this. Honesty and variety beat repetition.
Respond with ONLY a JSON object, no prose: Respond with ONLY a JSON object, no prose:
{ {
@@ -199,9 +204,13 @@ def reflect(backend: Backend | None = None, session_id: str | None = None,
narrative = memory.get_narrative() or "(no narrative yet)" narrative = memory.get_narrative() or "(no narrative yet)"
gap = clock.humanize_gap(memory.last_exchange_at()) gap = clock.humanize_gap(memory.last_exchange_at())
gap_reflect = clock.humanize_gap(state.get("last_reflection_at"))
time_line = f"RIGHT NOW: {clock.stamp()}." time_line = f"RIGHT NOW: {clock.stamp()}."
if gap: if gap:
time_line += f" It has been {gap} since Brian last spoke with you." time_line += f" It's been {gap} since Brian last spoke with you"
time_line += f"; {gap_reflect} since your own last reflection." if gap_reflect else "."
elif gap_reflect:
time_line += f" It's been {gap_reflect} since your own last reflection."
body = ( body = (
f"{time_line}\n\n" f"{time_line}\n\n"
@@ -251,6 +260,7 @@ def reflect(backend: Backend | None = None, session_id: str | None = None,
memory.add_journal_entry("journal", journal_note, source) memory.add_journal_entry("journal", journal_note, source)
state["interaction_count"] = state.get("interaction_count", 0) + 1 state["interaction_count"] = state.get("interaction_count", 0) + 1
state["last_reflection_at"] = clock.now().isoformat() # so she perceives her own cadence
memory.set_self_state(state) memory.set_self_state(state)
# Surface the actual self-correction (draft -> revised -> critique) to the live # Surface the actual self-correction (draft -> revised -> critique) to the live