fix(intelligence): label citation gains/regressions with the project's own domain#628
Merged
arberx merged 1 commit intoMay 25, 2026
Conversation
…s own domain A project citation gain/regression is correctly gated on `citationState === 'cited'` (project-owned domain in the sources), but the `citationUrl` carried into the insight was `citedDomains[0]` — the first entry of the FULL co-cited set, in provider order. When a competitor or third-party sorts ahead of the project's own domain, the insight's `recommendation.target` points at the wrong site, e.g. a real regression on the project's page surfaced as "audit winntile.com". Fix: `buildRunData` now resolves `Snapshot.citationUrl` via a new `pickProjectCitedDomain(citedDomains, projectDomains)` helper, which returns the first cited domain that matches the project's canonical or owned domains, or `undefined` when the citation was established via a grounding-source match with no project domain in `citedDomains` (better an empty target than a competitor's). Project domains are loaded once per run in `buildRunData` via `effectiveDomains`. The detection gate is unchanged — this only corrects the labeled URL. Tests: three new intelligence-service cases — regression and gain label the project domain (not a co-cited competitor sorted first), and a grounding-only citation leaves the URL undefined. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
A project citation gain/regression is correctly gated on
citationState === 'cited'(the project's own domain appearing in the sources) — that part is fine. But thecitationUrlcarried into the resulting insight wascitedDomains[0]:citedDomainsis the full co-cited set in provider order — project domains, tracked competitors, and third-party references intermingled. When a competitor or third-party sorts ahead of the project's own domain, the insight'srecommendation.targetpoints at the wrong site: a genuine regression on the project's page surfaces asaudit winntile.com.The detection is right; only the labeled URL is wrong.
Fix
buildRunDatanow resolvesSnapshot.citationUrlthrough a new helper:It returns the first cited domain that matches the project's canonical or owned domains (reusing the existing
domainMatchessemantics), orundefinedwhen the citation was established via a grounding-source match with no project domain incitedDomains— better an empty target than a competitor's. Project domains are loaded once per run inbuildRunDataviaeffectiveDomains.The transition gate (
cited: r.citationState === CitationStates.cited) is untouched.Tests
Three new
intelligence-service.test.tscases:citedDomains: ['winntile.com', 'example.com']→previousCitationUrland the persistedrecommendation.targetareexample.com, not the competitor sorted first.citationUrlisexample.com.citationState: 'cited',citedDomains: ['winntile.com'], no project domain) →previousCitationUrlisundefined.All existing intelligence-service tests use
citedDomains: ['example.com'](project first), so they're unaffected.Test plan
pnpm --filter @ainyc/canonry run typechecknpx vitest run packages/canonry/test/intelligence-service.test.ts— 31 passed (28 existing + 3 new)pnpm run test— only 2 unrelated pre-existing failures remain (packages/db/test/schedules-migration.test.ts, which shells out to asqlite3CLI binary absent from the sandbox; verified identical on cleanmain)eslintclean on both changed source files (0 new warnings)@ainyc/canonry)Context
Found while triaging a real project whose dashboard kept surfacing
audit <competitor>.comrecommendations for its own citation losses. Companion to #399 (the short-displayName matcher fix) — same investigation, different subsystem.🤖 Generated with Claude Code