agent-reviews 0.5.2 → 0.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.
@@ -169,7 +169,7 @@ ${colors.bright}Options:${colors.reset}
169
169
  -v, --version Show version
170
170
 
171
171
  ${colors.bright}Watch Mode:${colors.reset}
172
- -w, --watch Poll for new comments periodically
172
+ -w, --watch Poll for new comments (exits on detection)
173
173
  -i, --interval Poll interval in seconds (default: 30)
174
174
  --timeout Exit after N seconds of inactivity (default: 600)
175
175
 
@@ -276,17 +276,48 @@ async function watchForComments(context, options) {
276
276
  const newComments = filtered.filter((c) => !seenIds.has(c.id));
277
277
 
278
278
  if (newComments.length > 0) {
279
- lastActivityTime = Date.now();
279
+ for (const comment of newComments) {
280
+ seenIds.add(comment.id);
281
+ }
280
282
 
281
283
  console.log(
282
284
  `\n${colors.green}=== NEW COMMENTS DETECTED [${formatTimestamp()}] ===${colors.reset}`
283
285
  );
284
286
  console.log(
285
- `${colors.bright}Found ${newComments.length} new comment${newComments.length === 1 ? "" : "s"}${colors.reset}\n`
287
+ `${colors.bright}Found ${newComments.length} new comment${newComments.length === 1 ? "" : "s"}${colors.reset}`
286
288
  );
287
289
 
288
- for (const comment of newComments) {
290
+ // Brief grace period to catch any stragglers from the same bot batch
291
+ console.log(
292
+ `${colors.dim}Waiting 5s for additional comments...${colors.reset}`
293
+ );
294
+ await sleep(5);
295
+
296
+ // Re-fetch to catch any comments posted during the grace period
297
+ const graceData = await fetchPRComments(
298
+ owner,
299
+ repo,
300
+ prNumber,
301
+ token,
302
+ proxyFetch
303
+ );
304
+ const graceProcessed = processComments(graceData);
305
+ const graceFiltered = filterComments(graceProcessed, options);
306
+ const lateComments = graceFiltered.filter((c) => !seenIds.has(c.id));
307
+
308
+ for (const comment of lateComments) {
289
309
  seenIds.add(comment.id);
310
+ newComments.push(comment);
311
+ }
312
+
313
+ if (lateComments.length > 0) {
314
+ console.log(
315
+ `${colors.bright}Caught ${lateComments.length} additional comment${lateComments.length === 1 ? "" : "s"}${colors.reset}`
316
+ );
317
+ }
318
+
319
+ console.log("");
320
+ for (const comment of newComments) {
290
321
  console.log(formatComment(comment));
291
322
  console.log("");
292
323
  }
@@ -294,7 +325,16 @@ async function watchForComments(context, options) {
294
325
  // JSON output for AI agent parsing
295
326
  console.log(`${colors.dim}--- JSON for processing ---${colors.reset}`);
296
327
  console.log(JSON.stringify(newComments, null, 2));
297
- console.log(`${colors.dim}--- end JSON ---${colors.reset}\n`);
328
+ console.log(`${colors.dim}--- end JSON ---${colors.reset}`);
329
+
330
+ // Exit immediately so the caller can process and restart if needed
331
+ console.log(
332
+ `\n${colors.green}=== WATCH: EXITING WITH NEW COMMENTS ===${colors.reset}`
333
+ );
334
+ console.log(
335
+ `${colors.dim}Restart watcher after processing to catch further comments.${colors.reset}`
336
+ );
337
+ return;
298
338
  } else {
299
339
  const inactiveSeconds = Math.round(
300
340
  (Date.now() - lastActivityTime) / 1000
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "agent-reviews",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "description": "CLI and Claude Code skill for managing GitHub PR review comments. List, filter, reply, and watch for bot findings.",
5
5
  "license": "MIT",
6
6
  "author": "Paul Bakaus",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/pbakaus/agent-reviews.git"
9
+ "url": "git+https://github.com/pbakaus/agent-reviews.git"
10
10
  },
11
11
  "keywords": [
12
12
  "github",
@@ -6,7 +6,7 @@ compatibility: Requires git and gh (GitHub CLI) installed. Designed for Claude C
6
6
  allowed-tools: Bash(node scripts/agent-reviews.js *) Bash(gh pr view *)
7
7
  metadata:
8
8
  author: pbakaus
9
- version: "0.5.2"
9
+ version: "0.6.0"
10
10
  homepage: https://github.com/pbakaus/agent-reviews
11
11
  ---
12
12
 
@@ -110,27 +110,29 @@ Run `scripts/agent-reviews.js --reply <comment_id> "Skipped per user request"`
110
110
 
111
111
  ---
112
112
 
113
- ## Phase 2: POLL FOR NEW COMMENTS (10-minute inactivity timeout)
113
+ ## Phase 2: POLL FOR NEW COMMENTS (loop until quiet)
114
114
 
115
- ### Step 6: Start Watcher
115
+ The watcher exits immediately when new comments are found (after a 5s grace period to catch batch posts). This means you run it in a loop: start watcher, process any comments it returns, restart watcher, repeat until the watcher times out with no new comments.
116
116
 
117
- Launch the watcher in the background. It polls every 30 seconds and exits after 10 minutes of inactivity (no new comments):
117
+ ### Step 6: Start Watcher Loop
118
118
 
119
- Run `scripts/agent-reviews.js --watch --bots-only` as a background task.
119
+ Repeat the following until the watcher exits with no new comments:
120
120
 
121
- **CRITICAL: DO NOT cancel the background task early. Let it complete its full cycle.**
121
+ **6a.** Launch the watcher in the background:
122
122
 
123
- ### Step 7: Wait for Results
123
+ Run `scripts/agent-reviews.js --watch --bots-only` as a background task.
124
124
 
125
- Use `TaskOutput` to wait for the watcher to complete (blocks up to 12 minutes).
125
+ **6b.** Use `TaskOutput` to wait for the watcher to complete (blocks up to 12 minutes).
126
126
 
127
- ### Step 8: Process New Comments (if any)
127
+ **6c.** Check the output:
128
128
 
129
- If the watcher found new comments:
130
- 1. Use `--detail <id>` to read each new comment's full detail
131
- 2. Process them exactly as in Phase 1, Steps 3-5
129
+ - **If new comments were found** (output contains `EXITING WITH NEW COMMENTS`):
130
+ 1. Use `--detail <id>` to read each new comment's full detail
131
+ 2. Process them exactly as in Phase 1, Steps 3-5 (evaluate, fix, commit, push, reply)
132
+ 3. **Go back to Step 6a** to restart the watcher
132
133
 
133
- If no new comments were found, move to the summary.
134
+ - **If no new comments** (output contains `WATCH COMPLETE`):
135
+ Stop looping and move to the Summary Report.
134
136
 
135
137
  ---
136
138
 
@@ -169,7 +169,7 @@ ${colors.bright}Options:${colors.reset}
169
169
  -v, --version Show version
170
170
 
171
171
  ${colors.bright}Watch Mode:${colors.reset}
172
- -w, --watch Poll for new comments periodically
172
+ -w, --watch Poll for new comments (exits on detection)
173
173
  -i, --interval Poll interval in seconds (default: 30)
174
174
  --timeout Exit after N seconds of inactivity (default: 600)
175
175
 
@@ -276,17 +276,48 @@ async function watchForComments(context, options) {
276
276
  const newComments = filtered.filter((c) => !seenIds.has(c.id));
277
277
 
278
278
  if (newComments.length > 0) {
279
- lastActivityTime = Date.now();
279
+ for (const comment of newComments) {
280
+ seenIds.add(comment.id);
281
+ }
280
282
 
281
283
  console.log(
282
284
  `\n${colors.green}=== NEW COMMENTS DETECTED [${formatTimestamp()}] ===${colors.reset}`
283
285
  );
284
286
  console.log(
285
- `${colors.bright}Found ${newComments.length} new comment${newComments.length === 1 ? "" : "s"}${colors.reset}\n`
287
+ `${colors.bright}Found ${newComments.length} new comment${newComments.length === 1 ? "" : "s"}${colors.reset}`
286
288
  );
287
289
 
288
- for (const comment of newComments) {
290
+ // Brief grace period to catch any stragglers from the same bot batch
291
+ console.log(
292
+ `${colors.dim}Waiting 5s for additional comments...${colors.reset}`
293
+ );
294
+ await sleep(5);
295
+
296
+ // Re-fetch to catch any comments posted during the grace period
297
+ const graceData = await fetchPRComments(
298
+ owner,
299
+ repo,
300
+ prNumber,
301
+ token,
302
+ proxyFetch
303
+ );
304
+ const graceProcessed = processComments(graceData);
305
+ const graceFiltered = filterComments(graceProcessed, options);
306
+ const lateComments = graceFiltered.filter((c) => !seenIds.has(c.id));
307
+
308
+ for (const comment of lateComments) {
289
309
  seenIds.add(comment.id);
310
+ newComments.push(comment);
311
+ }
312
+
313
+ if (lateComments.length > 0) {
314
+ console.log(
315
+ `${colors.bright}Caught ${lateComments.length} additional comment${lateComments.length === 1 ? "" : "s"}${colors.reset}`
316
+ );
317
+ }
318
+
319
+ console.log("");
320
+ for (const comment of newComments) {
290
321
  console.log(formatComment(comment));
291
322
  console.log("");
292
323
  }
@@ -294,7 +325,16 @@ async function watchForComments(context, options) {
294
325
  // JSON output for AI agent parsing
295
326
  console.log(`${colors.dim}--- JSON for processing ---${colors.reset}`);
296
327
  console.log(JSON.stringify(newComments, null, 2));
297
- console.log(`${colors.dim}--- end JSON ---${colors.reset}\n`);
328
+ console.log(`${colors.dim}--- end JSON ---${colors.reset}`);
329
+
330
+ // Exit immediately so the caller can process and restart if needed
331
+ console.log(
332
+ `\n${colors.green}=== WATCH: EXITING WITH NEW COMMENTS ===${colors.reset}`
333
+ );
334
+ console.log(
335
+ `${colors.dim}Restart watcher after processing to catch further comments.${colors.reset}`
336
+ );
337
+ return;
298
338
  } else {
299
339
  const inactiveSeconds = Math.round(
300
340
  (Date.now() - lastActivityTime) / 1000
@@ -328,7 +368,7 @@ async function main() {
328
368
  const options = parseArgs();
329
369
 
330
370
  if (options.version) {
331
- console.log("0.5.2");
371
+ console.log("0.6.0");
332
372
  process.exit(0);
333
373
  }
334
374