Skip to content

feat(sqlite): a package of SQLite builds, built and checked in CI - #278

Merged
leemour merged 1 commit into
mainfrom
feat/sqlite-package
Oct 1, 2026
Merged

leemour merged 1 commit into
mainfrom
feat/sqlite-package

Conversation

@leemour

@leemour leemour commented Oct 1, 2026

Copy link
Copy Markdown
Member

Task

SQLite plan, item 2: the libraries.

Why

Bun on macOS uses the system SQLite. A Linux distribution's Node uses the system libsqlite3. Both can fall short of what the store needs.

What

  • packages/sqlite: @leemour/cli-messaging-sqlite, with build.sh, check.sh and probe.mjs. Not part of the pnpm workspace.
  • .github/workflows/sqlite.yml: builds five libraries, checks them, packs, loads them on real systems, and publishes on manual dispatch.
  • bin/publish-sqlite: the owner's one-time empty 0.0.0, so a trusted publisher can be set.

Testing

The workflow on this PR. Locally: our build loads into Ubuntu 26.04's Node (3.53.4, full-text search), and check.sh catches a missing symbol and a glibc above the floor.


Reviewed against the review checklist — §B for code.

🤖 Generated with Claude Code

@leemour/cli-messaging-sqlite holds SQLite 3.53.4 for Bun on macOS (one
universal dylib, minimum macOS 13.0, ad-hoc signed) and for a Linux
distribution's Node (x64/arm64, glibc 2.28+ or musl). Each library is
built from the official amalgamation with Homebrew's flags plus what
Node's own build enables, and checked to export every sqlite3_* symbol
Node 22 and 24 import.

The workflow loads the packed libraries under Bun on macOS 14, 15, 26 and
Intel, and under the distribution Node of Ubuntu 26.04, Fedora 43 and
Alpine 3.22. It publishes from CI only; bin/publish-sqlite publishes the
empty 0.0.0 the trusted publisher needs first.

Plan: docs/storage/plans/sqlite-runtime.md, item 2.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@leemour
leemour marked this pull request as ready for review October 1, 2026 16:12
@leemour
leemour merged commit 87f57ec into main Oct 1, 2026
21 checks passed
@leemour
leemour deleted the feat/sqlite-package branch October 1, 2026 17:12
leemour added a commit that referenced this pull request Oct 31, 2026
…lter in --discover (#2254)

## Task
Owner decision NEED-173 = B, plus RISK-61 and FIND-112 (wirecat-desktop
journal).

## Why
- `search messages --discover` with `-`, `NOT`, `OR`, groups, phrases or
`exact:` ran strict search alone: no meaning hits. Notes have given such
queries meaning hits that obey the whole query since 0.496.0 (#2223).
- Meaning took the 100 nearest messages overall, then dropped those
outside the filter, so a narrow filter lost hits. #2236 fixed the same
for notes.
- The follow-up step created a temporary `fts5vocab` table, which a
read-only connection refuses.

## What
- **Explicit syntax:** the words keep the whole query
(`discovery.method: "lexical-strict"`). Meaning embeds only the wanted
words. Its hits, and the replies and follow-ups that discovery adds,
must match every field and every excluded word. This uses the same
`fieldsOfQuery` / `meaningWords` as notes, moved to
`src/search/lucene/meaning-parts.ts`. Only the "match everything"
stand-in differs: `in:notes` for notes, `date:[* TO *]` for messages. A
query with no word to embed (`date:today`, `Helix*`) stays strict.
- **Inside a filter:** when the query's fields hold at most
`RANK_WITHIN_MESSAGES` = 100,000 messages, every one of them that has a
vector is scored (`QueriesStore.matchingPks`,
`AccountVectors.scoreMessages`, `MeaningLane`'s new `within` argument).
A larger filter, or one with row-by-row leaves, keeps the old way.
- **Read-only:** rare stems are now counted with a bounded `MATCH …
LIMIT rareAt + 1` query, not a temp vocab table.
- The tests that pinned "explicit syntax means strict search" are
replaced by tests showing that meaning hits obey negation, `NOT`, `OR`
and groups. New tests: ranking inside a narrow filter (it fails with the
threshold off), and follow-ups on a read-only connection (it fails on
main with "attempt to write a readonly database").

## Testing
- Full Vitest suite: 8,492 passed. `pnpm lint`, `tsc` and `pnpm
docs:check` are clean.
- Owner's real store, read-only, through cli-core's services, without
the reranker. Before = main plus the read-only fix only.
- 6 explicit-syntax queries (`-date`, `NOT`, `OR`, a group of dates,
`-chat`, `-(chat OR chat)`): 0 meaning hits before, 10–17 of 20 after.
**0 hits break the query.**
- `word chat:<1k-message chat>`: 9 hits / 3 meaning candidates before,
20 / 100 after. Another chat: 0 meaning hits before, 20 hits found by
both words and meaning after. `word date>=30d` (91k messages, 957 with
vectors): 10 candidates before, 100 after. `оплата date>=14d`: 5 meaning
hits before, 10 after.
- Cost: listing a filter takes ~2 µs a message (161 ms for 91k), and
scoring ~22 µs a vector (174 ms for 7.7k).
- Totals and method: [cli-testing
#278](WireCatLabs/cli-testing#278)
(`performance/search/messages-meaning-filters`).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant