v1.27.18
[1.27.18] — 2026-08-16
Release notes
Improvements
- PRF corpus weighting now really runs. The recall query-expansion path
extracts terms via the FTS5 vocabulary — corpus document-frequency weighting
was the design since v0.9.1, but the vocab query never executed against the
bundled SQLite (wrong column names), degrading every expansion to the
unweighted fallback. The queries now target the real schema, the df
round-trip is capped (MAX_DF_TERMS, adversarial-vocab bound), and the
expanded term lists are pinned by tests. Because the weighting now applies,
expansion output CHANGES versus 1.27.17 (corpus-idf re-ranking) — recall
eval rows will shift. - Release binary tuned for speed (
opt-level"z" → 2; LTO/strip/
codegen-units unchanged). The server is an in-process vector store, not a
download; "z" traded measurable recall-latency headroom for binary size. - Evidence enrichment batched (one links lookup per result set, was one
probe + one query per hit) — and the batched query's placeholder-pair bug
(one of twoINgroups never bound → silent empty links) is fixed and
regression-pinned. - Read-seam fast path:
sanitize_read_cowreturns the input borrowed —
zero copies — when every transform is provably a no-op (clean rows dominate). - Search filters become
Arc(cheap clones across per-domain recall
loops), and a process-localVEC0_READYflag replaces the per-query
"does vec0 exist" probe. /domains/{name}/importdial 1 GiB (was capped by the global 1 MiB
limit — the route's dedicated layer now sits before the global one; every
other route keeps the 1 MiB cap).
Bug fixes
/ingest/memorycould store an oversized entry or silently report
"Empty content" for invalid UTF-8. Both now hard-reject: per-entry content
overMAX_CONTENT→400 entry_too_large(all-or-nothing, before any
write), non-UTF-8 body →400 invalid_utf8. Every legacy wire shape is
unchanged.- Entity-mention dedup was quadratic (O(m²) containment scan per
sentence); now a linear running-scan with the old result pinned as a test
oracle on randomized fixtures. - The retention read-gate used
strftime('%s', …)TEXT math; the exact
same predicate now usesunixepoch(COALESCE(…))— value-identical (pinned
SQL-side) and index-friendly.
Security fixes
- Connection-tracker slot leak on ingest timeout. An
/ingest/memory
that exceeded the 60 s bound (and panics) kept its single-connection slot
until the next sweep; the slot is now an RAII guard released on every exit. - Reserved index slots vacuumed:
idx_knowledge_domain,
idx_knowledge_owner,idx_knowledge_title_headingadded (domain delete,
DSAR subject resolution, proposal write-gate dedup);idx_tombstones_kid,
idx_entities_name,idx_evidence_links_fromdropped (each a strict
duplicate of a UNIQUE autoindex or newer sibling). Schema → 1.27.18.
Full Changelog: v1.27.17...v1.27.18