patchrelay 0.35.12 → 0.35.13
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/dist/build-info.json +3 -3
- package/dist/cli/args.js +19 -0
- package/dist/cli/commands/issues.js +17 -1
- package/dist/cli/data.js +50 -0
- package/dist/cli/formatters/text.js +45 -0
- package/dist/cli/help.js +12 -0
- package/dist/cli/index.js +3 -10
- package/dist/cli/watch/App.js +22 -2
- package/dist/cli/watch/HelpBar.js +1 -1
- package/dist/cli/watch/IssueDetailView.js +63 -161
- package/dist/cli/watch/IssueRow.js +11 -0
- package/dist/cli/watch/StatusBar.js +2 -1
- package/dist/cli/watch/detail-rows.js +589 -0
- package/dist/cli/watch/render-rich-text.js +226 -0
- package/dist/cli/watch/watch-state.js +111 -6
- package/dist/github-webhook-handler.js +176 -2
- package/dist/github-webhooks.js +2 -0
- package/dist/linear-session-sync.js +1 -1
- package/dist/run-orchestrator.js +75 -7
- package/dist/status-note.js +1 -1
- package/package.json +3 -2
package/dist/run-orchestrator.js
CHANGED
|
@@ -151,6 +151,67 @@ function appendLinearContext(lines, context) {
|
|
|
151
151
|
lines.push("## Human Follow-up Comment", "", userComment, "");
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
+
function readReviewFixComments(context) {
|
|
155
|
+
const raw = context?.reviewComments;
|
|
156
|
+
if (!Array.isArray(raw)) {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
const comments = [];
|
|
160
|
+
for (const entry of raw) {
|
|
161
|
+
if (!entry || typeof entry !== "object")
|
|
162
|
+
continue;
|
|
163
|
+
const record = entry;
|
|
164
|
+
const body = typeof record.body === "string" ? record.body.trim() : "";
|
|
165
|
+
if (!body)
|
|
166
|
+
continue;
|
|
167
|
+
comments.push({
|
|
168
|
+
body,
|
|
169
|
+
...(typeof record.path === "string" ? { path: record.path } : {}),
|
|
170
|
+
...(typeof record.line === "number" ? { line: record.line } : {}),
|
|
171
|
+
...(typeof record.side === "string" ? { side: record.side } : {}),
|
|
172
|
+
...(typeof record.startLine === "number" ? { startLine: record.startLine } : {}),
|
|
173
|
+
...(typeof record.startSide === "string" ? { startSide: record.startSide } : {}),
|
|
174
|
+
...(typeof record.url === "string" ? { url: record.url } : {}),
|
|
175
|
+
...(typeof record.authorLogin === "string" ? { authorLogin: record.authorLogin } : {}),
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return comments;
|
|
179
|
+
}
|
|
180
|
+
function appendStructuredReviewContext(lines, context) {
|
|
181
|
+
const reviewId = typeof context?.reviewId === "number" ? context.reviewId : undefined;
|
|
182
|
+
const reviewCommitId = typeof context?.reviewCommitId === "string" ? context.reviewCommitId : undefined;
|
|
183
|
+
const reviewUrl = typeof context?.reviewUrl === "string" ? context.reviewUrl : undefined;
|
|
184
|
+
const reviewComments = readReviewFixComments(context);
|
|
185
|
+
if (!reviewId && !reviewCommitId && !reviewUrl && reviewComments.length === 0) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
lines.push("## Structured Review Context", "");
|
|
189
|
+
if (reviewId !== undefined) {
|
|
190
|
+
lines.push(`Review ID: ${reviewId}`);
|
|
191
|
+
}
|
|
192
|
+
if (reviewCommitId) {
|
|
193
|
+
lines.push(`Reviewed commit: ${reviewCommitId}`);
|
|
194
|
+
}
|
|
195
|
+
if (reviewUrl) {
|
|
196
|
+
lines.push(`Review URL: ${reviewUrl}`);
|
|
197
|
+
}
|
|
198
|
+
if (reviewComments.length === 0) {
|
|
199
|
+
lines.push("No inline review comments were captured for this review.", "");
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
lines.push(`Inline review comments captured: ${reviewComments.length}`, "Resolve each comment below or verify it is already fixed on the current head before you stop.", "");
|
|
203
|
+
for (const comment of reviewComments) {
|
|
204
|
+
const location = comment.path
|
|
205
|
+
? `${comment.path}${comment.line !== undefined ? `:${comment.line}` : ""}${comment.side ? ` (${comment.side})` : ""}`
|
|
206
|
+
: "general";
|
|
207
|
+
lines.push(`- ${location}`);
|
|
208
|
+
lines.push(comment.body);
|
|
209
|
+
if (comment.url) {
|
|
210
|
+
lines.push(` URL: ${comment.url}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
lines.push("");
|
|
214
|
+
}
|
|
154
215
|
function collectFollowUpInputs(context) {
|
|
155
216
|
const followUps = Array.isArray(context?.followUps) ? context.followUps : [];
|
|
156
217
|
const inputs = [];
|
|
@@ -330,7 +391,8 @@ export function buildInitialRunPrompt(issue, runType, repoPath, context) {
|
|
|
330
391
|
break;
|
|
331
392
|
}
|
|
332
393
|
case "review_fix":
|
|
333
|
-
lines.push("## Review Changes Requested", "", "A reviewer has requested changes on your PR. Address the feedback and push.", context?.reviewerName ? `Reviewer: ${String(context.reviewerName)}` : "", context?.reviewBody ? `\n## Review comment\n\n${String(context.reviewBody)}` : "", "", "Steps:", "1.
|
|
394
|
+
lines.push("## Review Changes Requested", "", "A reviewer has requested changes on your PR. Address the feedback and push.", context?.reviewerName ? `Reviewer: ${String(context.reviewerName)}` : "", context?.reviewBody ? `\n## Review comment\n\n${String(context.reviewBody)}` : "", "", "Steps:", "1. Start with the structured review context below. Treat the inline review comments as the primary repair checklist for this turn.", "2. Check the current diff (`git diff origin/main`) — a prior rebase may have already resolved some concerns (e.g., scope-bundling from stale commits).", "3. For each review point: if already resolved on the current head, note why. If not, fix it.", "4. If the structured review context looks incomplete, inspect the latest GitHub review threads directly before deciding you are done.", "5. Run verification, commit and push.", "6. If you believe all concerns are resolved, request a re-review: `gh pr edit <PR#> --add-reviewer <reviewer>`.", " Do NOT just post a comment saying \"resolved\" — the reviewer must re-review to dismiss the CHANGES_REQUESTED state.", "");
|
|
395
|
+
appendStructuredReviewContext(lines, context);
|
|
334
396
|
break;
|
|
335
397
|
case "queue_repair":
|
|
336
398
|
appendQueueRepairContext(lines, context);
|
|
@@ -364,7 +426,8 @@ export function buildFollowUpRunPrompt(issue, runType, repoPath, context) {
|
|
|
364
426
|
break;
|
|
365
427
|
}
|
|
366
428
|
case "review_fix":
|
|
367
|
-
lines.push("## Review Changes Requested", "", "A reviewer has requested changes on your PR. Address the feedback and push.", context?.reviewerName ? `Reviewer: ${String(context.reviewerName)}` : "", context?.reviewBody ? `\n## Review comment\n\n${String(context.reviewBody)}` : "", "", "Steps:", "1.
|
|
429
|
+
lines.push("## Review Changes Requested", "", "A reviewer has requested changes on your PR. Address the feedback and push.", context?.reviewerName ? `Reviewer: ${String(context.reviewerName)}` : "", context?.reviewBody ? `\n## Review comment\n\n${String(context.reviewBody)}` : "", "", "Steps:", "1. Start with the structured review context below. Treat the inline review comments as the primary repair checklist for this turn.", "2. Check the current diff (`git diff origin/main`) — a prior rebase may have already resolved some concerns (e.g., scope-bundling from stale commits).", "3. For each review point: if already resolved on the current head, note why. If not, fix it.", "4. If the structured review context looks incomplete, inspect the latest GitHub review threads directly before deciding you are done.", "5. Run verification, commit and push.", "6. If you believe all concerns are resolved, request a re-review: `gh pr edit <PR#> --add-reviewer <reviewer>`.", " Do NOT just post a comment saying \"resolved\" — the reviewer must re-review to dismiss the CHANGES_REQUESTED state.", "");
|
|
430
|
+
appendStructuredReviewContext(lines, context);
|
|
368
431
|
break;
|
|
369
432
|
case "queue_repair":
|
|
370
433
|
appendQueueRepairContext(lines, context);
|
|
@@ -401,6 +464,9 @@ function shouldCompactThread(issue, threadGeneration, context) {
|
|
|
401
464
|
&& (threadGeneration ?? 0) >= MAX_THREAD_GENERATION_BEFORE_COMPACTION
|
|
402
465
|
&& followUpCount >= MAX_FOLLOW_UPS_BEFORE_COMPACTION;
|
|
403
466
|
}
|
|
467
|
+
export function shouldReuseIssueThread(params) {
|
|
468
|
+
return Boolean(params.existingThreadId) && !params.compactThread && params.resumeThread;
|
|
469
|
+
}
|
|
404
470
|
function isBranchUpkeepRequired(context) {
|
|
405
471
|
return context?.branchUpkeepRequired === true;
|
|
406
472
|
}
|
|
@@ -663,15 +729,17 @@ export class RunOrchestrator {
|
|
|
663
729
|
throw new Error(`prepare-worktree hook failed (exit ${prepareResult.exitCode}): ${prepareResult.stderr?.slice(0, 500) ?? ""}`);
|
|
664
730
|
}
|
|
665
731
|
this.assertLaunchLease(run, "before starting the Codex turn");
|
|
666
|
-
// Reuse the existing thread
|
|
667
|
-
//
|
|
668
|
-
//
|
|
669
|
-
//
|
|
732
|
+
// Reuse the existing thread only for additive follow-ups that explicitly
|
|
733
|
+
// request continuity. Fresh review-fix runs now start a new thread so the
|
|
734
|
+
// model is not anchored to the implementation conversation that produced
|
|
735
|
+
// the rejected patch. If the thread has accumulated many resumptions and
|
|
736
|
+
// batched follow-ups, compact by starting a fresh main thread while
|
|
737
|
+
// keeping a parent link.
|
|
670
738
|
const compactThread = shouldCompactThread(issue, issueSession?.threadGeneration, effectiveContext);
|
|
671
739
|
if (compactThread && issue.threadId) {
|
|
672
740
|
parentThreadId = issue.threadId;
|
|
673
741
|
}
|
|
674
|
-
if (issue.threadId
|
|
742
|
+
if (shouldReuseIssueThread({ existingThreadId: issue.threadId, compactThread, resumeThread })) {
|
|
675
743
|
threadId = issue.threadId;
|
|
676
744
|
}
|
|
677
745
|
else {
|
package/dist/status-note.js
CHANGED
|
@@ -38,7 +38,7 @@ export function deriveIssueStatusNote(params) {
|
|
|
38
38
|
break;
|
|
39
39
|
case "failed":
|
|
40
40
|
case "escalated":
|
|
41
|
-
note =
|
|
41
|
+
note = latestEventNote ?? failureSummary ?? latestRunNote ?? sessionSummary;
|
|
42
42
|
break;
|
|
43
43
|
case "repairing_ci":
|
|
44
44
|
case "repairing_queue":
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "patchrelay",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.13",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"node": ">=24.0.0"
|
|
26
26
|
},
|
|
27
27
|
"workspaces": [
|
|
28
|
-
"packages/merge-steward"
|
|
28
|
+
"packages/merge-steward",
|
|
29
|
+
"packages/review-quill"
|
|
29
30
|
],
|
|
30
31
|
"scripts": {
|
|
31
32
|
"dev": "node --watch --experimental-transform-types src/index.ts",
|