Repository navigation
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
Problem
fingerprintIssue (src/issue-fingerprint.ts:16-19) hashes check + rule + normalised path + lower-cased message (:42-48).
- Unstable across commits. Many messages embed a measurement: "AdminLayout: 65 lines (max 60)" (
runners/complexity.ts:43), "~4620 tokens (>4000)" (context), "329 lines — consider splitting" (standards large-file), "imports 12 modules" (architecture), "Barrel file with 5 re-exports" (performance). When the number moves,trend.tsreports one fixed + one new. On a 1,501-issue report (CLI 0.54.4) 600 messages contain digits. - Duplication identity includes line numbers.
runners/duplication.ts:82setsfileto`${fileA}:${lineA} ↔ ${fileB}:${lineB}`and:81puts the clone length in the message; any edit above either clone re-identifies it. - Not unique within a report. Repeated findings in one file share a fingerprint (on that report: 156 groups covering 529 issues; mostly error-handling, performance, accessibility, type-safety).
delta.ts:57-73already counts them as a multiset, buttrend.ts:55-60collapses them in aMap, so fixing one of two identical findings reports nothing.
What to do (cheapest first)
trend.tsmultiset — count per fingerprint likedelta.ts. Ships alone, no fingerprint change.- Per-runner identity (v2):
- File-scoped measured rules (standards
large-file, contexthigh-token-count, architecturehigh-fan-out, performancebarrel-import): key = check + rule + file; message excluded. - complexity: key = check + rule + file + function name (
f.name). - duplication: key = sorted pair of paths without
:line+ hash of the normalised snippet. - Everything else: current key.
Implemented as an optional per-runnersubject(emitted asIssue.subjectonce schema 0.6.0 declares it); never a global digit regex.
- File-scoped measured rules (standards
- Disambiguate repeats with a content anchor: for issues with
file+line, add a hash of the whitespace-normalised source line (read from the raw file viaFileInventory, not SFC-extracted content); only among identical line contents append an occurrence ordinal. Issues without a line: ordinal by emission order. - Versioning:
meta.fingerprintVersion = 2. Intrend.ts/delta.ts, when the two reports' versions differ (absent = 1), recompute v1 on both sides from check/rule/file/message (available onIssueSnapshottoo) so the boundary scan reports no churn. Do not rely onreadIssueFingerprint's stored-value preference (:37-40) — that is what would cause the churn.
Rejected
- Global "replace digits with #":
dependenciesissues have no file/rule and say "95 high vulnerabilities" (runners/dependencies.ts:83-93); 95 → 96 would keep identity and hide a new vulnerability; also collapses version strings andCWE-nn. - Pure line-order ordinal: inserting an identical finding above existing ones shifts every later ordinal, so the "new" finding reported is the wrong one and any per-fingerprint state attaches to the wrong finding. ~⅓ of issues have no line, so line order is not even total.
- Symbol for type-safety: it is a line regex (
runners/type-safety.ts:147) with no AST; its messages carry no measurement anyway. The content anchor covers it.
Acceptance criteria
- Each measured rule above: same finding with a changed number keeps its fingerprint (test per runner).
- Duplication: inserting lines above both clones keeps the fingerprint.
- Two identical findings on different lines get distinct fingerprints; inserting a third identical line above them leaves the first two unchanged; fixing one reports exactly that one fixed.
-
dependenciescount change still reports a change. - A trend/delta between a v1 report and a v2 report of unchanged code reports 0 new / 0 fixed.
- CHANGELOG notes the fingerprint version change.
Open question
Project-level aggregate findings ("14 unused files detected by Knip", "Mixed styling approaches: tailwind (1031)…", "Only 20% of exports…") are metrics phrased as findings. Keep the message in their key (churn on every change, today's behaviour) or key by rule (identity stable, count change invisible to identity)? Recommend: keep message for now; per-advisory dependency findings would be the real fix.
Constraints
- mcp's committed fixture changes when its CLI_SPEC next moves to the release containing this; note it in that pin issue.
Issue.subject/meta.fingerprintVersionare declared in schema 0.6.0 (Reports don't say which commit, branch, CI run or producer they describe — declare scan provenance in VibeReport.meta (0.6.0) schema#6);fingerprintalready passes through, so this is not hard-blocked.
Related: #45 (closed, introduced fingerprints), app#27 (fingerprints unread in the monitor).
🤖 Filed with Claude Code
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
serge-ivo commentedon Oct 5, 2026
Delivered in two stacked PRs:
fix/97-trend-multiset, 685299b): step 1.trend.tscounts repeated fingerprints as a multiset.pnpm testpasses 740/740.fix/97-fingerprint-v2, 57693ec, stacked on fix(trend): count repeated fingerprints as a multiset (#97) #114): steps 2–4, with per-runnersubject, content anchor plus ordinal,meta.fingerprintVersion = 2, and the v1/v2 boundary recompute in trend/delta. It adds the CHANGELOGUnreleasednote.pnpm testpasses 757/757, with every acceptance criterion covered insrc/fingerprint-v2.test.ts.Both:
pnpm buildis clean andpnpm linthas 0 errors (62 warnings, same as main). Aggregate findings keep their message in the key, as recommended. Schema is not bumped:subjectandfingerprintVersionare typed locally until schema#6 publishes.mcp's
report-cli-0.55.0.jsonfixture changes at the next CLI_SPEC bump that includes this, so note it in that pin issue. This stays open until both PRs merge.test(fingerprint): stop the barrel-import test spawning Knip (#97)
fix(fingerprint): do not content-anchor Vue/Svelte findings (#97)
fix(history): record fingerprintVersion in history snapshots (#97)
fix(complexity): stop counting if/for/switch blocks as functions (#97)
test(fingerprint): pin the identical-source-line limit (#97)
serge-ivo commentedon Oct 5, 2026
Documented limit (from review of #116): the acceptance criterion "inserting a third identical line above them leaves the first two unchanged" is met for counts but not for naming.
src/fingerprint-v2.test.tsand stated in the CHANGELOG.Vue/Svelte findings are not content-anchored (mixed line provenance across runners) and use line-order ordinals instead.
docs(changelog): note the complexity functionCount change and the SFC…
Merge pull request #114 from vibecodeqa/fix/97-trend-multiset
Merge pull request #116 from vibecodeqa/fix/97-fingerprint-v2