@humanbased/crosscheck 0.15.1-beta.0 → 0.16.0-beta.16
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 +7 -3
- package/dist/__tests__/board.test.js +27 -0
- package/dist/__tests__/board.test.js.map +1 -1
- package/dist/__tests__/clone.test.d.ts +2 -0
- package/dist/__tests__/clone.test.d.ts.map +1 -0
- package/dist/__tests__/clone.test.js +9 -0
- package/dist/__tests__/clone.test.js.map +1 -0
- package/dist/__tests__/error-classification.test.js +14 -0
- package/dist/__tests__/error-classification.test.js.map +1 -1
- package/dist/__tests__/fix.test.js +45 -0
- package/dist/__tests__/fix.test.js.map +1 -1
- package/dist/__tests__/remediation.test.d.ts +2 -0
- package/dist/__tests__/remediation.test.d.ts.map +1 -0
- package/dist/__tests__/remediation.test.js +53 -0
- package/dist/__tests__/remediation.test.js.map +1 -0
- package/dist/__tests__/reviewer-error.test.js +20 -3
- package/dist/__tests__/reviewer-error.test.js.map +1 -1
- package/dist/__tests__/verdict-gate.test.js +4 -2
- package/dist/__tests__/verdict-gate.test.js.map +1 -1
- package/dist/__tests__/verdict.test.d.ts +2 -0
- package/dist/__tests__/verdict.test.d.ts.map +1 -0
- package/dist/__tests__/verdict.test.js +83 -0
- package/dist/__tests__/verdict.test.js.map +1 -0
- package/dist/commands/kickass.d.ts.map +1 -1
- package/dist/commands/kickass.js +20 -3
- package/dist/commands/kickass.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +64 -13
- package/dist/commands/run.js.map +1 -1
- package/dist/lib/board.d.ts.map +1 -1
- package/dist/lib/board.js +15 -1
- package/dist/lib/board.js.map +1 -1
- package/dist/lib/clone.d.ts +1 -0
- package/dist/lib/clone.d.ts.map +1 -1
- package/dist/lib/clone.js +21 -5
- package/dist/lib/clone.js.map +1 -1
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +3 -2
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/remediation.d.ts +3 -0
- package/dist/lib/remediation.d.ts.map +1 -0
- package/dist/lib/remediation.js +34 -0
- package/dist/lib/remediation.js.map +1 -0
- package/dist/lib/reviewer-error.d.ts.map +1 -1
- package/dist/lib/reviewer-error.js +17 -2
- package/dist/lib/reviewer-error.js.map +1 -1
- package/dist/lib/runner.d.ts +3 -0
- package/dist/lib/runner.d.ts.map +1 -1
- package/dist/lib/runner.js +65 -29
- package/dist/lib/runner.js.map +1 -1
- package/dist/lib/verdict.d.ts +1 -1
- package/dist/lib/verdict.d.ts.map +1 -1
- package/dist/lib/verdict.js +10 -10
- package/dist/lib/verdict.js.map +1 -1
- package/dist/reviewers/codex.d.ts.map +1 -1
- package/dist/reviewers/codex.js +4 -2
- package/dist/reviewers/codex.js.map +1 -1
- package/dist/reviewers/fix.d.ts.map +1 -1
- package/dist/reviewers/fix.js +2 -1
- package/dist/reviewers/fix.js.map +1 -1
- package/docs/growth/agent-execution.md +144 -0
- package/docs/growth/cycle-01-assets.md +198 -0
- package/docs/growth/cycle-2026-06-03.md +170 -0
- package/docs/proof-demo.md +12 -0
- package/get-started.md +4 -4
- package/package.json +2 -3
package/dist/lib/clone.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFileSync } from 'child_process';
|
|
2
2
|
// Bypass `gh repo clone` so gh's keyring auth (which may bridge to VS Code's
|
|
3
3
|
// GitHub extension) is never invoked. HTTPS embeds the token in the URL.
|
|
4
4
|
function buildCloneUrl(owner, repo, token, protocol) {
|
|
@@ -6,22 +6,38 @@ function buildCloneUrl(owner, repo, token, protocol) {
|
|
|
6
6
|
? `https://x-access-token:${token}@github.com/${owner}/${repo}.git`
|
|
7
7
|
: `git@github.com:${owner}/${repo}.git`;
|
|
8
8
|
}
|
|
9
|
+
export function redactCloneSecrets(value) {
|
|
10
|
+
return value.replace(/https:\/\/x-access-token:[^@\s]+@github\.com\//g, 'https://x-access-token:[REDACTED]@github.com/');
|
|
11
|
+
}
|
|
12
|
+
function runGit(args, cwd) {
|
|
13
|
+
try {
|
|
14
|
+
execFileSync('git', args, { cwd, stdio: 'pipe' });
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
if (!(err instanceof Error))
|
|
18
|
+
throw err;
|
|
19
|
+
const redacted = redactCloneSecrets(err.message);
|
|
20
|
+
const wrapped = new Error(redacted);
|
|
21
|
+
wrapped.stack = err.stack ? redactCloneSecrets(err.stack) : undefined;
|
|
22
|
+
throw wrapped;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
9
25
|
// Clone the repo, fetch & checkout the PR head, and fetch the base ref into
|
|
10
26
|
// refs/remotes/origin/<base>. onBaseFetchFailed lets callers log a warning;
|
|
11
27
|
// other failures bubble up.
|
|
12
28
|
export function clonePRForReview(params) {
|
|
13
29
|
const { owner, repo, prNumber, baseRef, tmpDir, token, protocol, onBaseFetchFailed } = params;
|
|
14
30
|
const cloneUrl = buildCloneUrl(owner, repo, token, protocol);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
31
|
+
runGit(['clone', '--depth=50', '--quiet', cloneUrl, tmpDir]);
|
|
32
|
+
runGit(['fetch', 'origin', `pull/${prNumber}/head:pr-${prNumber}`], tmpDir);
|
|
33
|
+
runGit(['checkout', `pr-${prNumber}`], tmpDir);
|
|
18
34
|
// Fetch base after PR checkout so we are never on the base branch during the fetch
|
|
19
35
|
// (git refuses to update a checked-out ref). Explicit refs/remotes/origin/<base>
|
|
20
36
|
// target so the remote-tracking ref is always created — `git fetch origin <branch>`
|
|
21
37
|
// alone only writes FETCH_HEAD in shallow clones when the branch is absent from
|
|
22
38
|
// the default refspec mapping.
|
|
23
39
|
try {
|
|
24
|
-
|
|
40
|
+
runGit(['fetch', 'origin', `${baseRef}:refs/remotes/origin/${baseRef}`], tmpDir);
|
|
25
41
|
}
|
|
26
42
|
catch {
|
|
27
43
|
onBaseFetchFailed?.();
|
package/dist/lib/clone.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clone.js","sourceRoot":"","sources":["../../src/lib/clone.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"clone.js","sourceRoot":"","sources":["../../src/lib/clone.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAG5C,6EAA6E;AAC7E,yEAAyE;AACzE,SAAS,aAAa,CAAC,KAAa,EAAE,IAAY,EAAE,KAAa,EAAE,QAAkC;IACnG,OAAO,QAAQ,KAAK,OAAO;QACzB,CAAC,CAAC,0BAA0B,KAAK,eAAe,KAAK,IAAI,IAAI,MAAM;QACnE,CAAC,CAAC,kBAAkB,KAAK,IAAI,IAAI,MAAM,CAAA;AAC3C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,OAAO,KAAK,CAAC,OAAO,CAAC,iDAAiD,EAAE,+CAA+C,CAAC,CAAA;AAC1H,CAAC;AAED,SAAS,MAAM,CAAC,IAAc,EAAE,GAAY;IAC1C,IAAI,CAAC;QACH,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,CAAC,GAAG,YAAY,KAAK,CAAC;YAAE,MAAM,GAAG,CAAA;QACtC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QAChD,MAAM,OAAO,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAA;QACnC,OAAO,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QACrE,MAAM,OAAO,CAAA;IACf,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,4EAA4E;AAC5E,4BAA4B;AAC5B,MAAM,UAAU,gBAAgB,CAAC,MAShC;IACC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAAA;IAC7F,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAA;IAC5D,MAAM,CAAC,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAA;IAC5D,MAAM,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,QAAQ,YAAY,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;IAC3E,MAAM,CAAC,CAAC,UAAU,EAAE,MAAM,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;IAC9C,mFAAmF;IACnF,iFAAiF;IACjF,oFAAoF;IACpF,gFAAgF;IAChF,+BAA+B;IAC/B,IAAI,CAAC;QACH,MAAM,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,OAAO,wBAAwB,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;IAClF,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB,EAAE,EAAE,CAAA;IACvB,CAAC;AACH,CAAC"}
|
package/dist/lib/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAErD,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,QAAQ,GACR,SAAS,GACT,SAAS,GACT,YAAY,GACZ,SAAS,CAAA;AAQb,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAsBnD;AAED,wBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAKzC;AAWD,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAKjD;AAED,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAErD,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,QAAQ,GACR,SAAS,GACT,SAAS,GACT,YAAY,GACZ,SAAS,CAAA;AAQb,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAsBnD;AAED,wBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAKzC;AAWD,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAKjD;AAED,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAoB5D;AAuBD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,GAAG,IAAI,CAE7E;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AAGD,wBAAgB,WAAW,CAAC,MAAM,EAAE,mBAAmB,GAAG,oBAAoB,EAAE,GAAG,EAAE,OAAO,GAAG,IAAI,CAElG"}
|
package/dist/lib/logger.js
CHANGED
|
@@ -71,13 +71,14 @@ export function classifyError(message) {
|
|
|
71
71
|
return 'overloaded';
|
|
72
72
|
if (/maximum budget|budget (?:exhausted|exceeded)|error_max_budget|reached maximum budget/.test(m))
|
|
73
73
|
return 'budget';
|
|
74
|
-
if (/bad credentials|401|not logged in|not authenticated|github_token|authentication required|token/.test(m))
|
|
74
|
+
if (/bad credentials|401|not logged in|not authenticated|github_token|authentication required|token|auth failure/.test(m))
|
|
75
75
|
return 'auth';
|
|
76
76
|
if (/admin:org|admin:repo|forbidden|403|insufficient scope|requires.*scope|write:org/.test(m))
|
|
77
77
|
return 'permission';
|
|
78
78
|
// Network check must precede timeout: subprocess stderr containing 'fetch failed'
|
|
79
79
|
// would otherwise be shadowed by '--no-timeout' in the CLI command string.
|
|
80
|
-
|
|
80
|
+
// ssl_error_syscall / libressl covers macOS LibreSSL errors on git clone/fetch.
|
|
81
|
+
if (/fetch failed|econnrefused|enotfound|network error|socket hang|socket timeout|ssl_error_syscall|libressl/.test(m))
|
|
81
82
|
return 'network';
|
|
82
83
|
if (/timeout|timed out|etimedout|deadline/.test(m))
|
|
83
84
|
return 'timeout';
|
package/dist/lib/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAc,MAAM,IAAI,CAAA;AACzF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAA;AAoB5B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,MAAM,CAAC,CAAA;AAEtD,IAAI,QAAQ,GAAG,KAAK,CAAA;AACpB,IAAI,gBAAgB,GAAG,KAAK,CAAA;AAC5B,IAAI,QAAQ,GAAG,EAAE,CAAA;AAEjB,MAAM,UAAU,UAAU,CAAC,MAAkB;IAC3C,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAA;IACzB,yEAAyE;IACzE,8EAA8E;IAC9E,gBAAgB,GAAG,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,IAAI,KAAK,CAAC,CAAA;IAClE,IAAI,CAAC,QAAQ;QAAE,OAAM;IAErB,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAEvC,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,cAAc,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;IACzE,IAAI,CAAC;QACH,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAE,SAAQ;YACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YACpC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAA;YACxC,IAAI,KAAK,GAAG,QAAQ;gBAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAE7B,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACnD,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC,CAAA;AAC7C,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,KAAe;IACjC,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ;QAAE,OAAM;IAClC,IAAI,CAAC;QACH,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAA;IAC7F,CAAC;IAAC,MAAM,CAAC,CAAC,gDAAgD,CAAC,CAAC;AAC9D,CAAC;AAED,oFAAoF;AACpF,iFAAiF;AACjF,EAAE;AACF,4EAA4E;AAC5E,uEAAuE;AACvE,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,qFAAqF;AACrF,MAAM,UAAU,WAAW,CAAC,KAAe;IACzC,IAAI,CAAC,gBAAgB,IAAI,CAAC,QAAQ;QAAE,OAAM;IAC1C,IAAI,CAAC;QACH,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAA;IAC9G,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,OAAO,gBAAgB,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;IAC/B,6EAA6E;IAC7E,+EAA+E;IAC/E,+EAA+E;IAC/E,qFAAqF;IACrF,yEAAyE;IACzE,+EAA+E;IAC/E,IAAI,mCAAmC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,YAAY,CAAA;IACpE,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,YAAY,CAAA;IACrD,IAAI,sFAAsF,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,QAAQ,CAAA;IACnH,IAAI,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAc,MAAM,IAAI,CAAA;AACzF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAA;AAoB5B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,MAAM,CAAC,CAAA;AAEtD,IAAI,QAAQ,GAAG,KAAK,CAAA;AACpB,IAAI,gBAAgB,GAAG,KAAK,CAAA;AAC5B,IAAI,QAAQ,GAAG,EAAE,CAAA;AAEjB,MAAM,UAAU,UAAU,CAAC,MAAkB;IAC3C,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAA;IACzB,yEAAyE;IACzE,8EAA8E;IAC9E,gBAAgB,GAAG,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,IAAI,KAAK,CAAC,CAAA;IAClE,IAAI,CAAC,QAAQ;QAAE,OAAM;IAErB,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAEvC,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,cAAc,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;IACzE,IAAI,CAAC;QACH,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAE,SAAQ;YACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YACpC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAA;YACxC,IAAI,KAAK,GAAG,QAAQ;gBAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAE7B,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACnD,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC,CAAA;AAC7C,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,KAAe;IACjC,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ;QAAE,OAAM;IAClC,IAAI,CAAC;QACH,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAA;IAC7F,CAAC;IAAC,MAAM,CAAC,CAAC,gDAAgD,CAAC,CAAC;AAC9D,CAAC;AAED,oFAAoF;AACpF,iFAAiF;AACjF,EAAE;AACF,4EAA4E;AAC5E,uEAAuE;AACvE,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,qFAAqF;AACrF,MAAM,UAAU,WAAW,CAAC,KAAe;IACzC,IAAI,CAAC,gBAAgB,IAAI,CAAC,QAAQ;QAAE,OAAM;IAC1C,IAAI,CAAC;QACH,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAA;IAC9G,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,OAAO,gBAAgB,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;IAC/B,6EAA6E;IAC7E,+EAA+E;IAC/E,+EAA+E;IAC/E,qFAAqF;IACrF,yEAAyE;IACzE,+EAA+E;IAC/E,IAAI,mCAAmC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,YAAY,CAAA;IACpE,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,YAAY,CAAA;IACrD,IAAI,sFAAsF,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,QAAQ,CAAA;IACnH,IAAI,6GAA6G,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAA;IACxI,IAAI,iFAAiF,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,YAAY,CAAA;IAClH,kFAAkF;IAClF,2EAA2E;IAC3E,gFAAgF;IAChF,IAAI,yGAAyG,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IACvI,IAAI,sCAAsC,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IACpE,IAAI,2DAA2D,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,YAAY,CAAA;IAC5F,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,8FAA8F;AAC9F,SAAS,kBAAkB,CAAC,GAAY;IACtC,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAA;IAEhD,MAAM,UAAU,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACnE,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,UAAU,CAAA;IACnG,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAC1E,MAAM,QAAQ,GAAG,aAAa,CAAC,UAAU,CAAC,CAAA;IAE1C,0EAA0E;IAC1E,MAAM,UAAU,GAAG,GAA8B,CAAA;IACjD,MAAM,QAAQ,GAAG,OAAO,UAAU,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAA;IAC1F,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;IAChE,MAAM,MAAM,GAAG,OAAO,UAAU,CAAC,MAAM,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE;QAC9E,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAE,qBAAqB;QAC/D,CAAC,CAAC,SAAS,CAAA;IACb,MAAM,OAAO,GAAG,OAAO,UAAU,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;IAEvF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;AAC1E,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAgC,EAAE,GAAY;IACrE,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAA;AACjF,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACnD,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC,CAAA;AACzC,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,WAAW,CAAC,MAAkD,EAAE,GAAY;IAC1F,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;AACrF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remediation.d.ts","sourceRoot":"","sources":["../../src/lib/remediation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAKhD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CA0B7E"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Returns a short one-line remediation hint for the operator given an error
|
|
2
|
+
// category and the raw error message. Returns empty string when no specific
|
|
3
|
+
// action can be suggested (subprocess / unknown — too varied to generalise).
|
|
4
|
+
export function hintForError(category, message) {
|
|
5
|
+
const m = message.toLowerCase();
|
|
6
|
+
switch (category) {
|
|
7
|
+
case 'auth':
|
|
8
|
+
if (/codex/.test(m))
|
|
9
|
+
return 'run: codex login';
|
|
10
|
+
if (/claude/.test(m))
|
|
11
|
+
return 'run: claude auth login';
|
|
12
|
+
if (/github_token|bad credentials/.test(m))
|
|
13
|
+
return 'check env: GITHUB_TOKEN';
|
|
14
|
+
return 'run: claude auth login (or codex login, or check GITHUB_TOKEN)';
|
|
15
|
+
case 'network':
|
|
16
|
+
if (/ssl_error_syscall|libressl|ssl_connect/.test(m))
|
|
17
|
+
return 'transient macOS/LibreSSL SSL error — retry in a moment; or set clone_protocol: ssh in crosscheck.config.yml';
|
|
18
|
+
return 'check network connectivity to github.com';
|
|
19
|
+
case 'timeout':
|
|
20
|
+
return 'raise vendor.<reviewer>.timeout_sec in config, or pass --timeout 600s';
|
|
21
|
+
case 'rate_limit':
|
|
22
|
+
return 'GitHub or model API rate limit — wait a few minutes and retry';
|
|
23
|
+
case 'overloaded':
|
|
24
|
+
return 'model API temporarily overloaded — retry in ~1 minute';
|
|
25
|
+
case 'budget':
|
|
26
|
+
return 'raise per_review_budget_usd in config, or run with --no-timeout for uncapped mode';
|
|
27
|
+
case 'permission':
|
|
28
|
+
return 'check GITHUB_TOKEN scopes — requires: repo, read:org';
|
|
29
|
+
case 'subprocess':
|
|
30
|
+
case 'unknown':
|
|
31
|
+
return '';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=remediation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remediation.js","sourceRoot":"","sources":["../../src/lib/remediation.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,4EAA4E;AAC5E,6EAA6E;AAC7E,MAAM,UAAU,YAAY,CAAC,QAAuB,EAAE,OAAe;IACnE,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;IAC/B,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,MAAM;YACT,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;gBAAE,OAAO,kBAAkB,CAAA;YAC9C,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;gBAAE,OAAO,wBAAwB,CAAA;YACrD,IAAI,8BAA8B,CAAC,IAAI,CAAC,CAAC,CAAC;gBAAE,OAAO,yBAAyB,CAAA;YAC5E,OAAO,iEAAiE,CAAA;QAC1E,KAAK,SAAS;YACZ,IAAI,wCAAwC,CAAC,IAAI,CAAC,CAAC,CAAC;gBAClD,OAAO,6GAA6G,CAAA;YACtH,OAAO,0CAA0C,CAAA;QACnD,KAAK,SAAS;YACZ,OAAO,uEAAuE,CAAA;QAChF,KAAK,YAAY;YACf,OAAO,+DAA+D,CAAA;QACxE,KAAK,YAAY;YACf,OAAO,uDAAuD,CAAA;QAChE,KAAK,QAAQ;YACX,OAAO,mFAAmF,CAAA;QAC5F,KAAK,YAAY;YACf,OAAO,sDAAsD,CAAA;QAC/D,KAAK,YAAY,CAAC;QAClB,KAAK,SAAS;YACZ,OAAO,EAAE,CAAA;IACb,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewer-error.d.ts","sourceRoot":"","sources":["../../src/lib/reviewer-error.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAU7D,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,kBAAkB,CAAA;IAE1B,OAAO,EAAE,MAAM,CAAA;IAEf,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,uBAAuB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"reviewer-error.d.ts","sourceRoot":"","sources":["../../src/lib/reviewer-error.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAU7D,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,kBAAkB,CAAA;IAE1B,OAAO,EAAE,MAAM,CAAA;IAEf,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,uBAAuB,GAAG,IAAI,CAmElF"}
|
|
@@ -44,11 +44,26 @@ export function classifyReviewerError(err) {
|
|
|
44
44
|
details: `Vendor: \`${vendor}\`\nError: ${stripVendorPrefix(err.message)}`,
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
-
//
|
|
47
|
+
// Auth failure — surface a specific login command rather than a generic message.
|
|
48
|
+
const msgBody = stripVendorPrefix(err.message);
|
|
49
|
+
if (/not logged in|auth failure|authentication required|bad credentials|unauthorized/i.test(msgBody)) {
|
|
50
|
+
const loginCmd = vendor === 'claude' ? 'claude auth login' : 'codex login';
|
|
51
|
+
return {
|
|
52
|
+
reason: 'subprocess_error',
|
|
53
|
+
summary: `${vendor} auth expired — run \`${loginCmd}\` on the crosscheck host`,
|
|
54
|
+
details: [
|
|
55
|
+
`Vendor: \`${vendor}\``,
|
|
56
|
+
`Fix: run \`${loginCmd}\` on the machine running crosscheck to re-authenticate.`,
|
|
57
|
+
'',
|
|
58
|
+
`Error: ${msgBody}`,
|
|
59
|
+
].join('\n'),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// Catch-all: network, subprocess crash, garbled output, etc.
|
|
48
63
|
const detailLines = [`Vendor: \`${vendor}\``];
|
|
49
64
|
if (ann.exitCode !== undefined)
|
|
50
65
|
detailLines.push(`Exit code: ${ann.exitCode}`);
|
|
51
|
-
detailLines.push(`Error: ${
|
|
66
|
+
detailLines.push(`Error: ${msgBody}`);
|
|
52
67
|
if (ann.stderr && ann.stderr.trim().length > 0) {
|
|
53
68
|
const tail = ann.stderr.trim().split('\n').slice(-5).join('\n');
|
|
54
69
|
detailLines.push('', '```', tail, '```');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewer-error.js","sourceRoot":"","sources":["../../src/lib/reviewer-error.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,4EAA4E;AAC5E,yEAAyE;AACzE,4CAA4C;AAC5C,EAAE;AACF,yEAAyE;AACzE,8EAA8E;AAC9E,8EAA8E;AAC9E,4BAA4B;AAC5B,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAA;AAmB5D,MAAM,UAAU,qBAAqB,CAAC,GAAY;IAChD,IAAI,CAAC,CAAC,GAAG,YAAY,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACxC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IAExD,MAAM,GAAG,GAAG,GAAuC,CAAA;IACnD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAA;IAErE,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC1B,MAAM,UAAU,GAAG,GAAG,CAAC,kBAAkB,KAAK,SAAS;YACrD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,kBAAkB,GAAG,IAAI,CAAC;YAC3C,CAAC,CAAC,SAAS,CAAA;QACb,MAAM,aAAa,GAAG,GAAG,CAAC,YAAY,KAAK,SAAS;YAClD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC;YACrC,CAAC,CAAC,SAAS,CAAA;QACb,MAAM,OAAO,GAAG,UAAU,KAAK,SAAS;YACtC,CAAC,CAAC,GAAG,MAAM,wCAAwC,UAAU,GAAG;YAChE,CAAC,CAAC,GAAG,MAAM,gCAAgC,CAAA;QAC7C,MAAM,WAAW,GAAG;YAClB,aAAa,MAAM,IAAI;SACxB,CAAA;QACD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,WAAW,CAAC,IAAI,CAAC,uBAAuB,UAAU,GAAG,CAAC,CAAA;QACxD,CAAC;QACD,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,WAAW,CAAC,IAAI,CAAC,wBAAwB,aAAa,yCAAyC,CAAC,CAAA;QAClG,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,kGAAkG,CAAC,CAAA;QACxH,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;IACxE,CAAC;IAED,IAAI,wBAAwB,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,MAAM,EAAE,aAAa;YACrB,OAAO,EAAE,GAAG,MAAM,oCAAoC;YACtD,OAAO,EAAE,aAAa,MAAM,cAAc,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;SAC3E,CAAA;IACH,CAAC;IAED,
|
|
1
|
+
{"version":3,"file":"reviewer-error.js","sourceRoot":"","sources":["../../src/lib/reviewer-error.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,4EAA4E;AAC5E,yEAAyE;AACzE,4CAA4C;AAC5C,EAAE;AACF,yEAAyE;AACzE,8EAA8E;AAC9E,8EAA8E;AAC9E,4BAA4B;AAC5B,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAA;AAmB5D,MAAM,UAAU,qBAAqB,CAAC,GAAY;IAChD,IAAI,CAAC,CAAC,GAAG,YAAY,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACxC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IAExD,MAAM,GAAG,GAAG,GAAuC,CAAA;IACnD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAA;IAErE,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC1B,MAAM,UAAU,GAAG,GAAG,CAAC,kBAAkB,KAAK,SAAS;YACrD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,kBAAkB,GAAG,IAAI,CAAC;YAC3C,CAAC,CAAC,SAAS,CAAA;QACb,MAAM,aAAa,GAAG,GAAG,CAAC,YAAY,KAAK,SAAS;YAClD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC;YACrC,CAAC,CAAC,SAAS,CAAA;QACb,MAAM,OAAO,GAAG,UAAU,KAAK,SAAS;YACtC,CAAC,CAAC,GAAG,MAAM,wCAAwC,UAAU,GAAG;YAChE,CAAC,CAAC,GAAG,MAAM,gCAAgC,CAAA;QAC7C,MAAM,WAAW,GAAG;YAClB,aAAa,MAAM,IAAI;SACxB,CAAA;QACD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,WAAW,CAAC,IAAI,CAAC,uBAAuB,UAAU,GAAG,CAAC,CAAA;QACxD,CAAC;QACD,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,WAAW,CAAC,IAAI,CAAC,wBAAwB,aAAa,yCAAyC,CAAC,CAAA;QAClG,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,kGAAkG,CAAC,CAAA;QACxH,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;IACxE,CAAC;IAED,IAAI,wBAAwB,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,MAAM,EAAE,aAAa;YACrB,OAAO,EAAE,GAAG,MAAM,oCAAoC;YACtD,OAAO,EAAE,aAAa,MAAM,cAAc,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;SAC3E,CAAA;IACH,CAAC;IAED,iFAAiF;IACjF,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAC9C,IAAI,kFAAkF,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACrG,MAAM,QAAQ,GAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,aAAa,CAAA;QAC1E,OAAO;YACL,MAAM,EAAE,kBAAkB;YAC1B,OAAO,EAAE,GAAG,MAAM,yBAAyB,QAAQ,2BAA2B;YAC9E,OAAO,EAAE;gBACP,aAAa,MAAM,IAAI;gBACvB,cAAc,QAAQ,0DAA0D;gBAChF,EAAE;gBACF,UAAU,OAAO,EAAE;aACpB,CAAC,IAAI,CAAC,IAAI,CAAC;SACb,CAAA;IACH,CAAC;IAED,6DAA6D;IAC7D,MAAM,WAAW,GAAG,CAAC,aAAa,MAAM,IAAI,CAAC,CAAA;IAC7C,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS;QAAE,WAAW,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC9E,WAAW,CAAC,IAAI,CAAC,UAAU,OAAO,EAAE,CAAC,CAAA;IACrC,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC/D,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;IAC1C,CAAC;IACD,OAAO;QACL,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,GAAG,MAAM,6BAA6B;QAC/C,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;KAChC,CAAA;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IACpC,OAAO,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAA;AAC/C,CAAC"}
|
package/dist/lib/runner.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ export interface WorkflowCompleteInputs {
|
|
|
20
20
|
round?: number;
|
|
21
21
|
trigger?: WorkflowTrigger;
|
|
22
22
|
qualityTier?: string;
|
|
23
|
+
workflowError?: unknown;
|
|
24
|
+
failedStep?: string;
|
|
23
25
|
now?: number;
|
|
24
26
|
}
|
|
25
27
|
export type WorkflowEndedReason = 'completed' | 'error' | 'progress_gate' | 'max_iterations' | 'manual_abort';
|
|
@@ -70,6 +72,7 @@ export interface WorkflowContext {
|
|
|
70
72
|
export interface WorkflowResult {
|
|
71
73
|
verdict: string | null;
|
|
72
74
|
fixAppliedCount?: number;
|
|
75
|
+
fixSkipReason?: string;
|
|
73
76
|
latestReviewComment?: {
|
|
74
77
|
id?: number;
|
|
75
78
|
body: string;
|
package/dist/lib/runner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lib/runner.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAa9C,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAChF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lib/runner.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/runner.js
CHANGED
|
@@ -10,13 +10,14 @@ import { runConflictResolveStep, findConflictedFiles } from '../reviewers/confli
|
|
|
10
10
|
import { parseVerdict, prependVerdictToComment, NULL_VERDICT_WARNING, applySeverityGate, SEVERITY_GATE_NOTE } from '../lib/verdict.js';
|
|
11
11
|
import { createGithubClient, postReviewComment, getLastCrossCheckCommentId, getLastCrossCheckReviewComment } from '../github/client.js';
|
|
12
12
|
import { acquireRemoteLock, releaseRemoteLock } from '../github/review-status.js';
|
|
13
|
-
import { log as fileLog, logError } from '../lib/logger.js';
|
|
13
|
+
import { log as fileLog, logError, classifyError } from '../lib/logger.js';
|
|
14
14
|
import { buildCommitTrailers } from '../lib/annotation.js';
|
|
15
15
|
import { resolveClaudeModel, resolveCodexModel } from '../lib/review-models.js';
|
|
16
16
|
import { buildStepIdentityFields } from '../lib/event-fields.js';
|
|
17
17
|
import { buildFixAppliedCommentBody, buildConflictResolvedCommentBody, buildRetriedReviewBanner } from '../lib/comment-bodies.js';
|
|
18
18
|
import { loadWorkflow, evaluateWhen } from '../lib/workflow.js';
|
|
19
19
|
import { isSubscriptionLimitError } from '../lib/smart-switch.js';
|
|
20
|
+
import { tierTimeoutMs } from '../reviewers/tier-timeouts.js';
|
|
20
21
|
const MAX_CROSSCHECK_COMMITS = 5;
|
|
21
22
|
const FIX_RETRY_DELAY_MS = 2 * 60 * 1000;
|
|
22
23
|
// Per-vendor configured timeout (seconds) → execa milliseconds, or undefined when
|
|
@@ -70,6 +71,10 @@ export function buildWorkflowCompleteEvent(inputs) {
|
|
|
70
71
|
const lastStep = inputs.stepsRun.length > 0 ? inputs.stepsRun[inputs.stepsRun.length - 1] : null;
|
|
71
72
|
const endedReason = inputs.workflowFailed ? 'error' : 'completed';
|
|
72
73
|
const now = inputs.now ?? Date.now();
|
|
74
|
+
const rawErrorMessage = inputs.workflowError instanceof Error ? inputs.workflowError.message : inputs.workflowError !== undefined ? String(inputs.workflowError) : undefined;
|
|
75
|
+
const errorMessage = rawErrorMessage !== undefined && rawErrorMessage.length > 500
|
|
76
|
+
? `${rawErrorMessage.slice(0, 500)} …[truncated]`
|
|
77
|
+
: rawErrorMessage;
|
|
73
78
|
const totalTokens = stepValues.reduce((s, r) => s + (r.tokens_used ?? 0), 0);
|
|
74
79
|
// Only emit split fields when at least one step actually recorded them — avoid
|
|
75
80
|
// emitting 0/0 for codex-only or fix-only workflows where splits are unavailable.
|
|
@@ -93,6 +98,8 @@ export function buildWorkflowCompleteEvent(inputs) {
|
|
|
93
98
|
...(inputs.qualityTier !== undefined && { quality_tier: inputs.qualityTier }),
|
|
94
99
|
...(inputs.round !== undefined && { round: inputs.round }),
|
|
95
100
|
...(inputs.trigger !== undefined && { trigger: inputs.trigger }),
|
|
101
|
+
...(inputs.failedStep !== undefined && { failed_step: inputs.failedStep }),
|
|
102
|
+
...(errorMessage !== undefined && { error_message: errorMessage, error_category: classifyError(rawErrorMessage ?? '') }),
|
|
96
103
|
};
|
|
97
104
|
}
|
|
98
105
|
// Returns true when fix/recheck steps should be skipped because the configured
|
|
@@ -269,11 +276,14 @@ export async function runWorkflow(ctx) {
|
|
|
269
276
|
// mid-workflow (process.exit there bypasses our finally below).
|
|
270
277
|
const pushedShasNeedingRelease = ctx.pushedShas ?? [];
|
|
271
278
|
let workflowFailed = false;
|
|
279
|
+
let workflowError = undefined;
|
|
280
|
+
let failedStep = undefined;
|
|
272
281
|
// When a fix commits and a structural review/recheck step follows, we acquire
|
|
273
282
|
// the remote lock on the pushed SHA. Track it here so the finally can detect
|
|
274
283
|
// whether the recheck was actually skipped (by `when`, no_reviewer, etc.) and
|
|
275
284
|
// release the SHA as `failure` rather than `success` in that case.
|
|
276
285
|
let fixPushedShaRequiresRecheck = null;
|
|
286
|
+
let lastFixSkipReason;
|
|
277
287
|
// workflow_complete event accumulators. Each step the runner dispatches is
|
|
278
288
|
// recorded in stepsRun (including ones that get logged as step_skipped —
|
|
279
289
|
// the event records the workflow's declared shape, the per-step skip
|
|
@@ -281,9 +291,11 @@ export async function runWorkflow(ctx) {
|
|
|
281
291
|
const workflowId = randomUUID();
|
|
282
292
|
const workflowStart = Date.now();
|
|
283
293
|
const stepsRun = [];
|
|
294
|
+
let currentStepName;
|
|
284
295
|
emitPRComplexity(ctx, triggerField);
|
|
285
296
|
try {
|
|
286
297
|
for (const step of steps) {
|
|
298
|
+
currentStepName = step.name;
|
|
287
299
|
stepsRun.push(step.name);
|
|
288
300
|
const effectiveType = getEffectiveStepType(step.type, ctx.isRecheckRun === true);
|
|
289
301
|
if (exceedsMaxRounds(effectiveType, step.type, ctx.overrideMaxRounds ?? step.max_rounds, ctx.round)) {
|
|
@@ -351,29 +363,39 @@ export async function runWorkflow(ctx) {
|
|
|
351
363
|
await runReviewWithVendor(reviewer);
|
|
352
364
|
}
|
|
353
365
|
catch (err) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
366
|
+
const isReconnect = err instanceof Error && /reconnect/i.test(err.message);
|
|
367
|
+
if (isReconnect) {
|
|
368
|
+
fileLog({ level: 'warn', event: 'review_reconnect_retry', repo: `${owner}/${repoName}`, pr: prNumber, reviewer, ...stepIdentity });
|
|
369
|
+
log(chalk.yellow(`⚠ codex connection dropped — retrying in 30s...`));
|
|
370
|
+
await new Promise(r => setTimeout(r, 30_000));
|
|
371
|
+
await runReviewWithVendor(reviewer);
|
|
372
|
+
}
|
|
373
|
+
else if (!isSubscriptionLimitError(err)) {
|
|
361
374
|
throw err;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
const failedVendor = reviewer;
|
|
378
|
+
const fallbackVendor = resolveLimitFallbackVendor(failedVendor, effectiveType, config);
|
|
379
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
380
|
+
ctx.onVendorLimit?.(failedVendor, fallbackVendor, reason, step.name);
|
|
381
|
+
if (!fallbackVendor)
|
|
382
|
+
throw err;
|
|
383
|
+
fileLog({
|
|
384
|
+
level: 'warn',
|
|
385
|
+
event: 'vendor_fallback',
|
|
386
|
+
repo: `${owner}/${repoName}`,
|
|
387
|
+
pr: prNumber,
|
|
388
|
+
step: step.name,
|
|
389
|
+
step_type: effectiveType,
|
|
390
|
+
failed_vendor: failedVendor,
|
|
391
|
+
fallback_vendor: fallbackVendor,
|
|
392
|
+
reason: reason.slice(0, 300),
|
|
393
|
+
});
|
|
394
|
+
log(chalk.yellow(`⚠ ${failedVendor} hit a usage limit — switching ${effectiveType} step to ${fallbackVendor}`));
|
|
395
|
+
reviewer = fallbackVendor;
|
|
396
|
+
onPhaseChange(`${reviewer} ${isRecheck ? 'rechecking' : 'reviewing'}...`, { phase: startPhase });
|
|
397
|
+
await runReviewWithVendor(reviewer);
|
|
398
|
+
}
|
|
377
399
|
}
|
|
378
400
|
// First attempt timed out but the delayed retry succeeded — surface a
|
|
379
401
|
// soft notice on the review comment so the author knows it was a transient blip.
|
|
@@ -385,8 +407,9 @@ export async function runWorkflow(ctx) {
|
|
|
385
407
|
if (parsed.verdict === null) {
|
|
386
408
|
fileLog({ level: 'warn', event: 'verdict_parse_failed', repo: `${owner}/${repoName}`, pr: prNumber, reviewer, ...stepIdentity, output_length: rawReview.length });
|
|
387
409
|
}
|
|
388
|
-
// Severity gate:
|
|
389
|
-
//
|
|
410
|
+
// Severity gate: NEEDS WORK with only P3 nits is downgraded to APPROVE so
|
|
411
|
+
// suggestion-only reviews don't drive the fix/recheck loop. P2 (correctness)
|
|
412
|
+
// and above keep NEEDS WORK and require human attention before merge.
|
|
390
413
|
const gate = applySeverityGate(parsed.verdict, clean);
|
|
391
414
|
const verdict = gate.verdict;
|
|
392
415
|
if (gate.downgraded) {
|
|
@@ -446,6 +469,7 @@ export async function runWorkflow(ctx) {
|
|
|
446
469
|
}
|
|
447
470
|
else if (effectiveType === 'fix') {
|
|
448
471
|
const skipFix = (reason) => {
|
|
472
|
+
lastFixSkipReason = reason;
|
|
449
473
|
onPhaseChange('', { phase: 'fixed', fixCount: 0 });
|
|
450
474
|
results[step.name] = { skipped: true };
|
|
451
475
|
fileLog({ level: 'info', event: 'step_skipped', repo: `${owner}/${repoName}`, pr: prNumber, step: step.name, reason });
|
|
@@ -504,9 +528,11 @@ export async function runWorkflow(ctx) {
|
|
|
504
528
|
// Guard: don't push more than MAX_CROSSCHECK_COMMITS per PR.
|
|
505
529
|
// Scope to commits ahead of base so long-lived branches (e.g. staging)
|
|
506
530
|
// don't count [crosscheck] commits from previously merged PRs.
|
|
531
|
+
// Crazy/halfcrazy mode doubles the cap since it deliberately loops.
|
|
507
532
|
const existingCount = countCrosscheckCommitsForPR(tmpDir, pr.base.ref);
|
|
508
|
-
|
|
509
|
-
|
|
533
|
+
const effectiveCommitLimit = ctx.roundMode ? MAX_CROSSCHECK_COMMITS * 2 : MAX_CROSSCHECK_COMMITS;
|
|
534
|
+
if (existingCount >= effectiveCommitLimit) {
|
|
535
|
+
log(chalk.yellow(`⚠ PR #${prNumber}: ${effectiveCommitLimit} [crosscheck] commits already — stopping auto-fix`));
|
|
510
536
|
skipFix('commit_limit_reached');
|
|
511
537
|
continue;
|
|
512
538
|
}
|
|
@@ -516,11 +542,12 @@ export async function runWorkflow(ctx) {
|
|
|
516
542
|
let fixTokensUsed;
|
|
517
543
|
let fixErr = undefined;
|
|
518
544
|
let activeVendor = vendor;
|
|
545
|
+
const tierMs = tierTimeoutMs(config.quality.tier);
|
|
519
546
|
const runFix = async (v) => {
|
|
520
547
|
if (v === 'codex') {
|
|
521
|
-
return runCodexFixStep(tmpDir, pr.base.ref, pr.title, reviewCommentBody, step.instructions ?? '', codexFixModel, ctx.overrideTimeoutMs ?? vendorTimeoutMs(config.vendors.codex.timeout_sec));
|
|
548
|
+
return runCodexFixStep(tmpDir, pr.base.ref, pr.title, reviewCommentBody, step.instructions ?? '', codexFixModel, ctx.overrideTimeoutMs ?? vendorTimeoutMs(config.vendors.codex.timeout_sec) ?? tierMs);
|
|
522
549
|
}
|
|
523
|
-
return runFixStep(tmpDir, pr.base.ref, pr.title, reviewCommentBody, step.instructions ?? '', config, 'default', ctx.overrideTimeoutMs ?? vendorTimeoutMs(config.vendors.claude.timeout_sec));
|
|
550
|
+
return runFixStep(tmpDir, pr.base.ref, pr.title, reviewCommentBody, step.instructions ?? '', config, 'default', ctx.overrideTimeoutMs ?? vendorTimeoutMs(config.vendors.claude.timeout_sec) ?? tierMs);
|
|
524
551
|
};
|
|
525
552
|
try {
|
|
526
553
|
;
|
|
@@ -543,6 +570,7 @@ export async function runWorkflow(ctx) {
|
|
|
543
570
|
}
|
|
544
571
|
catch (fallbackErr) {
|
|
545
572
|
logError({ repo: `${owner}/${repoName}`, pr: prNumber, phase: 'fix', attempt: 1, vendor: fallbackVendor }, fallbackErr);
|
|
573
|
+
activeVendor = fallbackVendor; // retry uses the fallback vendor since primary already failed
|
|
546
574
|
fixErr = fallbackErr;
|
|
547
575
|
}
|
|
548
576
|
}
|
|
@@ -581,6 +609,9 @@ export async function runWorkflow(ctx) {
|
|
|
581
609
|
}
|
|
582
610
|
catch { /* best-effort notification */ }
|
|
583
611
|
}
|
|
612
|
+
// The review was already posted — treat fix failure as a skipped step so the
|
|
613
|
+
// workflow completes with the review's verdict rather than exiting non-zero and
|
|
614
|
+
// releasing the remote lock as a workflow failure.
|
|
584
615
|
continue;
|
|
585
616
|
}
|
|
586
617
|
if (appliedCount === 0) {
|
|
@@ -941,6 +972,7 @@ export async function runWorkflow(ctx) {
|
|
|
941
972
|
return {
|
|
942
973
|
verdict: verdict ?? null,
|
|
943
974
|
fixAppliedCount,
|
|
975
|
+
...(fixAppliedCount === undefined && lastFixSkipReason !== undefined && { fixSkipReason: lastFixSkipReason }),
|
|
944
976
|
...(latestReviewResult?.commentBody && {
|
|
945
977
|
latestReviewComment: {
|
|
946
978
|
body: latestReviewResult.commentBody,
|
|
@@ -951,6 +983,8 @@ export async function runWorkflow(ctx) {
|
|
|
951
983
|
}
|
|
952
984
|
catch (err) {
|
|
953
985
|
workflowFailed = true;
|
|
986
|
+
workflowError = err;
|
|
987
|
+
failedStep = currentStepName;
|
|
954
988
|
throw err;
|
|
955
989
|
}
|
|
956
990
|
finally {
|
|
@@ -1001,6 +1035,8 @@ export async function runWorkflow(ctx) {
|
|
|
1001
1035
|
fileLog(buildWorkflowCompleteEvent({
|
|
1002
1036
|
owner, repoName, prNumber,
|
|
1003
1037
|
workflowId, workflowStart, stepsRun, results, workflowFailed,
|
|
1038
|
+
workflowError,
|
|
1039
|
+
failedStep,
|
|
1004
1040
|
round: ctx.round,
|
|
1005
1041
|
trigger: ctx.trigger,
|
|
1006
1042
|
qualityTier: config.quality.tier,
|