feat(api): link adoption ledger for a deterministic noise guard (#709) - #712
Conversation
Adds a per-target D1 ledger (github_adopted_links, mirroring the ingest ledger pattern) recording which resolved source keys have been adopted into which PR/issue. The noise guard now counts TOTAL currently-adopted files from the ledger rather than the current pass's copy count, so two links pasted in two separate comments deterministically trip the >=2 threshold on the second one regardless of ordering. Idempotent: a rescan of the same source cheaply skips an already-ledgered, non-detached key (no re-copy). Un-adoption parity with ingest's detach: a rescan of one exact source (body or a single comment) that no longer references a previously-adopted key marks it detached and re-syncs the managed comment; the copy itself is never deleted, only hidden from the render via a gh.detached metadata flag (gatherAttachments now filters on it unconditionally). A re-pasted link un-detaches without a re-copy. A pinning test confirms the two-separate-comments scenario from the issue already synced correctly pre-ledger (the pre-adoption copy already counted as a "pre-existing attachment" via the prefix listing) — kept as regression coverage now that the guard reads the ledger instead.
|
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (2)
🚫 Excluded labels (none allowed) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Follow-up to #701/#707. Adds a per-target D1 ledger (
github_adopted_links,mirroring
github-ingest-ledger.ts's pattern) so the link-adoption noiseguard is deterministic across passes and supports un-adoption, closing #709.
What changed
apps/api/src/github-link-adopt-ledger.ts,apps/api/migrations/20260818200000_github_adopted_links.sql): one row per(repo, kind, num, source_key)— the resolved workspace key a pasteduploads.sh link pointed to, scoped to the PR/issue it was adopted into.
detached_atNULL means currently referenced bysource(the body or thespecific comment it was last seen in).
shouldSyncAfterAdoptreads theTOTAL non-detached rows for the target, not the current pass's copy count,
so two links pasted in two separate comments deterministically trip the
≥2 threshold on the second one.
key already ledgered and not detached skips re-attaching entirely — no
re-copy, no metadata rewrite.
adoptLinkedFilesnowreconciles per-source (body or one comment) — a ledgered key no longer
referenced when that exact source is rescanned gets marked detached and
the managed comment resyncs. The copy is never deleted, only hidden from
the render via a
gh.detachedmetadata flag;gatherAttachments(
github-comment.ts) now filters on it unconditionally. A re-pasted linkun-detaches without a re-copy.
Pinning test
Before touching the guard, I wrote a test pinning the issue's own scenario
(two links pasted in two separate comments, one at a time) against the
pre-ledger code. It already synced correctly on the second comment — the
first comment's copy landed in R2 regardless of whether the guard fired,
so
gatherCommentBody's pre-adoption listing saw it as a "pre-existingattachment" and tripped the guard by coincidence. Kept as regression
coverage (
github-link-adopt.test.ts, "PIN (issue #709)") now that theguard reads the ledger directly instead of relying on that side effect.
Tests
apps/api/src/github-link-adopt.test.ts— ledger-backed idempotency, thepinning test, and the detach/re-adopt round-trip.
apps/api/test/github-link-adopt-ledger-sqlite.test.ts— real-SQL-semanticscoverage for the ledger, mirroring
github-ingest-ledger-sqlite.test.ts.apps/api/src/github-comment.test.ts— updated for the unconditionalgh.detachedfilter read.pnpm test(4536 tests) andpnpm -r typecheckboth green.No changeset — this is server-only (
apps/api), no published-package(
@buildinternet/uploads) behavior changed.