The choice is unchanged and now better argued: a deployment does not announce which language its notes are in, so any stemmer picked here is the wrong one somewhere — and applying the wrong one does not fail loudly, it quietly stops finding things. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
45 lines
2.2 KiB
SQL
45 lines
2.2 KiB
SQL
-- Ported from the SQLite migration of the same number, and the only one that
|
|
-- is not a mechanical translation.
|
|
--
|
|
-- SQLite gets full-text search from an FTS5 virtual table with an external
|
|
-- content table and three triggers keeping it in step. PostgreSQL derives a
|
|
-- tsvector from the row itself, so there is nothing to keep in step and no
|
|
-- trigger to forget: the column cannot disagree with the row it is computed
|
|
-- from.
|
|
--
|
|
-- The search query differs too, and that difference lives in the Go code
|
|
-- rather than being hidden here — a query that means "match these words" is
|
|
-- spelled MATCH in one and @@ in the other, and pretending otherwise would
|
|
-- cost more than admitting it.
|
|
|
|
ALTER TABLE projects ADD COLUMN memory_retention_hours BIGINT;
|
|
|
|
CREATE TABLE memory_notes (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
-- Scoped to a project and checked in SQL on every read, like threads.
|
|
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
-- A namespace inside the project, so two agents sharing a key do not read
|
|
-- each other's notes.
|
|
agent_id TEXT NOT NULL,
|
|
key TEXT NOT NULL,
|
|
text TEXT NOT NULL,
|
|
-- Normalised to ",a,b," so a tag matches whole, never as part of another.
|
|
tags TEXT NOT NULL DEFAULT '',
|
|
created_at BIGINT NOT NULL,
|
|
-- Touched on every write, so retention measures how long a note has gone
|
|
-- unrefreshed rather than how old it is.
|
|
updated_at BIGINT NOT NULL,
|
|
-- 'simple' rather than a language configuration. These are an agent's own
|
|
-- notes, in whatever language it chose, and a deployment does not announce
|
|
-- which that is — so any stemmer picked here is the wrong one somewhere.
|
|
-- Applying English rules to text that is not English does not fail loudly:
|
|
-- it quietly stops finding things, which is the worst way for a search to
|
|
-- be wrong.
|
|
search tsvector GENERATED ALWAYS AS (
|
|
to_tsvector('simple', coalesce(key, '') || ' ' || coalesce(text, '') || ' ' || coalesce(tags, ''))
|
|
) STORED,
|
|
UNIQUE (project_id, agent_id, key)
|
|
);
|
|
CREATE INDEX memory_notes_by_updated ON memory_notes(updated_at);
|
|
CREATE INDEX memory_notes_search ON memory_notes USING GIN (search);
|