| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
Resolve and persist the concrete commit SHA each file citation was sourced at (git rev-parse for read_file; the repo's indexed commit for grep, glob, and symbol search), and fetch the evidence panel + build copied links at that SHA. This keeps a citation's content and line ranges aligned with the code as it was when the answer was generated, instead of drifting against a moving HEAD. commitSha is optional, so pre-pinning chats fall back to the symbolic ref. Co-authored-by: Cursor <cursoragent@cursor.com>
WalkthroughAdds indexed commit metadata to repository and file-source shapes, propagates commit SHAs through search and file tools, adds a freshness API for cited files, and updates chat citation rendering to prefer pinned commits and show freshness status. ChangesCommit SHA pinning for file citations
Sequence Diagram(s)sequenceDiagram
participant ReferencedFileSourceListItemContainer
participant ClientAPI as getFileFreshness
participant FreshnessRoute as GET /api/source/freshness
participant getFileFreshnessApi
participant ReferencedFileSourceListItem
ReferencedFileSourceListItemContainer->>ClientAPI: filePath, repo, sinceSha
ClientAPI->>FreshnessRoute: GET query params
FreshnessRoute->>getFileFreshnessApi: { repo, path, sinceSha }
getFileFreshnessApi-->>FreshnessRoute: freshness status + currentSha
FreshnessRoute-->>ClientAPI: JSON response
ClientAPI-->>ReferencedFileSourceListItemContainer: freshness data
ReferencedFileSourceListItemContainer->>ReferencedFileSourceListItem: pinnedSha, freshnessStatus, currentSha
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. ❤️ ShareComment @coderabbitai help to get the list of available commands. |
Sorry, something went wrong.
Co-authored-by: Cursor <cursoragent@cursor.com>
If the pinned commit SHA can no longer be resolved (e.g. a force-push + GC pruned it), refetch the evidence-panel file once at the symbolic ref so the citation still renders instead of erroring. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)packages/web/src/features/tools/findSymbolReferences.ts (1)packages/web/src/features/tools/findSymbolDefinitions.ts (1)67-87: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Pin from the same search snapshot, not a follow-up lookup.
commitSha here comes from getRepoInfoByName(repo) after the symbol search has already returned response.files. If Zoekt reindexes between those two calls, Line 86 can attach a newer commit than the one the match ranges were computed from, and the downstream citation fetch will render the wrong revision. Carry the indexed hash from the search response that produced these matches instead of doing a second repo-info read here.
🤖 Prompt for AI AgentsVerify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/web/src/features/tools/findSymbolReferences.ts` around lines 67 - 87, The metadata assembly in findSymbolReferences is re-reading repo info after the symbol search, which can desync commitSha from the snapshot that produced response.files. Update the search flow so the indexed commit hash is carried through from the same Zoekt/search response used for match extraction, and use that value when building FindSymbolReferencesMetadata instead of repoInfoResult.indexedCommitHash from getRepoInfoByName(repo).56-76: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Use the indexed commit that came with the definitions result.
This pins definitions with a separate getRepoInfoByName(repo) call after the search result is already in hand. If the index advances between those calls, Line 75 can point citations at a different commit than the one the returned definition ranges came from. To keep “as answered” rendering stable, source commitSha from the same search response snapshot instead of this follow-up lookup.
🤖 Prompt for AI AgentsVerify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/web/src/features/tools/findSymbolDefinitions.ts` around lines 56 - 76, The commit SHA used in findSymbolDefinitions is being pulled from a follow-up getRepoInfoByName(repo) lookup, which can drift from the search snapshot that produced the definition ranges. Update the metadata assembly in findSymbolDefinitions so each file’s commitSha comes from the same definitions/search response payload that supplied response.files, not from repoInfoResult. Keep repoInfo construction if needed, but ensure the citation snapshot and commit hash are sourced consistently from the original search result.
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. Inline comments: In `@packages/web/src/ee/features/chat/components/chatThread/referencedFileSourceListItemContainer.tsx`: - Around line 54-61: The fallback in referencedFileSourceListItemContainer.tsx is too broad because it retries on any ServiceError and can silently substitute fileSource.revision for unrelated failures. Update the retry logic in the referenced file source loader to only fall back when the /api/source response specifically indicates the pinned ref cannot be resolved, and keep other ServiceError cases surfaced as-is. Use the existing isServiceError check around the getFileSource / unwrapServiceError path, but add a narrow guard for the “pinned ref unavailable” condition before retrying with fileSource.revision. In `@packages/web/src/features/git/getFileSourceApi.ts`: - Around line 64-71: Resolve the commit SHA before any git reads in getFileSourceApi so all content comes from the same revision. The current flow reads the file and .gitattributes from gitRef before rev-parse runs, which can mix revisions if the ref moves. Update the logic around git.raw, git.show, and commitSha to resolve gitRef to a concrete SHA first, then use that resolved value for the subsequent reads, falling back to gitRef only when rev-parse fails. --- Outside diff comments: In `@packages/web/src/features/tools/findSymbolDefinitions.ts`: - Around line 56-76: The commit SHA used in findSymbolDefinitions is being pulled from a follow-up getRepoInfoByName(repo) lookup, which can drift from the search snapshot that produced the definition ranges. Update the metadata assembly in findSymbolDefinitions so each file’s commitSha comes from the same definitions/search response payload that supplied response.files, not from repoInfoResult. Keep repoInfo construction if needed, but ensure the citation snapshot and commit hash are sourced consistently from the original search result. In `@packages/web/src/features/tools/findSymbolReferences.ts`: - Around line 67-87: The metadata assembly in findSymbolReferences is re-reading repo info after the symbol search, which can desync commitSha from the snapshot that produced response.files. Update the search flow so the indexed commit hash is carried through from the same Zoekt/search response used for match extraction, and use that value when building FindSymbolReferencesMetadata instead of repoInfoResult.indexedCommitHash from getRepoInfoByName(repo).
Fix all unresolved CodeRabbit comments on this PR:
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1caad508-3dff-44ac-b7eb-0e5dfc7b351c
📥 CommitsReviewing files that changed from the base of the PR and between f7f0fef and 01f7716.
📒 Files selected for processing (14)
Sorry, something went wrong.
- Resolve the git ref to a concrete commit before reading file content and .gitattributes, so all of source, language, and commitSha come from the same revision even if the ref moves mid-request. - Narrow the evidence-panel fallback to only retry at the symbolic ref when the pinned commit is unresolvable (INVALID_GIT_REF); surface other errors. - Pin symbol-search citations from the indexed commit carried by the same search snapshot instead of a follow-up getRepoInfoByName lookup. - Regenerate the public OpenAPI spec for the new commitSha/indexedCommitHash fields. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
packages/web/src/features/git/getFileSourceApi.test.ts (1)🤖 Prompt for all review comments with AI agents288-297: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Assert the returned commitSha in the success-path test.
This only checks the git call sequence. A regression that stops returning the pinned SHA would still pass even though that field is the new contract being added here.
Proposed test tightening🤖 Prompt for AI Agents- await getFileSourceForRepo( + const result = await getFileSourceForRepo( { path: 'src/index.ts', repo: 'github.com/owner/repo', ref: 'abc123sha' }, { org: MOCK_ORG, prisma: mockPrisma }, ); @@ expect(mockGitRaw).toHaveBeenCalledWith(['rev-parse', 'abc123sha^{commit}']); // ...and content is read at the resolved sha, not the symbolic ref. expect(mockGitRaw).toHaveBeenCalledWith(['show', 'resolvedsha:src/index.ts']); + expect(result).toMatchObject({ commitSha: 'resolvedsha' });Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/web/src/features/git/getFileSourceApi.test.ts` around lines 288 - 297, The success-path test for getFileSourceForRepo only verifies the git command sequence and should also assert the returned commitSha. Update the existing test case in getFileSourceApi.test.ts to check that the result includes the resolved pinned SHA (the value returned from the rev-parse/show flow), using the getFileSourceForRepo call and its returned object so a regression in the new contract is caught.
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. Nitpick comments: In `@packages/web/src/features/git/getFileSourceApi.test.ts`: - Around line 288-297: The success-path test for getFileSourceForRepo only verifies the git command sequence and should also assert the returned commitSha. Update the existing test case in getFileSourceApi.test.ts to check that the result includes the resolved pinned SHA (the value returned from the rev-parse/show flow), using the getFileSourceForRepo call and its returned object so a regression in the new contract is caught.
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: eb670102-7140-4e47-bf23-0af3c1c48bfc
📥 CommitsReviewing files that changed from the base of the PR and between 01f7716 and 5da3214.
📒 Files selected for processing (6)
Sorry, something went wrong.
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
Sorry, something went wrong.
) * feat(web): flag Ask citations whose code changed since the answer Adds a per-citation freshness check: a `/api/source/freshness` endpoint compares a pinned commit against the repo's current default-branch tip (file-level blob comparison) and the evidence panel renders a badge when the cited file has changed, was removed, or its pinned commit is gone, with a link to the latest version. Also resolves citations to a pinned source when multiple tools sourced the same file in one turn. Co-authored-by: Cursor <cursoragent@cursor.com> * docs: add CHANGELOG entry for citation staleness hint Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agentsVerify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@packages/web/src/ee/features/chat/components/chatThread/referencedFileSourceListItem.tsx`:
- Around line 82-96: The latest-version link in referencedFileSourceListItem
should appear for every stale file state, not only when status is changed.
Update the conditional around the Link that uses getBrowsePath so it also covers
removed and pinned_unavailable, while still requiring currentSha, and keep the
existing navigation props and styling unchanged.
In `@packages/web/src/features/git/getFileFreshnessApi.ts`:
- Around line 16-25: resolveBlobOid currently catches every git.raw('rev-parse',
...) failure and returns undefined, which hides real git/I/O/repo-state errors.
Update resolveBlobOid in getFileFreshnessApi so it only maps missing ref/path
cases to undefined and rethrows all other errors, then let the caller’s
freshness logic continue to surface those as UNEXPECTED_ERROR instead of
pinned_unavailable/removed. Use the existing resolveBlobOid and
getFileFreshnessApi flow to distinguish expected missing-object failures from
unexpected git failures.
Fix all unresolved CodeRabbit comments on this PR:
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7a4ff756-39be-443c-8953-edde152b4cda
📥 CommitsReviewing files that changed from the base of the PR and between d6d8279 and cbfcfa4.
📒 Files selected for processing (10)
Sorry, something went wrong.
| {status === 'changed' && currentSha && ( | ||
| <Link | ||
| href={getBrowsePath({ | ||
| repoName, | ||
| revisionName: currentSha, | ||
| path, | ||
| pathType: 'blob', | ||
| })} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="text-xs text-muted-foreground underline hover:text-foreground" | ||
| > | ||
| View latest | ||
| </Link> | ||
| )} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Show the latest link for all stale statuses, not just changed.
The PR scope says the badge should expose a latest-version link when the file changed, was removed, or the pinned commit is unavailable. This condition hides that link for removed and pinned_unavailable, so two of the new states lose the intended navigation affordance.
Suggested fix- {status === 'changed' && currentSha && (
+ {currentSha && status !== 'fresh' && (
<Link
href={getBrowsePath({
repoName,
revisionName: currentSha,
path,
pathType: 'blob',
})}‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {status === 'changed' && currentSha && ( | |
| <Link | |
| href={getBrowsePath({ | |
| repoName, | |
| revisionName: currentSha, | |
| path, | |
| pathType: 'blob', | |
| })} | |
| target="_blank" | |
| rel="noopener noreferrer" | |
| className="text-xs text-muted-foreground underline hover:text-foreground" | |
| > | |
| View latest | |
| </Link> | |
| )} | |
| {currentSha && status !== 'fresh' && ( | |
| <Link | |
| href={getBrowsePath({ | |
| repoName, | |
| revisionName: currentSha, | |
| path, | |
| pathType: 'blob', | |
| })} | |
| target="_blank" | |
| rel="noopener noreferrer" | |
| className="text-xs text-muted-foreground underline hover:text-foreground" | |
| > | |
| View latest | |
| </Link> | |
| )} |
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/web/src/ee/features/chat/components/chatThread/referencedFileSourceListItem.tsx` around lines 82 - 96, The latest-version link in referencedFileSourceListItem should appear for every stale file state, not only when status is changed. Update the conditional around the Link that uses getBrowsePath so it also covers removed and pinned_unavailable, while still requiring currentSha, and keep the existing navigation props and styling unchanged.
Sorry, something went wrong.
| const resolveBlobOid = async ( | ||
| git: ReturnType<typeof simpleGit>, | ||
| ref: string, | ||
| path: string, | ||
| ): Promise<string | undefined> => { | ||
| try { | ||
| return (await git.raw(['rev-parse', `${ref}:${path}`])).trim(); | ||
| } catch { | ||
| return undefined; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Don’t turn every rev-parse failure into a freshness status.
resolveBlobOid() currently swallows all git errors, so I/O or repo-state failures get reported as pinned_unavailable / removed instead of bubbling up as UNEXPECTED_ERROR. Only missing-ref / missing-path cases should map to undefined; everything else should be rethrown.
Suggested fix const resolveBlobOid = async (
git: ReturnType<typeof simpleGit>,
ref: string,
path: string,
): Promise<string | undefined> => {
try {
return (await git.raw(['rev-parse', `${ref}:${path}`])).trim();
- } catch {
- return undefined;
+ } catch (error) {
+ const message = error instanceof Error ? error.message : String(error);
+ if (
+ /bad revision|unknown revision|ambiguous argument|does not exist|exists on disk, but not in/i.test(message)
+ ) {
+ return undefined;
+ }
+ throw error;
}
};‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const resolveBlobOid = async ( | |
| git: ReturnType<typeof simpleGit>, | |
| ref: string, | |
| path: string, | |
| ): Promise<string | undefined> => { | |
| try { | |
| return (await git.raw(['rev-parse', `${ref}:${path}`])).trim(); | |
| } catch { | |
| return undefined; | |
| } | |
| const resolveBlobOid = async ( | |
| git: ReturnType<typeof simpleGit>, | |
| ref: string, | |
| path: string, | |
| ): Promise<string | undefined> => { | |
| try { | |
| return (await git.raw(['rev-parse', `${ref}:${path}`])).trim(); | |
| } catch (error) { | |
| const message = error instanceof Error ? error.message : String(error); | |
| if ( | |
| /bad revision|unknown revision|ambiguous argument|does not exist|exists on disk, but not in/i.test(message) | |
| ) { | |
| return undefined; | |
| } | |
| throw error; | |
| } |
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/web/src/features/git/getFileFreshnessApi.ts` around lines 16 - 25,
resolveBlobOid currently catches every git.raw('rev-parse', ...) failure and
returns undefined, which hides real git/I/O/repo-state errors. Update
resolveBlobOid in getFileFreshnessApi so it only maps missing ref/path cases to
undefined and rethrows all other errors, then let the caller’s freshness logic
continue to surface those as UNEXPECTED_ERROR instead of
pinned_unavailable/removed. Use the existing resolveBlobOid and
getFileFreshnessApi flow to distinguish expected missing-object failures from
unexpected git failures.
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Pins each Ask file citation to the commit SHA it was sourced at (git rev-parse for read_file; the repo's indexed commit for grep/glob/symbol search), and fetches the evidence panel + copied links at that SHA. Keeps citation content and line ranges aligned with the code as it was when answered, rather than drifting against HEAD. commitSha is optional, so older chats fall back to the symbolic ref.
Groundwork for a follow-up freshness hint. get_diff/list_tree left unpinned for now.
Should be basically indistinguishable UI/UX difference, just now that any code referenced in the evidence panel should be as-the-agent-saw-it. In the event that the revision was lost in git history, it will fallback to one retry fetch from effectively latest, which is the existing behaviour.
Additional
Adds a per-citation freshness hint: /api/source/freshness compares a pinned commit to the repo's current default-branch tip (file-level blob comparison), and the evidence panel shows a badge when the cited file has changed / removed / pinned_unavailable, with a "View latest" link. Also resolves a citation to a pinned source when multiple tools sourced the same file in one turn.
Scope: panel-only (no inline-chip dots or answer rollup yet); list_tree/get_diff remain unpinned.
(removed the "view latest" button from these two, but here's what the badges look like for the other two statuses (not included in the screenrecording)
Summary by CodeRabbit