@humanbased/crosscheck 1.2.0-beta.81 → 1.3.0-beta.100

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.
Files changed (203) hide show
  1. package/README.md +2 -1
  2. package/crosscheck.config.example.yml +23 -2
  3. package/dist/__tests__/adoption.test.d.ts +2 -0
  4. package/dist/__tests__/adoption.test.d.ts.map +1 -0
  5. package/dist/__tests__/adoption.test.js +175 -0
  6. package/dist/__tests__/adoption.test.js.map +1 -0
  7. package/dist/__tests__/auto-fix-branch.test.d.ts +2 -0
  8. package/dist/__tests__/auto-fix-branch.test.d.ts.map +1 -0
  9. package/dist/__tests__/auto-fix-branch.test.js +143 -0
  10. package/dist/__tests__/auto-fix-branch.test.js.map +1 -0
  11. package/dist/__tests__/board.test.js +2 -0
  12. package/dist/__tests__/board.test.js.map +1 -1
  13. package/dist/__tests__/codex-env.test.d.ts +2 -0
  14. package/dist/__tests__/codex-env.test.d.ts.map +1 -0
  15. package/dist/__tests__/codex-env.test.js +70 -0
  16. package/dist/__tests__/codex-env.test.js.map +1 -0
  17. package/dist/__tests__/codex.test.js +89 -1
  18. package/dist/__tests__/codex.test.js.map +1 -1
  19. package/dist/__tests__/commit-subject.test.d.ts +2 -0
  20. package/dist/__tests__/commit-subject.test.d.ts.map +1 -0
  21. package/dist/__tests__/commit-subject.test.js +72 -0
  22. package/dist/__tests__/commit-subject.test.js.map +1 -0
  23. package/dist/__tests__/credential-free-origin.test.d.ts +2 -0
  24. package/dist/__tests__/credential-free-origin.test.d.ts.map +1 -0
  25. package/dist/__tests__/credential-free-origin.test.js +59 -0
  26. package/dist/__tests__/credential-free-origin.test.js.map +1 -0
  27. package/dist/__tests__/detector.test.js +87 -1
  28. package/dist/__tests__/detector.test.js.map +1 -1
  29. package/dist/__tests__/error-classification.test.js +34 -0
  30. package/dist/__tests__/error-classification.test.js.map +1 -1
  31. package/dist/__tests__/fix.test.js +37 -1
  32. package/dist/__tests__/fix.test.js.map +1 -1
  33. package/dist/__tests__/harness-section.test.d.ts +2 -0
  34. package/dist/__tests__/harness-section.test.d.ts.map +1 -0
  35. package/dist/__tests__/harness-section.test.js +46 -0
  36. package/dist/__tests__/harness-section.test.js.map +1 -0
  37. package/dist/__tests__/kickass.test.js +31 -0
  38. package/dist/__tests__/kickass.test.js.map +1 -1
  39. package/dist/__tests__/linear-worker.test.js.map +1 -1
  40. package/dist/__tests__/loader.test.js +2 -2
  41. package/dist/__tests__/loader.test.js.map +1 -1
  42. package/dist/__tests__/onboard-preservation.test.js +0 -1
  43. package/dist/__tests__/onboard-preservation.test.js.map +1 -1
  44. package/dist/__tests__/optimize.test.js +1 -1
  45. package/dist/__tests__/optimize.test.js.map +1 -1
  46. package/dist/__tests__/pr-status.test.js +213 -3
  47. package/dist/__tests__/pr-status.test.js.map +1 -1
  48. package/dist/__tests__/pr-workflow-state.test.js +247 -7
  49. package/dist/__tests__/pr-workflow-state.test.js.map +1 -1
  50. package/dist/__tests__/repository-guidance.test.js +21 -21
  51. package/dist/__tests__/repository-guidance.test.js.map +1 -1
  52. package/dist/__tests__/reviewed-sha.test.d.ts +2 -0
  53. package/dist/__tests__/reviewed-sha.test.d.ts.map +1 -0
  54. package/dist/__tests__/reviewed-sha.test.js +116 -0
  55. package/dist/__tests__/reviewed-sha.test.js.map +1 -0
  56. package/dist/__tests__/runner.test.js +178 -2
  57. package/dist/__tests__/runner.test.js.map +1 -1
  58. package/dist/__tests__/skill-broker.test.js +44 -2
  59. package/dist/__tests__/skill-broker.test.js.map +1 -1
  60. package/dist/__tests__/superseded-fix-pr.test.d.ts +2 -0
  61. package/dist/__tests__/superseded-fix-pr.test.d.ts.map +1 -0
  62. package/dist/__tests__/superseded-fix-pr.test.js +225 -0
  63. package/dist/__tests__/superseded-fix-pr.test.js.map +1 -0
  64. package/dist/__tests__/webhook.test.js +60 -0
  65. package/dist/__tests__/webhook.test.js.map +1 -1
  66. package/dist/cli.js +8 -0
  67. package/dist/cli.js.map +1 -1
  68. package/dist/commands/adoption.d.ts +6 -0
  69. package/dist/commands/adoption.d.ts.map +1 -0
  70. package/dist/commands/adoption.js +132 -0
  71. package/dist/commands/adoption.js.map +1 -0
  72. package/dist/commands/detect-step.d.ts.map +1 -1
  73. package/dist/commands/detect-step.js +5 -1
  74. package/dist/commands/detect-step.js.map +1 -1
  75. package/dist/commands/diagnose.d.ts.map +1 -1
  76. package/dist/commands/diagnose.js +2 -2
  77. package/dist/commands/diagnose.js.map +1 -1
  78. package/dist/commands/init.d.ts.map +1 -1
  79. package/dist/commands/init.js +1 -2
  80. package/dist/commands/init.js.map +1 -1
  81. package/dist/commands/issue.js +1 -1
  82. package/dist/commands/issue.js.map +1 -1
  83. package/dist/commands/kickass.d.ts +1 -1
  84. package/dist/commands/kickass.d.ts.map +1 -1
  85. package/dist/commands/kickass.js +36 -22
  86. package/dist/commands/kickass.js.map +1 -1
  87. package/dist/commands/linear-test.js.map +1 -1
  88. package/dist/commands/onboard.d.ts.map +1 -1
  89. package/dist/commands/onboard.js +30 -3
  90. package/dist/commands/onboard.js.map +1 -1
  91. package/dist/commands/optimize.d.ts.map +1 -1
  92. package/dist/commands/optimize.js +1 -0
  93. package/dist/commands/optimize.js.map +1 -1
  94. package/dist/commands/review.d.ts.map +1 -1
  95. package/dist/commands/review.js +1 -1
  96. package/dist/commands/review.js.map +1 -1
  97. package/dist/commands/run.d.ts.map +1 -1
  98. package/dist/commands/run.js +40 -4
  99. package/dist/commands/run.js.map +1 -1
  100. package/dist/commands/scan.d.ts.map +1 -1
  101. package/dist/commands/scan.js +6 -0
  102. package/dist/commands/scan.js.map +1 -1
  103. package/dist/commands/watch.d.ts.map +1 -1
  104. package/dist/commands/watch.js +132 -61
  105. package/dist/commands/watch.js.map +1 -1
  106. package/dist/config/loader.js +6 -6
  107. package/dist/config/loader.js.map +1 -1
  108. package/dist/config/schema.d.ts +8 -0
  109. package/dist/config/schema.d.ts.map +1 -1
  110. package/dist/config/schema.js +19 -2
  111. package/dist/config/schema.js.map +1 -1
  112. package/dist/github/detector.d.ts.map +1 -1
  113. package/dist/github/detector.js +28 -1
  114. package/dist/github/detector.js.map +1 -1
  115. package/dist/github/merge.d.ts +0 -5
  116. package/dist/github/merge.d.ts.map +1 -1
  117. package/dist/github/merge.js +0 -9
  118. package/dist/github/merge.js.map +1 -1
  119. package/dist/github/reviewed-sha.d.ts +13 -0
  120. package/dist/github/reviewed-sha.d.ts.map +1 -0
  121. package/dist/github/reviewed-sha.js +62 -0
  122. package/dist/github/reviewed-sha.js.map +1 -0
  123. package/dist/github/superseded-fix-pr.d.ts +19 -0
  124. package/dist/github/superseded-fix-pr.d.ts.map +1 -0
  125. package/dist/github/superseded-fix-pr.js +97 -0
  126. package/dist/github/superseded-fix-pr.js.map +1 -0
  127. package/dist/github/webhook.d.ts +4 -1
  128. package/dist/github/webhook.d.ts.map +1 -1
  129. package/dist/github/webhook.js +8 -1
  130. package/dist/github/webhook.js.map +1 -1
  131. package/dist/lib/adoption.d.ts +64 -0
  132. package/dist/lib/adoption.d.ts.map +1 -0
  133. package/dist/lib/adoption.js +165 -0
  134. package/dist/lib/adoption.js.map +1 -0
  135. package/dist/lib/annotation.js +0 -7
  136. package/dist/lib/annotation.js.map +1 -1
  137. package/dist/lib/auto-fix-branch.d.ts +35 -0
  138. package/dist/lib/auto-fix-branch.d.ts.map +1 -0
  139. package/dist/lib/auto-fix-branch.js +88 -0
  140. package/dist/lib/auto-fix-branch.js.map +1 -0
  141. package/dist/lib/clone.d.ts +1 -0
  142. package/dist/lib/clone.d.ts.map +1 -1
  143. package/dist/lib/clone.js +38 -1
  144. package/dist/lib/clone.js.map +1 -1
  145. package/dist/lib/comment-bodies.d.ts.map +1 -1
  146. package/dist/lib/comment-bodies.js +6 -3
  147. package/dist/lib/comment-bodies.js.map +1 -1
  148. package/dist/lib/logger.d.ts.map +1 -1
  149. package/dist/lib/logger.js +17 -1
  150. package/dist/lib/logger.js.map +1 -1
  151. package/dist/lib/pr-picker.d.ts +1 -1
  152. package/dist/lib/pr-picker.d.ts.map +1 -1
  153. package/dist/lib/pr-picker.js +10 -5
  154. package/dist/lib/pr-picker.js.map +1 -1
  155. package/dist/lib/pr-status.d.ts +2 -1
  156. package/dist/lib/pr-status.d.ts.map +1 -1
  157. package/dist/lib/pr-status.js +70 -6
  158. package/dist/lib/pr-status.js.map +1 -1
  159. package/dist/lib/pr-workflow-state.d.ts +17 -1
  160. package/dist/lib/pr-workflow-state.d.ts.map +1 -1
  161. package/dist/lib/pr-workflow-state.js +110 -5
  162. package/dist/lib/pr-workflow-state.js.map +1 -1
  163. package/dist/lib/repo-picker.d.ts.map +1 -1
  164. package/dist/lib/repo-picker.js +0 -1
  165. package/dist/lib/repo-picker.js.map +1 -1
  166. package/dist/lib/runner.d.ts +31 -1
  167. package/dist/lib/runner.d.ts.map +1 -1
  168. package/dist/lib/runner.js +460 -58
  169. package/dist/lib/runner.js.map +1 -1
  170. package/dist/lib/vendor.d.ts +1 -0
  171. package/dist/lib/vendor.d.ts.map +1 -1
  172. package/dist/lib/vendor.js +6 -0
  173. package/dist/lib/vendor.js.map +1 -1
  174. package/dist/lib/workflow.d.ts +4 -0
  175. package/dist/lib/workflow.d.ts.map +1 -1
  176. package/dist/lib/workflow.js +4 -1
  177. package/dist/lib/workflow.js.map +1 -1
  178. package/dist/linear/comment.d.ts.map +1 -1
  179. package/dist/linear/comment.js.map +1 -1
  180. package/dist/reviewers/address.d.ts +1 -1
  181. package/dist/reviewers/address.d.ts.map +1 -1
  182. package/dist/reviewers/address.js +1 -1
  183. package/dist/reviewers/address.js.map +1 -1
  184. package/dist/reviewers/codex-env.d.ts +12 -0
  185. package/dist/reviewers/codex-env.d.ts.map +1 -0
  186. package/dist/reviewers/codex-env.js +54 -0
  187. package/dist/reviewers/codex-env.js.map +1 -0
  188. package/dist/reviewers/codex.d.ts +16 -1
  189. package/dist/reviewers/codex.d.ts.map +1 -1
  190. package/dist/reviewers/codex.js +110 -33
  191. package/dist/reviewers/codex.js.map +1 -1
  192. package/dist/reviewers/fix.d.ts +1 -1
  193. package/dist/reviewers/fix.d.ts.map +1 -1
  194. package/dist/reviewers/fix.js +16 -6
  195. package/dist/reviewers/fix.js.map +1 -1
  196. package/dist/skills/broker.d.ts +2 -1
  197. package/dist/skills/broker.d.ts.map +1 -1
  198. package/dist/skills/broker.js +28 -2
  199. package/dist/skills/broker.js.map +1 -1
  200. package/docs/metrics.md +115 -0
  201. package/docs/trust.md +159 -0
  202. package/get-started.md +115 -5
  203. package/package.json +3 -1
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
- import { buildProgressSummary, computeLastActive, computeTokenTotals, derivePRStatus, foldPRStatus, isStale, parseCrosscheckAnnotation, } from '../lib/pr-status.js';
2
+ import { buildProgressSummary, computeLastActive, computeTokenTotals, applyRepoWorkflowOverrideToStatus, derivePRStatus, foldPRStatus, isStale, parseCrosscheckAnnotation, } from '../lib/pr-status.js';
3
3
  const NOW = Date.parse('2026-05-29T12:00:00.000Z');
