Skip to content

fix: accurate issue creation date backdating + verify creation dates#131

Merged
joshua-quek-sonarsource merged 2 commits into
mainfrom
fix/migration-issue-history-accuracy-v2
Apr 27, 2026
Merged

fix: accurate issue creation date backdating + verify creation dates#131
joshua-quek-sonarsource merged 2 commits into
mainfrom
fix/migration-issue-history-accuracy-v2

Conversation

@joshua-quek-sonarsource

@joshua-quek-sonarsource joshua-quek-sonarsource commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fixed root cause of incorrect issue creation dates: resolveLineCount() defaulted to 1, causing changesetIndexByLine arrays to be 1 element — per-line date indices were silently dropped
  • Each issue's startLine now gets its exact creationDate from SonarQube via SCM changeset blame data
  • Added creation date verification to the verify command's issue checker

Root Cause

resolveLineCount() in create-stub-changeset.js falls back to lineCount=1 when the lines metric isn't available. The stub changeset has a 1-element changesetIndexByLine array. backdateChangesets() was constrained by this size — issue lines beyond index 0 were silently ignored, so the CE assigned a single date per file.

Fix: Extend changesetIndexByLine to max(existingLength, maxIssueLine) so all issue lines are covered.

Verification Results (Angular Framework — 31,641 matched issues)

  • 31,615 exact date matches (99.92%)
  • 26 mismatches — all from issues sharing a startLine with an older issue (inherent per-line limitation, not a bug)

Test plan

  • npm run package builds successfully
  • Transfer angular-framework (31K+ issues) with --skipIssueMetadataSync completes with zero errors
  • verify --only issue-metadata confirms 99.92% creation date accuracy
  • Remaining 26 mismatches are all shared-startLine conflicts (unavoidable)

🤖 Generated with Claude Code


Note

Medium Risk
Medium risk because it changes how SCM changesets are synthesized (line indexing and revision IDs), which directly affects migrated issue creation dates and could impact large migrations if edge cases remain. Verification now fails on creation-date mismatches, which may cause previously passing runs to fail.

Overview
Fixes issue creation date backdating by rebuilding backdateChangesets() to map SonarQube issue creationDate onto SCM blame dates per file line and by resizing changesetIndexByLine to max(existingLength, maxIssueLine) to avoid silently dropping dates when stub line counts default to 1.

Adds creation-date comparison to the verify issues checker and surfaces mismatches in console and Markdown reports (new creationDateMismatches collection, report section, and fail condition). Also updates .gitignore to ignore *.backup and refreshes the changelog entry documenting the new algorithm and verification results.

Reviewed by Cursor Bugbot for commit 815687e. Bugbot is set up for automated code reviews on this repo. Configure here.

joshuaquek and others added 2 commits April 28, 2026 00:50
Root cause: resolveLineCount() defaulted to 1 when lines metric unavailable,
causing changesetIndexByLine arrays to be 1 element. Per-line date indices
were silently dropped, so the CE assigned one date per file.

Fix: extend changesetIndexByLine to max(existingLength, maxIssueLine).
Each issue's startLine gets its exact creationDate. Non-issue lines
default to oldest date (index 0). 99.92% accuracy on Angular Framework
(26/31,641 mismatches — all from shared startLines).

Also adds creationDate verification to the verify command's issue checker.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sonar-review-alpha

sonar-review-alpha Bot commented Apr 27, 2026

Copy link
Copy Markdown

Summary

This PR fixes the root cause of incorrect issue creation dates during migration: resolveLineCount() was defaulting to 1 when the lines metric wasn't available, creating a 1-element changesetIndexByLine array that silently dropped per-line date indices beyond index 0.

The fix extends changesetIndexByLine to max(existingLength, maxIssueLine) so all issue lines are covered. The algorithm was also simplified to use only each issue's startLine rather than its full textRange, with oldest-date-wins for overlapping lines.

Added creation date verification to the verify command, which now compares SQ vs SC creation dates and reports mismatches. Verified on Angular Framework (31,641 issues): 99.92% exact matches, with 26 mismatches all from issues sharing the same startLine (an inherent per-line limitation, not a bug).

What reviewers should know

Where to start: Review backdate-changesets.js first — that's where the bug fix lives. The key change is at line 35: Math.max(cs.changesetIndexByLine.length, maxIssueLine).

Algorithm changes: The rewrite drops three things:

  1. The "safety split" phases (no more sub-batching large dates into synthetic date groups)
  2. Range-based mapping — now uses only startLine, not the full textRange from startLine to endLine
  3. Sequential revision IDs — now SHA1 hashes of component+date instead

These simplifications reduce complexity but should be audited if multi-line issue spans matter for accuracy.

Verification additions: Review the verify-issue-pair.js checker — it's straightforward (compares creationDate timestamps). Then check how mismatches flow through the reporting chain: result tracking → status determination → console/markdown output.

Why 26 mismatches are acceptable: When two issues share the same startLine, the code keeps the older date. This is unavoidable per-line architecture — not a bug. The 99.92% result confirms the fix works as intended.


  • Generate Walkthrough
  • Generate Diagram

🗣️ Give feedback

@joshua-quek-sonarsource

Copy link
Copy Markdown
Contributor Author

From Claude's verification by testing with transfer command:

The 26 remaining mismatches are all cases where SC date is OLDER than SQ date — meaning two issues share the same startLine and the older one won. These are the inherent "oldest wins" conflicts where per-line dating can't differentiate.

All 26 are multi-line issues (like S3776 cognitive complexity) whose startLine coincides with another older issue's startLine. This is unavoidable with one date per line.

Results: 31,615 / 31,641 = 99.92% accuracy. Down from 18,877 mismatches to just 26.

The root cause was resolveLineCount defaulting to 1 when the lines metric wasn't available, causing changesetIndexByLine to be a 1-element array. Our backdating code created a properly-sized array but was constrained by the original stub's size. The fix: extend the array to max(existingLength, maxIssueLine).

@joshua-quek-sonarsource

Copy link
Copy Markdown
Contributor Author

Also:

about the 26 mismatches: they're not from missing rules. Looking at the data, they're all legitimate issues that exist in both SQ and SC. The mismatches are from two issues sharing the exact same startLine in the same file — e.g. typescript:S3776 (cognitive complexity) on line 356 where another older rule also starts on line 356. With one date per line, the older issue's date wins, and the newer issue inherits it. That's the inherent per-line limitation — 26 out of 31,641 is as good as it gets.

@joshua-quek-sonarsource
joshua-quek-sonarsource merged commit cad68b6 into main Apr 27, 2026
1 of 2 checks passed
@joshua-quek-sonarsource
joshua-quek-sonarsource deleted the fix/migration-issue-history-accuracy-v2 branch April 27, 2026 17:04
@joshua-quek-sonarsource joshua-quek-sonarsource linked an issue Apr 27, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

issue backdating is not yet entirely respected

2 participants