cairn remember: capture-time recurrence detection#47
Merged
Conversation
Covers cmd/remember.go's pre-check for an existing VISIBLE entry with an exact topic_key match (via crn-28ge.1.3's Conflicts primitive, not a new equality check): on a match, increments RecurrenceCount via the entry's own tier-appropriate commit path instead of writing a duplicate. internal/cairn: WriteBackRecurrenceCount patches recurrence_count into on-disk frontmatter; CommitRecurrenceToReviewBranch appends a second commit to an entry's existing remember/<id> branch, or falls back to CommitToReviewBranch's create path when absent. cmd: cross-call CLI tests for both tiers (shared reuses the review branch, private commits directly), plus the near-miss/no-topic/ not-visible cases that must NOT increment. TestRememberSameScopeTopicKeyRepeatDoesNotIncrementRecurrence documents a known gap: Conflicts' shadowExempt suppresses even the topic_key signal for equal/superset/subset-scope pairs, so the most intuitive recurrence (same agent, same private scope, same topic) isn't caught by this pre-check.
….1.4) cmd/remember.go's create flow now pre-checks for an existing VISIBLE entry with an exact topic_key match before writing a new one: - recurrenceMatch resolves identity, force-reindexes, then filters IterEntries down to Visible's ID set and runs the candidate through Conflicts (crn-28ge.1.3's single-candidate primitive) -- reused as mandated (NFR-05), not reimplemented as a second equality check. Only a "topic_key" finding counts; "content" (Jaccard) is a near-miss signal, not a repeat. - The forced Reindex is required, not cosmetic: ensureFresh's git-HEAD watermark can never observe a shared-tier entry on its own, because CommitToReviewBranch deliberately never advances the store's own HEAD (the entry sits on its own remember/<id> branch pending review). Without it, a same-session recurrence while the first report is still unmerged -- the common case, not an edge case -- would be silently missed. Find hits the identical gap for the identical reason and is fixed the same way (internal/cairn/entry.go). - On a match, recordRecurrence increments RecurrenceCount, persists it via the new WriteBackRecurrenceCount (patches recurrence_count into on-disk frontmatter, mirroring verified_at's insertion point), and commits through the entry's own tier-appropriate path: CommitDirect for private, or the new CommitRecurrenceToReviewBranch for shared (appends a second commit to the entry's existing review branch, or falls back to CommitToReviewBranch's create path when absent). No duplicate entry is ever written -- the candidate is discarded. - On no match, today's create-new-entry behavior is unchanged. Known limitation (documented via TestRememberSameScopeTopicKeyRepeatDoesNotIncrementRecurrence): Conflicts' shadowExempt suppresses even the topic_key signal for pairs whose scopes are equal or in a superset/subset relationship, so the single most intuitive recurrence -- same agent, same private scope, same topic -- is not caught by this pre-check. Flagged for reviewer follow-up.
… (refs crn-28ge.1.4) Reviewer-requested fix: golangci-lint's nilnil check flagged the (nil, nil) "no recurrence match" return. The sole caller already gates on `matched != nil` before use, so document the contract with a nolint rather than restructure the signature.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cairn remember's create flow now pre-checks for an existing visible entry with an exacttopic_keymatch (via the sharedConflicts()primitive, filtered to thetopic_keysignal — not the fuzzy content/Jaccard signal) before writing a new entry.RecurrenceCountinstead of creating a duplicate, committed through the same tier-appropriate path the entry already uses (CommitDirectfor private scope, a newCommitRecurrenceToReviewBranchfor shared scope re-entering an in-flight review branch).topic_key) does not trigger a false-positive increment.Known, intentionally out-of-scope limitation
Same-scope (or scope-superset) repeat captures of the same topic are not currently detected as recurrences — only topic_key collisions between entries with incomparable scopes are caught. This is pre-existing behavior of the shared conflict-detection primitive (shadow-exemption logic), not a regression introduced by this change. Tracked separately for a possible follow-up.
Test plan
go build ./...go vet ./...gofmt -l .(0 files)golangci-lint run ./...(0 issues)go test ./... -race -count=1(all packages green)