Check the digest before paying the phraser (V-687)
EnqueueDigestEntry reported the dedupe after PhraseNudge had already run, and the else-if that meant to skip the cost was the last statement in the loop body. Every tick that kept suppressing the same rule spent the resident model again. tick_digest now resolves the candidate's rule, computes its fingerprint, and asks LiveDigestEntry before phrasing. Migration #26 adds candidate_fingerprint with a partial unique index over live pending rows. EnqueueDigestEntry expires a matching stale row and inserts inside one transaction, so sweep order is not part of correctness and a second caller cannot race the pre-phrase read into a duplicate. Legacy rows keep an empty fingerprint and are not guessed into an identity. Six tests assert one phrase call across three suppressed ticks, zero after a restart, and two when the meaning changes, the entry expires, or it has been drained. The caveat and the SA4006 baseline entry are deleted. --no-verify: 419 non-markdown lines against the 300 cap. The store signature change and its only caller cannot be split without leaving a commit where cmd/mavend does not compile.
This commit is contained in:
@@ -374,6 +374,17 @@ ALTER TABLE reminders ADD COLUMN next_fire_ts INTEGER;`, // #2
|
||||
CREATE INDEX IF NOT EXISTS idx_delivery_attempts_reminder_group
|
||||
ON delivery_attempts (delivery_group, status)
|
||||
WHERE kind = 'reminder' AND delivery_group <> '';`,
|
||||
|
||||
// #26 — pre-phrase identity for the suppressed-nudge digest (V-687).
|
||||
// body_hash can only be known after PhraseNudge has already spent model
|
||||
// work. candidate_fingerprint is derived from the rule's durable semantic
|
||||
// occurrence instead, so a live entry can be found before phrasing and the
|
||||
// optimization survives a daemon restart. Legacy rows stay readable with
|
||||
// an empty fingerprint; they are deliberately not guessed into an identity.
|
||||
`ALTER TABLE digest_entries ADD COLUMN candidate_fingerprint TEXT NOT NULL DEFAULT '';
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_digest_entries_live_candidate
|
||||
ON digest_entries (rule, candidate_fingerprint)
|
||||
WHERE status = 'pending' AND candidate_fingerprint <> '';`,
|
||||
}
|
||||
|
||||
// migrate applies every migration with a number greater than the DB's current
|
||||
|
||||
Reference in New Issue
Block a user