Files
Ilker ManapandClaude Opus 5 f2f375d824
CI / test (push) Successful in 1m41s
Stop the text-search comment naming one language
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>
2026-09-27 08:09:49 +02:00

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);