Repository navigation
[AAASM-6206] 🔧 (ci): Derive the Sonar copy-paste exclusion list from the snippet manifest - #632
Merged
Chisanan232 merged 2 commits intoSep 28, 2026
Conversation
…n list `.sonarcloud.properties` is the only config SonarCloud's Automatic Analysis honours here, and it forbids wildcards, so `snippets/**` cannot be expressed and each generated snippet has to be named. The list was seeded from the duplication report of 2026-07-23 — the pairs that exceeded the detector's minimum block size on that one day, not the pairs that are duplicated by construction. Only 6 of the 26 snippets were listed. Every `snippets/<sdk>/<framework>.<ext>` is a verbatim extraction of the `region: quickstart` slice of its example entrypoint, so all 26 duplicate their source by design and merely become visible to the detector once the region grows. AAASM-6204 grew all 16 Python regions by one argument plus a comment, which pushed llamaindex-tool-policy across that boundary and failed the new-code duplication gate on a pair already byte-identical on main. The remaining 20 were each one region-growth from the same failure. Adds those 20, keeping the list sorted: 32 -> 52 entries. Nothing is removed, and only the generated side is excluded — every hand-written source stays under full duplication analysis, matching the AAASM-5095 precedent in agent-assembly of excluding machine-generated artefacts so the metric reflects hand-written code. Also corrects the snippet count in the comment introduced by 8af190f: there are 26 snippets (16 python, 6 node, 4 go), not 28. Refs AAASM-6206 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The list above is only correct as of the day it was written unless something keeps it correct. This derives the required set from `snippets/manifest.json` rather than from a duplication report, so a new example cannot reach main with its snippet unprotected. `scripts/check_cpd_exclusions.py` asserts five things: every manifest `snippet_path` is excluded (A1); the list is sorted and duplicate-free so adding one path stays a one-entry diff (A2); no entry names a path that no longer exists, since a stale entry survives a rename while protecting nothing (A3); the scan is non-vacuous — the manifest yielded snippets and the property was found (A4); and no entry contains a wildcard, because one would silently match no file here and look like a fix while protecting nothing (A5). It does not require `source_example` to be excluded. Retiring the generated side is enough to retire a pair, and leaving the hand-written side analysed is the stronger posture. The non-snippet entries stay untouched: those are the per-framework templates that duplicate each other, independently of any snippet. `--selftest` mutates an in-memory copy of the real files once per assertion — dropping a snippet, unsorting, duplicating, adding a wildcard, naming a deleted path, emptying the manifest, removing the property — and requires each to be caught. It runs before the real check, because a gate that has stopped detecting anything passes everything. All 7 mutations are detected. Wired into Example Metadata Drift Check, which already regenerates these snippets and so already owns their contract, rather than a new workflow. `.sonarcloud.properties` and the script join its `paths:` filter. Refs AAASM-6206 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Chisanan232
deleted the
v0.0.1/AAASM-6206/fix/cpd_exclusion_completeness_gate
branch
September 28, 2026 08:12
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.



What changed
Two commits.
acbae7dadds the 20 generated snippets that were missing fromsonar.cpd.exclusionsin.sonarcloud.properties, taking the list from 32 to 52 entries and keeping it sorted. Nothing is removed.9b86b05addsscripts/check_cpd_exclusions.pyand runs it from Example Metadata Drift Check, so the list is derived fromsnippets/manifest.jsoninstead of hand-maintained against a duplication report.Why
examplesuses SonarCloud Automatic Analysis (sonar.autoscan.enabled = true), which ignoressonar-project.properties; the only honoured file is.sonarcloud.properties, and that file forbids wildcard patterns. Sosnippets/**cannot be expressed and every generated snippet must be named individually.The list's own comment recorded how it was built: "taken from the duplication report as of 2026-07-23". That captured the pairs that exceeded Sonar's minimum block size on that one day — not the pairs that are duplicated by construction. Those are different sets.
Every
snippets/<sdk>/<framework>.<ext>is a verbatim (dedented) extraction of theregion: quickstart…endregionslice of its example entrypoint, produced byscripts/extract_snippets.pyand drift-gated byexample-metadata-check.yml. All 26 therefore duplicate their source by design. They merely become visible to the detector once the region grows past its minimum block size.That is exactly what happened in #631. AAASM-6204 added one argument plus a two-line comment to all 16 Python quickstart regions, which pushed
llamaindex-tool-policyacross the boundary. The gate reported 3 new duplicated lines on each side of a 31-line block that is the entire extracted region and was already byte-identical on main — where Sonar reports zero duplication for the same file. Three siblings (agno,crewai,haystack) were already excluded for precisely this reason;llamaindexwas absent only because it was under threshold on 2026-07-23.Running the new gate against main before this change shows the exposure:
20 of the 26 snippets were unprotected. Each was one region-growth away from reddening an unrelated PR that introduced no duplication at all.
This narrows nothing that matters
Only the generated side is excluded, and only from copy-paste detection. Every hand-written source stays under full duplication analysis, and all other rules continue to apply to the snippets themselves. Because a snippet is a verbatim copy of a source that is itself analysed, no signal is lost — what is removed is double-counting. That matches the established precedent in
agent-assembly/sonar-project.properties, whereopenapi/v1.yamlanddashboard/src/api/generated/**are excluded under AAASM-5095 "so the duplication metric reflects only hand-written code".The gate deliberately does not require
source_exampleto be excluded. Retiring the generated side is enough to retire a pair, and leaving the hand-written side analysed is the stronger posture. The 26 non-snippet entries are untouched — those are the per-frameworkmain.py/index.ts/policy.*templates that duplicate each other, independently of any snippet, which is the by-design duplication the file's comment already describes.No paid SonarCloud capacity is involved.
The contract
snippet_pathinsnippets/manifest.jsonappears verbatim insonar.cpd.exclusionsA5 is the one that matters most for recurrence. The intuitive fix for a stale exact-path list is to replace it with
snippets/**; in this file that silently protects nothing, and the gate now rejects it outright rather than letting it look correct.Anti-vacuity
A gate is only worth its runtime if it can fail.
--selftestmutates an in-memory copy of the real files once per assertion and requires each mutation to be caught. It runs before the real check in CI.How to verify
Expected from the first:
actionlintis clean on the modified workflow.Why this workflow
Wired into Example Metadata Drift Check rather than a new workflow: that job already regenerates these snippets and so already owns their contract.
.sonarcloud.propertiesand the script were added to itspaths:filter so editing the exclusion list re-triggers the gate. It is one Python file with no third-party imports and finishes in well under a second.Note on scope
This addresses the structural half of AAASM-6206. The immediate symptom was already fixed in #631 by adding the llamaindex pair. Two options recorded on the ticket are not taken here and are explained there: moving to CI-based analysis (where
snippets/**would be one wildcard, but which needs aSONAR_TOKENandautoscandisabled), and querying the live duplication report from CI (which would make a required gate depend on an external service and reintroduce the skip-on-unreachable failure mode).Refs AAASM-6206