pub const NOTE_UPSERT_SQL: &str = "INSERT INTO notes \
(id, namespace, kind, status, name, content, salience, decay_factor, expires_at, \
properties, created_at, updated_at, deleted_at) \
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13) \
ON CONFLICT(id) DO UPDATE SET \
namespace = excluded.namespace, \
kind = excluded.kind, \
status = excluded.status, \
name = excluded.name, \
content = excluded.content, \
salience = excluded.salience, \
decay_factor = excluded.decay_factor, \
expires_at = excluded.expires_at, \
properties = excluded.properties, \
updated_at = excluded.updated_at, \
deleted_at = excluded.deleted_at";Expand description
The single true UPSERT every note writer (single, batch, and note-merge)
issues against notes (ADR-116 memory-ANN-generation-coherence prereq).
INSERT OR REPLACE is a SQLite DELETE-then-INSERT on a conflicting id:
it fires DELETE-path triggers (spuriously invalidating ANN generation
state once ADR-116’s liveness triggers land) and discards the row’s
original created_at/rowid identity. This form updates in place on a
primary-key conflict instead. created_at is deliberately absent from
the DO UPDATE SET list — it is bound for the INSERT branch only and
left untouched by the UPDATE branch, so an existing row keeps its
original created_at across any number of upserts.