Repository navigation
feat!: everalgo 2026-11 line, per-task LLM, profile from episodes - #595
Conversation
Every pipeline EpisodeExtracted now folds that one episode into its owner's user.md through ProfileExtractor.aextract_from_episodes. The profile no longer re-reads memcells selected through the owner's clusters or the episode index, so it no longer depends on clustering and no episode is sent to it twice. The event carries owner_name, the label the owner's chat lines had in the memcell (sender_name, else sender_id); the extractor finds the owner in the narrative by it, and a narrative that does not name them is skipped with a warning. The episode is read back from md and its memcell must still exist, so a deletion racing the run is not undone. ProfileClusterUpdated had no other consumer and is removed; trigger_profile_clustering still clusters episodes for agentic search and Reflection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EpisodeIndex.count and EpisodeIndex.list_after, with the repositories' count_by_owner and list_by_owner_after_ts on LanceDB and Milvus, served only the profile's old memcell selection and throttle. With the profile built from each new episode they have no caller left. The EpisodeIndexRepository protocol held nothing else and goes too; the episode repositories are plain IndexRepository implementations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ingestion records the latest non-blank sender_name of every (app_id, project_id, sender_id) in a new sender_name table of system.db and gives it to that sender's later messages that arrive without one; blank names count as absent and names are stripped. One person is then labelled the same way in every memcell, episode narrative and profile, which the profile needs to find its owner. ingest.process takes the SenderNameStore explicitly; the Memorizer passes the one bootstrap builds. Deleting a whole user or agent forgets its name; deleting a session does not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pin everalgo-core 0.7.0rc1, everalgo-boundary 0.5.0rc1, everalgo-user-memory 0.9.0rc5, everalgo-agent-memory 0.6.0rc4 and everalgo-rank 0.5.0rc5, and adopt what they ship: - Boundary detection runs on BoundaryDetector, which returns Cuts; [boundary_detection] strategy picks batch (default) or step. - Each memcell's summary is written by EpisodeSummarizer in parallel with the episode; a failed summary falls back to the first 200 characters. - [memory] timezone sets the zone the model sees times in, across boundary detection, extraction strategies and agentic search. - The detected output language is Chinese, Japanese or English only. - [tokenizer] name selects the keyword tokenizer (jieba or nltk). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
User-profile extraction can now run on its own model. With [profile].model empty (the default) it keeps using [llm], field for field. Once model is set, api_key and base_url fall back to [llm] when blank, and the section brings its own timeout_seconds (default 240), extra, response_format_mode and invalid_reply_retries: the everalgo profile evaluation ran claude-haiku-5-5 with thinking at about 28s median and 41s p90 per call, which [llm]'s 60s deadline would cut off. resolve_profile_config resolves the section; the bootstrap builds Providers.profile_llm from it, and MemoryDeps carries it to extract_user_profile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Profile runs are serialised per owner, and the OME run timeout also counts the wait for that owner's partition lock. With a slow profile model, one call per episode let a burst for one owner (a bulk import) queue past it: in a time-scaled replay on the real engine (0.28s per call, 18s deadline), 500 episodes at once left 314 never folded. A run now also folds the owner's newer episodes the index holds, oldest first after Profile.timestamp, up to [profile] max_episodes_per_call (default 10), and ProfileBatcher marks them in memory so their own runs end without a call. The same replay folds all 500 in 50 calls; 2000 at once still leave 160. A crash loses the marks and can fold an episode twice, the at-least-once repeat the strategy already accepts. EpisodeIndex.list_after and the repositories' list_by_owner_after_ts (LanceDB, Milvus) return for this read, with the EpisodeIndexRepository protocol; EpisodeIndex.count stays removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The everalgo profile evaluation switched thinking on and left its effort at the default. Say so where [profile] is recommended: default.toml, docs/configuration.md, the CHANGELOG entry and ProfileSettings.extra. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
[llm] stays the one required section. Every task -- boundary, episode, summary, atomic_fact, foresight, profile, reflection, agent_case, agent_skill, knowledge, search and decider -- may override any of its fields in an optional [llm.<task>] table; a field left out inherits [llm]'s. Tasks that resolve to the same client share one provider; the decider always gets its own and keeps its own timeout, max_tokens, sdk_max_retries and invalid_reply_retries defaults. - New fields on [llm] and every task: temperature, max_tokens and sdk_max_retries, sent only when a call does not set its own. - Unknown keys or task names under [llm] fail at startup and list the valid names; other sections keep their policy. - Startup logs llm.task.resolved per task; `everos config show` prints the resolution table with the key masked. - [decider] and EVEROS_DECIDER__* keep working with a deprecation warning; [llm.decider] wins when both are set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…odes-rc6 Brings the episode-built user profile onto the integration stack (everalgo 2026-11-11 rcs + per-task LLM sections). Resolution: - The profile's LLM is [llm.profile], like every other task: the [profile] LLM fields and resolve_profile_config are dropped, and [profile] keeps only max_episodes_per_call. The docs recommend a reasoning model with timeout_seconds = 240 under [llm.profile]. - The strategy runs on deps.llms.profile and passes deps.tz to aextract_from_episodes; MemoryDeps keeps llms plus profile_batcher. - Tests follow both sides: ingest callers pass sender_names, the profile time-zone test uses the episode path, the e2e speaker check reads everalgo-user-memory 0.9.0rc5's episode rendering, and the dual-trigger test file stays deleted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rc6 grounds every profile item in a quote from the batch's episode narratives, holds an unrepeated pattern on a `pending` list until a later batch repeats it, keeps a `do_not_record` list of matters the user asked not to be recorded, and adds no new implicit_traits item. - Profile (domain) gains do_not_record and pending; the mapper carries them between everalgo's top-level extras and the domain profile, so each update passes them back and stores the lists it returns (an empty pending replaces the stored one). - user.md keeps both lists in its frontmatter, written only when non-empty, so existing files read and write unchanged. They are not indexed and never returned by /get or /search. - The strategy builds ProfileExtractor with its defaults (item checks on). - Canned profile replies follow rc6's reply shapes, with quotes found in the canned narrative; tests cover the round trip, the replacement of an empty pending, and that neither list reaches the API. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The harness stops building its own decider configuration: the servers' environment is assembled once (server_launch_env) for both the fleet and the probe, and the fleet exports EVEROS_LLM__DECIDER__*. - The probe runs benchmarks/decider_probe.py in a child process under that environment: load_settings -> resolve_llm_task(DECIDER) -> llm_client_config -> build_llm_provider -> one achat with a json_schema reply format, nothing passed per call -- the request the decider makes. The key never leaves the child; the child prints one JSON line. - The serving record takes the decider's model, base_url and field sources from that resolution; the backbone scan skips EVEROS_LLM__<TASK>__*. - _decider_extra, _decider_max_tokens and resolve_decider_endpoint are gone; evermembench.toml uses EVEROS_LLM__DECIDER__TIMEOUT_SECONDS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings the benchmark's decider resolution through [llm.decider]. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> # Conflicts: # CHANGELOG.md
run_spec.json named the decider's model, endpoint and the section each field came from, but not the values themselves, so a run's output cap, timeout or thinking switch could not be read back from its record. decider_probe.py now reports every effective field but model, endpoint and key, and the decider entry of run_spec.json carries it next to the sources. extra_headers and extra_query values are masked -- the SDK sends them as HTTP headers and URL query parameters, where a gateway's credentials go -- while extra_body and top-level fields stay readable. The read identity still compares only model and endpoint, so resuming an existing run is unaffected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: Preserve persisted profile-job recovery and make the deletion/writer property pass.
I reviewed the repository guidance, the full origin/main...HEAD diff, affected callers and composition wiring, commit history, persisted-event compatibility, test changes (including removed tests), and the architecture contracts. The per-task LLM, profile-from-episodes, boundary/sender, persistence, and benchmark paths otherwise look coherent.
Validation:
- All lint, formatting, import-architecture, repository-policy, datetime/singleton, and OpenAPI gates passed.
- Unit: 3,708 passed, 4 skipped, 1 failed (
test_memory_delete_jitter), and the minimized failure reproduces directly. - Integration: 213 passed, 9 skipped, 7 deselected; 7 allocator-probe tests could not run because the host system
/tmpis full and their glibctmpfile()setup therefore produces no probe log.
Two blocking findings are inline.
Following benchmarks/README.md as an outside user: - every ADD died in run.py's readiness wait: OME empties a succeeded run's event_payload (since #555) and json_extract raised "malformed JSON" on it. Emptied rows now skip the payload filter and still count; - .env.example pointed embedding at a local server and had no reranker key, which agentic search refuses to run without; README now lists both keys and a one-line LoCoMo download; - the "no decider endpoint" notice called agentic runs "not comparable" although they call no decider; it now shows for llm_multiround only. locomo.toml now runs the EverAlgo LoCoMo reference setup BOSS agreed on: agentic at top 10, three judge runs, chat mode, temperature 0.3, max_tokens 16384, 1024-dim embeddings, clustering threshold 0.7, and every message filed under the queried speaker (message_owner, ported from the benchmark branch, part of the ingest identity). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0.9.0rc6's Episode-path profile replies carried untyped fields that
OpenAI refuses under the default strict reply format, so every
episode-based profile update failed (found by the LoCoMo smoke run).
rc7 types them and also requires a found quote for a do-not-record
entry, adds withdrawal (allow) and caps the list at 30.
The canned INIT reply's do_not_record entry now carries its quote
instead of evidence, the e2e check reads the matter tag's text (rc7
adds index and date attributes), and storage_layout.md shows the
stored entry shape ({topic, observed_at} plus except).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LoCoMo answers without the user profile, yet every server ran the profile strategy: calls spent on output nothing reads, and a strategy that failed for good stopped the conversation (the 1% OME tolerance). EverOS reads strategy switches from <root>/ome.toml only, so a config's new [ome_strategies] table is written there before each server starts, replacing the file so a rerun keeps no older switches. It is part of the ingest identity. locomo.toml turns extract_user_profile off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rc7's profile calls now and then stalled under the default strict reply format: its examples showed items with three fields while the strict schema requires every reply-only field, so the model emitted whitespace until max_tokens (1 in 15 gpt-4.1-mini calls, about 2 minutes each). rc8's examples write every field; 0 of 27 calls stalled on the same episodes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The LoCoMo loader sent each turn's text alone, so the captions of the 910 turns that share an image never reached the extractor, while the EverAlgo loader and every reference experiment write "[<speaker> shared an image: <caption>] <text>". Ported from the benchmark branch (_message_text and its tests). The ingest identity gains a message_format version, so a store extracted from the old text is not resumed as if it had the captions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every reference experiment ran on a harness whose fixes stayed uncommitted
on the benchmark branch, so a user following benchmarks/README.md ran a
different one. Ported feature by feature onto this branch's structure:
- JUDGE re-judges the audit's disputed questions (dial481/locomo-audit,
WRONG_CITATION excluded) against its corrected answers, with the same
judge, runs and majority vote; Re-judged sits beside Accuracy in every
report. Nothing is dropped, and the original score is computed as before.
- The ingest identity also records the message cap of a smoke run, the
flush scope and the server settings that change what is stored.
- run.py loads benchmarks/.env before expanding ${...}; --smoke runs
conversation 0; flush_scope = "conversation" is available (LoCoMo keeps
"session").
- download_data.sh, preflight.py (missing data and keys before a server
starts, missing embedding / rerank capability right after), a Scope and
a Decider line on the report, multi-server stores found on a stage-only
rerun, and two adapter fixes.
- README / .env.example / CHANGELOG / root README entries merged.
Offline recompute of four existing LoCoMo runs gives the same original
and re-judged counts as the standalone scripts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in #591 (guard profile sources during index lag and deletion). - Kept from #591: session deletion detaches the deleted episodes from their clusters and a retry finishes that cleanup (_delete.py, merged cleanly), with its retry test moved to tests/integration/test_session_delete_cluster_cleanup.py. - Superseded by this branch: the profile-source guards. This branch builds the profile from episodes read back from markdown (its own episode is never waited on in the index; a deleted source is left out, and a run whose own episode is gone ends) and removes ProfileClusterUpdated, so #591's episode_entry_id field, its _select_via_cluster change, the cluster-selection integration and property tests and the TLA+ model of cluster-triggered selection are dropped. The same guarantees are pinned by test_a_deleted_source_is_not_profiled and test_a_waiting_episode_whose_memcell_is_gone_is_left_out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: Preserve old profile-job recovery, fix the deletion/writer race, and reject legacy smoke stores during full benchmark resume.
The two previous blockers still reproduce on this head: resolve_topic("everos.memory.events:ProfileClusterUpdated") raises TypeError, and the standard unit suite still minimizes the deletion/writer property to the same cross-owner episode loss.
I also found one new backward-compatibility blocker inline: the new message_cap identity does not protect full runs from smoke stores created by the pre-change harness, because missing legacy identity keys are discarded as unknown.
Coverage this round: the delta from the previously reviewed head, the current complete branch diff, CLAUDE.md (no AGENTS.md or CONTEXT files are present), affected callers and resume markers, relevant history, upgrade/backward compatibility, test additions/removals, and the architecture contracts.
Checks: pytest -q tests/unit finished with 3,817 passed, 4 skipped, 1 failed in 10:59 (the deletion/writer property above); 229 focused changed benchmark tests passed; 4 new session-cluster cleanup integration tests passed; Ruff formatting passed; all 14 import-linter contracts passed. Ruff check also reports one pre-existing RUF006 in untouched use-cases/openher/integration/evermemos_mixin.py.
Both leave release candidate. everalgo-core 0.7.0 is 0.7.0rc1 unchanged. everalgo-boundary 0.5.0 keeps each boundary reply to one sentence of at most 25 words on both strategies and asks whether a message starts a new episode: the median batch reply on qwen3-4b-instruct-2507 falls from 299 to 38-78 output tokens, and the LoCoMo batch score does not change measurably (-0.15 points re-judged, 95% CI [-0.87, +0.52]). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A run took any answer on its port as its own server's. EverOS binds only after startup, so a run launched in the same seconds as another could pick the same ports, read the other run's servers as ready and send its whole ADD stage into the other run's stores while its own children died at bind. Observed with three LoCoMo runs started together: two shared 9798-9807. GET /health now reports pid, the answering process's id. The fleet's readiness check and its later /health reads accept an answer only when the pid is its child's; otherwise readiness moves to another port block, the existing lost-race path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
configs/locomo-step.toml is locomo.toml with step boundary detection and prompt-only replies on every EverOS call, so the step number is reproduced with one name (DATASET=locomo-step) rather than environment overrides that leave no trace in the run. A unit test pins the difference to those two [retrieval_env] entries. EVEROS_LLM__RESPONSE_FORMAT_MODE joins INGEST_SERVER_SETTINGS: it changes what extraction stores, so a store built under one reply format is not reused by a run under another. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A start that lost a port block cleared the processes, URLs and roots but kept the lost attempt's logs, so the capability check's zip of them failed with "zip() argument 2 is longer than argument 1" once the retry had started. Two of six LoCoMo runs launched together crashed on it, before ADD. Each attempt now builds all four lists from empty. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every config's decider comment had lost its first line and still said a model name without an endpoint 404s and falls back silently; run.py now falls back to the extraction model with a warning, and refuses a decider that does not answer. The comment now says which method uses the decider, where to serve it (OpenRouter for LoCoMo's) and what happens without one. .env.example says the same for LoCoMo. The README adds locomo-step to DATASET, and how to score another retrieval method on stores a run already built: a new run name with --everos-root and STAGES without add. Changing --methods under the original run's name sets that directory's earlier stage files aside, so the guide says not to. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The banner printed the config's pre-filled decider model even with no BENCH_DECIDER_BASE_URL, while the run then fell back to the extraction model, and printed it for agentic runs that never consult a decider. It now shows "(= backbone)" without an endpoint and says the decider is for llm_multiround only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
deepseek-v4-flash, LoCoMo's llm_multiround decider on OpenRouter, thinks before it answers and spent the decider's 512-token output cap doing so: about one question in six fell back to a fixed core, which measures a different method. The startup probe passed, its one short request leaving room to answer. Raising the cap to 16384 still cut some calls short after two minutes each; with thinking off (reasoning.enabled false), conversation 0's 152 questions ran 201 decider rounds without a fallback. Both LoCoMo configs set EVEROS_LLM__DECIDER__EXTRA to turn thinking off. run.py now checks each conversation's trace right after SEARCH and stops it before ANSWER when a decider round fell back, instead of answering and judging a run whose report it then refuses; the message gives the OpenRouter and vLLM spellings of thinking off. The README says LoCoMo's decider is on OpenRouter, why a reasoning decider must not think, and to search again under a new RUN. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LoCoMo's published figures are measured on everalgo-core 0.7.0 and everalgo-boundary 0.5.0 and graded against the gold audit's corrected answers for the 99 disputed questions (marked *), best of three full runs per config: 94.61% with locomo-step (step boundary detection, prompt-only replies) and 94.35% with the default locomo (batch, strict), agentic. The other four retrieval methods are scored on those runs' stores. A "Batch or step" section and its counterpart in docs/configuration.md give the cost of step (about ten times the boundary calls, five times the ingest time, chat messages only) against a score within LoCoMo's run-to-run noise; batch stays the default. The previous 94.42% is retired. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: Preserve persisted profile-job recovery and make the deletion/writer unit property pass.
Both remaining blockers meet the fourth-round bar:
- Persisted-event recovery is introduced by this change deleting
ProfileClusterUpdated; it is reached during an ordinary upgrade with a queued or running profile job; and an owner with no later episode has no recovery path after topic resolution fails. - The deletion/writer failure is introduced on this branch and reached by every standard unit/CI run through Hypothesis’s saved minimized example; it deterministically leaves another owner’s episode missing, and there is no permitted test bypass or working green gate.
No new blocker survived review of the new fleet PID identity, retry-state reset, decider fallback gate, LoCoMo step configuration, dependency releases, health API addition, callers, and history.
Nonblocking follow-up: legacy pre-change smoke stores can still be mistaken for full stores when message_cap was not recorded. The defect remains reproducible, but it is legacy-only and operators can use a fresh RUN/store, so I withdrew and resolved that thread under the round-four convergence bar.
Coverage: the delta from the prior reviewed head, the current complete branch diff, CLAUDE.md (no AGENTS.md or CONTEXT files are present), affected callers and history, backward compatibility, test additions/removals and weakening checks, and all architecture contracts.
Checks: pytest -q tests/unit finished with 3,826 passed, 4 skipped, 1 failed in 11:09 (the deletion/writer property); the 77 focused new benchmark/health tests finished with 76 passed and 1 skipped; Ruff formatting passed; all 14 import-linter contracts passed. Ruff check reports the same pre-existing RUF006 in untouched use-cases/openher/integration/evermemos_mixin.py.
The multi-round decider took max_tokens 512 from its own task defaults, a guard sized for a reply of a few dozen tokens. A decider that thinks before it answers, such as deepseek-v4-flash with its default thinking on, spends that cap thinking and its rounds fall back to a fixed core. The decider now inherits [llm]'s max_tokens like every other task (no cap by default); its timeout and retry defaults stay. The LoCoMo configs no longer turn the decider's thinking off. The probe's hint for a cut-short or empty reply now says to leave the decider's cap unset or raise it, and the per-conversation fallback check points at the server log's reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A review run reported the deletion/writer property failing on one minimized interleaving (u2 clustered, deleted by id and reflected while u1 adds a session and its facts, seed 0). It passes here and in CI; an @example now runs it on every run so any host that can reproduce it fails the same test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The benchmark guide (English and Chinese), docs/configuration.md, .env.example and the CHANGELOG now describe current behaviour and its trade-offs only. Batch or step: the defaults (batch, strict json_schema) are faster and keep every reply to its schema; step with prompt-only replies scores higher on LoCoMo, within its run-to-run spread. Both LoCoMo configs run the llm_multiround decider with thinking off again. With thinking on, deepseek-v4-flash-0731 keeps re-checking long candidate lists until it reaches any output cap (replayed at 16384, 32768 and 65536), so rounds fall back to a fixed core. The published llm_multiround figures are the thinking-off runs at d278a2c. The decider defaults table no longer lists a 512-token cap, and the CHANGELOG gains an Upgrade note: stop the old server normally, since a profile run queued under ProfileClusterUpdated is not resumed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: Make the pinned deletion/writer example pass on Linux/ext4.
The author’s new @example reproduces the open cross-owner loss twice on this head, including in the focused changed-code run. TMPDIR was explicitly placed on the workspace ext4 filesystem with about 91 GiB free, so the earlier full system /tmp does not explain it; full host and assertion details are posted in the thread.
This remains the sole blocker and meets the later-round bar: the branch introduces the failing behavior, an ordinary unit run executes the pinned example and models normal multi-owner background concurrency, and an unrelated episode lost without a matching deletion has no recovery path.
I accepted the author’s documented normal-stop/drain-log procedure as the upgrade-scope decision for old ProfileClusterUpdated jobs and resolved that thread. Named nonblocking constraints remain: a crash/kill -9/drain-timeout during upgrade can drop an old queued profile run, and pre-change smoke stores need a fresh RUN/store to avoid ambiguous reuse.
No new finding survived review of the decider output-cap change, its resolution callers and tests, the benchmark configuration/docs delta, the pinned property change, or relevant history.
Coverage: the delta from the prior reviewed head, the current complete branch diff, CLAUDE.md (no AGENTS.md or CONTEXT files are present), affected callers and history, backward compatibility and upgrade behavior, test changes/weakening, and architecture contracts.
Checks: the focused 92-test changed-code run finished with 90 passed, 1 skipped, 1 failed (the pinned deletion/writer example); Ruff formatting passed; all 14 import-linter contracts passed. Ruff check reports the same pre-existing RUF006 in untouched use-cases/openher/integration/evermemos_mixin.py.
The LoCoMo results open with one number, 94.61%*, then a table of every retrieval method under step and batch boundary detection, with the re-judged footnote and the measurement conditions below it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The deletion/writer property's pinned interleaving fails on a reviewer's Linux host and nowhere else we can run it. When I4 finds an episode gone with no deletion, the failure now carries the owner's markdown files as they are (entry ids, entry_count, deprecated_entries) and every store call in order, start and outcome, with the owner each was scoped to. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gloryfromca
left a comment
There was a problem hiding this comment.
No blockers; suggestions only, and they are marked inline.
This revision clears my remaining block. The new property-test instrumentation preserves both I4 and the pinned example while adding failure evidence; the README edits only reorganize the published LoCoMo result. On this host the property passed its pytest run and 20 additional direct runs of the exact action lists. ruff format --check, ruff check, and git diff --check also pass.
I covered the repository's CLAUDE.md rules, the new delta in the context of the full PR diff, relevant production callers and history, backward-compatibility items already on the record, test weakening, and architecture boundaries. No new defect survived refutation.
Named nonblocking follow-ups remain: the rare deletion/writer race observed on the prior revision but no longer reproducible here; persisted profile jobs after abnormal old-server shutdown, handled by the documented upgrade/drain procedure; and legacy smoke stores, for which operators must use a fresh run/store before a full ingest.
The Upgrade section now covers the whole move from 1.6.0, checked by upgrading a 1.6.0 store: install commands (uv needs --prerelease=allow), no migration or rebuild, a table of the config and Python-API changes that need a step ([llm] unknown keys, [decider] keys, the decider's inherited extra and response format and its removed 512 cap, turning the profile off, Providers/MemoryDeps.llms), queued ProfileClusterUpdated runs, how far the first profile run after the upgrade catches up (max_episodes_per_call), and the output changes that need no action. default_ome.toml no longer says the profile runs after clustering. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gloryfromca
left a comment
There was a problem hiding this comment.
No blockers; suggestions only, and they are marked inline.
The new upgrade notes and default_ome.toml comment agree with the implementation: startup creates the new SQLite table, legacy decider settings remain bridged with a warning, profile catch-up uses the documented cap and ordering, and an unresolved persisted legacy event fails its recovered job without stopping the engine. The delta changes no runtime behavior or test assertions.
I covered CLAUDE.md, this delta in the context of the full change, the relevant configuration/schema/profile/OME callers and history, backward compatibility, test weakening, and architecture boundaries. Targeted CLI-init, profile-strategy, and OME-engine tests pass: 76 passed. git diff --check also passes.
The previously named nonblocking follow-ups remain: the rare deletion/writer race, abnormal-shutdown profile-job recovery handled by the upgrade procedure, and pre-change smoke-store reuse requiring a fresh run/store. All review threads I opened are resolved.
Brings in the online purge (#594). Conflicts kept both sides: the sender_name and purge_job system tables and repos, MemoryService's sender_names and purge_marks arguments, the storage layout table list, and the CHANGELOG (the purge entry leads Added). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gloryfromca
left a comment
There was a problem hiding this comment.
Blocking: Include sender_name in scoped purge.
The merge combines the new persisted sender-name table with main's scoped-purge path, but the purge repository does not count or delete that table. I reviewed the project rules, the merge diff and conflict resolutions, callers and history, backward compatibility, test changes, and the affected persistence architecture. The full unit suite passed (4,033 passed, 4 skipped), and all repository lint/architecture/documentation gates passed; a direct SQLite reproduction nevertheless shows project purge reporting success while the sender name remains.
This meets the post-fourth-round blocker bar: this merge introduces the interaction, it is reached in ordinary use by persisting a named sender and purging its project/app/space, and there is no supported purge path left after the successful job to remove the retained identity. The previously named upgrade recovery, legacy smoke-store, and deletion/writer items remain nonblocking under the earlier conclusions.
| from .memorize_inbox import MemorizeInbox as MemorizeInbox | ||
| from .purge_job import PurgeJob as PurgeJob | ||
| from .reflection_report import ReflectionReport as ReflectionReport | ||
| from .sender_name import SenderName as SenderName |
There was a problem hiding this comment.
Blocking: Include sender_name in scoped purge.
The new table is exported here, but ScopePurgeRepo._SCOPED does not include it. I reproduced this with a temporary SQLite database: after storing a1/p1/u1 -> Alice, a project purge returned zero remaining/deleted rows and reported success, while SqliteSenderNameStore.get_many() still returned {"u1": "Alice"}. A later unnamed message can therefore reuse identity data that the project/app/space purge promised to remove.
This satisfies all three late-round blocker conditions: the merge introduces the combination of this table and scoped purge, named-sender storage followed by a purge is ordinary use, and after the purge job succeeds there is no supported project/app/space cleanup path for the retained row. Register this table in scoped purge counting/deletion and cover it in the purge tests.
Summary
Moves EverOS onto the everalgo 2026-11 contract line and lands four changes built on it.
CHANGELOG.md[Unreleased]has the full list and the upgrade steps; in short:everalgo-core 0.7.0,everalgo-boundary 0.5.0,everalgo-user-memory 0.9.0rc8,everalgo-agent-memory 0.6.0rc4,everalgo-rank 0.5.0rc5. Boundary detection runs on everalgo'sBoundaryDetector([boundary_detection] strategy = batch | step,batchthe default); episode summaries come from a second model call made alongside the episode call (falling back to the first 200 characters);[memory] timezonealso sets the zone the model sees message times in;[tokenizer] name = jieba | nltk; language detection covers Chinese, Japanese and English.[llm.<task>]: twelve tasks (boundary...decider) can override any[llm]field, inherited field by field (extrareplaced whole).[llm]gainstemperature,max_tokensandsdk_max_retries, and rejects unknown keys. The decider's LLM is[llm.decider](the old[decider]LLM keys still work, with a warning); it no longer has its own 512-token output cap.everos config showand the startup log print each task's resolution.ProfileExtractor.aextract_from_episodes): every item quotes the conversation, no newimplicit_traits, anduser.mdkeeps the extractor'sdo_not_record/pendinglists.[profile] max_episodes_per_call(default 10); the profile's LLM is[llm.profile]. A sender keeps the name it was last given (sender_nametable).locomo-step,agentic), with every retrieval method under step and batch boundary detection inbenchmarks/README.md. Newlocomo-stepconfig (step + prompt-only replies). Runs started together no longer share servers (GET /healthreportspid); the decider is resolved and probed exactly as the servers resolve it, and anllm_multiroundconversation stops before ANSWER if any decider round fell back. The guide is rewritten as a step-by-step user guide (English and Chinese).* Re-judged: the 99 questions whose gold answer the LoCoMo audit disputes are graded against its corrected answers.
Area
Verification
On
b4c48220:Not run:
make acceptance(real LLM / embedding).Checklist
main..envfiles, dependency folders, or generated output.Notes for Reviewers
feat!; steps in the CHANGELOG### Upgradetable): unknown keys under[llm]/[llm.<task>](or anEVEROS_LLM__*variable naming none) fail startup;MemoryDeps.llm/Providers.llm/Providers.decider->.llms;resolve_llm_config,resolve_decider_config,DeciderClientConfig,ProfileClusterUpdatedandEpisodeIndex.countremoved. HTTP and CLI are unchanged apart frompidadded to/health.--prerelease=allow(exact rc pins).max_episodes_per_call - 1older episodes; a deletion/writer race seen on one reviewer host, no longer reproducible, with diagnostics kept in the property test.nltktokenizer tests.🤖 Generated with Claude Code