diff --git a/src/ui/components/panes/FileListItem.tsx b/src/ui/components/panes/FileListItem.tsx
index 36276e9..f01f409 100644
--- a/src/ui/components/panes/FileListItem.tsx
+++ b/src/ui/components/panes/FileListItem.tsx
@@ -116,7 +116,15 @@ export function FileListItem({
style={{ height: 1, flexDirection: "row", backgroundColor: rowBackground }}
>
{index > 0 && }
-
+
{stat.text}
diff --git a/src/ui/components/ui-components.test.tsx b/src/ui/components/ui-components.test.tsx
index 4eb55cf..0cd5dc0 100644
--- a/src/ui/components/ui-components.test.tsx
+++ b/src/ui/components/ui-components.test.tsx
@@ -416,7 +416,7 @@ describe("UI components", () => {
expect(frame).toContain(" App.tsx");
expect(frame).toContain(" MenuDropdown.tsx");
expect(frame).toContain(" watch.ts");
- expect(frame).toContain("+2 -1");
+ expect(frame).toContain("*1 +2 -1");
expect(frame).toContain("+5");
expect(frame).toContain("-3");
expect(frame).not.toContain("+0");
diff --git a/src/ui/lib/files.test.ts b/src/ui/lib/files.test.ts
index 63adaa4..4e2b653 100644
--- a/src/ui/lib/files.test.ts
+++ b/src/ui/lib/files.test.ts
@@ -46,21 +46,77 @@ describe("files helpers", () => {
expect(entries).toHaveLength(3);
expect(entries[0]).toMatchObject({
name: "only-add.ts",
+ agentCommentsText: null,
additionsText: "+5",
deletionsText: null,
});
expect(entries[1]).toMatchObject({
name: "only-remove.ts",
+ agentCommentsText: null,
additionsText: null,
deletionsText: "-3",
});
expect(entries[2]).toMatchObject({
name: "Legacy.tsx -> Renamed.tsx",
+ agentCommentsText: null,
additionsText: null,
deletionsText: null,
});
});
+ test("buildSidebarEntries includes compact per-file comment counts before diff stats", () => {
+ const withComments = createTestDiffFile({
+ id: "with-comments",
+ path: "src/ui/commented.ts",
+ before: lines("const alpha = 1;", "const beta = 2;", "const gamma = 3;"),
+ after: lines("const alpha = 10;", "const beta = 2;", "const gamma = 30;"),
+ agent: {
+ path: "src/ui/commented.ts",
+ annotations: [
+ { summary: "Note on first hunk", newRange: [1, 1] },
+ { summary: "Another note on first hunk", newRange: [1, 1] },
+ { summary: "Note on second hunk", newRange: [3, 3] },
+ ],
+ },
+ });
+
+ const [entry] = buildSidebarEntries([withComments]).filter((item) => item.kind === "file");
+
+ expect(entry).toMatchObject({
+ name: "commented.ts",
+ agentCommentsText: "*3",
+ additionsText: "+2",
+ deletionsText: "-2",
+ });
+ });
+
+ test("buildSidebarEntries counts all comments attached to a file, even off-range ones", () => {
+ const withComments = createTestDiffFile({
+ id: "all-comments",
+ path: "src/ui/all-comments.ts",
+ before: lines("const alpha = 1;", "const beta = 2;", "const gamma = 3;"),
+ after: lines("const alpha = 10;", "const beta = 2;", "const gamma = 30;"),
+ agent: {
+ path: "src/ui/all-comments.ts",
+ annotations: [
+ { summary: "First note", newRange: [1, 1] },
+ { summary: "Second note", newRange: [1, 1] },
+ // The sidebar count is per-file, so even comments outside a visible hunk still count.
+ { summary: "Third note", newRange: [20, 20] },
+ ],
+ },
+ });
+
+ const [entry] = buildSidebarEntries([withComments]).filter((item) => item.kind === "file");
+
+ expect(entry).toMatchObject({
+ name: "all-comments.ts",
+ agentCommentsText: "*3",
+ additionsText: "+2",
+ deletionsText: "-2",
+ });
+ });
+
test("fileLabelParts strips parser-added line endings from rename labels", () => {
const renamedAcrossDirectories = {
...createTestDiffFile({
diff --git a/src/ui/lib/files.ts b/src/ui/lib/files.ts
index eed9314..7729c68 100644
--- a/src/ui/lib/files.ts
+++ b/src/ui/lib/files.ts
@@ -7,6 +7,7 @@ export interface FileListEntry {
kind: "file";
id: string;
name: string;
+ agentCommentsText: string | null;
additionsText: string | null;
deletionsText: string | null;
changeType: FileDiffMetadata["type"];
@@ -40,9 +41,17 @@ function formatSidebarStat(prefix: "+" | "-", value: number) {
return value > 0 ? `${prefix}${value}` : null;
}
-/** Build the visible stats badges for one sidebar row. */
-export function sidebarEntryStats(entry: Pick) {
- const stats: Array<{ kind: "addition" | "deletion"; text: string }> = [];
+/** Build the visible stats badges for one sidebar row.
+ * Keep the agent-note badge first so it reads as review context before line churn.
+ */
+export function sidebarEntryStats(
+ entry: Pick,
+) {
+ const stats: Array<{ kind: "agent-comment" | "addition" | "deletion"; text: string }> = [];
+
+ if (entry.agentCommentsText) {
+ stats.push({ kind: "agent-comment", text: entry.agentCommentsText });
+ }
if (entry.additionsText) {
stats.push({ kind: "addition", text: entry.additionsText });
@@ -57,7 +66,7 @@ export function sidebarEntryStats(entry: Pick,
+ entry: Pick,
) {
return sidebarEntryStats(entry).reduce(
(width, stat, index) => width + stat.text.length + (index > 0 ? 1 : 0),
@@ -128,10 +137,13 @@ export function buildSidebarEntries(files: DiffFile[]): SidebarEntry[] {
}
}
+ const agentCommentCount = file.agent?.annotations.length ?? 0;
+
entries.push({
kind: "file",
id: file.id,
name: sidebarFileName(file),
+ agentCommentsText: agentCommentCount > 0 ? `*${agentCommentCount}` : null,
additionsText: formatSidebarStat("+", file.stats.additions),
deletionsText: formatSidebarStat("-", file.stats.deletions),
changeType: file.metadata.type,
diff --git a/test/pty/ui-integration.test.ts b/test/pty/ui-integration.test.ts
index b7d7679..ba8b72b 100644
--- a/test/pty/ui-integration.test.ts
+++ b/test/pty/ui-integration.test.ts
@@ -429,7 +429,8 @@ describe("live UI integration", () => {
await session.type("beta");
const filtered = await harness.waitForSnapshot(
session,
- (text) => text.includes("betaValue") && !text.includes("add = true"),
+ (text) =>
+ text.includes("betaValue") && !text.includes("alpha.ts") && !text.includes("add = true"),
5_000,
);