Feat: flag divergent user-facing copy for the same data across surfaces - #215
Merged
Conversation
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
The same data or policy rendered with different labels on different surfaces — "Ships after payment clears" on a summary card, "Ships when the order completes" on the confirmation screen — reads to users as contradictory policy. Each string looks fine in isolation, so per-file review misses the divergence. QAMap now compares label-like copy a diff adds or edits against the existing copy elsewhere in the project, reports the pair with both locations, and plans a side-by-side comparison.
Behavioral Contract
When a diff adds a user-facing string inside a label-like component (
Badge,Tag,Chip,Pill,Label,Status,Caption,Hint,Tooltip,Toast,Button,Cta,Banner,Notice,Alert,Callout, with or without a namespace prefix) or in a user-facing prop (label,title,placeholder,aria-label,alt) of a product UI file, QAMap reads the project's existing copy of the same component family from other product UI files at the head revision. If an existing string is not identical but starts with the same token or shares at least 60% of its tokens, QAMap emits diff risk evidence (divergent-copy:<Component>) anchored to the added line, naming both strings and the existing file and line, and adds the QA scenario "Divergent copy for the same data across surfaces".Identical strings, strings in the same file, strings from different component families, prose outside label-like components, single-word labels, and paragraphs over eight tokens are not flagged. The corpus is only read when the diff actually adds label-like copy, is capped at 400 files and 200 KB per file, and excludes test, story, fixture, and build paths. Findings are capped at five per changed file and only the best-matching existing string is reported per added string.
Evidence
Closes #213.
test/benchmarks/web-divergent-surface-copy— an order confirmation page adds<Badge>Ships when the order completes</Badge>while the summary page already renders<Badge>Ships after payment clears</Badge>; contract pins the intent, reached file, and the new scenario title.file:linein the evidence, anchored to the added line.<Button>Search purchases</Button>beside an existing<Button>Search orders</Button>in another feature.<p>, and two similar badges inside one file — none flagged, scenario absent.Checks
pnpm testpnpm bench:cifor inference, routing, trace, or outputpnpm bench:executionfor E2E compiler or execution fixturespnpm scanfor scanner, security, or repository policypnpm plugin:checkandpnpm plugin:smokefor plugin changesPublic OSS Check
Review Notes
pnpm scan(0 findings),pnpm bench:context(10/10),pnpm plugin:check, andpnpm plugin:smokealso pass locally; marked N/A above because this change touches none of those surfaces. The detector is deliberately narrow: single-line JSX only, same component family only, other files only. Multi-line JSX children, copy assembled from template literals or i18n keys, and strings that share meaning without sharing a leading token remain review work. The existing surface is read from the head revision, so a surface that the same diff rewrote is excluded from the corpus to avoid matching stale text.