Repository navigation
v2.0.0 — architecture review remediation
An architecture review of the storage and memory layers found defects reproducible on the default configuration. This release fixes them, adds regression coverage that fails against the previous code, and withdraws or restates published claims that were measured on an instrument that could not fail.
Verification is A/B — the same behaviour probe against the previous release and against this one:
v1.5.0: 14 defects present in this tree
v2.0.0: 0 defects present in this tree
Tests 282 → 417. With PostgreSQL available: 417 passed. Without: 403 passed, 14 skipped.
⚠️ Breaking: defaults changed
| setting | was | now |
|---|---|---|
backend |
postgres |
sqlite |
host |
0.0.0.0 |
127.0.0.1 |
cors_origins |
["*"] |
[] |
vision_enabled |
true |
false |
With auth unenforced, the old combination made the workspace reachable from the local network, scriptable by any web page the developer visited, and uploaded indexed images to a third-party API off an ambient env var. An upgrade that does not set these explicitly will find a Postgres-backed server running on SQLite and no longer reachable off localhost.
Data loss and correctness
- Supersede destroyed data on the default memory type. Three dated bug-fix records about one component collapsed into one, and
superseded_idpointed at a row that no longer existed. Prior versions now go tomemory_revisions, readable viamemory_history(). - Reading a memory reset its time-decay clock. A 400-day-old fact that had been read once outranked the fresh fact that replaced it.
- Recall set
confidence = 1.0on every hit, so the FSRS curve could only demote memories nobody read. Recall is read-only now. totalwas the candidate-window size, not the match count. Anyoffset >= 60returned nothing however many memories matched.
Transactions, retrieval, PostgreSQL parity
- All writes go through one
write_txn():BEGIN IMMEDIATE, rollback on anyBaseException, bounded retry with jitter onSQLITE_BUSY. CreateInvoicewas a single unicode61 token, soinvoice,create invoiceand "where do we create invoices" all returned zero results — on the project's own flagship example.- Japanese and Korean were routed to jieba, a Chinese segmenter. Tokenization is now fingerprinted and skew is reported by
opendb doctor. - PostgreSQL had carried none of the SQLite fixes, plus an unconditional
BEFORE UPDATEtrigger. It now passes the same conformance suite, every assertion parametrised over both backends.
Security
ApiKeyMiddleware was implemented, documented, unit-tested — and never mounted, so FILEDB_AUTH_API_KEY did nothing. _resolve_workspace swallowed the ValueError from relative_to() and returned the path anyway, making the only containment check a no-op. A crafted grep pattern hung over 20 seconds on a two-line file. sort_field/sort_dir were interpolated into ORDER BY unvalidated on PostgreSQL. Uploads read the whole body then checked the size.
⚠️ Benchmark claims withdrawn and restated
"100% R@5" is withdrawn. It was measured on longmemeval_oracle.json, where all 500 questions satisfy set(haystack_session_ids) == set(answer_session_ids) with zero distractors — R@5 is arithmetically guaranteed for 497/500. Pooled mode indexes every question's sessions into one 882-session corpus: R@5 = 79.1%, median recall 7.5 ms.
CodeMemEval is restated with its error bars. 96.3% is 26/27, whose 95% interval is [81.7%, 99.3%] — 17.6 points wide, overlapping the cheap reader's 92.6% across nearly its whole width. This benchmark cannot tell those two readers apart, and per-category results (n = 3–6) are now reported as counts.
The paraphrase split is now measured rather than asserted. Same corpus, same gold sessions, only the question wording differs:
| Questions | R@1 | R@5 |
|---|---|---|
| as written | 100% (24/24) | 100% (24/24) |
| restated, 0% lexical overlap | 45.8% (11/24) | 75.0% (18/24) |
That gap is the honest boundary of a pure-lexical retriever, and it was previously averaged away.
The LLM judge is unvalidated. Both accuracy figures come from a judge sharing a model family with the reader it grades, and nothing has yet measured how often it accepts a wrong answer — treat them as upper bounds. codemem_hard.py --run-judge now measures it, scoring 10 plausible-but-false answers against correct-answer controls (a judge that rejects everything otherwise scores a flawless 0% false-accept rate).
Notes
- Eight existing tests asserted the defective behaviour (e.g.
test_recall_resets_confidence_to_oneliterally tested the bug). They are rewritten to assert corrected semantics, not deleted. - PostgreSQL tests skip unless
OPENDB_TEST_PG_DSNis set, so CI stays green without a server.
Full changelog: https://github.com/opendb-ai/openDB/blob/main/CHANGELOG.md