patchrelay 0.35.13 → 0.35.14
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
CHANGED
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import { summarizeIssueStatusNote } from "./issue-status-note.js";
|
|
4
4
|
import { relativeTime, truncate } from "./format-utils.js";
|
|
5
|
+
import { hasDisplayPrBlocker, isRereviewNeeded, prChecksFact } from "./pr-status.js";
|
|
5
6
|
// ─── State display ──────────────────────────────────────────────
|
|
6
7
|
const TERMINAL_STATES = new Set(["done", "failed", "escalated"]);
|
|
7
8
|
function needsOperatorIntervention(issue) {
|
|
@@ -14,10 +15,10 @@ function effectiveState(issue) {
|
|
|
14
15
|
return "failed";
|
|
15
16
|
if (issue.blockedByCount > 0 && !issue.activeRunType)
|
|
16
17
|
return "blocked";
|
|
17
|
-
if (issue.readyForExecution && !issue.activeRunType)
|
|
18
|
-
return "ready";
|
|
19
18
|
if (issue.sessionState === "waiting_input")
|
|
20
19
|
return "awaiting_input";
|
|
20
|
+
if (issue.readyForExecution && !issue.activeRunType && !hasDisplayPrBlocker(issue))
|
|
21
|
+
return "ready";
|
|
21
22
|
return issue.factoryState;
|
|
22
23
|
}
|
|
23
24
|
function sessionDisplay(issue) {
|
|
@@ -61,9 +62,7 @@ function stageLabel(issue) {
|
|
|
61
62
|
// ─── Context facts (what matters right now) ─────────────────────
|
|
62
63
|
function buildFacts(issue, selected) {
|
|
63
64
|
const facts = [];
|
|
64
|
-
const rereviewNeeded = issue
|
|
65
|
-
&& (issue.prCheckStatus === "passed" || issue.prCheckStatus === "success")
|
|
66
|
-
&& !issue.activeRunType;
|
|
65
|
+
const rereviewNeeded = isRereviewNeeded(issue);
|
|
67
66
|
// PR number
|
|
68
67
|
if (issue.prNumber !== undefined) {
|
|
69
68
|
facts.push({ text: `PR #${issue.prNumber}` });
|
|
@@ -94,23 +93,9 @@ function buildFacts(issue, selected) {
|
|
|
94
93
|
facts.push({ text: "awaiting review", color: "yellow" });
|
|
95
94
|
}
|
|
96
95
|
// Check status — compact
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
else if (issue.prCheckStatus === "failed" || issue.prCheckStatus === "failure") {
|
|
101
|
-
const failedNames = issue.prChecksSummary?.failedNames ?? [];
|
|
102
|
-
const checkInfo = issue.latestFailureCheckName
|
|
103
|
-
?? (failedNames.length > 0 ? failedNames.slice(0, 2).join(", ") : "checks");
|
|
104
|
-
facts.push({ text: `${checkInfo} failed`, color: "red" });
|
|
105
|
-
}
|
|
106
|
-
else if (issue.prCheckStatus === "pending" || issue.prCheckStatus === "in_progress") {
|
|
107
|
-
const summary = issue.prChecksSummary;
|
|
108
|
-
if (summary && summary.total > 0) {
|
|
109
|
-
facts.push({ text: `checks ${summary.completed}/${summary.total}`, color: "yellow" });
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
facts.push({ text: "checks running", color: "yellow" });
|
|
113
|
-
}
|
|
96
|
+
const checksFact = prChecksFact(issue);
|
|
97
|
+
if (checksFact) {
|
|
98
|
+
facts.push(checksFact);
|
|
114
99
|
}
|
|
115
100
|
// Blocker
|
|
116
101
|
if (issue.blockedByCount > 0) {
|
|
@@ -120,9 +105,7 @@ function buildFacts(issue, selected) {
|
|
|
120
105
|
}
|
|
121
106
|
// ─── What's blocking progress ───────────────────────────────────
|
|
122
107
|
function blockerText(issue) {
|
|
123
|
-
const rereviewNeeded = issue
|
|
124
|
-
&& (issue.prCheckStatus === "passed" || issue.prCheckStatus === "success")
|
|
125
|
-
&& !issue.activeRunType;
|
|
108
|
+
const rereviewNeeded = isRereviewNeeded(issue);
|
|
126
109
|
if (issue.sessionState === "waiting_input")
|
|
127
110
|
return issue.waitingReason ?? "Waiting for input";
|
|
128
111
|
if (needsOperatorIntervention(issue))
|
|
@@ -137,9 +120,12 @@ function blockerText(issue) {
|
|
|
137
120
|
const check = issue.latestFailureCheckName ?? "CI";
|
|
138
121
|
return `Repairing ${check}`;
|
|
139
122
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return
|
|
123
|
+
const checksFact = prChecksFact(issue);
|
|
124
|
+
if (checksFact?.color === "red") {
|
|
125
|
+
return checksFact.text;
|
|
126
|
+
}
|
|
127
|
+
if (checksFact?.color === "yellow" && checksFact.text.startsWith("checks ")) {
|
|
128
|
+
return `${checksFact.text} still running`;
|
|
143
129
|
}
|
|
144
130
|
if (rereviewNeeded)
|
|
145
131
|
return "Awaiting re-review after requested changes";
|
|
@@ -3,6 +3,7 @@ import { buildTimelineRows } from "./timeline-presentation.js";
|
|
|
3
3
|
import { planStepColor, planStepSymbol } from "./plan-helpers.js";
|
|
4
4
|
import { progressBar } from "./format-utils.js";
|
|
5
5
|
import { describePatchRelayFreshness } from "./freshness.js";
|
|
6
|
+
import { hasDisplayPrBlocker, isRereviewNeeded, prChecksFact } from "./pr-status.js";
|
|
6
7
|
import { renderRichTextLines, renderTextLines } from "./render-rich-text.js";
|
|
7
8
|
const SESSION_DISPLAY = {
|
|
8
9
|
idle: { label: "idle", color: "blueBright" },
|
|
@@ -117,7 +118,7 @@ function buildHeaderLines(input, width) {
|
|
|
117
118
|
}));
|
|
118
119
|
}
|
|
119
120
|
if (issue.statusNote && issue.statusNote !== blocker) {
|
|
120
|
-
lines.push(...
|
|
121
|
+
lines.push(...renderRichTextLines(issue.statusNote, {
|
|
121
122
|
key: "detail-note",
|
|
122
123
|
width,
|
|
123
124
|
style: { dimColor: true },
|
|
@@ -396,9 +397,7 @@ function renderSideTripLines(trip, runOffset, width) {
|
|
|
396
397
|
}
|
|
397
398
|
function buildFacts(issue, issueContext) {
|
|
398
399
|
const facts = [];
|
|
399
|
-
const rereviewNeeded = issue
|
|
400
|
-
&& (issue.prCheckStatus === "passed" || issue.prCheckStatus === "success")
|
|
401
|
-
&& !issue.activeRunType;
|
|
400
|
+
const rereviewNeeded = isRereviewNeeded(issue);
|
|
402
401
|
if (issue.prNumber !== undefined)
|
|
403
402
|
facts.push(`PR #${issue.prNumber}`);
|
|
404
403
|
if (issue.prReviewState === "approved")
|
|
@@ -409,14 +408,12 @@ function buildFacts(issue, issueContext) {
|
|
|
409
408
|
facts.push("changes requested");
|
|
410
409
|
if (issue.waitingReason && issue.sessionState === "waiting_input")
|
|
411
410
|
facts.push(issue.waitingReason);
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
else if (issue.prChecksSummary?.total) {
|
|
419
|
-
facts.push(`checks ${issue.prChecksSummary.completed}/${issue.prChecksSummary.total}`);
|
|
411
|
+
const checks = prChecksFact({
|
|
412
|
+
...issue,
|
|
413
|
+
latestFailureCheckName: issueContext?.latestFailureCheckName ?? issue.latestFailureCheckName,
|
|
414
|
+
});
|
|
415
|
+
if (checks) {
|
|
416
|
+
facts.push(checks.text);
|
|
420
417
|
}
|
|
421
418
|
return facts;
|
|
422
419
|
}
|
|
@@ -503,16 +500,14 @@ function effectiveState(issue) {
|
|
|
503
500
|
return "failed";
|
|
504
501
|
if (issue.blockedByCount > 0 && !issue.activeRunType)
|
|
505
502
|
return "blocked";
|
|
506
|
-
if (issue.readyForExecution && !issue.activeRunType)
|
|
507
|
-
return "ready";
|
|
508
503
|
if (issue.sessionState === "waiting_input")
|
|
509
504
|
return "awaiting_input";
|
|
505
|
+
if (issue.readyForExecution && !issue.activeRunType && !hasDisplayPrBlocker(issue))
|
|
506
|
+
return "ready";
|
|
510
507
|
return issue.factoryState;
|
|
511
508
|
}
|
|
512
509
|
function blockerText(issue, issueContext) {
|
|
513
|
-
const rereviewNeeded = issue
|
|
514
|
-
&& (issue.prCheckStatus === "passed" || issue.prCheckStatus === "success")
|
|
515
|
-
&& !issue.activeRunType;
|
|
510
|
+
const rereviewNeeded = isRereviewNeeded(issue);
|
|
516
511
|
if (issue.sessionState === "waiting_input")
|
|
517
512
|
return issue.waitingReason ?? "Waiting for input";
|
|
518
513
|
if (issue.sessionState === "failed" || issue.factoryState === "failed" || issue.factoryState === "escalated") {
|
|
@@ -528,9 +523,15 @@ function blockerText(issue, issueContext) {
|
|
|
528
523
|
const check = issueContext?.latestFailureCheckName ?? issue.latestFailureCheckName ?? "CI";
|
|
529
524
|
return `Repairing ${check}`;
|
|
530
525
|
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
526
|
+
const checks = prChecksFact({
|
|
527
|
+
...issue,
|
|
528
|
+
latestFailureCheckName: issueContext?.latestFailureCheckName ?? issue.latestFailureCheckName,
|
|
529
|
+
});
|
|
530
|
+
if (checks?.color === "red") {
|
|
531
|
+
return checks.text;
|
|
532
|
+
}
|
|
533
|
+
if (checks?.color === "yellow" && checks.text.startsWith("checks ")) {
|
|
534
|
+
return `${checks.text} still running`;
|
|
534
535
|
}
|
|
535
536
|
if (rereviewNeeded)
|
|
536
537
|
return "Awaiting re-review after requested changes";
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
function isPassingCheckStatus(status) {
|
|
2
|
+
return status === "passed" || status === "success";
|
|
3
|
+
}
|
|
4
|
+
function isFailingCheckStatus(status) {
|
|
5
|
+
return status === "failed" || status === "failure";
|
|
6
|
+
}
|
|
7
|
+
function isPendingCheckStatus(status) {
|
|
8
|
+
return status === "pending" || status === "in_progress";
|
|
9
|
+
}
|
|
10
|
+
export function hasPendingPrChecks(issue) {
|
|
11
|
+
const summary = issue.prChecksSummary;
|
|
12
|
+
if (summary?.total) {
|
|
13
|
+
return summary.pending > 0 || summary.completed < summary.total;
|
|
14
|
+
}
|
|
15
|
+
return isPendingCheckStatus(issue.prCheckStatus);
|
|
16
|
+
}
|
|
17
|
+
export function hasFailedPrChecks(issue) {
|
|
18
|
+
const summary = issue.prChecksSummary;
|
|
19
|
+
if (summary?.total) {
|
|
20
|
+
return summary.failed > 0 || summary.overall === "failure";
|
|
21
|
+
}
|
|
22
|
+
return isFailingCheckStatus(issue.prCheckStatus);
|
|
23
|
+
}
|
|
24
|
+
export function arePrChecksCompleteAndGreen(issue) {
|
|
25
|
+
const summary = issue.prChecksSummary;
|
|
26
|
+
if (summary?.total) {
|
|
27
|
+
return summary.pending === 0 && summary.failed === 0;
|
|
28
|
+
}
|
|
29
|
+
return isPassingCheckStatus(issue.prCheckStatus);
|
|
30
|
+
}
|
|
31
|
+
export function isRereviewNeeded(issue) {
|
|
32
|
+
return issue.prReviewState === "changes_requested"
|
|
33
|
+
&& arePrChecksCompleteAndGreen(issue)
|
|
34
|
+
&& !issue.activeRunType;
|
|
35
|
+
}
|
|
36
|
+
export function prChecksFact(issue) {
|
|
37
|
+
const summary = issue.prChecksSummary;
|
|
38
|
+
if (hasFailedPrChecks(issue)) {
|
|
39
|
+
const failedNames = summary?.failedNames ?? [];
|
|
40
|
+
const checkInfo = issue.latestFailureCheckName
|
|
41
|
+
?? (failedNames.length > 0 ? failedNames.slice(0, 2).join(", ") : "checks");
|
|
42
|
+
return { text: `${checkInfo} failed`, color: "red" };
|
|
43
|
+
}
|
|
44
|
+
if (summary?.total) {
|
|
45
|
+
if (summary.pending > 0 || summary.completed < summary.total) {
|
|
46
|
+
return { text: `checks ${summary.completed}/${summary.total}`, color: "yellow" };
|
|
47
|
+
}
|
|
48
|
+
if (summary.failed === 0) {
|
|
49
|
+
return { text: "checks passed", color: "green" };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (isPassingCheckStatus(issue.prCheckStatus)) {
|
|
53
|
+
return { text: "checks passed", color: "green" };
|
|
54
|
+
}
|
|
55
|
+
if (isPendingCheckStatus(issue.prCheckStatus)) {
|
|
56
|
+
return { text: "checks running", color: "yellow" };
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
export function hasDisplayPrBlocker(issue) {
|
|
61
|
+
if (issue.prNumber === undefined || issue.activeRunType) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
if (hasPendingPrChecks(issue) || hasFailedPrChecks(issue)) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
if (issue.prReviewState === "changes_requested" && !isRereviewNeeded(issue)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
if (!issue.prReviewState && issue.factoryState === "pr_open") {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
@@ -114,7 +114,6 @@ function parseInlineMarkdown(text, style) {
|
|
|
114
114
|
}
|
|
115
115
|
if (match[1] && match[2]) {
|
|
116
116
|
segments.push({ text: match[1], color: "cyan", bold: true });
|
|
117
|
-
segments.push({ text: ` (${match[2]})`, dimColor: true });
|
|
118
117
|
}
|
|
119
118
|
else if (match[3]) {
|
|
120
119
|
segments.push({ text: match[3], color: "yellow", bold: true });
|