@warpmetrics/review 0.1.6 → 0.1.8

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/review.js +34 -12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warpmetrics/review",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "type": "module",
5
5
  "description": "AI code reviewer that learns your codebase. Powered by WarpMetrics.",
6
6
  "bin": {
package/src/review.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { readFileSync, existsSync } from 'fs';
2
2
  import { minimatch } from 'minimatch';
3
- import { run, group, call, outcome, flush } from '@warpmetrics/warp';
3
+ import { run, group, call, outcome, act, flush } from '@warpmetrics/warp';
4
4
  import { createClient } from './llm.js';
5
5
  import { findRun } from './warpmetrics.js';
6
6
  import {
@@ -59,11 +59,13 @@ async function llmWithRetry(anthropic, params, maxRetries = 3) {
59
59
  }
60
60
  }
61
61
 
62
- function buildSummary(commentsPosted, filesReviewed, runId, wmAvailable, { totalFiltered = 0, truncatedCount = 0 } = {}) {
62
+ function buildSummary(commentsPosted, filesReviewed, runId, wmAvailable, { totalFiltered = 0, truncatedCount = 0, actId } = {}) {
63
63
  const analyticsLink = wmAvailable && runId
64
64
  ? `\n\n[View review analytics \u2192](https://app.warpmetrics.com/runs/${runId})`
65
65
  : '';
66
66
 
67
+ const actTag = actId ? `\n\n<!-- wm:act:${actId} -->` : '';
68
+
67
69
  const notes = [];
68
70
  if (totalFiltered > filesReviewed) {
69
71
  notes.push(`Reviewed ${filesReviewed}/${totalFiltered} files. Increase \`maxFilesPerReview\` in \`.warp-review/config.json\` to review more.`);
@@ -76,10 +78,10 @@ function buildSummary(commentsPosted, filesReviewed, runId, wmAvailable, { total
76
78
  if (commentsPosted.length > 0) {
77
79
  const fileCount = new Set(commentsPosted.map(c => c.file)).size;
78
80
  const firstComment = commentsPosted[0].body.slice(0, 100);
79
- return `**warp-review** found ${commentsPosted.length} issue(s) in ${fileCount} file(s).${notesText}\n\nMost critical: ${firstComment}${analyticsLink}\n\n<sub>Powered by [WarpMetrics](https://warpmetrics.com) \u00b7 Edit \`.warp-review/skills.md\` to customize</sub>`;
81
+ return `**warp-review** found ${commentsPosted.length} issue(s) in ${fileCount} file(s).${notesText}\n\nMost critical: ${firstComment}${analyticsLink}${actTag}\n\n<sub>Powered by [WarpMetrics](https://warpmetrics.com) \u00b7 Edit \`.warp-review/skills.md\` to customize</sub>`;
80
82
  }
81
83
 
82
- return `**warp-review** reviewed ${filesReviewed} file(s) \u2014 no issues found.${notesText}${analyticsLink}\n\n<sub>Powered by [WarpMetrics](https://warpmetrics.com)</sub>`;
84
+ return `**warp-review** reviewed ${filesReviewed} file(s) \u2014 no issues found.${notesText}${analyticsLink}${actTag}\n\n<sub>Powered by [WarpMetrics](https://warpmetrics.com)</sub>`;
83
85
  }
84
86
 
85
87
  export async function review(ctx) {
@@ -130,12 +132,18 @@ export async function review(ctx) {
130
132
  }
131
133
  runRef = runDetail.id;
132
134
  } else {
133
- // Create new run
135
+ // Create new run (link as follow-up if warp-coder act ID found in PR body)
134
136
  if (wmAvailable) {
135
- runRef = run('warp-review', {
137
+ const actMatch = body.match(/<!-- wm:act:(wm_act_\w+) -->/);
138
+ const runOpts = {
136
139
  name: `${fullRepo}#${pr}`, repo: fullRepo, pr, pr_url: htmlUrl,
137
140
  pr_author: prAuthor, additions, deletions, changed_files: changedFiles, base_branch: baseBranch,
138
- });
141
+ };
142
+ if (actMatch) {
143
+ runRef = run(actMatch[1], 'warp-review', runOpts);
144
+ } else {
145
+ runRef = run('warp-review', runOpts);
146
+ }
139
147
  }
140
148
  }
141
149
 
@@ -249,16 +257,30 @@ export async function review(ctx) {
249
257
 
250
258
  // Derive runId for summary link
251
259
  const runId = typeof runRef === 'string' ? runRef : runRef?.id;
260
+ const hasIssues = validComments.length > 0;
261
+
262
+ // 13. Log comment groups + outcome + act to WM (before posting review, so we know the act ID)
263
+ let reviewActId = null;
264
+ let commentIds = [];
252
265
 
253
- // 13. Post review
266
+ if (round) {
267
+ // Outcome + act on the round (for the chain)
268
+ const outcomeName = hasIssues ? 'Changes Requested' : 'Approved';
269
+ const oc = outcome(round, outcomeName, { comments: validComments.length });
270
+ if (oc) {
271
+ const actRef = act(oc, hasIssues ? 'revise' : 'merge', { pr, repo: fullRepo });
272
+ if (actRef) reviewActId = actRef.id;
273
+ }
274
+ }
275
+
276
+ // 14. Post review (with act ID embedded for warp-coder)
254
277
  const summaryBody = buildSummary(validComments, filesToReview.length, runId, wmAvailable, {
255
- totalFiltered: filtered.length, truncatedCount,
278
+ totalFiltered: filtered.length, truncatedCount, actId: reviewActId,
256
279
  });
257
280
  const reviewResult = await postReview(owner, repo, pr, headSha, summaryBody, validComments);
258
281
  const reviewId = reviewResult.id;
259
282
 
260
- // 14. Get comment IDs (matched by array index order)
261
- let commentIds = [];
283
+ // 15. Get comment IDs (matched by array index order)
262
284
  if (validComments.length > 0) {
263
285
  try {
264
286
  commentIds = await getReviewCommentIds(owner, repo, pr, reviewId);
@@ -267,7 +289,7 @@ export async function review(ctx) {
267
289
  }
268
290
  }
269
291
 
270
- // 15. Log comment groups + summary to WM
292
+ // 16. Log comment groups + summary to WM
271
293
  if (round) {
272
294
  for (let i = 0; i < validComments.length; i++) {
273
295
  const c = validComments[i];