Repository navigation
A server that stays healthy for days, not hours. Three faults in this
release compounded on exactly the deployments that ran longest: a long-lived
index leaked file descriptors until searches took seconds, interactive searches
queued behind the cascade's background embedding, and a memory root holding more
than one project had each project's index rows overwrite the other's. All three
are fixed, and a LanceDB root that the last fault already damaged repairs itself
on the first start after upgrading.
Changed
-
[embedding].max_concurrentdefaults to 10 instead of 5. The
EmbeddingSettingsclass default (50) is aligned to the same value; the
shippeddefault.tomlalways overrode it, so the effective default moves
from 5 to 10. (#486) -
Milvus collections must be rebuilt once after upgrading. They gain the
__pkprimary-key column; the server refuses to start on an old
collection and nameseveros cascade rebuild, which recreates them from
markdown. -
Response
ids are unique within(app_id, project_id), not globally; the
shape ofidis unchanged. -
The cascade optimizes a LanceDB table at most once a minute, not once
every ten seconds. Each optimize pass leaves an_indices/<uuid>/
directory behind until cleanup reclaims it, so the old 10 s floor set the
ceiling on how many could pile up: about 126k directories a day and ~1.8M
at the retention horizon. The 60 s default costs a sixth of that (~21k a
day, ~300k at the horizon, roughly 1.2 GB) and keeps a full index sweep
inside its 60 s deadline. The interval is a built-in floor on how often a
table may be optimized, not a setting; a write-heavy deployment sees an
index that trails its markdown by up to a minute longer than before.
Fixed
-
A long-running server no longer leaks file descriptors on LanceDB index
readers. Everyoptimize()mints a new index version whose reader is
kept in a session cache, and that reader holds the descriptors of its
_indices/<uuid>/files. Lance keys those cache entries by dataset
version and never evicts them when cleanup deletes the files underneath
(lance-format/lance#7718), so the count grew for the life of the
process: a 65-minute soak went from 74 to 558 index descriptors with no
plateau, and a deployment on a 1024-descriptor limit exhausts it in
hours. EverOS capped only one of the session's two caches and left the
metadata cache unbounded, which is the one that decides whether the count
converges. Both are now capped ([lancedb].metadata_cache_size_bytes,
default 1 MB): the same soak holds between 6 and 82 descriptors, falling
as often as it rises. Reported upstream aslance-format/lance#9934. -
An interactive search no longer queues behind the cascade's embedding
work. Query embeddings and background write embeddings shared one
process-wide semaphore, so a burst of writes put the query a user was
waiting on at the back of the queue. Under three concurrent writers,
vector search p50 measured 46 s and p95 112 s, while the keyword leg —
which needs no embedding — answered in 0.35 s. Queries now draw on their
own budget ([embedding].query_max_concurrent, default 4): vector p50
drops to 0.60 s and p95 to 3.70 s under the identical load. Total
in-flight requests to the endpoint becomemax_concurrent + query_max_concurrentrather than a silently shared bound. (#473) -
The same owner's memories in two projects no longer overwrite each other
in the derived index. Index rows were merged onidalone, andidis
unique only within one(app_id, project_id): a user's episodes, atomic
facts, agent cases, foresights, skills and profile written under a second
project replaced the first project's rows (markdown was never affected).
Every table now declaresPRIMARY_KEY = ("app_id", "project_id", "id");
LanceDB merges on it and Milvus keys its collections on the composed
__pkcolumn. Profile search and get, the handlers' change detection and
the vector backfill address rows by the full key; the backfill also keeps
each row's own vector within a batch, and reflection deprecates atomic
facts only inside the project it merged. -
A multi-project LanceDB root indexed before this release gets its
overwritten rows back by itself. The first full pass over the root
after upgrading (server start, oreveros cascade sync) re-reconciles
every indexed markdown file against the index once and records that in
.index/.index_reconcile_version. Entries whose rows are present and
unchanged are skipped by digest, so a healthy root pays one read pass
and no embedding; only the rows that were lost are re-embedded.
everos cascade sync --force-allruns the same pass on demand. Two
roots need that command instead: a server started with
EVEROS_DISABLE_CASCADE=1never runs the pass (stop it and run
everos cascade sync --force-allonce), and a multi-project root where
reflection ran before this release needseveros cascade rebuildonce,
because the pass does not clear thedeprecated_bystamps one project's
reflection left on another project's rows. -
POST /cascade/quiescefreezes a complete index. Its drain stopped
at the worker's per-drain bound, and inside a server it could also stop
while the background worker still held the last batch, which the stop
that follows then orphaned inprocessing; the ledger an upgrade
re-queues made both routine. The drain now runs until the ledger holds
nothing pending, waiting for the worker's in-flight batch, and
everos cascade sync/rebuilduse the same loop. -
A cascade pass embeds a file's changed entries in one batched request,
not one request per entry. The four daily-log handlers (episode, atomic
fact, foresight, agent case) each called the embedding endpoint once per
entry, so a turn that wrote ~20 atomic facts queued ~20 single-input
requests on the process-wide embedding semaphore, and the next search's
query embedding waited behind all of them: about five times the
endpoint's latency at the previous defaultmax_concurrent = 5. The
handlers now
send every text of a file throughembed_batch, which
[embedding].batch_sizesplits into requests (23 entries become 3
requests at the default 10), so after a single turn's writes the query
embedding waits for one request; a large backlog still queues ahead of
it (#473). (#486) -
Changing a knowledge document's category keeps it inside
knowledge/.
PATCH /knowledge/documents/{doc_id}withcategory_idset to..moved
the document's directory up into the project directory, where the markdown
scan no longer finds it. The category now goes through the same rule as
document creation, so.and..fall back toOthers, and the move is
refused if its target would leaveknowledge/. A document an earlier move
left outside is moved back on its next category change. Reported by
White0xdi3.
Upgrade
pip install --upgrade everos # or: uv syncpip install --upgrade everos is enough for most roots: the first full pass
after the upgrade (server start, or everos cascade sync) re-reconciles every
indexed markdown file against the index once, re-embeds only the rows that were
lost, and records that it ran in .index/.index_reconcile_version. A healthy
root pays one read pass and no embedding.
Three roots need a command instead:
- A root where reflection already ran across projects —
everos cascade rebuildonce. The automatic pass does not clear thedeprecated_bystamps
one project's reflection left on another project's rows. - A server started with
EVEROS_DISABLE_CASCADE=1— it never runs the
pass. Stop it and runeveros cascade sync --force-allonce. - A Milvus derived index —
everos cascade rebuildonce. Collections gain
the__pkprimary-key column and the server refuses to start on an old
collection.
Full changelog: v1.4.1...v1.4.2