@humanbased/crosscheck 0.14.0 → 0.15.0-beta.103
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 +147 -4
- package/crosscheck.config.example.yml +3 -1
- package/dist/__tests__/backtrace.test.js +1 -1
- package/dist/__tests__/backtrace.test.js.map +1 -1
- package/dist/__tests__/durations.test.js +5 -1
- package/dist/__tests__/durations.test.js.map +1 -1
- package/dist/__tests__/fix.test.js +48 -1
- package/dist/__tests__/fix.test.js.map +1 -1
- package/dist/__tests__/kickass.test.js +362 -69
- package/dist/__tests__/kickass.test.js.map +1 -1
- package/dist/__tests__/optimize.test.js +3 -3
- package/dist/__tests__/optimize.test.js.map +1 -1
- package/dist/__tests__/pr-picker.test.js +8 -7
- package/dist/__tests__/pr-picker.test.js.map +1 -1
- package/dist/__tests__/pr-status.test.js +41 -20
- package/dist/__tests__/pr-status.test.js.map +1 -1
- package/dist/__tests__/pr-workflow-state.test.d.ts +2 -0
- package/dist/__tests__/pr-workflow-state.test.d.ts.map +1 -0
- package/dist/__tests__/pr-workflow-state.test.js +184 -0
- package/dist/__tests__/pr-workflow-state.test.js.map +1 -0
- package/dist/__tests__/review-models.test.js +1 -0
- package/dist/__tests__/review-models.test.js.map +1 -1
- package/dist/__tests__/run.test.d.ts +2 -0
- package/dist/__tests__/run.test.d.ts.map +1 -0
- package/dist/__tests__/run.test.js +81 -0
- package/dist/__tests__/run.test.js.map +1 -0
- package/dist/__tests__/runner.test.js +117 -1
- package/dist/__tests__/runner.test.js.map +1 -1
- package/dist/__tests__/smart-switch.test.js +1 -1
- package/dist/__tests__/smart-switch.test.js.map +1 -1
- package/dist/__tests__/tier-timeouts.test.d.ts +2 -0
- package/dist/__tests__/tier-timeouts.test.d.ts.map +1 -0
- package/dist/__tests__/tier-timeouts.test.js +23 -0
- package/dist/__tests__/tier-timeouts.test.js.map +1 -0
- package/dist/__tests__/webhook.test.d.ts +2 -0
- package/dist/__tests__/webhook.test.d.ts.map +1 -0
- package/dist/__tests__/webhook.test.js +197 -0
- package/dist/__tests__/webhook.test.js.map +1 -0
- package/dist/cli.js +38 -5
- package/dist/cli.js.map +1 -1
- package/dist/commands/detect-step.d.ts +5 -0
- package/dist/commands/detect-step.d.ts.map +1 -0
- package/dist/commands/detect-step.js +124 -0
- package/dist/commands/detect-step.js.map +1 -0
- package/dist/commands/kickass.d.ts +18 -10
- package/dist/commands/kickass.d.ts.map +1 -1
- package/dist/commands/kickass.js +234 -63
- package/dist/commands/kickass.js.map +1 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +14 -5
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/run.d.ts +16 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +347 -44
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +41 -3
- package/dist/commands/serve.js.map +1 -1
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +200 -6
- package/dist/commands/watch.js.map +1 -1
- package/dist/config/schema.d.ts +52 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +24 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/github/client.d.ts +40 -1
- package/dist/github/client.d.ts.map +1 -1
- package/dist/github/client.js +69 -9
- package/dist/github/client.js.map +1 -1
- package/dist/github/review-status.d.ts.map +1 -1
- package/dist/github/review-status.js +7 -4
- package/dist/github/review-status.js.map +1 -1
- package/dist/github/webhook.d.ts +25 -1
- package/dist/github/webhook.d.ts.map +1 -1
- package/dist/github/webhook.js +37 -1
- package/dist/github/webhook.js.map +1 -1
- package/dist/lib/annotation.d.ts +4 -0
- package/dist/lib/annotation.d.ts.map +1 -1
- package/dist/lib/annotation.js +5 -1
- package/dist/lib/annotation.js.map +1 -1
- package/dist/lib/comment-bodies.d.ts.map +1 -1
- package/dist/lib/comment-bodies.js +3 -2
- package/dist/lib/comment-bodies.js.map +1 -1
- package/dist/lib/durations.d.ts.map +1 -1
- package/dist/lib/durations.js +5 -3
- package/dist/lib/durations.js.map +1 -1
- package/dist/lib/logger.d.ts +3 -0
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +29 -3
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/pr-picker.d.ts.map +1 -1
- package/dist/lib/pr-picker.js +5 -1
- package/dist/lib/pr-picker.js.map +1 -1
- package/dist/lib/pr-status.d.ts +4 -3
- package/dist/lib/pr-status.d.ts.map +1 -1
- package/dist/lib/pr-status.js +19 -13
- package/dist/lib/pr-status.js.map +1 -1
- package/dist/lib/pr-workflow-state.d.ts +68 -0
- package/dist/lib/pr-workflow-state.d.ts.map +1 -0
- package/dist/lib/pr-workflow-state.js +328 -0
- package/dist/lib/pr-workflow-state.js.map +1 -0
- package/dist/lib/product.d.ts +3 -0
- package/dist/lib/product.d.ts.map +1 -0
- package/dist/lib/product.js +5 -0
- package/dist/lib/product.js.map +1 -0
- package/dist/lib/repo-picker.d.ts +1 -0
- package/dist/lib/repo-picker.d.ts.map +1 -1
- package/dist/lib/repo-picker.js +50 -33
- package/dist/lib/repo-picker.js.map +1 -1
- package/dist/lib/runner.d.ts +19 -1
- package/dist/lib/runner.d.ts.map +1 -1
- package/dist/lib/runner.js +337 -54
- package/dist/lib/runner.js.map +1 -1
- package/dist/lib/smart-switch.js +1 -1
- package/dist/lib/smart-switch.js.map +1 -1
- package/dist/lib/vendor.d.ts +4 -0
- package/dist/lib/vendor.d.ts.map +1 -0
- package/dist/lib/vendor.js +14 -0
- package/dist/lib/vendor.js.map +1 -0
- package/dist/lib/workflow.d.ts +5 -0
- package/dist/lib/workflow.d.ts.map +1 -1
- package/dist/lib/workflow.js.map +1 -1
- package/dist/reviewers/claude.d.ts +3 -1
- package/dist/reviewers/claude.d.ts.map +1 -1
- package/dist/reviewers/claude.js +14 -9
- package/dist/reviewers/claude.js.map +1 -1
- package/dist/reviewers/codex.d.ts +1 -1
- package/dist/reviewers/codex.d.ts.map +1 -1
- package/dist/reviewers/codex.js +7 -10
- package/dist/reviewers/codex.js.map +1 -1
- package/dist/reviewers/conflict-resolve.d.ts +1 -1
- package/dist/reviewers/conflict-resolve.d.ts.map +1 -1
- package/dist/reviewers/conflict-resolve.js +3 -2
- package/dist/reviewers/conflict-resolve.js.map +1 -1
- package/dist/reviewers/fix.d.ts +5 -1
- package/dist/reviewers/fix.d.ts.map +1 -1
- package/dist/reviewers/fix.js +68 -2
- package/dist/reviewers/fix.js.map +1 -1
- package/dist/reviewers/tier-timeouts.d.ts +5 -0
- package/dist/reviewers/tier-timeouts.d.ts.map +1 -0
- package/dist/reviewers/tier-timeouts.js +14 -0
- package/dist/reviewers/tier-timeouts.js.map +1 -0
- package/get-started.md +56 -5
- package/get-started.zh.md +7 -1
- package/package.json +1 -1
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { parseAnnotation, parseAnnotationFields } from './annotation.js';
|
|
2
|
+
import { evaluateWhen, DEFAULT_RECHECK_INSTRUCTIONS } from './workflow.js';
|
|
3
|
+
import { parseVerdict } from './verdict.js';
|
|
4
|
+
import { fetchPRCommentPage, fetchPRCommitPage } from '../github/client.js';
|
|
5
|
+
const VALID_STEP_TYPES = new Set(['review', 'recheck', 'fix', 'conflict-resolve']);
|
|
6
|
+
function commentToRecord(comment) {
|
|
7
|
+
const fields = parseAnnotationFields(comment.body);
|
|
8
|
+
if (!fields) {
|
|
9
|
+
// No annotation at all — detect legacy review comments by header pattern
|
|
10
|
+
if (comment.body.includes('### Code Review by') && !comment.body.startsWith('> Recheck of')) {
|
|
11
|
+
const { verdict } = parseVerdict(comment.body);
|
|
12
|
+
return {
|
|
13
|
+
type: 'review',
|
|
14
|
+
...(verdict !== null && { verdict }),
|
|
15
|
+
round: 1,
|
|
16
|
+
commentId: comment.id,
|
|
17
|
+
commentBody: comment.body,
|
|
18
|
+
createdAt: comment.created_at,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
// Bareword markers: fix_applied and conflict_resolved have no origin/reviewer fields
|
|
24
|
+
const marker = fields.get('__marker__');
|
|
25
|
+
if (marker === 'fix_applied') {
|
|
26
|
+
// The fix comment body embeds the pushed SHA as a full commit URL — extract it
|
|
27
|
+
// so identifyNextWorkflowStep can verify the fix commit before routing to recheck.
|
|
28
|
+
const shaMatch = comment.body.match(/\/commit\/([0-9a-f]{40})/i);
|
|
29
|
+
const pushedSha = shaMatch ? shaMatch[1] : undefined;
|
|
30
|
+
return { type: 'fix', round: 1, commentId: comment.id, commentBody: comment.body, createdAt: comment.created_at, ...(pushedSha !== undefined && { pushedSha }) };
|
|
31
|
+
}
|
|
32
|
+
if (marker === 'conflict_resolved') {
|
|
33
|
+
return { type: 'conflict-resolve', round: 1, commentId: comment.id, commentBody: comment.body, createdAt: comment.created_at };
|
|
34
|
+
}
|
|
35
|
+
// Full annotation (requires origin + reviewer)
|
|
36
|
+
const parsed = parseAnnotation(comment.body);
|
|
37
|
+
if (!parsed)
|
|
38
|
+
return null;
|
|
39
|
+
const type = parsed.type;
|
|
40
|
+
if (!VALID_STEP_TYPES.has(type))
|
|
41
|
+
return null;
|
|
42
|
+
const verdict = parsed.verdict && parsed.verdict !== 'UNKNOWN' ? parsed.verdict : undefined;
|
|
43
|
+
return {
|
|
44
|
+
type,
|
|
45
|
+
...(verdict !== undefined && { verdict }),
|
|
46
|
+
...(parsed.sha !== undefined && { sha: parsed.sha }),
|
|
47
|
+
round: parsed.round,
|
|
48
|
+
commentId: comment.id,
|
|
49
|
+
commentBody: comment.body,
|
|
50
|
+
createdAt: comment.created_at,
|
|
51
|
+
reviewer: parsed.reviewer,
|
|
52
|
+
...(parsed.model !== 'default' && { model: parsed.model }),
|
|
53
|
+
...(parsed.next_step !== undefined && { next_step: parsed.next_step }),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export function commitToRecord(commit) {
|
|
57
|
+
const trailers = parseCommitTrailers(commit.commit.message);
|
|
58
|
+
const step = trailers.get('crosscheck-step');
|
|
59
|
+
if (step !== 'fix' && step !== 'conflict-resolve')
|
|
60
|
+
return null;
|
|
61
|
+
const createdAt = commit.commit.committer?.date ?? commit.commit.author?.date;
|
|
62
|
+
if (!createdAt)
|
|
63
|
+
return null;
|
|
64
|
+
return {
|
|
65
|
+
type: step,
|
|
66
|
+
pushedSha: commit.sha,
|
|
67
|
+
round: 1,
|
|
68
|
+
commentId: 0,
|
|
69
|
+
commentBody: commit.commit.message,
|
|
70
|
+
createdAt,
|
|
71
|
+
source: 'commit',
|
|
72
|
+
...(trailers.has('crosscheck-reviewer') && { reviewer: trailers.get('crosscheck-reviewer') }),
|
|
73
|
+
...(trailers.has('crosscheck-model') && { model: trailers.get('crosscheck-model') }),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function parseCommitTrailers(message) {
|
|
77
|
+
const trailers = new Map();
|
|
78
|
+
for (const line of message.split('\n')) {
|
|
79
|
+
const match = line.match(/^\s*(Crosscheck-[A-Za-z-]+):\s*(.*?)\s*$/);
|
|
80
|
+
if (match)
|
|
81
|
+
trailers.set(match[1].toLowerCase(), match[2]);
|
|
82
|
+
}
|
|
83
|
+
return trailers;
|
|
84
|
+
}
|
|
85
|
+
async function fetchCommitHistory(owner, repo, prNumber, token) {
|
|
86
|
+
const records = [];
|
|
87
|
+
let page = 1;
|
|
88
|
+
while (true) {
|
|
89
|
+
const commits = await fetchPRCommitPage(owner, repo, prNumber, token, page);
|
|
90
|
+
if (commits.length === 0)
|
|
91
|
+
break;
|
|
92
|
+
for (const commit of commits) {
|
|
93
|
+
const record = commitToRecord(commit);
|
|
94
|
+
if (record)
|
|
95
|
+
records.push(record);
|
|
96
|
+
}
|
|
97
|
+
if (commits.length < 100)
|
|
98
|
+
break;
|
|
99
|
+
page++;
|
|
100
|
+
}
|
|
101
|
+
return records;
|
|
102
|
+
}
|
|
103
|
+
function mergeStepHistory(commentRecords, commitRecords) {
|
|
104
|
+
const commentedStepShas = new Set(commentRecords
|
|
105
|
+
.filter(r => (r.type === 'fix' || r.type === 'conflict-resolve') && r.pushedSha)
|
|
106
|
+
.map(r => r.pushedSha));
|
|
107
|
+
const uniqueCommitRecords = commitRecords.filter(r => !r.pushedSha || !commentedStepShas.has(r.pushedSha));
|
|
108
|
+
return [...commentRecords, ...uniqueCommitRecords]
|
|
109
|
+
.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Fetch all crosscheck step records from PR comments and crosscheck commit
|
|
113
|
+
* trailers in chronological order.
|
|
114
|
+
* All HTTP calls go through github/client.ts.
|
|
115
|
+
*
|
|
116
|
+
* Fast path (new annotations with next_step):
|
|
117
|
+
* 1. Fetch the last page to find the most recent review/recheck annotation.
|
|
118
|
+
* 2. If it carries next_step, fetch only comments after it (?since=) to check for
|
|
119
|
+
* trailing fix markers — skipping the entire earlier thread.
|
|
120
|
+
*
|
|
121
|
+
* Full scan fallback (legacy annotations without next_step):
|
|
122
|
+
* Read all pages from page 1.
|
|
123
|
+
*/
|
|
124
|
+
export async function fetchStepHistory(owner, repo, prNumber, token) {
|
|
125
|
+
// Fetch the first page to discover total pagination
|
|
126
|
+
const { comments: firstPage, lastPage } = await fetchPRCommentPage(owner, repo, prNumber, token);
|
|
127
|
+
const commitHistory = await fetchCommitHistory(owner, repo, prNumber, token);
|
|
128
|
+
if (firstPage.length === 0)
|
|
129
|
+
return mergeStepHistory([], commitHistory);
|
|
130
|
+
// ── Fast path ──────────────────────────────────────────────────────────────
|
|
131
|
+
if (lastPage !== null && lastPage > 1) {
|
|
132
|
+
const { comments: tailPage } = await fetchPRCommentPage(owner, repo, prNumber, token, { page: lastPage });
|
|
133
|
+
const anchor = [...tailPage].reverse().find(c => {
|
|
134
|
+
const r = commentToRecord(c);
|
|
135
|
+
return r !== null && (r.type === 'review' || r.type === 'recheck') && r.next_step !== undefined;
|
|
136
|
+
});
|
|
137
|
+
if (anchor) {
|
|
138
|
+
const anchorRecord = commentToRecord(anchor);
|
|
139
|
+
const { comments: sinceComments } = await fetchPRCommentPage(owner, repo, prNumber, token, { since: anchor.created_at });
|
|
140
|
+
const seen = new Set([anchorRecord.commentId]);
|
|
141
|
+
const trailing = [];
|
|
142
|
+
for (const c of sinceComments) {
|
|
143
|
+
if (seen.has(c.id))
|
|
144
|
+
continue;
|
|
145
|
+
seen.add(c.id);
|
|
146
|
+
const r = commentToRecord(c);
|
|
147
|
+
if (r)
|
|
148
|
+
trailing.push(r);
|
|
149
|
+
}
|
|
150
|
+
return mergeStepHistory([anchorRecord, ...trailing], commitHistory);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// ── Full scan fallback ─────────────────────────────────────────────────────
|
|
154
|
+
const allComments = [...firstPage];
|
|
155
|
+
let page = 2;
|
|
156
|
+
while (true) {
|
|
157
|
+
const { comments } = await fetchPRCommentPage(owner, repo, prNumber, token, { page });
|
|
158
|
+
if (comments.length === 0)
|
|
159
|
+
break;
|
|
160
|
+
allComments.push(...comments);
|
|
161
|
+
if (comments.length < 100)
|
|
162
|
+
break;
|
|
163
|
+
page++;
|
|
164
|
+
}
|
|
165
|
+
const records = [];
|
|
166
|
+
for (const comment of allComments) {
|
|
167
|
+
const record = commentToRecord(comment);
|
|
168
|
+
if (record)
|
|
169
|
+
records.push(record);
|
|
170
|
+
}
|
|
171
|
+
return mergeStepHistory(records, commitHistory);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Given the PR's step history and the current HEAD SHA, determine which workflow
|
|
175
|
+
* step should run next.
|
|
176
|
+
*
|
|
177
|
+
* The algorithm replays the history from the end:
|
|
178
|
+
* 1. No review/recheck on record → start from the first workflow step.
|
|
179
|
+
* 2. Any non-APPROVE review/recheck without a later fix → fix is next.
|
|
180
|
+
* 3. A fix after the last review/recheck → recheck is next.
|
|
181
|
+
* 4. Current SHA has not been analyzed after the initial review → recheck is next.
|
|
182
|
+
* 5. Current SHA already reviewed → walk the workflow steps that follow
|
|
183
|
+
* and return the first whose `when` condition evaluates to true and
|
|
184
|
+
* that hasn't already been completed in history.
|
|
185
|
+
*/
|
|
186
|
+
export function identifyNextWorkflowStep(history, steps, currentSha) {
|
|
187
|
+
const reviewHistory = history.filter(r => r.type === 'review' || r.type === 'recheck');
|
|
188
|
+
const hasExistingReview = reviewHistory.length > 0;
|
|
189
|
+
if (!hasExistingReview) {
|
|
190
|
+
const firstStep = firstIncompleteInitialStep(history, steps);
|
|
191
|
+
return { step: firstStep, hasExistingReview: false, round: 1, history };
|
|
192
|
+
}
|
|
193
|
+
const lastReview = reviewHistory[reviewHistory.length - 1];
|
|
194
|
+
const lastReviewIdx = history.lastIndexOf(lastReview);
|
|
195
|
+
const historyAfterReview = history.slice(lastReviewIdx + 1);
|
|
196
|
+
// Only check for explicit fix/conflict-resolve markers after the last review.
|
|
197
|
+
// Do NOT short-circuit based on lastReview.type === 'recheck': after a BLOCK or
|
|
198
|
+
// NEEDS_WORK recheck, fix still needs to run. The fix step's `when` condition
|
|
199
|
+
// (e.g. "review.verdict != 'APPROVE'") correctly gates it on APPROVE alone.
|
|
200
|
+
const lastFixAfterReview = historyAfterReview.filter(r => r.type === 'fix').at(-1);
|
|
201
|
+
const conflictAfterReview = historyAfterReview.some(r => r.type === 'conflict-resolve');
|
|
202
|
+
const fixAfterReview = lastFixAfterReview !== undefined || conflictAfterReview;
|
|
203
|
+
// Build synthetic results so evaluateWhen works correctly for downstream steps.
|
|
204
|
+
// Always populate under the literal key 'review' so conditions like
|
|
205
|
+
// "review.verdict != 'APPROVE'" work regardless of the step's name in the workflow.
|
|
206
|
+
const syntheticResults = {
|
|
207
|
+
review: { verdict: lastReview.verdict },
|
|
208
|
+
};
|
|
209
|
+
const reviewStepDef = steps.find(s => s.type === 'review' || s.type === 'recheck');
|
|
210
|
+
if (reviewStepDef && reviewStepDef.name !== 'review') {
|
|
211
|
+
syntheticResults[reviewStepDef.name] = { verdict: lastReview.verdict };
|
|
212
|
+
}
|
|
213
|
+
if (fixAfterReview) {
|
|
214
|
+
syntheticResults['fix'] = { applied_count: 1 };
|
|
215
|
+
const fixStepDef = steps.find(s => s.type === 'fix');
|
|
216
|
+
if (fixStepDef && fixStepDef.name !== 'fix')
|
|
217
|
+
syntheticResults[fixStepDef.name] = { applied_count: 1 };
|
|
218
|
+
}
|
|
219
|
+
const reviewComment = { id: lastReview.commentId, body: lastReview.commentBody };
|
|
220
|
+
const reviewedCurrentSha = lastReview.sha !== undefined && lastReview.sha === currentSha;
|
|
221
|
+
const fixedCurrentSha = lastFixAfterReview?.pushedSha !== undefined && lastFixAfterReview.pushedSha === currentSha;
|
|
222
|
+
if (fixedCurrentSha) {
|
|
223
|
+
return {
|
|
224
|
+
step: effectiveRecheckStep(steps),
|
|
225
|
+
reviewComment,
|
|
226
|
+
hasExistingReview: true,
|
|
227
|
+
round: lastReview.round,
|
|
228
|
+
history,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
if (lastFixAfterReview !== undefined && !fixedCurrentSha) {
|
|
232
|
+
const reviewStep = steps.find(s => s.type === 'review') ?? steps[0] ?? null;
|
|
233
|
+
return {
|
|
234
|
+
step: reviewStep,
|
|
235
|
+
hasExistingReview: true,
|
|
236
|
+
round: lastReview.round + 1,
|
|
237
|
+
history,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const fixStep = firstRunnableFixStep(steps, syntheticResults);
|
|
241
|
+
if (fixStep) {
|
|
242
|
+
return {
|
|
243
|
+
step: fixStep,
|
|
244
|
+
reviewComment,
|
|
245
|
+
hasExistingReview: true,
|
|
246
|
+
round: lastReview.round,
|
|
247
|
+
history,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
if (!reviewedCurrentSha) {
|
|
251
|
+
const reviewStep = steps.find(s => s.type === 'review') ?? steps[0] ?? null;
|
|
252
|
+
return {
|
|
253
|
+
step: reviewStep,
|
|
254
|
+
hasExistingReview: true,
|
|
255
|
+
round: lastReview.round + 1,
|
|
256
|
+
history,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
// Current SHA has been reviewed — find the first incomplete step that follows
|
|
260
|
+
let passedReview = false;
|
|
261
|
+
for (const step of steps) {
|
|
262
|
+
if (step.type === 'review' || step.type === 'recheck') {
|
|
263
|
+
passedReview = true;
|
|
264
|
+
continue; // done for this sha
|
|
265
|
+
}
|
|
266
|
+
if (!passedReview)
|
|
267
|
+
continue;
|
|
268
|
+
if (step.when && !evaluateWhen(step.when, syntheticResults))
|
|
269
|
+
continue;
|
|
270
|
+
if (step.type === 'fix') {
|
|
271
|
+
if (fixAfterReview) {
|
|
272
|
+
syntheticResults[step.name] = { applied_count: 1 };
|
|
273
|
+
syntheticResults['fix'] = { applied_count: 1 };
|
|
274
|
+
continue; // already ran
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
step,
|
|
278
|
+
reviewComment: { id: lastReview.commentId, body: lastReview.commentBody },
|
|
279
|
+
hasExistingReview: true,
|
|
280
|
+
round: lastReview.round,
|
|
281
|
+
history,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
if (step.type === 'conflict-resolve') {
|
|
285
|
+
const conflictDone = historyAfterReview.some(r => r.type === 'conflict-resolve');
|
|
286
|
+
if (conflictDone)
|
|
287
|
+
continue;
|
|
288
|
+
return { step, hasExistingReview: true, round: lastReview.round, history };
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return { step: null, hasExistingReview: true, round: lastReview.round, history };
|
|
292
|
+
}
|
|
293
|
+
function firstIncompleteInitialStep(history, steps) {
|
|
294
|
+
for (const step of steps) {
|
|
295
|
+
if (step.type === 'conflict-resolve') {
|
|
296
|
+
const conflictDone = history.some(r => r.type === 'conflict-resolve');
|
|
297
|
+
if (!conflictDone)
|
|
298
|
+
return step;
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
return step;
|
|
302
|
+
}
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
function firstRunnableFixStep(steps, syntheticResults) {
|
|
306
|
+
for (const step of steps) {
|
|
307
|
+
if (step.type !== 'fix')
|
|
308
|
+
continue;
|
|
309
|
+
if (step.when && !evaluateWhen(step.when, syntheticResults))
|
|
310
|
+
continue;
|
|
311
|
+
return step;
|
|
312
|
+
}
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
function effectiveRecheckStep(steps) {
|
|
316
|
+
const recheckStep = steps.find(s => s.type === 'recheck');
|
|
317
|
+
if (recheckStep)
|
|
318
|
+
return recheckStep;
|
|
319
|
+
const reviewBase = steps.find(s => s.type === 'review');
|
|
320
|
+
return {
|
|
321
|
+
...(reviewBase ?? { reviewer: 'auto', max_rounds: 1 }),
|
|
322
|
+
name: 'recheck',
|
|
323
|
+
type: 'recheck',
|
|
324
|
+
when: undefined,
|
|
325
|
+
instructions: DEFAULT_RECHECK_INSTRUCTIONS,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
//# sourceMappingURL=pr-workflow-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-workflow-state.js","sourceRoot":"","sources":["../../src/lib/pr-workflow-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product.d.ts","sourceRoot":"","sources":["../../src/lib/product.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB,gDAAgD,CAAA;AAChF,eAAO,MAAM,qBAAqB,uDAAkC,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Single source of truth for crosscheck's own project URLs.
|
|
2
|
+
// Update here if the project moves to a different org or repo name.
|
|
3
|
+
export const CROSSCHECK_REPO_URL = 'https://github.com/humanbased-ai/crosscheck';
|
|
4
|
+
export const CROSSCHECK_ISSUES_URL = `${CROSSCHECK_REPO_URL}/issues`;
|
|
5
|
+
//# sourceMappingURL=product.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product.js","sourceRoot":"","sources":["../../src/lib/product.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,oEAAoE;AACpE,MAAM,CAAC,MAAM,mBAAmB,GAAG,6CAA6C,CAAA;AAChF,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,mBAAmB,SAAS,CAAA"}
|
|
@@ -17,6 +17,7 @@ export interface PickerOptions {
|
|
|
17
17
|
title?: string;
|
|
18
18
|
initialSelected?: string[];
|
|
19
19
|
pageSize?: number;
|
|
20
|
+
selectAllLabel?: string;
|
|
20
21
|
getDescription?: (item: string) => string;
|
|
21
22
|
}
|
|
22
23
|
export declare function promptRepoPicker(items: string[], opts?: PickerOptions): Promise<string[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repo-picker.d.ts","sourceRoot":"","sources":["../../src/lib/repo-picker.ts"],"names":[],"mappings":"AAuBA,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAQtE;AAID,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,MAAM,CAOR;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAK9F;AAKD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK5D;AAOD,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,GAChB,MAAM,CAIR;AAID,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAID,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,UAAU,EAAE,EACnB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACtE,OAAO,CAAC,MAAM,CAAC,CA2GjB;AAID,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"repo-picker.d.ts","sourceRoot":"","sources":["../../src/lib/repo-picker.ts"],"names":[],"mappings":"AAuBA,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAQtE;AAID,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,MAAM,CAOR;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAK9F;AAKD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK5D;AAOD,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,GAChB,MAAM,CAIR;AAID,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAID,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,UAAU,EAAE,EACnB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACtE,OAAO,CAAC,MAAM,CAAC,CA2GjB;AAID,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAC1C;AASD,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC,CAsPnB"}
|
package/dist/lib/repo-picker.js
CHANGED
|
@@ -188,25 +188,39 @@ export async function promptRepoPicker(items, opts = {}) {
|
|
|
188
188
|
if (items.length === 0)
|
|
189
189
|
return [];
|
|
190
190
|
return new Promise((resolve, reject) => {
|
|
191
|
+
const allRow = -1;
|
|
191
192
|
const selected = new Set(opts.initialSelected
|
|
192
193
|
? opts.initialSelected.map(s => items.indexOf(s)).filter(i => i !== -1)
|
|
193
194
|
: []);
|
|
194
195
|
let filterText = '';
|
|
195
196
|
let filterMode = false;
|
|
196
197
|
let filtered = filterIndices(items, '');
|
|
197
|
-
let cursorPos = 0; // index into `filtered`
|
|
198
|
+
let cursorPos = opts.selectAllLabel && items.length > 0 ? 1 : 0; // index into `filtered`
|
|
198
199
|
let windowStart = 0; // index into `filtered`
|
|
199
200
|
let lastLineCount = 0;
|
|
200
201
|
const viewport = () => resolveViewport(opts.pageSize, process.stdout.rows);
|
|
202
|
+
const displayIndices = () => (opts.selectAllLabel && filtered.length > 0 ? [allRow, ...filtered] : filtered);
|
|
203
|
+
const allVisibleSelected = () => filtered.length > 0 && filtered.every(i => selected.has(i));
|
|
204
|
+
const toggleAllVisible = () => {
|
|
205
|
+
const allOn = allVisibleSelected();
|
|
206
|
+
if (allOn)
|
|
207
|
+
for (const i of filtered)
|
|
208
|
+
selected.delete(i);
|
|
209
|
+
else
|
|
210
|
+
for (const i of filtered)
|
|
211
|
+
selected.add(i);
|
|
212
|
+
};
|
|
201
213
|
function recomputeFiltered() {
|
|
202
214
|
filtered = filterIndices(items, filterText);
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
215
|
+
const displayed = displayIndices();
|
|
216
|
+
if (cursorPos >= displayed.length)
|
|
217
|
+
cursorPos = Math.max(0, displayed.length - 1);
|
|
218
|
+
windowStart = adjustWindowStart(windowStart, cursorPos, viewport(), displayed.length);
|
|
206
219
|
}
|
|
207
220
|
function render(firstRender = false) {
|
|
208
221
|
const vp = viewport();
|
|
209
|
-
|
|
222
|
+
const displayed = displayIndices();
|
|
223
|
+
windowStart = adjustWindowStart(windowStart, cursorPos, vp, displayed.length);
|
|
210
224
|
if (!firstRender) {
|
|
211
225
|
process.stdout.write(`\x1b[${lastLineCount}A`);
|
|
212
226
|
// Erase leftover content from the previous (possibly taller) render so a
|
|
@@ -215,8 +229,8 @@ export async function promptRepoPicker(items, opts = {}) {
|
|
|
215
229
|
}
|
|
216
230
|
// Render exactly as many item rows as we have items, capped at the
|
|
217
231
|
// viewport. Empty filter result → one "(no matches)" hint row instead.
|
|
218
|
-
const visibleRows = Math.min(vp,
|
|
219
|
-
const emptyHint =
|
|
232
|
+
const visibleRows = Math.min(vp, displayed.length);
|
|
233
|
+
const emptyHint = displayed.length === 0;
|
|
220
234
|
const itemRows = emptyHint ? 1 : visibleRows;
|
|
221
235
|
lastLineCount = (opts.title ? 1 : 0) + 1 + itemRows + 1 + 1;
|
|
222
236
|
if (opts.title) {
|
|
@@ -246,12 +260,13 @@ export async function promptRepoPicker(items, opts = {}) {
|
|
|
246
260
|
else {
|
|
247
261
|
for (let row = 0; row < visibleRows; row++) {
|
|
248
262
|
const fi = windowStart + row;
|
|
249
|
-
const origIdx =
|
|
250
|
-
const
|
|
251
|
-
const
|
|
263
|
+
const origIdx = displayed[fi];
|
|
264
|
+
const isAllRow = origIdx === allRow;
|
|
265
|
+
const item = isAllRow ? opts.selectAllLabel ?? 'all' : items[origIdx];
|
|
266
|
+
const isSelected = isAllRow ? allVisibleSelected() : selected.has(origIdx);
|
|
252
267
|
const isFocused = cursorPos === fi;
|
|
253
268
|
const checkStr = isSelected ? `${CYAN}[x]${RESET}` : '[ ]';
|
|
254
|
-
const desc = opts.getDescription ? opts.getDescription(item) : '';
|
|
269
|
+
const desc = isAllRow ? `${filtered.length} PRs` : opts.getDescription ? opts.getDescription(item) : '';
|
|
255
270
|
// Budget: cols - 2 (indent) - 4 ("[x] ") - (desc.length + 2 spaces if desc).
|
|
256
271
|
const descBudget = desc ? desc.length + 2 : 0;
|
|
257
272
|
const labelMax = Math.max(1, cols - 6 - descBudget);
|
|
@@ -262,15 +277,16 @@ export async function promptRepoPicker(items, opts = {}) {
|
|
|
262
277
|
}
|
|
263
278
|
}
|
|
264
279
|
const total = filtered.length;
|
|
265
|
-
const
|
|
280
|
+
const displayedTotal = displayed.length;
|
|
281
|
+
const pos = displayedTotal === 0 ? 0 : cursorPos + 1;
|
|
266
282
|
const selCount = selected.size;
|
|
267
283
|
const filterNote = filterText ? ` · filter: "${filterText}"` : '';
|
|
268
284
|
const selNote = selCount > 0 ? ` · ${selCount} selected` : '';
|
|
269
|
-
const statusLine = truncate(`${pos}/${
|
|
285
|
+
const statusLine = truncate(`${pos}/${displayedTotal}${filterNote}${selNote}`, innerWidth);
|
|
270
286
|
process.stdout.write(`${ERASE_LINE}${DIM} ${statusLine}${RESET}\n`);
|
|
271
287
|
// PgUp/PgDn only when the *current* visible list overflows the viewport.
|
|
272
288
|
// After a filter narrows the list, the hint shrinks accordingly.
|
|
273
|
-
const navHint =
|
|
289
|
+
const navHint = displayed.length > vp ? '↑↓ PgUp/PgDn move' : '↑↓ move';
|
|
274
290
|
const footerLine = filterMode
|
|
275
291
|
? `${navHint} · type to filter · backspace · esc clear · enter done`
|
|
276
292
|
: `${navHint} · space select · a all · / filter · enter confirm`;
|
|
@@ -303,16 +319,18 @@ export async function promptRepoPicker(items, opts = {}) {
|
|
|
303
319
|
}
|
|
304
320
|
// Navigation keys work in both modes — let the user scroll while filtering.
|
|
305
321
|
if (key === '\x1b[A') {
|
|
306
|
-
|
|
322
|
+
const displayed = displayIndices();
|
|
323
|
+
if (displayed.length === 0)
|
|
307
324
|
return;
|
|
308
|
-
cursorPos = cursorPos > 0 ? cursorPos - 1 :
|
|
325
|
+
cursorPos = cursorPos > 0 ? cursorPos - 1 : displayed.length - 1;
|
|
309
326
|
render();
|
|
310
327
|
return;
|
|
311
328
|
}
|
|
312
329
|
if (key === '\x1b[B') {
|
|
313
|
-
|
|
330
|
+
const displayed = displayIndices();
|
|
331
|
+
if (displayed.length === 0)
|
|
314
332
|
return;
|
|
315
|
-
cursorPos = cursorPos <
|
|
333
|
+
cursorPos = cursorPos < displayed.length - 1 ? cursorPos + 1 : 0;
|
|
316
334
|
render();
|
|
317
335
|
return;
|
|
318
336
|
}
|
|
@@ -320,21 +338,23 @@ export async function promptRepoPicker(items, opts = {}) {
|
|
|
320
338
|
// PageUp — advance window AND cursor by one viewport so the page
|
|
321
339
|
// actually flips. Without the windowStart bump, adjustWindowStart would
|
|
322
340
|
// only scroll far enough to keep the cursor visible (one row).
|
|
323
|
-
|
|
341
|
+
const displayed = displayIndices();
|
|
342
|
+
if (displayed.length === 0)
|
|
324
343
|
return;
|
|
325
344
|
const vp = viewport();
|
|
326
345
|
cursorPos = Math.max(0, cursorPos - vp);
|
|
327
|
-
windowStart = advancePageStart(windowStart, vp,
|
|
346
|
+
windowStart = advancePageStart(windowStart, vp, displayed.length, -1);
|
|
328
347
|
render();
|
|
329
348
|
return;
|
|
330
349
|
}
|
|
331
350
|
if (key === '\x1b[6~') {
|
|
332
351
|
// PageDown — see PageUp comment.
|
|
333
|
-
|
|
352
|
+
const displayed = displayIndices();
|
|
353
|
+
if (displayed.length === 0)
|
|
334
354
|
return;
|
|
335
355
|
const vp = viewport();
|
|
336
|
-
cursorPos = Math.min(
|
|
337
|
-
windowStart = advancePageStart(windowStart, vp,
|
|
356
|
+
cursorPos = Math.min(displayed.length - 1, cursorPos + vp);
|
|
357
|
+
windowStart = advancePageStart(windowStart, vp, displayed.length, 1);
|
|
338
358
|
render();
|
|
339
359
|
return;
|
|
340
360
|
}
|
|
@@ -376,10 +396,13 @@ export async function promptRepoPicker(items, opts = {}) {
|
|
|
376
396
|
render();
|
|
377
397
|
}
|
|
378
398
|
else if (key === ' ') {
|
|
379
|
-
|
|
399
|
+
const displayed = displayIndices();
|
|
400
|
+
if (displayed.length === 0)
|
|
380
401
|
return;
|
|
381
|
-
const origIdx =
|
|
382
|
-
if (
|
|
402
|
+
const origIdx = displayed[cursorPos];
|
|
403
|
+
if (origIdx === allRow)
|
|
404
|
+
toggleAllVisible();
|
|
405
|
+
else if (selected.has(origIdx))
|
|
383
406
|
selected.delete(origIdx);
|
|
384
407
|
else
|
|
385
408
|
selected.add(origIdx);
|
|
@@ -387,13 +410,7 @@ export async function promptRepoPicker(items, opts = {}) {
|
|
|
387
410
|
}
|
|
388
411
|
else if (key === 'a') {
|
|
389
412
|
// Toggle every item in the current filtered view.
|
|
390
|
-
|
|
391
|
-
if (allOn)
|
|
392
|
-
for (const i of filtered)
|
|
393
|
-
selected.delete(i);
|
|
394
|
-
else
|
|
395
|
-
for (const i of filtered)
|
|
396
|
-
selected.add(i);
|
|
413
|
+
toggleAllVisible();
|
|
397
414
|
render();
|
|
398
415
|
}
|
|
399
416
|
else if (key === '\r' || key === '\n') {
|