v3.3.0
Added
- A CI job now runs the full test suite against a live SurrealDB. Every prior job
either mocked the database or skipped wheneverSURREALDB_URLwas unset, so the only
production backend went untested in the pipeline — the exact gap#143's bug walked
through (a query that returns plausible garbage instead of failing loudly). The job
starts the official image via adocker runstep (GitHub Actions'services:cannot
pass the datastore/flags SurrealDB's entrypoint requires), waits for/surreal isready,
then runs the whole suite sequentially — no-n auto, since parallel workers sharing one
connection produce transaction-conflict errors unrelated to any real regression.
Fixed
- Polish stop words
ma/na/co/saswallowed the acronymsMA/NA/CO/SA.
A contributor's audit (#64) showed the fix everyone assumed — removing the words from
the stop list — was wrong:N/AandS.A.never actually collide (punctuation
fragments them below the minimum word length before the stop-word check ever runs), so
removing the words would only trade real function-word noise for a niche acronym gain.
A token that is ALL-CAPS in the source now survives even when its lowercased form is a
stop word, gated by how much of the text is uppercase — a shouted note or an all-caps
heading has no acronym to rescue, only every word incidentally capitalized, and must not
have its stop-word filtering disabled wholesale. check_dead_modulespassed silently while five files imported a module that no
longer exists. Reachability is computed from each file's imports, so one naming a
module the tree no longer has (the SQLite backend, removed in3.0.0) contributed
nothing to the graph and produced no diagnostic — the guard reportedNo unreachable modules.while five benchmark/script files could not run. It now resolves every import
against the tree and reports the ones that don't. The five files were fixed: one
(stress_at_scale.py) measured only the removed backend and is deleted; the other four
now require a liveSURREALDB_URLinstead of silently falling back to it.- Two read-only endpoints in the sync hub could redirect scheduled maintenance onto
the wrong brain.GET /hub/status/{id}andGET /hub/devices/{id}switched the
process-wide shared storage's active brain to answer a lookup, and the background
consolidation/decay loops read that same mutable state on their next tick — so a
read-only request for brain B could cause the next scheduled pass to run against B
instead of the brain the operator actually left active. Both endpoints now read through
an isolated, brain-scoped connection instead of mutating the shared one — the same
pattern already used for reasoning-training's read endpoints. - The tool-stats
daysfilter changed the daily chart but not the summary above it.
get_tool_statstook nodaysargument, so its summary was always computed over all
time; switching the dashboard's range selector between 7/30/90 days produced a
byte-identical summary while the chart below it changed correctly. The summary now
respects the same window as the daily series, and the two storage methods behind it are
declared on the storage interface (with an in-memory implementation) instead of being
reachable only on the SurrealDB backend behind an unchecked attribute access. - A
SELECT VALUEquery on an array-typed field could be read as if it were rows.
The shared query helper's return type says it hands back row dictionaries, which is not
what aSELECT VALUEquery returns — the field it selects for one matching row can
itself be an array, indistinguishable by shape alone from several separate scalar rows.
That mismatch is the mechanism behind a prior release's fixed bug (a result iterated
character by character). The one live call site reachable this way now goes through a
separate, honestly-typed helper instead of the row-shaped one. - The Settings brain-files panel showed a plausible path to a file that was never
written. A brain that exists only in SurrealDB has no on-disk database file, but the
panel built and returned a path for it regardless — worse when a stale file from an
older install happened to sit at that exact path for one brain while its neighbours
showed nothing. The path is now omitted rather than fabricated when the file does not
exist.
Removed
- The
smem_drifttool and its underlying tag-drift detector. Every call path into it
swallowed its own failures, so on the only shipped backend it always reported "clean" —
indistinguishable from a real analysis that found nothing, because the two things it
measures (tag co-occurrence, session summaries) were never implemented on that backend
and never had been, even before the SQLite backend's removal. Itsmergeaction never
actually merged tags either.TagNormalizer's own drift detection, which needs no
storage and already backssmem doctor's tag-drift warnings, remains and covers the
same practical need. A small unrelated write path — recording tag co-occurrence for the
now-removed detector, and a periodic session-summary persist with the same swallowed
failure — is removed alongside it. - A CLI sandbox-guard helper was renamed from
ensure_aiosqlite_or_exit_clito
ensure_sqlite_or_exit_cli: it has only ever checked the stdlibsqlite3module, never
the optionalaiosqlitepackage, and the name was misleading anyone reading the CLI
startup path. Internal-only; no public interface changed.
Changed
- BREAKING: the
smem_driftMCP tool is gone. If anything called it expecting a real
answer, that answer was never trustworthy on the SurrealDB backend to begin with — see
Removed, above.
Full diff: v3.2.0...v3.3.0