@humanbased/crosscheck 1.5.0 → 1.6.0-beta.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/__tests__/board.test.js +527 -20
- package/dist/__tests__/board.test.js.map +1 -1
- package/dist/__tests__/lock-ownership.test.d.ts +2 -0
- package/dist/__tests__/lock-ownership.test.d.ts.map +1 -0
- package/dist/__tests__/lock-ownership.test.js +167 -0
- package/dist/__tests__/lock-ownership.test.js.map +1 -0
- package/dist/__tests__/vendor-error-summary.test.d.ts +2 -0
- package/dist/__tests__/vendor-error-summary.test.d.ts.map +1 -0
- package/dist/__tests__/vendor-error-summary.test.js +74 -0
- package/dist/__tests__/vendor-error-summary.test.js.map +1 -0
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/review.d.ts +3 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +88 -2
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +22 -5
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +27 -23
- package/dist/commands/watch.js.map +1 -1
- package/dist/github/review-status.d.ts +33 -0
- package/dist/github/review-status.d.ts.map +1 -1
- package/dist/github/review-status.js +94 -9
- package/dist/github/review-status.js.map +1 -1
- package/dist/lib/board.d.ts +59 -4
- package/dist/lib/board.d.ts.map +1 -1
- package/dist/lib/board.js +376 -64
- package/dist/lib/board.js.map +1 -1
- package/dist/lib/pr-lock.d.ts +37 -1
- package/dist/lib/pr-lock.d.ts.map +1 -1
- package/dist/lib/pr-lock.js +176 -29
- package/dist/lib/pr-lock.js.map +1 -1
- package/dist/lib/pr-workflow-state.d.ts +2 -0
- package/dist/lib/pr-workflow-state.d.ts.map +1 -1
- package/dist/lib/pr-workflow-state.js +15 -0
- package/dist/lib/pr-workflow-state.js.map +1 -1
- package/dist/lib/tips.d.ts.map +1 -1
- package/dist/lib/tips.js +1 -0
- package/dist/lib/tips.js.map +1 -1
- package/dist/lib/vendor-error-summary.d.ts +19 -0
- package/dist/lib/vendor-error-summary.d.ts.map +1 -0
- package/dist/lib/vendor-error-summary.js +95 -0
- package/dist/lib/vendor-error-summary.js.map +1 -0
- package/dist/reviewers/claude.d.ts.map +1 -1
- package/dist/reviewers/claude.js +2 -1
- package/dist/reviewers/claude.js.map +1 -1
- package/dist/reviewers/codex.d.ts.map +1 -1
- package/dist/reviewers/codex.js +2 -1
- package/dist/reviewers/codex.js.map +1 -1
- package/get-started.md +18 -0
- package/package.json +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { INSTANCE_ID } from '../lib/pr-lock.js';
|
|
1
2
|
const CONTEXT = 'crosscheck/review';
|
|
2
3
|
// Lock is stale when the process hasn't heartbeated within this window.
|
|
3
4
|
// Shorter = faster self-heal after a crash; must exceed HEARTBEAT_INTERVAL_MS
|
|
@@ -6,16 +7,51 @@ const STALE_MS = 5 * 60 * 1000;
|
|
|
6
7
|
// Heartbeat keeps the pending status fresh so long-running reviews don't look
|
|
7
8
|
// abandoned. Must be well under STALE_MS so a live review never goes stale.
|
|
8
9
|
const HEARTBEAT_INTERVAL_MS = 2 * 60 * 1000;
|
|
10
|
+
// How long to let concurrent claims settle before reading back who won.
|
|
11
|
+
// createCommitStatus is an upsert, not a compare-and-swap — GitHub offers no
|
|
12
|
+
// conditional create for a commit status — so two instances can both write. The
|
|
13
|
+
// settle-then-read-back below is what turns that into a decision instead of two
|
|
14
|
+
// instances both proceeding. It must comfortably exceed a write round-trip.
|
|
15
|
+
const CLAIM_SETTLE_MS = 2_500;
|
|
16
|
+
// The claim marker. Kept short: GitHub truncates a status description at 140 chars,
|
|
17
|
+
// and the instance id has to survive that intact to be readable on the way back.
|
|
18
|
+
function claimDescription(id) {
|
|
19
|
+
return `crosscheck ${id}`;
|
|
20
|
+
}
|
|
21
|
+
/** Parse the instance id out of a claim description. Null for a foreign or legacy status. */
|
|
22
|
+
export function parseClaimOwner(description) {
|
|
23
|
+
if (!description)
|
|
24
|
+
return null;
|
|
25
|
+
const m = description.match(/^crosscheck ([^\s]+)/);
|
|
26
|
+
return m ? (m[1] ?? null) : null;
|
|
27
|
+
}
|
|
28
|
+
async function readClaim(octokit, owner, repo, sha) {
|
|
29
|
+
const { data } = await octokit.rest.repos.getCombinedStatusForRef({ owner, repo, ref: sha });
|
|
30
|
+
const status = data.statuses
|
|
31
|
+
.filter(s => s.context === CONTEXT)
|
|
32
|
+
.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime())[0];
|
|
33
|
+
if (!status)
|
|
34
|
+
return null;
|
|
35
|
+
return {
|
|
36
|
+
state: status.state,
|
|
37
|
+
owner: parseClaimOwner(status.description),
|
|
38
|
+
updatedAt: new Date(status.updated_at).getTime(),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Is another instance actively reviewing this commit?
|
|
43
|
+
*
|
|
44
|
+
* Our own claim does not count: a retry inside the same process must not be
|
|
45
|
+
* blocked by the pending status that process itself just wrote.
|
|
46
|
+
*/
|
|
9
47
|
export async function checkRemoteLock(octokit, owner, repo, sha) {
|
|
10
48
|
try {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
.filter(s => s.context === CONTEXT)
|
|
14
|
-
.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime())[0];
|
|
15
|
-
if (!status || status.state !== 'pending')
|
|
49
|
+
const claim = await readClaim(octokit, owner, repo, sha);
|
|
50
|
+
if (!claim || claim.state !== 'pending')
|
|
16
51
|
return false;
|
|
17
|
-
|
|
18
|
-
|
|
52
|
+
if (claim.owner === INSTANCE_ID)
|
|
53
|
+
return false;
|
|
54
|
+
return Date.now() - claim.updatedAt < STALE_MS;
|
|
19
55
|
}
|
|
20
56
|
catch {
|
|
21
57
|
return false;
|
|
@@ -26,9 +62,43 @@ export async function acquireRemoteLock(octokit, owner, repo, sha) {
|
|
|
26
62
|
owner, repo, sha,
|
|
27
63
|
state: 'pending',
|
|
28
64
|
context: CONTEXT,
|
|
29
|
-
description:
|
|
65
|
+
description: `${claimDescription(INSTANCE_ID)} started ${new Date().toISOString()}`,
|
|
30
66
|
});
|
|
31
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Claim the commit and confirm the claim held. Returns false when another instance
|
|
70
|
+
* won, in which case this caller must not review.
|
|
71
|
+
*
|
|
72
|
+
* `checkRemoteLock` then `acquireRemoteLock` is a check-then-act race: two instances
|
|
73
|
+
* that receive the same webhook within a round-trip of each other both see no pending
|
|
74
|
+
* status, both write one, and both review the same commit — the duplicate same-SHA
|
|
75
|
+
* reviews this arbitration exists to stop. GitHub has no conditional status write, so
|
|
76
|
+
* instead of pretending the write was exclusive, both writers read back after a settle
|
|
77
|
+
* window and only the instance whose id survived as the newest status proceeds. Last
|
|
78
|
+
* write wins, deterministically, rather than nobody losing.
|
|
79
|
+
*
|
|
80
|
+
* This is arbitration, not a mutex: a peer writing after the read-back still gets in.
|
|
81
|
+
* The window is milliseconds against a review measured in minutes, and the local lock
|
|
82
|
+
* covers same-machine collisions outright.
|
|
83
|
+
*/
|
|
84
|
+
export async function claimRemoteLock(octokit, owner, repo, sha, settleMs = CLAIM_SETTLE_MS) {
|
|
85
|
+
await acquireRemoteLock(octokit, owner, repo, sha);
|
|
86
|
+
await new Promise(resolve => setTimeout(resolve, settleMs));
|
|
87
|
+
try {
|
|
88
|
+
const claim = await readClaim(octokit, owner, repo, sha);
|
|
89
|
+
// No claim readable, or one with no owner (a legacy status, or a description
|
|
90
|
+
// GitHub truncated): nothing proves we lost, and refusing to review on an
|
|
91
|
+
// unreadable status would strand the PR. Proceed — the local lock still holds.
|
|
92
|
+
if (!claim || claim.owner === null)
|
|
93
|
+
return true;
|
|
94
|
+
return claim.owner === INSTANCE_ID;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// The read-back is the optional half. Failing it leaves us exactly where the
|
|
98
|
+
// old unconditional acquire always was, which is still safe enough to review.
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
32
102
|
// Starts a repeating interval that refreshes the pending status timestamp so
|
|
33
103
|
// checkRemoteLock never treats an active review as stale. Returns a stop
|
|
34
104
|
// function that must be called in the finally block after the review completes.
|
|
@@ -38,15 +108,30 @@ export function startRemoteLockHeartbeat(octokit, owner, repo, sha) {
|
|
|
38
108
|
owner, repo, sha,
|
|
39
109
|
state: 'pending',
|
|
40
110
|
context: CONTEXT,
|
|
41
|
-
description:
|
|
111
|
+
description: `${claimDescription(INSTANCE_ID)} active ${new Date().toISOString()}`,
|
|
42
112
|
}).catch(() => { });
|
|
43
113
|
}, HEARTBEAT_INTERVAL_MS);
|
|
44
114
|
return () => clearInterval(id);
|
|
45
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Publish the review outcome and drop the claim — but only if the claim is still ours.
|
|
118
|
+
*
|
|
119
|
+
* Writing unconditionally let any instance clear any other instance's lock. Worse than
|
|
120
|
+
* the lost mutual exclusion, `crosscheck/review` is a status a repo can require for
|
|
121
|
+
* merge: a late `success` from an instance that reviewed an older commit, or one whose
|
|
122
|
+
* claim was superseded, marks a commit green that nothing has actually reviewed.
|
|
123
|
+
*/
|
|
46
124
|
export async function releaseRemoteLock(octokit, owner, repo, sha, outcome) {
|
|
47
125
|
try {
|
|
126
|
+
const claim = await readClaim(octokit, owner, repo, sha);
|
|
127
|
+
// A claim owned by someone else is theirs to resolve. An unowned claim (legacy
|
|
128
|
+
// or truncated) is indistinguishable from our own predecessor's, so resolve it
|
|
129
|
+
// rather than leaving a pending status behind forever.
|
|
130
|
+
if (claim && claim.owner !== null && claim.owner !== INSTANCE_ID)
|
|
131
|
+
return;
|
|
48
132
|
await octokit.rest.repos.createCommitStatus({
|
|
49
133
|
owner, repo, sha, state: outcome, context: CONTEXT,
|
|
134
|
+
description: `${claimDescription(INSTANCE_ID)} ${outcome}`,
|
|
50
135
|
});
|
|
51
136
|
}
|
|
52
137
|
catch { /* best-effort */ }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-status.js","sourceRoot":"","sources":["../../src/github/review-status.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"review-status.js","sourceRoot":"","sources":["../../src/github/review-status.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/board.d.ts
CHANGED
|
@@ -24,10 +24,31 @@ export interface PRCompletionData {
|
|
|
24
24
|
* run, such as one the review strategy short-circuited. */
|
|
25
25
|
label?: string;
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* The terminal state of one settled slot, for the session outcome distribution.
|
|
29
|
+
* `skipped` is a PR that settled without any verdict at all — the review
|
|
30
|
+
* strategy short-circuited it (lockfile-only, doc-only) — as distinct from
|
|
31
|
+
* `no verdict`, where a reviewer ran and returned nothing parseable.
|
|
32
|
+
*/
|
|
33
|
+
export type Outcome = 'APPROVE' | 'NEEDS WORK' | 'BLOCK' | 'no verdict' | 'skipped' | 'error';
|
|
27
34
|
export declare function fmtTime(d?: Date): string;
|
|
28
35
|
export declare const FMT_TIME_WIDTH = 11;
|
|
36
|
+
export declare function fmtUptime(ms: number): string;
|
|
37
|
+
/**
|
|
38
|
+
* Whole percentages summing to exactly 100, by the largest-remainder method.
|
|
39
|
+
* Plain rounding drifts — three equal shares render as 33/33/33 — and a
|
|
40
|
+
* distribution that visibly fails to add up reads as a bug in the numbers.
|
|
41
|
+
*
|
|
42
|
+
* A non-zero count too small to earn a point comes back as 0; the caller
|
|
43
|
+
* renders those as "<1%" rather than claiming the outcome never happened.
|
|
44
|
+
*/
|
|
45
|
+
export declare function distribute(counts: readonly number[]): number[];
|
|
29
46
|
export declare function fmtTokens(n?: number): string;
|
|
30
47
|
export declare function fmtTokensRaw(n?: number): string;
|
|
48
|
+
export declare function isNoticeLine(msg: string): boolean;
|
|
49
|
+
export type PageKey = 'older' | 'newer' | null;
|
|
50
|
+
/** Map a raw stdin key sequence to a page direction, or null when it is not a page key. */
|
|
51
|
+
export declare function pageKeyAction(seq: string): PageKey;
|
|
31
52
|
export declare class PRBoard {
|
|
32
53
|
private slots;
|
|
33
54
|
private frameIdx;
|
|
@@ -36,6 +57,10 @@ export declare class PRBoard {
|
|
|
36
57
|
private liveContent;
|
|
37
58
|
private readonly isTTY;
|
|
38
59
|
private connLog;
|
|
60
|
+
private page;
|
|
61
|
+
private pageCount;
|
|
62
|
+
private keyHandler;
|
|
63
|
+
private stdinWasRaw;
|
|
39
64
|
private stats;
|
|
40
65
|
private tunnel;
|
|
41
66
|
private config;
|
|
@@ -45,9 +70,20 @@ export declare class PRBoard {
|
|
|
45
70
|
setTunnel(type: string, url: string | null, alive: boolean): void;
|
|
46
71
|
start(): void;
|
|
47
72
|
stop(): void;
|
|
73
|
+
/** Flip one page toward older history. No-op when already at the oldest page. */
|
|
74
|
+
pageOlder(): void;
|
|
75
|
+
/** Flip one page toward the live page. No-op when already on it. */
|
|
76
|
+
pageNewer(): void;
|
|
48
77
|
addPR(key: string, prNumber: number, repo: string, branch: string, round?: number): void;
|
|
49
78
|
updatePR(key: string, updates: PRUpdate): void;
|
|
50
79
|
completePR(key: string, data: PRCompletionData): void;
|
|
80
|
+
/**
|
|
81
|
+
* Settle a slot that ended in an error. The slot stays in the workspace as a
|
|
82
|
+
* settled row, the same as a completed one: a failed run is a session record,
|
|
83
|
+
* and deleting it here was what pushed reviewer timeouts out of the table and
|
|
84
|
+
* into raw scrollback, where a long watch session showed 43 errors above an
|
|
85
|
+
* empty workspace reading "no PRs yet".
|
|
86
|
+
*/
|
|
51
87
|
failPR(key: string, error: string): void;
|
|
52
88
|
/** Print 1–2 static lines to scrollback (above the live block). */
|
|
53
89
|
log(line1: string, line2?: string): void;
|
|
@@ -60,7 +96,13 @@ export declare class PRBoard {
|
|
|
60
96
|
private verdictBadge;
|
|
61
97
|
private crFillFn;
|
|
62
98
|
private crLabelFn;
|
|
63
|
-
|
|
99
|
+
/** "since 08:25 PM · up 3h32m" — when watch started, and how long it has run. */
|
|
100
|
+
private sessionRow;
|
|
101
|
+
/**
|
|
102
|
+
* Outcome shares across every PR that settled this session, e.g.
|
|
103
|
+
* "APPROVE 45% · BLOCK 30% · error 25%". Empty when nothing has settled yet.
|
|
104
|
+
*/
|
|
105
|
+
private outcomeRow;
|
|
64
106
|
private statsRow;
|
|
65
107
|
private renderPRSlot;
|
|
66
108
|
private phaseLine1Label;
|
|
@@ -68,17 +110,30 @@ export declare class PRBoard {
|
|
|
68
110
|
private renderFixSection;
|
|
69
111
|
private renderRecheckSection;
|
|
70
112
|
private render;
|
|
113
|
+
/**
|
|
114
|
+
* Pick the slots the live page shows: the expanded layout when it fits, then
|
|
115
|
+
* the compact one, then compact with the oldest settled slots handed over to
|
|
116
|
+
* history until the block fits the viewport. Active slots are never handed
|
|
117
|
+
* over — a running review must stay on screen.
|
|
118
|
+
*/
|
|
119
|
+
private fitLivePage;
|
|
120
|
+
/** Rows the panels and footer cost, i.e. everything but the PR rows. */
|
|
121
|
+
private chromeRows;
|
|
122
|
+
private fitToBudget;
|
|
71
123
|
private renderLayout;
|
|
72
|
-
/**
|
|
73
|
-
private
|
|
124
|
+
/** Drop the oldest settled slots once the session history outgrows the cap. */
|
|
125
|
+
private trimHistory;
|
|
74
126
|
/** Drop rows from the top until the content (plus an indicator line) fits the budget. */
|
|
75
127
|
private truncateTop;
|
|
76
128
|
private renderConfigPanel;
|
|
77
129
|
private renderStatsPanel;
|
|
78
130
|
private renderTipLine;
|
|
79
131
|
private renderPRWorkspace;
|
|
132
|
+
/** Footer: where in the retained history this page sits, and how to move. */
|
|
133
|
+
private renderFooter;
|
|
80
134
|
private renderPRSlotFolded;
|
|
81
|
-
private evictOverflow;
|
|
82
135
|
private redraw;
|
|
136
|
+
private attachKeys;
|
|
137
|
+
private detachKeys;
|
|
83
138
|
}
|
|
84
139
|
//# sourceMappingURL=board.d.ts.map
|
package/dist/lib/board.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../src/lib/board.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAgB,MAAM,qBAAqB,CAAA;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../src/lib/board.ts"],"names":[],"mappings":"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"}
|