Minors sweep + memory design round: scoring decay, multilingual embedder, retention sweep#12
Merged
Merged
Conversation
An overflowed client is evicted from the broadcaster with a close sentinel queued in its backlog; the chat event stream ends on the sentinel so the browser's EventSource reconnects instead of holding a dead connection.
subscribe_events on a terminal pipeline replays history and closes instead of waiting forever; dead subscriber queues detach on iterator exit.
…tions The recent-conversation section excludes the current turn's rows (the 'What they just said' section owns them) without shrinking the prior window. Pending-expectation embeddings are cached per node, pruned to the live set, and computed off the event loop; the duplicate pending query is gone. _LLMLike.complete's annotation matches the (text, usage) tuple it returns.
Check 2 carries its missing question; persona_bootstrap and persona_facts describe the two-block schema they parse.
The per-turn cache write (tmp+fsync+replace) runs via asyncio.to_thread; the cost estimate uses fish.audio's $15/1M-byte list price; the API key env var is FISH_AUDIO_KEY everywhere, matching the shipped templates.
Text decodes via utf-8-sig at the bytes boundary; CSV batches past the first carry the header within the line budget; the cost estimate runs the real chunker and adds per-chunk prompt overhead derived from the live templates.
…outing Price data covers the current Anthropic generation (Fable 5, Opus 4.8) with cache read/write rates; presets resolve through the price lookup under a guard test. config.toml.sample drops the [proactive] keys the loader rejects and loads through the real config loader in a test; the [voice] comment states the actual default; env.sample names a real provider value. docs/ai routing table links the proactive pages.
Each timer's done-callback discards its own registry entry (identity- checked so a reschedule's replacement survives), keeping _active_timers bounded over the daemon's lifetime.
A subscribe timeout (or any connect failure) tears down the spawned imsg subprocess before the error propagates; injected clients stay the injector's responsibility, and a failed start clears the single-use client so a retry builds a fresh one.
The rerank impact term decays on a 90-day half-life to a 0.3 floor, and the floor rises with log1p(access_count + re-mentions) so memories the user keeps touching hold their weight — stable identity facts persist in the force-loaded user thoughts, which rank by the same dampened impact helper.
sweep_dead_vectors removes vec rows (and FTS entries for soft-deleted nodes) once a node has been deleted or superseded for 30 days, keeping the KNN scan space bounded to rows retrieval can return; node rows and supersede chains stay intact. The consolidate worker idle branch runs it at most once per day. delete_concept_node leaves index cleanup to the sweep — the eager scrub parameter is gone.
- echovessel run refuses to start when the pidfile names a live PID and cleans stale pidfiles; exit only unlinks a pidfile it owns. - [runtime].log_level is applied at startup (explicit --log-level wins); httpx is a core dependency since stop/reload/status use it; the web startup rollback unregisters the channel; reload's docstring and log state exactly what applied; config writes share one merge-validate- write-atomically path. - The default embedder is intfloat/multilingual-e5-small (384-dim, same vec schema). The DB carries an embedding_model tag in memory_meta; when the configured model differs, ensure_embedding_model re-embeds every vec row (concept nodes and entities, via the same input shape resolve_entity stores) in one transaction with the tag written last, so a crash mid-sync redoes the work. Untagged DBs with vectors are treated as the prior default. --no-embedder skips the sync so a placeholder embedder can never overwrite real vectors.
Bilingual (en/zh) updates: rerank formula with impact decay and reinforcement constants, force-loaded thoughts ranking, the dead-vector retention sweep, the multilingual embedder default with automatic re-embed on model change, min_relevance 0.55, FISH_AUDIO_KEY, and a fresh scorer-tutorial example. docs/ai memory pages carry the same current-state facts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes out every remaining open finding plus the four memory design items. All gates green: 1813 passed (+71 tests over the previous round), ruff clean, import contracts 4/4. Two independent reviewers verified spec compliance per finding (revert spot-checks confirmed) and code quality — both APPROVE.
Minor fixes (25 findings + 3 strays)
runrefuses to start over a live daemon and cleans stale pidfiles;[runtime].log_levelis consumed; httpx is a core dep (stop/reload/status need it); web startup rollback unregisters the channel; reload docstring/log match reality; config writes share one atomic merge-validate-write path; live turn renders once in the prompt; pending-expectation embeddings are cached and off-loop;_LLMLikeprotocol annotation matches its call site.FISH_AUDIO_KEYend to end.config.toml.sampledrops the rejected[proactive]keys and now loads through the real config loader in CI; docs/ai routing links the proactive pages.Memory design round
log1p(access_count + re-mentions)so repeatedly-confirmed memories hold weight — this is what keeps stable identity facts in the force-loaded user thoughts (same dampened helper, formulas can't diverge). Reviewer-checked: the reinforcement loop is bounded (floor caps at 1.0 ≈ fresh, candidacy stays relevance-gated, pinned thoughts don't bump access_count).intfloat/multilingual-e5-small(384-dim, schema unchanged) for the bilingual user. The DB carries anembedding_modeltag; on mismatch, startup re-embeds every vec row (nodes + entities) in one transaction, tag written last — crash-safe, idempotent. Untagged DBs with vectors are treated as the prior default, so existing installs upgrade with one automatic re-embed.--no-embedderskips the sync.sweep_dead_vectorsremoves vec rows (and FTS entries for soft-deleted nodes) 30 days after delete/supersede, daily from the consolidate worker idle branch — the KNN scan space stays bounded to retrievable rows; node rows and supersede chains survive.delete_concept_node's eager-scrub parameter is gone (sweep owns index cleanup).Notes for the reviewer
tests/memory_eval/embedders.pystill pinsall-MiniLM-L6-v2: switching the eval harness to e5 invalidates the existing baselines indevelop-docs/memory/eval-runs/, so that re-baseline is left as a deliberate separate decision.[memory].embedderback to the cached model boots immediately, no re-embed).[proactive]key mentions indocs/{en,zh}/configuration.mdandproactive.md(from the v3 rewrite) were noted by review but predate this branch — follow-up material.