git-reviewer 2.5.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![CI](https://github.com/dheerajjha/reviewer/actions/workflows/ci.yml/badge.svg)](https://github.com/dheerajjha/reviewer/actions/workflows/ci.yml)
4
4
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5
5
  [![Node](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](package.json)
6
- [![Tests](https://img.shields.io/badge/tests-271-brightgreen.svg)](test/)
6
+ [![Tests](https://img.shields.io/badge/tests-272-brightgreen.svg)](test/)
7
7
  [![Dependencies](https://img.shields.io/badge/dependencies-3-brightgreen.svg)](package.json)
8
8
 
9
9
  When an agent writes the code, reading it becomes the bottleneck — and the tool
@@ -32,16 +32,18 @@ review was saved and keeps serving, because you may have more to read.
32
32
  Everything it says to you goes to stderr either way, so only the review is
33
33
  ever on stdout.
34
34
 
35
- ![A terminal installing git-reviewer and running it inside a project; the browser opens on the diff with the first changed file already showing; two review comments are written inline, one with a threaded follow-up; then reviewer export prints those same comments back for a coding agent to act on](docs/demo.gif)
35
+ ![A terminal installing git-reviewer and running it inside a project; the browser opens on the diff; two review comments are written inline, one with a threaded follow-up; submitting hands the review back to the terminal, where Claude reads it, explains both fixes and names a tradeoff in its own approach, and git diff shows the three files it changed](docs/demo.gif)
36
36
 
37
- *The whole loop, unedited and in real time — [full resolution](docs/demo.mp4).*
37
+ *One command, start to finish, unedited — [full resolution](docs/demo.mp4). Every
38
+ frame is the real tool: the terminal output is captured from the run you are
39
+ watching, and the code at the end is what the agent actually wrote.*
38
40
 
39
41
  Nothing is installed into the project, there is nothing to sign in to, and
40
42
  nothing leaves your machine. If you would rather not install it,
41
43
  `npx git-reviewer` works the same way.
42
44
 
43
- The recording above shows the two-step form, which still works and is the one
44
- to reach for when the review and the hand-off happen at different times:
45
+ When the review and the hand-off happen at different times, the two-step form
46
+ still works and is the one to reach for:
45
47
 
46
48
  ```bash
47
49
  reviewer # read the diff, comment on it
@@ -292,7 +294,7 @@ rather than a public issue.
292
294
 
293
295
  ```bash
294
296
  npm install # 3 dependencies, no build step, ~6MB
295
- npm test # 271 tests
297
+ npm test # 272 tests
296
298
  npm run test:watch
297
299
  npm run test:coverage
298
300
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-reviewer",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "description": "Review your coding agent's changes like a pull request — locally, with inline comments and threaded follow-ups, then hand the marked-up review back to the agent",
5
5
  "author": "Dheeraj Jha",
6
6
  "license": "MIT",
package/public/app.js CHANGED
@@ -254,8 +254,12 @@ function displayFiles(files) {
254
254
  // before the handler is parsed, so an escaped quote is a quote again by
255
255
  // the time it matters. The row carries its position instead, and the name
256
256
  // is read back out of `currentFiles`, where it stays data.
257
+ // The count is filled in by `updateFileCommentCounts`, not here. Rendering
258
+ // it now would mean re-rendering this list on every comment to keep it
259
+ // true, and re-rendering the list is what loses the selected row.
257
260
  return `<div class="file-item" onclick="openFileAt(${Number(index)})" title="${escapeHtml(file)}">
258
261
  ${statusBadge}<span class="file-path-text">${displayText}</span>
262
+ <span class="file-comment-count" data-file-index="${Number(index)}" hidden></span>
259
263
  </div>`;
260
264
  }).join('');
261
265
 
@@ -1470,12 +1474,46 @@ function initResizeHandle() {
1470
1474
  let currentFileIndex = -1;
1471
1475
 
1472
1476
  // Update comments sidebar
1477
+ /**
1478
+ * How many comments sit on each file, on the file rows themselves.
1479
+ *
1480
+ * In a review of any size the question you keep asking is which files you have
1481
+ * already covered, and the only answer on screen was a total in the sidebar
1482
+ * header — so you found out by clicking through every file (#48).
1483
+ *
1484
+ * Updated in place rather than by re-rendering the list. Re-rendering would be
1485
+ * one line, and it would drop the selected row and the scroll position of the
1486
+ * file list every time anyone typed a comment.
1487
+ */
1488
+ function updateFileCommentCounts() {
1489
+ const badges = document.querySelectorAll('.file-comment-count');
1490
+ if (badges.length === 0) return;
1491
+
1492
+ const perFile = new Map();
1493
+ for (const comment of comments) {
1494
+ perFile.set(comment.file, (perFile.get(comment.file) ?? 0) + 1);
1495
+ }
1496
+
1497
+ for (const badge of badges) {
1498
+ const file = currentFiles[Number(badge.dataset.fileIndex)];
1499
+ const count = file ? perFile.get(file.path) ?? 0 : 0;
1500
+
1501
+ badge.textContent = count;
1502
+ badge.title = `${count} comment${count === 1 ? '' : 's'} on this file`;
1503
+ badge.hidden = count === 0;
1504
+ }
1505
+ }
1506
+
1473
1507
  function updateCommentsSidebar() {
1474
1508
  const sidebar = document.getElementById('commentsSidebar');
1475
1509
  const commentsList = document.getElementById('commentsList');
1476
1510
  const commentsCount = document.getElementById('commentsCount');
1477
1511
  const commentsResizeHandle = document.getElementById('commentsResizeHandle');
1478
1512
 
1513
+ // Every path that changes a comment already calls this, so the per-file
1514
+ // counts ride along rather than needing ten more call sites of their own.
1515
+ updateFileCommentCounts();
1516
+
1479
1517
  commentsCount.textContent = comments.length;
1480
1518
 
1481
1519
  if (comments.length === 0) {
package/public/style.css CHANGED
@@ -1836,3 +1836,24 @@ button:disabled {
1836
1836
  @media (max-width: 640px) {
1837
1837
  .help-steps { grid-template-columns: 1fr; }
1838
1838
  }
1839
+
1840
+ /* Comments per file
1841
+ *
1842
+ * In a review of any size the question you keep asking is which files you have
1843
+ * already covered. The only answer on screen was a total in the sidebar
1844
+ * header, so you found out by clicking through every file.
1845
+ */
1846
+ .file-comment-count {
1847
+ flex: none;
1848
+ min-width: 18px;
1849
+ margin-left: auto;
1850
+ padding: 1px 6px;
1851
+ border-radius: 20px;
1852
+ background: #fff3cd;
1853
+ border: 1px solid #f0e0a0;
1854
+ font-size: 11px;
1855
+ font-weight: 600;
1856
+ line-height: 1.5;
1857
+ color: #7a5d00;
1858
+ text-align: center;
1859
+ }