4
4
  function input(overrides = {}) {
5
5
  return {
@@ -82,10 +82,10 @@ describe('derivePRStatus', () => {
82
82
  expect(status.freshness).toBe('stale');
83
83
  expect(status.nextAction).toBe('review');
84
84
  });
85
- it('moves to APPROVED stage when verdict is APPROVE', () => {
85
+ it('moves to APPROVED stage when the APPROVE covers HEAD', () => {
86
86
  const status = derivePRStatus(input({
87
87
  comments: [{
88
- body: '<!-- crosscheck: origin=claude reviewer=codex verdict=APPROVE type=review -->',
88
+ body: '<!-- crosscheck: origin=claude reviewer=codex verdict=APPROVE type=review sha=abc123 -->',
89
89
  createdAt: '2026-05-27T11:00:00.000Z',
90
90
  updatedAt: '2026-05-27T11:00:00.000Z',
91
91
  }],
@@ -95,6 +95,216 @@ describe('derivePRStatus', () => {
95
95
  expect(status.nextAction).toBe('merge');
96
96
  expect(status.freshness).toBe('stale');
97
97
  });
98
+ // An approval covers a commit, not a PR. Reporting `merge` for an approval that
99
+ // predates the current HEAD would put never-reviewed code in kickass's read-only
100
+ // "needs merge (manual)" list instead of dispatching the review it is owed.
101
+ it('needs review again when the APPROVE covers an older SHA', () => {
102
+ const status = derivePRStatus(input({
103
+ headSha: 'def456',
104
+ comments: [{
105
+ body: '<!-- crosscheck: origin=claude reviewer=codex verdict=APPROVE type=review sha=abc123 -->',
106
+ createdAt: '2026-05-27T11:00:00.000Z',
107
+ updatedAt: '2026-05-27T11:00:00.000Z',
108
+ }],
109
+ }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
110
+ expect(status.reviewState).toBe('NEEDS_REVIEW');
111
+ expect(status.nextAction).toBe('review');
112
+ // The verdict field still reports the last verdict on record — it is the review
113
+ // state, not the history, that HEAD invalidates.
114
+ expect(status.verdict).toBe('APPROVE');
115
+ });
116
+ // A legacy annotation predates the `sha=` field, so it cannot prove which commit it
117
+ // describes. Fail open: one review re-establishes the SHA and the approval sticks.
118
+ it('needs review again when the APPROVE carries no SHA', () => {
119
+ const status = derivePRStatus(input({
120
+ comments: [{
121
+ body: '<!-- crosscheck: origin=claude reviewer=codex verdict=APPROVE type=review -->',
122
+ createdAt: '2026-05-27T11:00:00.000Z',
123
+ updatedAt: '2026-05-27T11:00:00.000Z',
124
+ }],
125
+ }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
126
+ expect(status.reviewState).toBe('NEEDS_REVIEW');
127
+ expect(status.nextAction).toBe('review');
128
+ });
129
+ it('matches the approved SHA in short and long form', () => {
130
+ const status = derivePRStatus(input({
131
+ headSha: 'abc123456789abcdef',
132
+ comments: [{
133
+ body: '<!-- crosscheck: origin=claude reviewer=codex verdict=APPROVE type=review sha=abc1234 -->',
134
+ createdAt: '2026-05-27T11:00:00.000Z',
135
+ updatedAt: '2026-05-27T11:00:00.000Z',
136
+ }],
137
+ }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
138
+ expect(status.nextAction).toBe('merge');
139
+ });
140
+ // Only APPROVE is SHA-scoped: a stale NEEDS_WORK still means the PR has unresolved
141
+ // findings, and kickass separately demotes a fix to a review when the annotation
142
+ // covers an older SHA.
143
+ it('still reports fix for a NEEDS_WORK that covers an older SHA', () => {
144
+ const status = derivePRStatus(input({
145
+ headSha: 'def456',
146
+ comments: [{
147
+ body: '<!-- crosscheck: origin=claude reviewer=codex verdict=NEEDS_WORK type=review sha=abc123 -->',
148
+ createdAt: '2026-05-27T11:00:00.000Z',
149
+ updatedAt: '2026-05-27T11:00:00.000Z',
150
+ }],
151
+ }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
152
+ expect(status.reviewState).toBe('NEEDS_FIX');
153
+ expect(status.nextAction).toBe('fix');
154
+ });
155
+ // Logging is on by default, and runWorkflow writes workflow_complete AFTER posting the
156
+ // review comment — so the newest verdict on a freshly approved PR is a SHA-less log
157
+ // entry. Reading the approval SHA from it would fail every check and have scan/kickass
158
+ // re-dispatch approved PRs forever.
159
+ it('stays APPROVED when a newer workflow_complete log follows the approval comment', () => {
160
+ const status = derivePRStatus(input({
161
+ comments: [{
162
+ body: '<!-- crosscheck: origin=claude reviewer=codex verdict=APPROVE type=review sha=abc123 -->',
163
+ createdAt: '2026-05-27T11:00:00.000Z',
164
+ updatedAt: '2026-05-27T11:00:00.000Z',
165
+ }],
166
+ logEvents: [{
167
+ ts: '2026-05-27T11:00:05.000Z',
168
+ event: 'workflow_complete',
169
+ repo: 'acme/web',
170
+ pr: 7,
171
+ last_verdict: 'APPROVE',
172
+ }],
173
+ }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
174
+ expect(status.reviewState).toBe('APPROVED');
175
+ expect(status.nextAction).toBe('merge');
176
+ });
177
+ // The SHA still has to cover HEAD — the log entry must not paper over a later push.
178
+ it('needs review when a workflow_complete log follows an approval of an older SHA', () => {
179
+ const status = derivePRStatus(input({
180
+ headSha: 'def456',
181
+ comments: [{
182
+ body: '<!-- crosscheck: origin=claude reviewer=codex verdict=APPROVE type=review sha=abc123 -->',
183
+ createdAt: '2026-05-27T11:00:00.000Z',
184
+ updatedAt: '2026-05-27T11:00:00.000Z',
185
+ }],
186
+ logEvents: [{
187
+ ts: '2026-05-27T11:00:05.000Z',
188
+ event: 'workflow_complete',
189
+ repo: 'acme/web',
190
+ pr: 7,
191
+ last_verdict: 'APPROVE',
192
+ }],
193
+ }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
194
+ expect(status.reviewState).toBe('NEEDS_REVIEW');
195
+ expect(status.nextAction).toBe('review');
196
+ });
197
+ // A newer annotation disagreeing with an older APPROVE must win: the approval SHA is
198
+ // read only when the newest verdict-bearing annotation is itself the APPROVE.
199
+ it('does not resurrect an older approval when a newer annotation disagrees', () => {
200
+ const status = derivePRStatus(input({
201
+ comments: [
202
+ {
203
+ body: '<!-- crosscheck: origin=claude reviewer=codex verdict=APPROVE type=review sha=abc123 -->',
204
+ createdAt: '2026-05-27T11:00:00.000Z',
205
+ updatedAt: '2026-05-27T11:00:00.000Z',
206
+ },
207
+ {
208
+ body: '<!-- crosscheck: origin=claude reviewer=codex verdict=NEEDS_WORK type=review sha=abc123 -->',
209
+ createdAt: '2026-05-27T12:00:00.000Z',
210
+ updatedAt: '2026-05-27T12:00:00.000Z',
211
+ },
212
+ ],
213
+ }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
214
+ expect(status.reviewState).toBe('NEEDS_FIX');
215
+ expect(status.nextAction).toBe('fix');
216
+ });
217
+ // Fix log events carry no SHA, so one that no longer describes HEAD — force-pushed
218
+ // away, or delivered as its own PR — must not pin an approved commit to NEEDS_RECHECK
219
+ // and have kickass dispatch no-op rechecks at it forever.
220
+ it('stays APPROVED when a post-approval fix left HEAD untouched', () => {
221
+ const status = derivePRStatus(input({
222
+ comments: [{
223
+ body: '<!-- crosscheck: origin=claude reviewer=codex verdict=APPROVE type=review sha=abc123 -->',
224
+ createdAt: '2026-05-27T11:00:00.000Z',
225
+ updatedAt: '2026-05-27T11:00:00.000Z',
226
+ }],
227
+ logEvents: [{
228
+ ts: '2026-05-27T12:00:00.000Z',
229
+ event: 'fix_complete',
230
+ repo: 'acme/web',
231
+ pr: 7,
232
+ applied_count: 2,
233
+ }],
234
+ }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
235
+ expect(status.reviewState).toBe('APPROVED');
236
+ expect(status.nextAction).toBe('merge');
237
+ });
238
+ // The self-correcting half: a fix that really did change HEAD moves HEAD off the
239
+ // approved SHA, so the approval stops covering it and the recheck is owed again.
240
+ it('needs a recheck when the post-approval fix moved HEAD', () => {
241
+ const status = derivePRStatus(input({
242
+ headSha: 'def456',
243
+ comments: [{
244
+ body: '<!-- crosscheck: origin=claude reviewer=codex verdict=APPROVE type=review sha=abc123 -->',
245
+ createdAt: '2026-05-27T11:00:00.000Z',
246
+ updatedAt: '2026-05-27T11:00:00.000Z',
247
+ }],
248
+ logEvents: [{
249
+ ts: '2026-05-27T12:00:00.000Z',
250
+ event: 'fix_complete',
251
+ repo: 'acme/web',
252
+ pr: 7,
253
+ applied_count: 2,
254
+ }],
255
+ }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
256
+ expect(status.reviewState).toBe('NEEDS_RECHECK');
257
+ expect(status.nextAction).toBe('recheck');
258
+ });
259
+ // A conflicted PR is actionable no matter where it sits in the review ladder — the base
260
+ // branch moved, and nothing else will notice, because that fires no webhook (#282).
261
+ describe('conflicted PRs', () => {
262
+ const conflicted = { mergeable: false, mergeStateStatus: 'dirty', protectedBase: false };
263
+ it('routes an unreviewed conflicted PR to resolve', () => {
264
+ const status = derivePRStatus(input({ merge: conflicted }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
265
+ expect(status.nextAction).toBe('resolve');
266
+ expect(status.reviewState).toBe('NEEDS_REVIEW');
267
+ });
268
+ it('routes an approved conflicted PR to resolve rather than merge', () => {
269
+ const status = derivePRStatus(input({
270
+ merge: conflicted,
271
+ comments: [{
272
+ body: '<!-- crosscheck: origin=claude reviewer=codex verdict=APPROVE type=review sha=abc123 -->',
273
+ createdAt: '2026-05-27T11:00:00.000Z',
274
+ updatedAt: '2026-05-27T11:00:00.000Z',
275
+ }],
276
+ }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
277
+ expect(status.nextAction).toBe('resolve');
278
+ // The review verdict is untouched — the conflict says nothing about code quality.
279
+ expect(status.reviewState).toBe('APPROVED');
280
+ expect(status.verdict).toBe('APPROVE');
281
+ });
282
+ it('leaves a mergeable PR alone', () => {
283
+ const status = derivePRStatus(input({
284
+ merge: { mergeable: true, mergeStateStatus: 'clean', protectedBase: false },
285
+ }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
286
+ expect(status.nextAction).toBe('review');
287
+ });
288
+ // null = GitHub still computing. Claiming a conflict on unknown would dispatch resolve
289
+ // runs against clean PRs.
290
+ it('leaves unknown mergeability alone', () => {
291
+ const status = derivePRStatus(input({
292
+ merge: { mergeable: null, protectedBase: false },
293
+ }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
294
+ expect(status.nextAction).toBe('review');
295
+ });
296
+ // `--steps conflict-resolve` synthesizes the step when the workflow lacks it, which is
297
+ // right for the explicit `crosscheck resolve` command and wrong for automatic
298
+ // dispatch: it would push a merge commit for a workflow that never asked for one.
299
+ it('drops the resolve action when the workflow defines no conflict-resolve step', () => {
300
+ const conflictedStatus = derivePRStatus(input({ merge: conflicted }), { nowMs: NOW, staleAfterMs: 24 * 60 * 60 * 1000 });
301
+ const withoutStep = applyRepoWorkflowOverrideToStatus(conflictedStatus, new Set(['review', 'fix', 'recheck']));
302
+ expect(withoutStep.nextAction).toBeNull();
303
+ expect(withoutStep.freshness).toBe('not_stale');
304
+ const withStep = applyRepoWorkflowOverrideToStatus(conflictedStatus, new Set(['conflict-resolve', 'review', 'fix']));
305
+ expect(withStep.nextAction).toBe('resolve');
306
+ });
307
+ });
98
308
  it('keeps the latest verdict when a newer bare crosscheck marker exists', () => {
99
309
  const status = derivePRStatus(input({
100
310
  comments: [
@@ -1 +1 @@
1
- {"version":3,"file":"pr-status.test.js","sourceRoot":"","sources":["../../src/__tests__/pr-status.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pr-status.test.js","sourceRoot":"","sources":["../../src/__tests__/pr-status.test.ts"],"names":[],"mappings":"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"}
@@ -53,14 +53,56 @@ describe('identifyNextWorkflowStep', () => {
53
53
  expect(next.step?.type).toBe('review');
54
54
  expect(next.round).toBe(1);
55
55
  });
56
- it('routes a non-APPROVE initial review to fix even when HEAD has moved', () => {
56
+ it('routes a non-APPROVE review to fix while HEAD is still the reviewed commit', () => {
57
57
  const next = identifyNextWorkflowStep([
58
58
  record({ type: 'review', verdict: 'BLOCK', sha: 'reviewed-sha' }),
59
- ], workflow, 'new-head-sha');
59
+ ], workflow, 'reviewed-sha');
60
60
  expect(next.step?.type).toBe('fix');
61
61
  expect(next.reviewComment?.id).toBe(100);
62
62
  expect(next.round).toBe(1);
63
63
  });
64
+ // Previously this routed to fix regardless of HEAD ("even when HEAD has moved").
65
+ // That is monorepo#2548: the author addressed the BLOCK themselves, the fix ran
66
+ // against a review of a tree that no longer existed, applied nothing, and — since
67
+ // a no-op fix records nothing — every later event replayed the same decision, so
68
+ // the PR sat on a stale BLOCK with no way to advance. The workflow already routes
69
+ // a moved HEAD to a fresh review when crosscheck's own fix moved it (see 'routes a
70
+ // stale fix followed by a new HEAD back to review'); who pushed says nothing about
71
+ // whether the reviewed tree still exists.
72
+ it('routes a non-APPROVE review to a fresh review once HEAD moves past it', () => {
73
+ const next = identifyNextWorkflowStep([
74
+ record({ type: 'review', verdict: 'BLOCK', sha: 'reviewed-sha' }),
75
+ ], workflow, 'new-head-sha');
76
+ expect(next.step?.type).toBe('review');
77
+ expect(next.round).toBe(2);
78
+ });
79
+ it('treats the short and long forms of the reviewed SHA as the same commit', () => {
80
+ const next = identifyNextWorkflowStep([
81
+ record({ type: 'review', verdict: 'BLOCK', sha: '59abeb6' }),
82
+ ], workflow, '59abeb630af4efbc874650db88ecf3dcb02724fb');
83
+ expect(next.step?.type).toBe('fix');
84
+ });
85
+ // A record that cannot say which commit it describes cannot prove it is stale.
86
+ // Legacy comments carry no `sha=`, and trading their working fix step for a
87
+ // re-review on every push would be a regression, so absence keeps the old path.
88
+ it('routes to fix when the review carries no SHA at all', () => {
89
+ const next = identifyNextWorkflowStep([
90
+ record({ type: 'review', verdict: 'BLOCK' }),
91
+ ], workflow, 'new-head-sha');
92
+ expect(next.step?.type).toBe('fix');
93
+ expect(next.reviewComment?.id).toBe(100);
94
+ });
95
+ // The fix loop still re-engages: the fresh review posts on the new HEAD, and the
96
+ // fix step runs off that. One extra review is the price of never fixing against a
97
+ // tree that no longer exists — and unlike the old path, it always terminates.
98
+ it('reaches fix again after the fresh review lands on the new HEAD', () => {
99
+ const next = identifyNextWorkflowStep([
100
+ record({ type: 'review', verdict: 'BLOCK', sha: 'reviewed-sha' }),
101
+ record({ type: 'review', verdict: 'BLOCK', sha: 'new-head-sha', round: 2, commentId: 103 }),
102
+ ], workflow, 'new-head-sha');
103
+ expect(next.step?.type).toBe('fix');
104
+ expect(next.reviewComment?.id).toBe(103);
105
+ });
64
106
  it('routes a non-APPROVE recheck to fix', () => {
65
107
  const next = identifyNextWorkflowStep([
66
108
  record({ type: 'review', verdict: 'BLOCK', sha: 'first-sha' }),
@@ -71,15 +113,17 @@ describe('identifyNextWorkflowStep', () => {
71
113
  expect(next.reviewComment?.id).toBe(102);
72
114
  expect(next.round).toBe(1);
73
115
  });
74
- it('routes a non-APPROVE recheck followed by an unannotated HEAD commit to fix', () => {
116
+ // Same rule one round deeper: a recheck is a verdict on a specific tree too, so a
117
+ // commit pushed past it re-opens the review rather than feeding a stale findings
118
+ // list to fix. The round carries forward from the recheck.
119
+ it('routes a non-APPROVE recheck followed by an unannotated HEAD commit to review', () => {
75
120
  const next = identifyNextWorkflowStep([
76
121
  record({ type: 'review', verdict: 'BLOCK', sha: 'first-sha', commentId: 100 }),
77
122
  record({ type: 'fix', commentId: 101, pushedSha: 'first-fix-sha' }),
78
123
  record({ type: 'recheck', verdict: 'NEEDS_WORK', sha: 'rechecked-sha', round: 7, commentId: 102 }),
79
124
  ], workflow, 'new-unannotated-head-sha');
80
- expect(next.step?.type).toBe('fix');
81
- expect(next.reviewComment?.id).toBe(102);
82
- expect(next.round).toBe(7);
125
+ expect(next.step?.type).toBe('review');
126
+ expect(next.round).toBe(8);
83
127
  });
84
128
  it('routes a current-head fix after review to recheck', () => {
85
129
  const next = identifyNextWorkflowStep([
@@ -173,12 +217,192 @@ describe('identifyNextWorkflowStep', () => {
173
217
  expect(next.step?.type).toBe('review');
174
218
  expect(next.round).toBe(2);
175
219
  });
176
- it('uses review rather than recheck when a new HEAD appears after APPROVE', () => {
220
+ // An APPROVE ends the workflow for the commit it covers. It does NOT end it for the
221
+ // PR: a later push materially changes what was approved, so the approval no longer
222
+ // applies and the new code is reviewed.
223
+ it('stops on the approved SHA', () => {
224
+ const next = identifyNextWorkflowStep([
225
+ record({ type: 'review', verdict: 'APPROVE', sha: 'approved-sha' }),
226
+ ], workflow, 'approved-sha');
227
+ expect(next.step).toBeNull();
228
+ expect(next.stopReason).toBe('approved');
229
+ });
230
+ it('stops when the APPROVE came from a recheck on the current SHA', () => {
231
+ const next = identifyNextWorkflowStep([
232
+ record({ type: 'review', verdict: 'BLOCK', sha: 'sha-A' }),
233
+ record({ type: 'fix', commentId: 101, pushedSha: 'sha-B' }),
234
+ record({ type: 'recheck', verdict: 'APPROVE', sha: 'sha-B', round: 2, commentId: 102 }),
235
+ ], workflow, 'sha-B');
236
+ expect(next.step).toBeNull();
237
+ expect(next.stopReason).toBe('approved');
238
+ });
239
+ it('matches the approved SHA in short and long form', () => {
240
+ const next = identifyNextWorkflowStep([
241
+ record({ type: 'review', verdict: 'APPROVE', sha: 'abc1234' }),
242
+ ], workflow, 'abc1234def5678');
243
+ expect(next.step).toBeNull();
244
+ expect(next.stopReason).toBe('approved');
245
+ });
246
+ it('reviews a new HEAD pushed after APPROVE — the approval no longer covers it', () => {
177
247
  const next = identifyNextWorkflowStep([
178
248
  record({ type: 'review', verdict: 'APPROVE', sha: 'approved-sha' }),
179
249
  ], workflow, 'new-head-sha');
180
250
  expect(next.step?.type).toBe('review');
181
251
  expect(next.round).toBe(2);
252
+ expect(next.stopReason).toBeUndefined();
253
+ });
254
+ it('reviews a new HEAD pushed after an APPROVE recheck', () => {
255
+ const next = identifyNextWorkflowStep([
256
+ record({ type: 'review', verdict: 'BLOCK', sha: 'sha-A' }),
257
+ record({ type: 'fix', commentId: 101, pushedSha: 'sha-B' }),
258
+ record({ type: 'recheck', verdict: 'APPROVE', sha: 'sha-B', round: 2, commentId: 102 }),
259
+ ], workflow, 'sha-C');
260
+ expect(next.step?.type).toBe('review');
261
+ expect(next.stopReason).toBeUndefined();
262
+ });
263
+ // A legacy APPROVE predates the `sha=` annotation field, so it cannot prove it covers
264
+ // HEAD. Fail open and review — that review records a SHA and re-establishes the stop.
265
+ it('reviews when an APPROVE carries no SHA', () => {
266
+ const next = identifyNextWorkflowStep([
267
+ record({ type: 'review', verdict: 'APPROVE' }),
268
+ ], workflow, 'head-sha');
269
+ expect(next.step?.type).toBe('review');
270
+ expect(next.stopReason).toBeUndefined();
271
+ });
272
+ // The stop gate must not swallow work that landed AFTER the approval. A workflow whose
273
+ // fix step is not gated on the verdict can push a commit past an APPROVE; that commit
274
+ // still has to be rechecked.
275
+ it('still rechecks a fix that landed after an APPROVE', () => {
276
+ const ungatedFix = { ...fixStep, when: undefined };
277
+ const next = identifyNextWorkflowStep([
278
+ record({ type: 'review', verdict: 'APPROVE', sha: 'approved-sha' }),
279
+ record({ type: 'fix', commentId: 101, pushedSha: 'fix-sha' }),
280
+ ], [reviewStep, ungatedFix, recheckStep], 'fix-sha');
281
+ expect(next.step?.type).toBe('recheck');
282
+ expect(next.stopReason).toBeUndefined();
283
+ });
284
+ // The post-approval exception is scoped to the pushed commit, not to the record. A
285
+ // force-push can drop the fix commit and put HEAD back on the approved SHA; the record
286
+ // then describes content that no longer exists, so the approval stands.
287
+ it('stops when a post-approval fix was force-pushed away', () => {
288
+ const next = identifyNextWorkflowStep([
289
+ record({ type: 'review', verdict: 'APPROVE', sha: 'approved-sha' }),
290
+ record({ type: 'fix', commentId: 101, pushedSha: 'dropped-sha' }),
291
+ ], workflow, 'approved-sha');
292
+ expect(next.step).toBeNull();
293
+ expect(next.stopReason).toBe('approved');
294
+ });
295
+ // A fix that pushed nothing to the PR head (pull_request delivery puts it on its own
296
+ // branch) leaves HEAD as the approved content, so the approval still stands.
297
+ it('stops when a post-approval fix record has no pushed SHA', () => {
298
+ const next = identifyNextWorkflowStep([
299
+ record({ type: 'review', verdict: 'APPROVE', sha: 'approved-sha' }),
300
+ record({ type: 'fix', commentId: 101 }),
301
+ ], workflow, 'approved-sha');
302
+ expect(next.step).toBeNull();
303
+ expect(next.stopReason).toBe('approved');
304
+ });
305
+ it('does not stop on a NEEDS_WORK verdict', () => {
306
+ const next = identifyNextWorkflowStep([
307
+ record({ type: 'review', verdict: 'NEEDS_WORK', sha: 'sha-A' }),
308
+ ], workflow, 'sha-A');
309
+ expect(next.step?.type).toBe('fix');
310
+ expect(next.stopReason).toBeUndefined();
311
+ });
312
+ // A PR becomes conflicted when the BASE branch moves — nothing about the reviewed code
313
+ // changes, and no webhook fires. Once a review exists, firstIncompleteInitialStep is out
314
+ // of reach and the tail loop only walks steps that follow review, so a conflict-resolve
315
+ // configured ahead of review (the onboard default) could never run again. See #282.
316
+ describe('conflict-resolve after a review exists', () => {
317
+ it('routes a conflicted PR to conflict-resolve even though the step precedes review', () => {
318
+ const next = identifyNextWorkflowStep([
319
+ record({ type: 'review', verdict: 'NEEDS_WORK', sha: 'sha-A' }),
320
+ ], workflow, 'sha-A', { mergeable: false });
321
+ expect(next.step?.type).toBe('conflict-resolve');
322
+ expect(next.round).toBe(1);
323
+ });
324
+ it('resolves conflicts on an approved PR rather than stopping', () => {
325
+ const next = identifyNextWorkflowStep([
326
+ record({ type: 'review', verdict: 'APPROVE', sha: 'sha-A' }),
327
+ ], workflow, 'sha-A', { mergeable: false });
328
+ expect(next.step?.type).toBe('conflict-resolve');
329
+ expect(next.stopReason).toBeUndefined();
330
+ });
331
+ it('keeps the approval stop when the PR merges cleanly', () => {
332
+ const next = identifyNextWorkflowStep([
333
+ record({ type: 'review', verdict: 'APPROVE', sha: 'sha-A' }),
334
+ ], workflow, 'sha-A', { mergeable: true });
335
+ expect(next.step).toBeNull();
336
+ expect(next.stopReason).toBe('approved');
337
+ });
338
+ // null = GitHub is still computing mergeability. Offering on unknown would churn, and
339
+ // the caller can simply ask again once GitHub settles.
340
+ it('does not offer conflict-resolve on unknown mergeability', () => {
341
+ for (const mergeable of [null, undefined]) {
342
+ const next = identifyNextWorkflowStep([
343
+ record({ type: 'review', verdict: 'APPROVE', sha: 'sha-A' }),
344
+ ], workflow, 'sha-A', { mergeable });
345
+ expect(next.step).toBeNull();
346
+ expect(next.stopReason).toBe('approved');
347
+ }
348
+ });
349
+ it('does not offer conflict-resolve when the workflow has no such step', () => {
350
+ const next = identifyNextWorkflowStep([
351
+ record({ type: 'review', verdict: 'NEEDS_WORK', sha: 'sha-A' }),
352
+ ], [reviewStep, fixStep, recheckStep], 'sha-A', { mergeable: false });
353
+ expect(next.step?.type).toBe('fix');
354
+ });
355
+ // One attempt per review round: a successful resolve pushes a merge commit, which gets
356
+ // reviewed, and that new review makes the PR eligible again if it re-conflicts.
357
+ // The merge commit a resolve pushes moves HEAD off the reviewed tree and brings
358
+ // in base content the review never saw. The changelog says this case gets a
359
+ // fresh review, but the fix step's `when` was still satisfied on a non-APPROVE
360
+ // verdict, so it took the fix branch first and fixed against the pre-merge
361
+ // review. Gating that branch on the reviewed SHA makes the code agree with the
362
+ // documented behaviour.
363
+ it('routes the merge commit a resolve pushed to a fresh review, not fix', () => {
364
+ const next = identifyNextWorkflowStep([
365
+ record({ type: 'review', verdict: 'BLOCK', sha: 'sha-A' }),
366
+ record({ type: 'conflict-resolve', commentId: 101, pushedSha: 'merge-sha' }),
367
+ ], workflow, 'merge-sha');
368
+ expect(next.step?.type).toBe('review');
369
+ expect(next.round).toBe(2);
370
+ });
371
+ it('does not re-offer conflict-resolve when one already ran since the last review', () => {
372
+ const next = identifyNextWorkflowStep([
373
+ record({ type: 'review', verdict: 'APPROVE', sha: 'sha-A' }),
374
+ record({ type: 'conflict-resolve', commentId: 101, pushedSha: 'merge-sha' }),
375
+ ], workflow, 'merge-sha', { mergeable: false });
376
+ expect(next.step?.type).not.toBe('conflict-resolve');
377
+ });
378
+ // max_rounds on the conflict-resolve step caps merge attempts, not review depth. A PR
379
+ // deep into fix→recheck cycles must not lose conflict resolution because its review
380
+ // round outgrew the cap.
381
+ it('reports the round as the conflict-resolve attempt count, not the review round', () => {
382
+ const first = identifyNextWorkflowStep([
383
+ record({ type: 'review', verdict: 'NEEDS_WORK', sha: 'sha-A', round: 7 }),
384
+ ], workflow, 'sha-A', { mergeable: false });
385
+ expect(first.round).toBe(1);
386
+ const second = identifyNextWorkflowStep([
387
+ record({ type: 'conflict-resolve', commentId: 99, pushedSha: 'merge-1' }),
388
+ record({ type: 'review', verdict: 'NEEDS_WORK', sha: 'merge-1', round: 7, commentId: 100 }),
389
+ ], workflow, 'merge-1', { mergeable: false });
390
+ expect(second.round).toBe(2);
391
+ });
392
+ it('offers it again after a later review', () => {
393
+ const next = identifyNextWorkflowStep([
394
+ record({ type: 'review', verdict: 'NEEDS_WORK', sha: 'sha-A' }),
395
+ record({ type: 'conflict-resolve', commentId: 101, pushedSha: 'merge-sha' }),
396
+ record({ type: 'review', verdict: 'APPROVE', sha: 'merge-sha', round: 2, commentId: 102 }),
397
+ ], workflow, 'merge-sha', { mergeable: false });
398
+ expect(next.step?.type).toBe('conflict-resolve');
399
+ });
400
+ // A never-reviewed PR already reaches conflict-resolve through the initial-step path,
401
+ // which must keep working without a mergeable hint.
402
+ it('leaves the pre-review path alone', () => {
403
+ const next = identifyNextWorkflowStep([], workflow, 'sha-A');
404
+ expect(next.step?.type).toBe('conflict-resolve');
405
+ });
182
406
  });
183
407
  // recheck-no-fix mode (per-repo `review,recheck`): crosscheck never auto-fixes, so a
184
408
  // human pushing their own fix commits is the trigger to re-evaluate — as a recheck
@@ -209,6 +433,13 @@ describe('identifyNextWorkflowStep', () => {
209
433
  expect(next.step?.type).toBe('review');
210
434
  expect(next.round).toBe(2);
211
435
  });
436
+ it('stops on the approved SHA (recheck-no-fix)', () => {
437
+ const next = identifyNextWorkflowStep([
438
+ record({ type: 'review', verdict: 'APPROVE', sha: 'sha-A' }),
439
+ ], reviewRecheckWorkflow, 'sha-A');
440
+ expect(next.step).toBeNull();
441
+ expect(next.stopReason).toBe('approved');
442
+ });
212
443
  it('still rechecks a post-BLOCK push (recheck-no-fix)', () => {
213
444
  const next = identifyNextWorkflowStep([
214
445
  record({ type: 'review', verdict: 'BLOCK', sha: 'sha-A' }),
@@ -233,6 +464,15 @@ describe('decideReviewOnly (per-repo review-only)', () => {
233
464
  it('reviews a fresh PR at round 1', () => {
234
465
  expect(decideReviewOnly([], 'head-sha')).toEqual({ alreadyReviewed: false, round: 1 });
235
466
  });
467
+ // Review-only needs no separate approval stop: the approved SHA is by definition an
468
+ // already-reviewed SHA (skipped), and a SHA pushed after the approval is new content.
469
+ it('skips the approved SHA and reviews the one pushed after it', () => {
470
+ const history = [
471
+ record({ type: 'review', verdict: 'APPROVE', sha: 'approved-sha', round: 1 }),
472
+ ];
473
+ expect(decideReviewOnly(history, 'approved-sha').alreadyReviewed).toBe(true);
474
+ expect(decideReviewOnly(history, 'later-sha')).toEqual({ alreadyReviewed: false, round: 2 });
475
+ });
236
476
  it('skips when the current SHA was already reviewed', () => {
237
477
  const decision = decideReviewOnly([
238
478
  record({ type: 'review', verdict: 'NEEDS_WORK', sha: 'reviewed-sha', round: 1 }),