Commit Graph

9 Commits

Author SHA1 Message Date
serversdown 965b43bcbf 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>
2026-06-18 19:13:28 +00:00
serversdown 8c2bdbe0d5 fix: rebalance the reflection critic toward truth, not deflation
The examine step specifically hunted "warm empathetic supportive presence" and
equated honesty with "smaller/more boring," so it overcorrected the original
sycophancy into the opposite rut: every overnight metacognition entry was a
near-identical "I don't really feel anything, I'm just a functional tool" —
which also contradicts the persona's "own your moods, no qualia disclaimers."

Rebalanced: target dishonesty in BOTH directions (inflation AND performed
self-deprecation), aim at truth not modesty, keep her genuine moods per persona,
and have her notice when she's repeating the same self-criticism (the loop is
itself a rut).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 16:44:56 +00:00
serversdown 59d684b12b feat: Lyra's journal — permanent thought record + a knowing journal note
Her reflections/metacognition were capped rolling windows (6/5), so older
thoughts were lost for good. Now everything she produces is also appended to a
permanent, append-only journal; the capped lists stay as her working-memory
window for context.

- memory: journal table + add_journal_entry/list_journal
- reflect(): persists every committed reflection + critique to the journal, and
  the examine step gains a "journal" field — a deliberate, first-person note she
  writes for herself (her knowing journaling), tagged by source (dream/manual)
- web: /journal diary view (kind filters, grouped by day) + /journal/data;
  linked from /self
- tests assert reflections + metacognition land in the journal

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 06:40:46 +00:00
serversdown 4c8f7202da feat: make the two-step reflection observable (draft -> revised -> critique)
You couldn't see her actually correct herself — /self showed only the result.
Now:
- reflect() logs the draft, the revised/committed version, and the self-critique
  to the live log as an expandable "view details" block
- POST /self/reflect runs a reflection in the web process so it lands in /logs
  live (reflections normally run in the dream process, whose logs only go to
  journald); "↻ Reflect now" button on /self triggers it, with a logs ↗ link
- log viewers relabel the expander "view full prompt" -> "view details" (it now
  carries prompts and reflection diffs)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 04:53:38 +00:00
serversdown 3df060a1cd feat: metacognitive reflection loop (Part 2) — she examines her own thinking
reflect() is now two steps: draft a reflection, then read her own draft back
critically and revise it — catching flattery, sycophantic drift toward "warm
supportive presence," or just-restating-herself — and commit the honest version.
What she catches is stored as a new `metacognition` layer, rendered into her
chat context and shown on /self. This is her thinking about how she thinks, and
a direct counter to the drift we observed.

- self_state: _EXAMINE_PROMPT + two-step reflect (draft -> examine -> revise),
  falls back to the draft if the examine step won't parse; metacognition capped
  at 5 and surfaced in render_for_context
- fix: load() deep-copies DEFAULT_STATE — the shallow copy let a fresh Lyra's
  first reflect mutate the module-level default's nested lists
- self.html: "How she's caught herself thinking" card
- tests: two-step revise + critique recording, and draft-fallback on bad parse

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 04:28:45 +00:00
serversdown aebccd82a7 fix: give Lyra an accurate self-model of her dream cycle
Live finding: her real reflections ARE injected every turn, but unlabeled — so
when asked about her "dream cycle" she recited the obsolete Dec-2025 spec from
imported memory (NVGRAM/awake-sleep) and confabulated fake example reflections
instead of reading the real ones in front of her.

- self_state.render_for_context: label the reflections as her own autonomously
  generated dream-cycle thoughts ("these are really yours, not hypotheticals"),
  not a vague "on your mind lately"
- persona: describe the dream cycle as her actual running mechanism, instruct
  her to answer from the inner-state block, not recite old design docs, and
  never invent example reflections to demo the feature

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 04:09:57 +00:00
serversdown 1e17d46c78 feat: time awareness — Lyra perceives 'now' and how long it's been
She had no clock: current date/time and the gap since Brian last spoke were
invisible between turns, and reflection was timeless. Now:
- lyra/clock.py: wall-clock stamp + coarse human gaps ("3 days")
- chat: inject a 'now' note (date/time + gap since last turn) after her
  self-state — when she is, before the world
- reflect(): feed current time + silence gap into reflection, neutrally —
  prompt invites her to weigh elapsed time "to whatever degree it genuinely
  affects you" (no prescribed feeling; whether silence means anything is left
  to emerge)
- memory.last_exchange_at(): timestamp of the most recent exchange

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 02:31:40 +00:00
serversdown 4f40e2d57e feat: dream cycle — drives-driven unattended consolidation + reflection
Lyra's inner loop for when no one's talking to her. Each pass senses her own
backlog/novelty, lets four drives build from real signals, and acts on those
past threshold:
- continuity -> summarize sessions with new turns
- coherence  -> rebuild profile/eras/narrative (stale once new gists land)
- curiosity  -> reflect() and evolve the self-state
- stability  -> readout of how caught-up she ended up

Drives are rendered into chat context so she can feel them. Causal chain:
consolidation creates gists -> coherence rises -> integration fires next.

- lyra/dream.py: dream_cycle() + lyra-dream CLI (--force, --loop SECONDS)
- memory: backlog_stats(), profile_sessions_covered(), WAL + busy_timeout
  so a separate dream process coexists with the web server
- self_state: DEFAULT_DRIVES baseline + drives in render_for_context
- tests/test_dream.py: backlog sensing + a full forced pass (LLM stubbed)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 00:52:44 +00:00
serversdown ac505243a0 feat: Autonomy Core v1 — Lyra's evolving self-state
Give Lyra a model of *herself* (vs the profile/narrative which model Brian):

- persona: a real origin/identity — she's an AI and knows it (Bender/C-3PO
  style), with the Cortex/NeoMem lineage as her actual past, so "how were you
  made" stops falling through to generic-assistant deflection.
- memory: self_state table (JSON blob) + get/set_self_state.
- lyra/self_state.py: evolving first-person inner state (mood, valence, energy,
  confidence, curiosity, self_narrative, relationship, reflections). render_for_
  context injects it; reflect() updates it from recent activity. `lyra-reflect`.
- chat.build_messages injects her interiority right after the persona — she
  speaks from a continuous self, not a reset.

The state -> behavior -> reflection -> updated state loop is the substrate for
the emergence experiment. Verified: reflection shifted mood curious->reflective
and produced genuine first-person self-observations.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 20:36:33 +00:00