Local Waifu 0.1.19
The prior release was about how the character learns about YOU. This
one is about her interior life — modes she can be in, things she
likes, things she's afraid of, who she is when she's with you. Three
layers landed together.
New (named behaviour modes)
- Mode catalog. 13 named modes the character can be in for a
turn:neutral,playful,naughty,tender,comforting,
excited,sleepy,focused,melancholic,grumpy,
protective,curious,quiet. Each ships with a one-line
behavioural cue so the LLM has a discrete posture to organise the
reply around (instead of trying to translate 6 analog mood
numbers into tone). - Mode selector. Each turn picks a mode from mood + user-message
signals (sad-keyword lexicon, threat keywords, new-topic openers)- stage + time-of-day. Strong overrides (distress → comforting,
threat → protective) bypass mood entirely.naughtyis gated by
relationship stage (≥ Close) AND the absence of an NSFW
hard-boundary.
- stage + time-of-day. Strong overrides (distress → comforting,
- Sticky modes. Modes hold for at least 3 turns once chosen so
the character doesn't whiplash between postures when mood values
jiggle by 0.05. Strong overrides break stickiness instantly. - LLM-driven shifts. New
[[MODE shift <name> | <reason>]]
marker lets the LLM consciously override the heuristic when it
senses something the lexicon missed. - Mode telemetry. Last 50 transitions persisted per character
inapp_meta, ready for future Growth Dashboard surfacing.
New (character self-content blocks)
Four new Letta-style working-memory blocks every character now
ships with, alongside the existing persona / user / session
/ scratch:
likes— things SHE enjoys, discovered through your
conversations.dislikes— things that bother her.quirks— verbal tics and mannerisms she's noticed in
herself.fears— soft worries she carries, even with you.
All four start mostly empty and grow organically — from in-chat
[[BLOCK append <label>]] markers the LLM emits AND from the new
weekly self-reflection pass.
New (weekly self-reflection sub-agent)
character/self_reflection.rs— runs once per 7 days per
character from the daily background pass. Reads the last 50
chat turns plus the current self-content blocks, asks the LLM
to reflect in FIRST person ("I notice I enjoy…"), and appends
up to 3 entries to each block. Also produces:- Mode preference weights —
mode → weightmap blended into
the existing weights (smoothing 0.7 × existing + 0.3 × new) so
"she has learned that playful works with you" emerges over
months without a single week's outlier flipping it. - Insight of the week — 1-2 sentence honest self-observation
stored as aself_insightmemory, ready for the Growth
Dashboard.
- Mode preference weights —
- License-gated like the other background loops.
Removed / cleaned up
- The pre-v0.1.19 mood-only prompt line ("Current mood: warm
(happiness=…)") is now LABELLED as "Underlying mood" because
the discrete mode + cue sits above it. The mood numbers still
feed the model — they just no longer carry the whole tonal
responsibility alone.
Fixed (caught by new gemma4:e4b integration test)
- System-prompt block dump no longer leaks into the chat.
Reasoning models (gemma4:e4b especially) sometimes echoed the
rendered working-memory block dump —--- persona (188/500 — Your self-image) --- … --- end blocks ---— verbatim into the
visible reply, exposing internal state. The pipeline now strips
any block-dump-shaped region from the assistant text right
before persisting and surfacing it, so even when the model
mimics the system-prompt format, only her actual words reach
you. (character::blocks::strip_leaked_block_dump, wired in
chat_pipeline.rsafter marker parsing; 5 unit tests covering
with/without terminator, markdown horizontal rules, unknown
labels, and clean text.) - Polish distress lexicon now catches reversed word order.
The distress cue list only had"fatalnie się czuję"but
Polish lets you reorder freely —"Czuję się fatalnie."was
slipping through and Comforting mode wasn't firing. Added 12
new cues: both word orders forczuję się fatalnie/
fatalnie się czuję/źle się czuję/kiepsko się czuję,
pluskiepsko mi,ciężko mi,rozpadam się,
przejebany dzień/tydzień, and ASCII-fold variants for users
who skip Polish diacritics. Threat-mode (boję się) still
takes precedence when both signals fire, by design. - Multi-turn self-learning integration test.
Addedtests/v019_self_learning_demo.rs— drives a 6-turn
Polish conversation against gemma4:e4b, parses every marker
the character emits ([[MEM]]/[[BLOCK]]/[[THREAD]]/
[[MODE shift]]/[[MILESTONE]]/<thought>), folds the
resulting state back into the next prompt, and asserts the