Local Waifu 0.1.16
Internal-quality release driven by a 4-agent backend audit. No
new user-facing features — just hardening every production-risk
finding the audit surfaced.
Fixed (BLOCKER class)
- Migration runner crash window. The DB migration tracker row
used to be inserted after the migration body's COMMIT. A crash
in the millisecond between those two writes would leave the
schema modified but the migration unrecorded; the next launch
would re-attempt the sameALTER TABLE ... ADD COLUMN, fail
(SQLite has noIF NOT EXISTSfor ADD COLUMN), and brick the
database. The body + bookkeeping now commit atomically. - Fire-and-forget tasks.
commands/feedback.rswas using raw
tokio::spawninstead oftauri::async_runtime::spawnfor the
background consolidation pass — broke the codebase convention.
Swapped. (Telegram dispatcher keepstokio::spawnbecause its
is_finished()API powers status reporting — panic visibility
is already covered by the global panic hook.)
Fixed (production hardening)
- Marker parser robustness.
[[MEM ...]],[[THREAD ...]],
[[BLOCK ...]]parsers used to terminate on the first]]
encountered — if the model mirrored user text containing]]
(markdown footnotes, nested quotes), the marker would fire on
the wrong delimiter and either drop a real call or swallow
user-visible content. Now any[[inside the body is treated
as nested content and the marker is preserved verbatim. - Lorebook write validation.
lorebook_upserthad no length
caps; a user could push a 50 MB entry into SQLite. Now bounded
at 200 chars (title), 4,000 chars (content), 32 keywords ×
80 chars each. Update path also now correctly returns the
originalcreated_atinstead ofnow, and rejects updates
against an ID that doesn't belong to the active character. - Anticipations table runaway. The pruning DELETE used
LIMIT = MAX_UNCONSUMED - parsed.len()which could go negative
if those constants ever drifted. Clamped to >= 0. - DB lock starvation.
anticipations::build_contextused to
hold the SQLite mutex across two prepared-statement iterations.
Concurrent chat turns now don't block on the background
reflection pass. - Ollama non-stream timeout. The shared client default 120 s
was killing background drift detection / KG extraction /
consolidation calls on Power-tier 27B models (real responses
take 2-5 min). Per-request override raised to 10 min on the
non-streaming path. - License gate for background loops. Daily consolidation +
sleep-time anticipations now checklicense::gate::current_status
and skip the LLM call entirely for Locked / TrialExpired /
NotStarted users. They can't chat with the app anyway — no
reason to burn their local CPU/GPU on reflection passes for a
product they haven't paid for.
Audit deferrals
- Retention sweep on memories / chat_messages / entities /
open_threads / relationship_milestones. All grow unboundedly.
Realistic ceiling for a daily-use install: ~100 MB after a year.
Acceptable for v0.1.x; will land as a configurable retention
policy in v0.2.