@motivation-labs/crosscheck 0.5.0 → 0.6.0
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 +24 -7
- package/crosscheck.config.example.yml +90 -4
- package/dist/__tests__/backtrace.test.d.ts +2 -0
- package/dist/__tests__/backtrace.test.d.ts.map +1 -0
- package/dist/__tests__/backtrace.test.js +158 -0
- package/dist/__tests__/backtrace.test.js.map +1 -0
- package/dist/__tests__/optimize.test.js +16 -3
- package/dist/__tests__/optimize.test.js.map +1 -1
- package/dist/cli.js +8 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/diagnose.d.ts +1 -0
- package/dist/commands/diagnose.d.ts.map +1 -1
- package/dist/commands/diagnose.js +14 -0
- package/dist/commands/diagnose.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +55 -18
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +11 -5
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/serve.d.ts +7 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +109 -16
- package/dist/commands/serve.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +1 -0
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/watch.d.ts +7 -1
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +349 -143
- package/dist/commands/watch.js.map +1 -1
- package/dist/config/loader.d.ts +8 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +143 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +445 -27
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +70 -7
- package/dist/config/schema.js.map +1 -1
- package/dist/github/client.d.ts +26 -0
- package/dist/github/client.d.ts.map +1 -1
- package/dist/github/client.js +153 -0
- package/dist/github/client.js.map +1 -1
- package/dist/github/detector.d.ts +8 -1
- package/dist/github/detector.d.ts.map +1 -1
- package/dist/github/detector.js +84 -12
- package/dist/github/detector.js.map +1 -1
- package/dist/lib/backtrace.d.ts +20 -0
- package/dist/lib/backtrace.d.ts.map +1 -0
- package/dist/lib/backtrace.js +75 -0
- package/dist/lib/backtrace.js.map +1 -0
- package/dist/lib/board.d.ts +52 -0
- package/dist/lib/board.d.ts.map +1 -0
- package/dist/lib/board.js +394 -0
- package/dist/lib/board.js.map +1 -0
- package/dist/lib/runner.d.ts +10 -1
- package/dist/lib/runner.d.ts.map +1 -1
- package/dist/lib/runner.js +129 -51
- package/dist/lib/runner.js.map +1 -1
- package/dist/lib/verdict.d.ts +1 -0
- package/dist/lib/verdict.d.ts.map +1 -1
- package/dist/lib/verdict.js +27 -7
- package/dist/lib/verdict.js.map +1 -1
- package/dist/lib/workflow.d.ts +8 -8
- package/dist/lib/workflow.d.ts.map +1 -1
- package/dist/lib/workflow.js +22 -5
- package/dist/lib/workflow.js.map +1 -1
- package/dist/reviewers/claude.d.ts +1 -1
- package/dist/reviewers/claude.d.ts.map +1 -1
- package/dist/reviewers/claude.js +4 -6
- package/dist/reviewers/claude.js.map +1 -1
- package/dist/reviewers/codex.d.ts +2 -2
- package/dist/reviewers/codex.d.ts.map +1 -1
- package/dist/reviewers/codex.js +6 -6
- package/dist/reviewers/codex.js.map +1 -1
- package/dist/reviewers/fix.d.ts +5 -0
- package/dist/reviewers/fix.d.ts.map +1 -0
- package/dist/reviewers/fix.js +87 -0
- package/dist/reviewers/fix.js.map +1 -0
- package/get-started.md +190 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,13 +74,15 @@ crosscheck watch
|
|
|
74
74
|
│ ├── clone PR branch │
|
|
75
75
|
│ ├── run reviewer (cross-vendor assignment) │
|
|
76
76
|
│ ├── post review comment │
|
|
77
|
-
│ └──
|
|
77
|
+
│ └── post-review auto-fix │
|
|
78
|
+
│ ├── authoring vendor reads review comment │
|
|
79
|
+
│ └── opens fix PR targeting original branch │
|
|
78
80
|
└────────────────────────────────────────────────────────────────┘
|
|
79
81
|
```
|
|
80
82
|
|
|
81
|
-
**Routing**
|
|
83
|
+
**Routing** uses a four-signal chain: PR body patterns → commit `Co-Authored-By:` trailers → branch prefix (`claude/` or `codex/`) → `author_routes` config fallback. `Generated with [Claude Code]` → Codex reviews. `Generated with [OpenAI Codex]` → Claude reviews. `allowed_authors` restricts reviews to your agent accounts.
|
|
82
84
|
|
|
83
|
-
**
|
|
85
|
+
**Post-review auto-fix** runs after the review when issues are found. The vendor that authored the PR (`fixer: same-as-author`) reads its own review comment and opens a new fix PR targeting the original branch. You review and merge the fix PR — the original PR then updates automatically. Controlled by `post_review.auto_fix` in your config.
|
|
84
86
|
|
|
85
87
|
**The feedback loop** closes via `crosscheck diagnose` → `crosscheck optimize`. Failure patterns and quality signals from `~/.crosscheck/logs/` feed back into improved reviewer instructions — no manual config editing required.
|
|
86
88
|
|
|
@@ -98,6 +100,7 @@ crosscheck watch
|
|
|
98
100
|
repos your-org/your-repo
|
|
99
101
|
mode cross-vendor
|
|
100
102
|
quality balanced
|
|
103
|
+
auto-fix on_issues · same-as-author · pull_request
|
|
101
104
|
config ./crosscheck.config.yml ← edit to change above
|
|
102
105
|
|
|
103
106
|
✓ tunnel ready: https://abc123.lhr.life
|
|
@@ -110,12 +113,14 @@ PR #47 opened: add retry logic for flaky network calls
|
|
|
110
113
|
review complete (12s)
|
|
111
114
|
posted → github.com/your-org/your-repo/pull/47
|
|
112
115
|
NEEDS WORK
|
|
116
|
+
auto-fix claude fixing...
|
|
117
|
+
fix PR #48 opened → github.com/your-org/your-repo/pull/48
|
|
113
118
|
|
|
114
|
-
PR #
|
|
119
|
+
PR #49 opened: implement caching layer
|
|
115
120
|
origin=codex reviewer=claude
|
|
116
121
|
claude reviewing... (18s)
|
|
117
122
|
review complete (18s)
|
|
118
|
-
posted → github.com/your-org/your-repo/pull/
|
|
123
|
+
posted → github.com/your-org/your-repo/pull/49
|
|
119
124
|
APPROVE
|
|
120
125
|
```
|
|
121
126
|
|
|
@@ -138,7 +143,7 @@ crosscheck impact [--money] # time saved, issues caught, code quality tr
|
|
|
138
143
|
|
|
139
144
|
## Configuration
|
|
140
145
|
|
|
141
|
-
|
|
146
|
+
Config lives at `~/.crosscheck/config.yml` by default — persistent across all projects, no per-repo file needed. Run `crosscheck init` to generate it. Project-local `crosscheck.config.yml` overrides the global config when present.
|
|
142
147
|
|
|
143
148
|
```yaml
|
|
144
149
|
# Which repos/orgs to watch (at least one required)
|
|
@@ -165,6 +170,16 @@ budget:
|
|
|
165
170
|
# smee — stable channel URL, queues events while offline
|
|
166
171
|
tunnel:
|
|
167
172
|
backend: localhost.run
|
|
173
|
+
|
|
174
|
+
# Post-review auto-fix — opens a fix PR when issues are found
|
|
175
|
+
post_review:
|
|
176
|
+
auto_fix:
|
|
177
|
+
enabled: true
|
|
178
|
+
trigger: on_issues # on_issues | always | never
|
|
179
|
+
min_severity: warning # error | warning | info
|
|
180
|
+
fixer: same-as-author # the vendor that wrote the PR also fixes it
|
|
181
|
+
delivery:
|
|
182
|
+
mode: pull_request # pull_request | commit | comment
|
|
168
183
|
```
|
|
169
184
|
|
|
170
185
|
Full configuration reference: [get-started.md](./get-started.md)
|
|
@@ -254,12 +269,14 @@ npm install -g smee-client
|
|
|
254
269
|
```
|
|
255
270
|
|
|
256
271
|
```yaml
|
|
257
|
-
# crosscheck
|
|
272
|
+
# ~/.crosscheck/config.yml
|
|
258
273
|
tunnel:
|
|
259
274
|
backend: smee
|
|
260
275
|
smee_channel: https://smee.io/your-channel-id
|
|
261
276
|
```
|
|
262
277
|
|
|
278
|
+
crosscheck registers the webhook automatically on first `watch` start — no manual webhook setup needed.
|
|
279
|
+
|
|
263
280
|
---
|
|
264
281
|
|
|
265
282
|
## Requirements
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
# This file is designed to be easily read and modified by coding agents.
|
|
3
3
|
# All fields are optional — crosscheck uses sensible defaults.
|
|
4
4
|
|
|
5
|
+
# ─── Deployment ──────────────────────────────────────────────────────────────
|
|
6
|
+
# Set automatically on first run of `crosscheck watch` or `crosscheck serve`.
|
|
7
|
+
# personal — monitor your own repos and orgs; review only PRs you author
|
|
8
|
+
# team — monitor org repos only; review all PRs from any author
|
|
9
|
+
# Absent = first-run prompt will ask you to choose.
|
|
10
|
+
# deployment: personal
|
|
11
|
+
|
|
5
12
|
# ─── Mode ────────────────────────────────────────────────────────────────────
|
|
6
13
|
# single-vendor: one AI reviews all PRs
|
|
7
14
|
# cross-vendor: each AI reviews the other's PRs (Claude ↔ Codex)
|
|
@@ -49,6 +56,15 @@ orgs:
|
|
|
49
56
|
- motivation-labs
|
|
50
57
|
- codatta
|
|
51
58
|
|
|
59
|
+
# ─── Users ───────────────────────────────────────────────────────────────────
|
|
60
|
+
# Monitor all repos owned by personal GitHub accounts (non-org).
|
|
61
|
+
# At startup, crosscheck enumerates each user's repos and registers webhooks.
|
|
62
|
+
# Useful when your AI agents open PRs across many personal repos.
|
|
63
|
+
# Combines with `orgs` and `repos` — all configured sources are additive.
|
|
64
|
+
# users:
|
|
65
|
+
# - beingzy # your personal account
|
|
66
|
+
# - my-agent-login # a bot account that pushes to its own repos
|
|
67
|
+
|
|
52
68
|
# ─── Repos ───────────────────────────────────────────────────────────────────
|
|
53
69
|
# Omit entirely to auto-detect from `git remote` (useful in watch mode)
|
|
54
70
|
# repos: still works for monitoring specific repos only
|
|
@@ -75,12 +91,28 @@ routing:
|
|
|
75
91
|
# author_routes:
|
|
76
92
|
# beingzy: claude
|
|
77
93
|
|
|
78
|
-
#
|
|
94
|
+
# Fallback reviewer when origin cannot be determined (no pattern/branch/route matched).
|
|
95
|
+
# 'auto' = pick whichever vendor is currently authenticated (codex first, then claude).
|
|
96
|
+
# 'codex' / 'claude' = always use that vendor.
|
|
97
|
+
# null = skip the PR (legacy cross-vendor behaviour).
|
|
98
|
+
fallback_reviewer: auto
|
|
99
|
+
|
|
100
|
+
# Branch-prefix routing — checked when body and commit patterns don't match.
|
|
101
|
+
# Agents should branch with these prefixes (claude/* and codex/*) so origin is
|
|
102
|
+
# always detectable even without attribution text in the PR body.
|
|
103
|
+
claude_branch_prefixes:
|
|
104
|
+
- "claude/"
|
|
105
|
+
codex_branch_prefixes:
|
|
106
|
+
- "codex/"
|
|
107
|
+
|
|
108
|
+
# Body and commit pattern matching — checked first, before branch prefix.
|
|
109
|
+
# Patterns are matched against both the PR body and commit messages (Co-Authored-By trailers).
|
|
79
110
|
codex_reviews_patterns:
|
|
80
|
-
- "Generated with \\[Claude Code\\]" #
|
|
111
|
+
- "Generated with \\[Claude Code\\]" # PR body attribution footer
|
|
112
|
+
- "Co-Authored-By: Claude" # commit trailer added by Claude Code
|
|
81
113
|
claude_reviews_patterns:
|
|
82
|
-
- "Generated with \\[OpenAI Codex\\]" #
|
|
83
|
-
- "Co-Authored-By: codex"
|
|
114
|
+
- "Generated with \\[OpenAI Codex\\]" # PR body attribution footer
|
|
115
|
+
- "Co-Authored-By: codex" # commit trailer added by Codex
|
|
84
116
|
|
|
85
117
|
# ─── Tunnel (watch mode only) ────────────────────────────────────────────────
|
|
86
118
|
# Controls how crosscheck watch receives GitHub webhook events on your laptop.
|
|
@@ -107,9 +139,63 @@ server:
|
|
|
107
139
|
webhook_path: /webhook
|
|
108
140
|
# pid_file: ~/.crosscheck/crosscheck.pid # for daemon management
|
|
109
141
|
|
|
142
|
+
# ─── Post-Review Auto-Fix ────────────────────────────────────────────────────
|
|
143
|
+
# After a CR completes, optionally dispatch the authoring agent to fix the issues.
|
|
144
|
+
#
|
|
145
|
+
# Complete loop:
|
|
146
|
+
# agent opens PR → opposite vendor reviews → authoring vendor fixes
|
|
147
|
+
# ↓
|
|
148
|
+
# fix PR opened targeting original branch
|
|
149
|
+
# ↓
|
|
150
|
+
# human reviews fix PR → merges → original PR updated
|
|
151
|
+
#
|
|
152
|
+
post_review:
|
|
153
|
+
auto_fix:
|
|
154
|
+
enabled: true
|
|
155
|
+
trigger: on_issues # on_issues | always | never
|
|
156
|
+
min_severity: warning # error | warning | info — skip cosmetic findings
|
|
157
|
+
|
|
158
|
+
# same-as-author: the vendor that wrote the PR also applies the fix (recommended)
|
|
159
|
+
# In cross-vendor mode: Claude wrote it → Claude fixes it, Codex wrote it → Codex fixes it
|
|
160
|
+
fixer: same-as-author # same-as-author | same-as-reviewer | codex | claude
|
|
161
|
+
|
|
162
|
+
delivery:
|
|
163
|
+
mode: pull_request # pull_request | commit | comment
|
|
164
|
+
# pull_request → fix PR targets the original branch; human approves before merge
|
|
165
|
+
# commit → fixes pushed directly onto the original PR branch
|
|
166
|
+
# comment → suggested fixes posted as review comments only
|
|
167
|
+
pr_title: "fix: address CR issues in #{original_pr_title}"
|
|
168
|
+
label: cr-autofix # GitHub label applied to the fix PR
|
|
169
|
+
|
|
170
|
+
# ─── Backtrace ───────────────────────────────────────────────────────────────
|
|
171
|
+
# On startup, scan all open PRs in the monitored scope and review any that have
|
|
172
|
+
# never received a [crosscheck] comment. Ensures coverage for PRs opened while
|
|
173
|
+
# crosscheck was offline or before it was first set up.
|
|
174
|
+
# backtrace:
|
|
175
|
+
# enabled: true # set to false to disable the startup scan entirely
|
|
176
|
+
|
|
110
177
|
# ─── Logs ────────────────────────────────────────────────────────────────────
|
|
111
178
|
# Structured debug logs written to ~/.crosscheck/logs/YYYY-MM-DD.ndjson
|
|
112
179
|
# Each line is a JSON object: { ts, level, event, ...context }
|
|
113
180
|
logs:
|
|
114
181
|
enabled: true
|
|
115
182
|
retention_days: 7 # delete files older than N days (min: 1, max: 30)
|
|
183
|
+
|
|
184
|
+
# ─── Display ─────────────────────────────────────────────────────────────────
|
|
185
|
+
# Terminal output theme for crosscheck watch.
|
|
186
|
+
# Override individual colors using chalk color names (red, green, blue, cyan,
|
|
187
|
+
# yellow, magenta, white, gray, dim, bold) or hex values (#rrggbb).
|
|
188
|
+
# display:
|
|
189
|
+
# theme:
|
|
190
|
+
# bar_fill: blue # filled █ segments on the PR size bar
|
|
191
|
+
# bar_empty: dim # empty ░ segments (all bars)
|
|
192
|
+
# cr_approve: green # CR bar + verdict label when APPROVE
|
|
193
|
+
# cr_needs_work: yellow # CR bar + verdict label when NEEDS WORK
|
|
194
|
+
# cr_block: red # CR bar + verdict label when BLOCK
|
|
195
|
+
# fix_fill: cyan # filled segments on the FIX bar
|
|
196
|
+
|
|
197
|
+
# ─── Backtrace ───────────────────────────────────────────────────────────────
|
|
198
|
+
# On startup, scan all open PRs in the monitored scope and review any that have
|
|
199
|
+
# never received a [crosscheck] comment.
|
|
200
|
+
# backtrace:
|
|
201
|
+
# enabled: true # set to false to disable the startup scan entirely
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backtrace.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/backtrace.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { scanUnreviewedPRs, buildScopesFromConfig } from '../lib/backtrace.js';
|
|
3
|
+
import { ConfigSchema } from '../config/schema.js';
|
|
4
|
+
vi.mock('../github/client.js', () => ({
|
|
5
|
+
listOpenPRs: vi.fn(),
|
|
6
|
+
listOrgRepos: vi.fn(),
|
|
7
|
+
listUserRepos: vi.fn(),
|
|
8
|
+
prHasCrossCheckComment: vi.fn(),
|
|
9
|
+
}));
|
|
10
|
+
const { listOpenPRs, listOrgRepos, listUserRepos, prHasCrossCheckComment } = await import('../github/client.js');
|
|
11
|
+
const mockListOpenPRs = vi.mocked(listOpenPRs);
|
|
12
|
+
const mockListOrgRepos = vi.mocked(listOrgRepos);
|
|
13
|
+
const mockListUserRepos = vi.mocked(listUserRepos);
|
|
14
|
+
const mockPrHasCrossCheckComment = vi.mocked(prHasCrossCheckComment);
|
|
15
|
+
const defaultConfig = ConfigSchema.parse({});
|
|
16
|
+
function makePR(overrides = {}) {
|
|
17
|
+
return {
|
|
18
|
+
number: overrides.number ?? 1,
|
|
19
|
+
title: 'test PR',
|
|
20
|
+
author: overrides.author ?? 'alice',
|
|
21
|
+
headSha: 'abc123',
|
|
22
|
+
headRef: 'feat/thing',
|
|
23
|
+
headRepo: 'acme/api',
|
|
24
|
+
baseRef: 'main',
|
|
25
|
+
body: null,
|
|
26
|
+
createdAt: overrides.createdAt ?? '2025-01-01T00:00:00Z',
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
vi.clearAllMocks();
|
|
31
|
+
});
|
|
32
|
+
describe('scanUnreviewedPRs', () => {
|
|
33
|
+
it('returns empty result for empty scopes without calling any API', async () => {
|
|
34
|
+
const result = await scanUnreviewedPRs([], defaultConfig, 'token');
|
|
35
|
+
expect(result).toEqual({ queued: [], alreadyReviewed: 0, skippedAuthor: 0 });
|
|
36
|
+
expect(mockListOpenPRs).not.toHaveBeenCalled();
|
|
37
|
+
});
|
|
38
|
+
it('includes a PR with no [crosscheck] comment', async () => {
|
|
39
|
+
const scopes = [{ owner: 'acme', repo: 'api' }];
|
|
40
|
+
mockListOpenPRs.mockResolvedValue([makePR()]);
|
|
41
|
+
mockPrHasCrossCheckComment.mockResolvedValue(false);
|
|
42
|
+
const result = await scanUnreviewedPRs(scopes, defaultConfig, 'token');
|
|
43
|
+
expect(result.queued).toHaveLength(1);
|
|
44
|
+
expect(result.queued[0].number).toBe(1);
|
|
45
|
+
expect(result.alreadyReviewed).toBe(0);
|
|
46
|
+
expect(result.skippedAuthor).toBe(0);
|
|
47
|
+
});
|
|
48
|
+
it('excludes a PR that already has a [crosscheck] comment', async () => {
|
|
49
|
+
const scopes = [{ owner: 'acme', repo: 'api' }];
|
|
50
|
+
mockListOpenPRs.mockResolvedValue([makePR()]);
|
|
51
|
+
mockPrHasCrossCheckComment.mockResolvedValue(true);
|
|
52
|
+
const result = await scanUnreviewedPRs(scopes, defaultConfig, 'token');
|
|
53
|
+
expect(result.queued).toHaveLength(0);
|
|
54
|
+
expect(result.alreadyReviewed).toBe(1);
|
|
55
|
+
});
|
|
56
|
+
it('excludes a PR whose author is not in allowed_authors', async () => {
|
|
57
|
+
const config = ConfigSchema.parse({ routing: { allowed_authors: ['bob'] } });
|
|
58
|
+
const scopes = [{ owner: 'acme', repo: 'api' }];
|
|
59
|
+
mockListOpenPRs.mockResolvedValue([makePR({ author: 'alice' })]);
|
|
60
|
+
const result = await scanUnreviewedPRs(scopes, config, 'token');
|
|
61
|
+
expect(result.queued).toHaveLength(0);
|
|
62
|
+
expect(result.skippedAuthor).toBe(1);
|
|
63
|
+
expect(mockPrHasCrossCheckComment).not.toHaveBeenCalled();
|
|
64
|
+
});
|
|
65
|
+
it('includes all authors when allowed_authors is empty', async () => {
|
|
66
|
+
const scopes = [{ owner: 'acme', repo: 'api' }];
|
|
67
|
+
mockListOpenPRs.mockResolvedValue([makePR({ author: 'anyone' })]);
|
|
68
|
+
mockPrHasCrossCheckComment.mockResolvedValue(false);
|
|
69
|
+
const result = await scanUnreviewedPRs(scopes, defaultConfig, 'token');
|
|
70
|
+
expect(result.queued).toHaveLength(1);
|
|
71
|
+
});
|
|
72
|
+
it('sorts queued PRs oldest-first', async () => {
|
|
73
|
+
const scopes = [{ owner: 'acme', repo: 'api' }];
|
|
74
|
+
mockListOpenPRs.mockResolvedValue([
|
|
75
|
+
makePR({ number: 3, createdAt: '2025-03-01T00:00:00Z' }),
|
|
76
|
+
makePR({ number: 1, createdAt: '2025-01-01T00:00:00Z' }),
|
|
77
|
+
makePR({ number: 2, createdAt: '2025-02-01T00:00:00Z' }),
|
|
78
|
+
]);
|
|
79
|
+
mockPrHasCrossCheckComment.mockResolvedValue(false);
|
|
80
|
+
const result = await scanUnreviewedPRs(scopes, defaultConfig, 'token');
|
|
81
|
+
expect(result.queued.map(p => p.number)).toEqual([1, 2, 3]);
|
|
82
|
+
});
|
|
83
|
+
it('expands org scopes to individual repos', async () => {
|
|
84
|
+
const scopes = [{ org: 'acme' }];
|
|
85
|
+
mockListOrgRepos.mockResolvedValue([
|
|
86
|
+
{ owner: 'acme', name: 'api' },
|
|
87
|
+
{ owner: 'acme', name: 'frontend' },
|
|
88
|
+
]);
|
|
89
|
+
mockListOpenPRs.mockResolvedValue([]);
|
|
90
|
+
await scanUnreviewedPRs(scopes, defaultConfig, 'token');
|
|
91
|
+
expect(mockListOrgRepos).toHaveBeenCalledWith('acme', 'token');
|
|
92
|
+
expect(mockListOpenPRs).toHaveBeenCalledWith('acme', 'api', 'token');
|
|
93
|
+
expect(mockListOpenPRs).toHaveBeenCalledWith('acme', 'frontend', 'token');
|
|
94
|
+
});
|
|
95
|
+
it('continues scan when listOpenPRs throws for one repo', async () => {
|
|
96
|
+
const scopes = [
|
|
97
|
+
{ owner: 'acme', repo: 'broken' },
|
|
98
|
+
{ owner: 'acme', repo: 'working' },
|
|
99
|
+
];
|
|
100
|
+
mockListOpenPRs
|
|
101
|
+
.mockRejectedValueOnce(new Error('API error'))
|
|
102
|
+
.mockResolvedValueOnce([makePR()]);
|
|
103
|
+
mockPrHasCrossCheckComment.mockResolvedValue(false);
|
|
104
|
+
const result = await scanUnreviewedPRs(scopes, defaultConfig, 'token');
|
|
105
|
+
expect(result.queued).toHaveLength(1);
|
|
106
|
+
});
|
|
107
|
+
it('skips a PR when prHasCrossCheckComment throws', async () => {
|
|
108
|
+
const scopes = [{ owner: 'acme', repo: 'api' }];
|
|
109
|
+
mockListOpenPRs.mockResolvedValue([makePR()]);
|
|
110
|
+
mockPrHasCrossCheckComment.mockRejectedValue(new Error('API error'));
|
|
111
|
+
const result = await scanUnreviewedPRs(scopes, defaultConfig, 'token');
|
|
112
|
+
expect(result.queued).toHaveLength(0);
|
|
113
|
+
expect(result.alreadyReviewed).toBe(0);
|
|
114
|
+
});
|
|
115
|
+
it('handles mixed queued / already-reviewed / skipped in one scan', async () => {
|
|
116
|
+
const config = ConfigSchema.parse({ routing: { allowed_authors: ['alice', 'bob'] } });
|
|
117
|
+
const scopes = [{ owner: 'acme', repo: 'api' }];
|
|
118
|
+
mockListOpenPRs.mockResolvedValue([
|
|
119
|
+
makePR({ number: 1, author: 'alice' }), // queued
|
|
120
|
+
makePR({ number: 2, author: 'bob' }), // already reviewed
|
|
121
|
+
makePR({ number: 3, author: 'carol' }), // skipped (author)
|
|
122
|
+
]);
|
|
123
|
+
mockPrHasCrossCheckComment
|
|
124
|
+
.mockResolvedValueOnce(false) // PR 1
|
|
125
|
+
.mockResolvedValueOnce(true); // PR 2
|
|
126
|
+
const result = await scanUnreviewedPRs(scopes, config, 'token');
|
|
127
|
+
expect(result.queued).toHaveLength(1);
|
|
128
|
+
expect(result.queued[0].number).toBe(1);
|
|
129
|
+
expect(result.alreadyReviewed).toBe(1);
|
|
130
|
+
expect(result.skippedAuthor).toBe(1);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe('buildScopesFromConfig', () => {
|
|
134
|
+
it('builds org and repo scopes from config', async () => {
|
|
135
|
+
const config = ConfigSchema.parse({
|
|
136
|
+
orgs: ['acme'],
|
|
137
|
+
repos: [{ owner: 'bob', name: 'myrepo' }],
|
|
138
|
+
});
|
|
139
|
+
const scopes = await buildScopesFromConfig(config, 'token');
|
|
140
|
+
expect(scopes).toContainEqual({ org: 'acme' });
|
|
141
|
+
expect(scopes).toContainEqual({ owner: 'bob', repo: 'myrepo' });
|
|
142
|
+
});
|
|
143
|
+
it('expands users to repo scopes', async () => {
|
|
144
|
+
const config = ConfigSchema.parse({ users: ['alice'] });
|
|
145
|
+
mockListUserRepos.mockResolvedValue([{ owner: 'alice', name: 'proj' }]);
|
|
146
|
+
const scopes = await buildScopesFromConfig(config, 'token');
|
|
147
|
+
expect(scopes).toContainEqual({ owner: 'alice', repo: 'proj' });
|
|
148
|
+
expect(mockListUserRepos).toHaveBeenCalledWith('alice', 'token');
|
|
149
|
+
});
|
|
150
|
+
it('continues when listUserRepos throws', async () => {
|
|
151
|
+
const config = ConfigSchema.parse({ users: ['alice'], orgs: ['acme'] });
|
|
152
|
+
mockListUserRepos.mockRejectedValue(new Error('API error'));
|
|
153
|
+
const scopes = await buildScopesFromConfig(config, 'token');
|
|
154
|
+
expect(scopes).toContainEqual({ org: 'acme' });
|
|
155
|
+
expect(scopes).not.toContainEqual(expect.objectContaining({ owner: 'alice' }));
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
//# sourceMappingURL=backtrace.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backtrace.test.js","sourceRoot":"","sources":["../../src/__tests__/backtrace.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,18 +4,30 @@ function makeConfig(claudeEnabled, codexEnabled) {
|
|
|
4
4
|
return {
|
|
5
5
|
mode: 'cross-vendor',
|
|
6
6
|
orgs: [],
|
|
7
|
+
users: [],
|
|
7
8
|
repos: [],
|
|
8
|
-
routing: { codex_reviews_patterns: [], claude_reviews_patterns: [], allowed_authors: [], author_routes: {} },
|
|
9
|
+
routing: { codex_reviews_patterns: [], claude_reviews_patterns: [], claude_branch_prefixes: [], codex_branch_prefixes: [], allowed_authors: [], author_routes: {}, fallback_reviewer: 'auto' },
|
|
9
10
|
server: { port: 7892, webhook_path: '/webhook' },
|
|
10
11
|
quality: { tier: 'balanced', focus: [], custom_prompt: undefined },
|
|
11
12
|
budget: { codex_monthly_usd: null, per_review_usd: 1 },
|
|
12
13
|
vendors: {
|
|
13
|
-
claude: { enabled: claudeEnabled, auth: 'subscription', effort: 'medium' },
|
|
14
|
-
codex: { enabled: codexEnabled, auth: 'subscription', effort: 'medium' },
|
|
14
|
+
claude: { enabled: claudeEnabled, model: null, auth: 'subscription', effort: 'medium' },
|
|
15
|
+
codex: { enabled: codexEnabled, model: null, auth: 'subscription', effort: 'medium', quality: 'medium' },
|
|
15
16
|
},
|
|
16
17
|
logs: { enabled: false, retention_days: 7 },
|
|
17
18
|
tunnel: { backend: 'localhost.run', smee_channel: '' },
|
|
18
19
|
impact: { assumed_human_review_minutes: 60, hourly_rate_usd: 150, defect_cost_usd: 150 },
|
|
20
|
+
backtrace: { enabled: true },
|
|
21
|
+
display: { theme: { bar_fill: 'blue', bar_empty: 'dim', cr_approve: 'green', cr_needs_work: 'yellow', cr_block: 'red', fix_fill: 'cyan' } },
|
|
22
|
+
post_review: {
|
|
23
|
+
auto_fix: {
|
|
24
|
+
enabled: false,
|
|
25
|
+
trigger: 'on_issues',
|
|
26
|
+
min_severity: 'warning',
|
|
27
|
+
fixer: 'same-as-author',
|
|
28
|
+
delivery: { mode: 'pull_request', pr_title: 'fix: address CR issues in #{original_pr_title}', label: 'cr-autofix' },
|
|
29
|
+
},
|
|
30
|
+
},
|
|
19
31
|
};
|
|
20
32
|
}
|
|
21
33
|
function makeReport(claudeAttempts = 0, claudeSuccesses = 0, codexAttempts = 0, codexSuccesses = 0) {
|
|
@@ -39,6 +51,7 @@ function makeReport(claudeAttempts = 0, claudeSuccesses = 0, codexAttempts = 0,
|
|
|
39
51
|
summary: { total_reviews: 0, successful: 0, failed: 0, failure_rate: 0 },
|
|
40
52
|
errors: [],
|
|
41
53
|
verdict_distribution: { APPROVE: 0, NEEDS_WORK: 0, BLOCK: 0 },
|
|
54
|
+
verdict_parse_failures: 0,
|
|
42
55
|
repos_seen: [],
|
|
43
56
|
languages_detected: [],
|
|
44
57
|
reviewer_performance: performance,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimize.test.js","sourceRoot":"","sources":["../../src/__tests__/optimize.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAI7D,SAAS,UAAU,CAAC,aAAsB,EAAE,YAAqB;IAC/D,OAAO;QACL,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,EAAE;QACR,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,EAAE,sBAAsB,EAAE,EAAE,EAAE,uBAAuB,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"optimize.test.js","sourceRoot":"","sources":["../../src/__tests__/optimize.test.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -28,12 +28,18 @@ program
|
|
|
28
28
|
.command('serve')
|
|
29
29
|
.description('[BETA] Always-on webhook server (mac-mini / home server mode)')
|
|
30
30
|
.option('-c, --config <path>', 'config file path')
|
|
31
|
-
.
|
|
31
|
+
.option('--personal', 'personal mode this session only (does not save to config)')
|
|
32
|
+
.option('--team', 'team mode this session only (does not save to config)')
|
|
33
|
+
.option('--reconfigure', 're-run deployment setup and save new choice to config')
|
|
34
|
+
.action((opts) => void runServe(opts));
|
|
32
35
|
program
|
|
33
36
|
.command('watch')
|
|
34
37
|
.description('Local dev mode — listen for PRs via gh webhook forward')
|
|
35
38
|
.option('-c, --config <path>', 'config file path')
|
|
36
|
-
.
|
|
39
|
+
.option('--personal', 'personal mode this session only (does not save to config)')
|
|
40
|
+
.option('--team', 'team mode this session only (does not save to config)')
|
|
41
|
+
.option('--reconfigure', 're-run deployment setup and save new choice to config')
|
|
42
|
+
.action((opts) => void runWatch(opts));
|
|
37
43
|
program
|
|
38
44
|
.command('review <pr-url>')
|
|
39
45
|
.description('Manually trigger a review for a single PR URL')
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAE9C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACzD,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAwB,CAAA;AAE/G,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,mDAAmD,CAAC;KAChE,OAAO,CAAC,OAAO,OAAO,EAAE,CAAC,CAAA;AAE5B,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,0DAA0D,CAAC;KACvE,MAAM,CAAC,qBAAqB,EAAE,2BAA2B,CAAC;KAC1D,MAAM,CAAC,CAAC,IAAyB,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;AAE9D,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,+DAA+D,CAAC;KAC5E,MAAM,CAAC,qBAAqB,EAAE,kBAAkB,CAAC;KACjD,MAAM,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../../src/commands/diagnose.ts"],"names":[],"mappings":"AAQA,KAAK,YAAY,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,SAAS,GAAG,cAAc,GAAG,OAAO,CAAA;AAEtG,UAAU,UAAU;IAClB,OAAO,EAAE,YAAY,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,gBAAgB,GAAG,aAAa,GAAG,eAAe,CAAA;IACxD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IACvD,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5F,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,oBAAoB,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5E,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,kBAAkB,EAAE,MAAM,EAAE,CAAA;IAC5B,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IAClD,WAAW,EAAE,UAAU,EAAE,CAAA;CAC1B;AAkDD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAY3G;AA8DD,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,cAAc,
|
|
1
|
+
{"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../../src/commands/diagnose.ts"],"names":[],"mappings":"AAQA,KAAK,YAAY,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,SAAS,GAAG,cAAc,GAAG,OAAO,CAAA;AAEtG,UAAU,UAAU;IAClB,OAAO,EAAE,YAAY,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,gBAAgB,GAAG,aAAa,GAAG,eAAe,CAAA;IACxD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IACvD,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5F,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,oBAAoB,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5E,sBAAsB,EAAE,MAAM,CAAA;IAC9B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,kBAAkB,EAAE,MAAM,EAAE,CAAA;IAC5B,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IAClD,WAAW,EAAE,UAAU,EAAE,CAAA;CAC1B;AAkDD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAY3G;AA8DD,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,cAAc,CA+GnF;AA0ED,wBAAsB,WAAW,CAAC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBzF"}
|
|
@@ -115,6 +115,7 @@ export function buildDiagnoseReport(since, logDir) {
|
|
|
115
115
|
const completed = new Set();
|
|
116
116
|
const errorPatterns = new Map();
|
|
117
117
|
const verdicts = { APPROVE: 0, NEEDS_WORK: 0, BLOCK: 0 };
|
|
118
|
+
let verdictParseFailures = 0;
|
|
118
119
|
const reposSeen = new Set();
|
|
119
120
|
const languagesSeen = new Set(); // from review_started log events
|
|
120
121
|
const reviewerStats = new Map();
|
|
@@ -147,6 +148,9 @@ export function buildDiagnoseReport(since, logDir) {
|
|
|
147
148
|
verdicts[v]++;
|
|
148
149
|
}
|
|
149
150
|
}
|
|
151
|
+
if (e.event === 'verdict_parse_failed') {
|
|
152
|
+
verdictParseFailures++;
|
|
153
|
+
}
|
|
150
154
|
if (e.event === 'error' && e.level === 'error') {
|
|
151
155
|
const msg = e.message ?? '';
|
|
152
156
|
const { pattern, command, branch } = classifyError(msg);
|
|
@@ -168,6 +172,12 @@ export function buildDiagnoseReport(since, logDir) {
|
|
|
168
172
|
const languagesFromErrors = detectLanguagesFromCommands(errors);
|
|
169
173
|
const languages = [...new Set([...languagesSeen, ...languagesFromErrors])];
|
|
170
174
|
const suggestions = buildSuggestions(errors, languages);
|
|
175
|
+
if (verdictParseFailures > 0) {
|
|
176
|
+
suggestions.push({
|
|
177
|
+
type: 'investigate',
|
|
178
|
+
reason: `Codex returned no verdict line ×${verdictParseFailures} — check your .codex/instructions file or lower vendors.codex.quality to "low"`,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
171
181
|
const fromDate = files[0]?.split('/').at(-1)?.replace('.ndjson', '') ?? 'N/A';
|
|
172
182
|
const toDate = files.at(-1)?.split('/').at(-1)?.replace('.ndjson', '') ?? 'N/A';
|
|
173
183
|
const totalReviews = started.size;
|
|
@@ -193,6 +203,7 @@ export function buildDiagnoseReport(since, logDir) {
|
|
|
193
203
|
},
|
|
194
204
|
errors,
|
|
195
205
|
verdict_distribution: verdicts,
|
|
206
|
+
verdict_parse_failures: verdictParseFailures,
|
|
196
207
|
repos_seen: [...reposSeen],
|
|
197
208
|
languages_detected: languages,
|
|
198
209
|
reviewer_performance,
|
|
@@ -212,6 +223,9 @@ function printReport(report) {
|
|
|
212
223
|
console.log(` total ${summary.total_reviews}`);
|
|
213
224
|
console.log(` successful ${chalk.green(summary.successful)}`);
|
|
214
225
|
console.log(` failed ${summary.failed > 0 ? chalk.red(summary.failed) : chalk.green(summary.failed)} ${summary.failed > 0 ? chalk.dim(`(${pct(summary.failed, summary.total_reviews)} failure rate)`) : ''}`);
|
|
226
|
+
if (report.verdict_parse_failures > 0) {
|
|
227
|
+
console.log(` no verdict ${chalk.yellow(report.verdict_parse_failures)} ${chalk.dim('(review completed but no VERDICT line found)')}`);
|
|
228
|
+
}
|
|
215
229
|
console.log();
|
|
216
230
|
if (Object.keys(rp).length > 0) {
|
|
217
231
|
console.log(chalk.dim(' Reviewer performance'));
|