@humanbased/crosscheck 0.14.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/AGENT.md +207 -0
- package/ISSUE.md +234 -0
- package/LICENSE +21 -0
- package/README.md +234 -0
- package/README.zh.md +169 -0
- package/assets/logo.png +0 -0
- package/assets/screenshot-watch-timing.png +0 -0
- package/assets/screenshot-watch-timing.svg +1 -0
- package/assets/screenshot-watch.png +0 -0
- package/crosscheck.config.example.yml +214 -0
- package/dist/__tests__/annotation.test.d.ts +2 -0
- package/dist/__tests__/annotation.test.d.ts.map +1 -0
- package/dist/__tests__/annotation.test.js +134 -0
- package/dist/__tests__/annotation.test.js.map +1 -0
- 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 +280 -0
- package/dist/__tests__/backtrace.test.js.map +1 -0
- package/dist/__tests__/board.test.d.ts +2 -0
- package/dist/__tests__/board.test.d.ts.map +1 -0
- package/dist/__tests__/board.test.js +149 -0
- package/dist/__tests__/board.test.js.map +1 -0
- package/dist/__tests__/codex.test.d.ts +2 -0
- package/dist/__tests__/codex.test.d.ts.map +1 -0
- package/dist/__tests__/codex.test.js +92 -0
- package/dist/__tests__/codex.test.js.map +1 -0
- package/dist/__tests__/comment-bodies.test.d.ts +2 -0
- package/dist/__tests__/comment-bodies.test.d.ts.map +1 -0
- package/dist/__tests__/comment-bodies.test.js +75 -0
- package/dist/__tests__/comment-bodies.test.js.map +1 -0
- package/dist/__tests__/conflict-resolve.test.d.ts +2 -0
- package/dist/__tests__/conflict-resolve.test.d.ts.map +1 -0
- package/dist/__tests__/conflict-resolve.test.js +123 -0
- package/dist/__tests__/conflict-resolve.test.js.map +1 -0
- package/dist/__tests__/crosscheck-commit.test.d.ts +2 -0
- package/dist/__tests__/crosscheck-commit.test.d.ts.map +1 -0
- package/dist/__tests__/crosscheck-commit.test.js +13 -0
- package/dist/__tests__/crosscheck-commit.test.js.map +1 -0
- package/dist/__tests__/detector.test.d.ts +2 -0
- package/dist/__tests__/detector.test.d.ts.map +1 -0
- package/dist/__tests__/detector.test.js +112 -0
- package/dist/__tests__/detector.test.js.map +1 -0
- package/dist/__tests__/diagnose.test.d.ts +2 -0
- package/dist/__tests__/diagnose.test.d.ts.map +1 -0
- package/dist/__tests__/diagnose.test.js +164 -0
- package/dist/__tests__/diagnose.test.js.map +1 -0
- package/dist/__tests__/diff-hash.test.d.ts +2 -0
- package/dist/__tests__/diff-hash.test.d.ts.map +1 -0
- package/dist/__tests__/diff-hash.test.js +126 -0
- package/dist/__tests__/diff-hash.test.js.map +1 -0
- package/dist/__tests__/durations.test.d.ts +2 -0
- package/dist/__tests__/durations.test.d.ts.map +1 -0
- package/dist/__tests__/durations.test.js +26 -0
- package/dist/__tests__/durations.test.js.map +1 -0
- package/dist/__tests__/event-fields.test.d.ts +2 -0
- package/dist/__tests__/event-fields.test.d.ts.map +1 -0
- package/dist/__tests__/event-fields.test.js +50 -0
- package/dist/__tests__/event-fields.test.js.map +1 -0
- package/dist/__tests__/filter.test.d.ts +2 -0
- package/dist/__tests__/filter.test.d.ts.map +1 -0
- package/dist/__tests__/filter.test.js +21 -0
- package/dist/__tests__/filter.test.js.map +1 -0
- package/dist/__tests__/fix.test.d.ts +2 -0
- package/dist/__tests__/fix.test.d.ts.map +1 -0
- package/dist/__tests__/fix.test.js +124 -0
- package/dist/__tests__/fix.test.js.map +1 -0
- package/dist/__tests__/github-client.test.d.ts +2 -0
- package/dist/__tests__/github-client.test.d.ts.map +1 -0
- package/dist/__tests__/github-client.test.js +22 -0
- package/dist/__tests__/github-client.test.js.map +1 -0
- package/dist/__tests__/github-scan-client.test.d.ts +2 -0
- package/dist/__tests__/github-scan-client.test.d.ts.map +1 -0
- package/dist/__tests__/github-scan-client.test.js +100 -0
- package/dist/__tests__/github-scan-client.test.js.map +1 -0
- package/dist/__tests__/is-fresh-review-comment.test.d.ts +2 -0
- package/dist/__tests__/is-fresh-review-comment.test.d.ts.map +1 -0
- package/dist/__tests__/is-fresh-review-comment.test.js +86 -0
- package/dist/__tests__/is-fresh-review-comment.test.js.map +1 -0
- package/dist/__tests__/issue.test.d.ts +2 -0
- package/dist/__tests__/issue.test.d.ts.map +1 -0
- package/dist/__tests__/issue.test.js +259 -0
- package/dist/__tests__/issue.test.js.map +1 -0
- package/dist/__tests__/kickass.test.d.ts +2 -0
- package/dist/__tests__/kickass.test.d.ts.map +1 -0
- package/dist/__tests__/kickass.test.js +268 -0
- package/dist/__tests__/kickass.test.js.map +1 -0
- package/dist/__tests__/loader.test.d.ts +2 -0
- package/dist/__tests__/loader.test.d.ts.map +1 -0
- package/dist/__tests__/loader.test.js +180 -0
- package/dist/__tests__/loader.test.js.map +1 -0
- package/dist/__tests__/onboard-preservation.test.d.ts +2 -0
- package/dist/__tests__/onboard-preservation.test.d.ts.map +1 -0
- package/dist/__tests__/onboard-preservation.test.js +506 -0
- package/dist/__tests__/onboard-preservation.test.js.map +1 -0
- package/dist/__tests__/optimize.test.d.ts +2 -0
- package/dist/__tests__/optimize.test.d.ts.map +1 -0
- package/dist/__tests__/optimize.test.js +101 -0
- package/dist/__tests__/optimize.test.js.map +1 -0
- package/dist/__tests__/post-review-comment.test.d.ts +2 -0
- package/dist/__tests__/post-review-comment.test.d.ts.map +1 -0
- package/dist/__tests__/post-review-comment.test.js +44 -0
- package/dist/__tests__/post-review-comment.test.js.map +1 -0
- package/dist/__tests__/pr-lock.test.d.ts +2 -0
- package/dist/__tests__/pr-lock.test.d.ts.map +1 -0
- package/dist/__tests__/pr-lock.test.js +115 -0
- package/dist/__tests__/pr-lock.test.js.map +1 -0
- package/dist/__tests__/pr-picker.test.d.ts +2 -0
- package/dist/__tests__/pr-picker.test.d.ts.map +1 -0
- package/dist/__tests__/pr-picker.test.js +57 -0
- package/dist/__tests__/pr-picker.test.js.map +1 -0
- package/dist/__tests__/pr-status-scan.test.d.ts +2 -0
- package/dist/__tests__/pr-status-scan.test.d.ts.map +1 -0
- package/dist/__tests__/pr-status-scan.test.js +92 -0
- package/dist/__tests__/pr-status-scan.test.js.map +1 -0
- package/dist/__tests__/pr-status.test.d.ts +2 -0
- package/dist/__tests__/pr-status.test.d.ts.map +1 -0
- package/dist/__tests__/pr-status.test.js +346 -0
- package/dist/__tests__/pr-status.test.js.map +1 -0
- package/dist/__tests__/repo-picker.test.d.ts +2 -0
- package/dist/__tests__/repo-picker.test.d.ts.map +1 -0
- package/dist/__tests__/repo-picker.test.js +115 -0
- package/dist/__tests__/repo-picker.test.js.map +1 -0
- package/dist/__tests__/review-comment-body.test.d.ts +2 -0
- package/dist/__tests__/review-comment-body.test.d.ts.map +1 -0
- package/dist/__tests__/review-comment-body.test.js +54 -0
- package/dist/__tests__/review-comment-body.test.js.map +1 -0
- package/dist/__tests__/review-models.test.d.ts +2 -0
- package/dist/__tests__/review-models.test.d.ts.map +1 -0
- package/dist/__tests__/review-models.test.js +39 -0
- package/dist/__tests__/review-models.test.js.map +1 -0
- package/dist/__tests__/review-status.test.d.ts +2 -0
- package/dist/__tests__/review-status.test.d.ts.map +1 -0
- package/dist/__tests__/review-status.test.js +95 -0
- package/dist/__tests__/review-status.test.js.map +1 -0
- package/dist/__tests__/runner.test.d.ts +2 -0
- package/dist/__tests__/runner.test.d.ts.map +1 -0
- package/dist/__tests__/runner.test.js +204 -0
- package/dist/__tests__/runner.test.js.map +1 -0
- package/dist/__tests__/scan-cache.test.d.ts +2 -0
- package/dist/__tests__/scan-cache.test.d.ts.map +1 -0
- package/dist/__tests__/scan-cache.test.js +59 -0
- package/dist/__tests__/scan-cache.test.js.map +1 -0
- package/dist/__tests__/scan-client.test.d.ts +2 -0
- package/dist/__tests__/scan-client.test.d.ts.map +1 -0
- package/dist/__tests__/scan-client.test.js +30 -0
- package/dist/__tests__/scan-client.test.js.map +1 -0
- package/dist/__tests__/scan.test.d.ts +2 -0
- package/dist/__tests__/scan.test.d.ts.map +1 -0
- package/dist/__tests__/scan.test.js +115 -0
- package/dist/__tests__/scan.test.js.map +1 -0
- package/dist/__tests__/scopes.test.d.ts +2 -0
- package/dist/__tests__/scopes.test.d.ts.map +1 -0
- package/dist/__tests__/scopes.test.js +101 -0
- package/dist/__tests__/scopes.test.js.map +1 -0
- package/dist/__tests__/sha-cache.test.d.ts +2 -0
- package/dist/__tests__/sha-cache.test.d.ts.map +1 -0
- package/dist/__tests__/sha-cache.test.js +40 -0
- package/dist/__tests__/sha-cache.test.js.map +1 -0
- package/dist/__tests__/smart-switch.test.d.ts +2 -0
- package/dist/__tests__/smart-switch.test.d.ts.map +1 -0
- package/dist/__tests__/smart-switch.test.js +145 -0
- package/dist/__tests__/smart-switch.test.js.map +1 -0
- package/dist/ck.d.ts +3 -0
- package/dist/ck.d.ts.map +1 -0
- package/dist/ck.js +8 -0
- package/dist/ck.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +132 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/diagnose.d.ts +54 -0
- package/dist/commands/diagnose.d.ts.map +1 -0
- package/dist/commands/diagnose.js +294 -0
- package/dist/commands/diagnose.js.map +1 -0
- package/dist/commands/impact.d.ts +38 -0
- package/dist/commands/impact.d.ts.map +1 -0
- package/dist/commands/impact.js +210 -0
- package/dist/commands/impact.js.map +1 -0
- package/dist/commands/init.d.ts +12 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +183 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/issue.d.ts +25 -0
- package/dist/commands/issue.d.ts.map +1 -0
- package/dist/commands/issue.js +445 -0
- package/dist/commands/issue.js.map +1 -0
- package/dist/commands/kickass.d.ts +59 -0
- package/dist/commands/kickass.d.ts.map +1 -0
- package/dist/commands/kickass.js +288 -0
- package/dist/commands/kickass.js.map +1 -0
- package/dist/commands/onboard.d.ts +70 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +883 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/optimize.d.ts +16 -0
- package/dist/commands/optimize.d.ts.map +1 -0
- package/dist/commands/optimize.js +244 -0
- package/dist/commands/optimize.js.map +1 -0
- package/dist/commands/review.d.ts +2 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +118 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/run.d.ts +13 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +243 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/scan.d.ts +94 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +276 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/serve.d.ts +9 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +402 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +89 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/watch.d.ts +9 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +902 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/config/loader.d.ts +47 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +334 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +814 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +152 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/github/client.d.ts +139 -0
- package/dist/github/client.d.ts.map +1 -0
- package/dist/github/client.js +711 -0
- package/dist/github/client.js.map +1 -0
- package/dist/github/detector.d.ts +12 -0
- package/dist/github/detector.d.ts.map +1 -0
- package/dist/github/detector.js +120 -0
- package/dist/github/detector.js.map +1 -0
- package/dist/github/merge.d.ts +9 -0
- package/dist/github/merge.d.ts.map +1 -0
- package/dist/github/merge.js +33 -0
- package/dist/github/merge.js.map +1 -0
- package/dist/github/review-status.d.ts +6 -0
- package/dist/github/review-status.d.ts.map +1 -0
- package/dist/github/review-status.js +51 -0
- package/dist/github/review-status.js.map +1 -0
- package/dist/github/webhook.d.ts +41 -0
- package/dist/github/webhook.d.ts.map +1 -0
- package/dist/github/webhook.js +50 -0
- package/dist/github/webhook.js.map +1 -0
- package/dist/lib/annotation.d.ts +23 -0
- package/dist/lib/annotation.d.ts.map +1 -0
- package/dist/lib/annotation.js +103 -0
- package/dist/lib/annotation.js.map +1 -0
- package/dist/lib/backtrace.d.ts +40 -0
- package/dist/lib/backtrace.d.ts.map +1 -0
- package/dist/lib/backtrace.js +169 -0
- package/dist/lib/backtrace.js.map +1 -0
- package/dist/lib/board.d.ts +74 -0
- package/dist/lib/board.d.ts.map +1 -0
- package/dist/lib/board.js +640 -0
- package/dist/lib/board.js.map +1 -0
- package/dist/lib/clone.d.ts +12 -0
- package/dist/lib/clone.d.ts.map +1 -0
- package/dist/lib/clone.js +30 -0
- package/dist/lib/clone.js.map +1 -0
- package/dist/lib/comment-bodies.d.ts +17 -0
- package/dist/lib/comment-bodies.d.ts.map +1 -0
- package/dist/lib/comment-bodies.js +51 -0
- package/dist/lib/comment-bodies.js.map +1 -0
- package/dist/lib/crosscheck-commit.d.ts +2 -0
- package/dist/lib/crosscheck-commit.d.ts.map +1 -0
- package/dist/lib/crosscheck-commit.js +4 -0
- package/dist/lib/crosscheck-commit.js.map +1 -0
- package/dist/lib/diff-hash.d.ts +16 -0
- package/dist/lib/diff-hash.d.ts.map +1 -0
- package/dist/lib/diff-hash.js +71 -0
- package/dist/lib/diff-hash.js.map +1 -0
- package/dist/lib/durations.d.ts +5 -0
- package/dist/lib/durations.d.ts.map +1 -0
- package/dist/lib/durations.js +39 -0
- package/dist/lib/durations.js.map +1 -0
- package/dist/lib/event-fields.d.ts +6 -0
- package/dist/lib/event-fields.d.ts.map +1 -0
- package/dist/lib/event-fields.js +20 -0
- package/dist/lib/event-fields.js.map +1 -0
- package/dist/lib/filter.d.ts +2 -0
- package/dist/lib/filter.d.ts.map +1 -0
- package/dist/lib/filter.js +4 -0
- package/dist/lib/filter.js.map +1 -0
- package/dist/lib/fortune.d.ts +2 -0
- package/dist/lib/fortune.d.ts.map +1 -0
- package/dist/lib/fortune.js +26 -0
- package/dist/lib/fortune.js.map +1 -0
- package/dist/lib/languages.d.ts +3 -0
- package/dist/lib/languages.d.ts.map +1 -0
- package/dist/lib/languages.js +26 -0
- package/dist/lib/languages.js.map +1 -0
- package/dist/lib/log-analysis.d.ts +17 -0
- package/dist/lib/log-analysis.d.ts.map +1 -0
- package/dist/lib/log-analysis.js +72 -0
- package/dist/lib/log-analysis.js.map +1 -0
- package/dist/lib/logger.d.ts +14 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +84 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/port.d.ts +2 -0
- package/dist/lib/port.d.ts.map +1 -0
- package/dist/lib/port.js +21 -0
- package/dist/lib/port.js.map +1 -0
- package/dist/lib/pr-lock.d.ts +4 -0
- package/dist/lib/pr-lock.d.ts.map +1 -0
- package/dist/lib/pr-lock.js +91 -0
- package/dist/lib/pr-lock.js.map +1 -0
- package/dist/lib/pr-picker.d.ts +10 -0
- package/dist/lib/pr-picker.d.ts.map +1 -0
- package/dist/lib/pr-picker.js +80 -0
- package/dist/lib/pr-picker.js.map +1 -0
- package/dist/lib/pr-status.d.ts +206 -0
- package/dist/lib/pr-status.d.ts.map +1 -0
- package/dist/lib/pr-status.js +613 -0
- package/dist/lib/pr-status.js.map +1 -0
- package/dist/lib/repo-picker.d.ts +23 -0
- package/dist/lib/repo-picker.d.ts.map +1 -0
- package/dist/lib/repo-picker.js +411 -0
- package/dist/lib/repo-picker.js.map +1 -0
- package/dist/lib/review-models.d.ts +7 -0
- package/dist/lib/review-models.d.ts.map +1 -0
- package/dist/lib/review-models.js +32 -0
- package/dist/lib/review-models.js.map +1 -0
- package/dist/lib/runner.d.ts +65 -0
- package/dist/lib/runner.d.ts.map +1 -0
- package/dist/lib/runner.js +710 -0
- package/dist/lib/runner.js.map +1 -0
- package/dist/lib/scan-cache.d.ts +31 -0
- package/dist/lib/scan-cache.d.ts.map +1 -0
- package/dist/lib/scan-cache.js +112 -0
- package/dist/lib/scan-cache.js.map +1 -0
- package/dist/lib/scopes.d.ts +16 -0
- package/dist/lib/scopes.d.ts.map +1 -0
- package/dist/lib/scopes.js +37 -0
- package/dist/lib/scopes.js.map +1 -0
- package/dist/lib/sha-cache.d.ts +7 -0
- package/dist/lib/sha-cache.d.ts.map +1 -0
- package/dist/lib/sha-cache.js +44 -0
- package/dist/lib/sha-cache.js.map +1 -0
- package/dist/lib/smart-switch.d.ts +44 -0
- package/dist/lib/smart-switch.d.ts.map +1 -0
- package/dist/lib/smart-switch.js +145 -0
- package/dist/lib/smart-switch.js.map +1 -0
- package/dist/lib/verdict.d.ts +9 -0
- package/dist/lib/verdict.d.ts.map +1 -0
- package/dist/lib/verdict.js +52 -0
- package/dist/lib/verdict.js.map +1 -0
- package/dist/lib/workflow.d.ts +85 -0
- package/dist/lib/workflow.d.ts.map +1 -0
- package/dist/lib/workflow.js +116 -0
- package/dist/lib/workflow.js.map +1 -0
- package/dist/reviewers/address.d.ts +5 -0
- package/dist/reviewers/address.d.ts.map +1 -0
- package/dist/reviewers/address.js +87 -0
- package/dist/reviewers/address.js.map +1 -0
- package/dist/reviewers/claude.d.ts +12 -0
- package/dist/reviewers/claude.d.ts.map +1 -0
- package/dist/reviewers/claude.js +78 -0
- package/dist/reviewers/claude.js.map +1 -0
- package/dist/reviewers/codex.d.ts +9 -0
- package/dist/reviewers/codex.d.ts.map +1 -0
- package/dist/reviewers/codex.js +121 -0
- package/dist/reviewers/codex.js.map +1 -0
- package/dist/reviewers/conflict-resolve.d.ts +15 -0
- package/dist/reviewers/conflict-resolve.d.ts.map +1 -0
- package/dist/reviewers/conflict-resolve.js +219 -0
- package/dist/reviewers/conflict-resolve.js.map +1 -0
- package/dist/reviewers/fix.d.ts +7 -0
- package/dist/reviewers/fix.d.ts.map +1 -0
- package/dist/reviewers/fix.js +197 -0
- package/dist/reviewers/fix.js.map +1 -0
- package/get-started.md +1271 -0
- package/get-started.zh.md +1208 -0
- package/package.json +75 -0
package/README.zh.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
<div align="right">
|
|
2
|
+
<h5><a href="./README.md">🌐 English</a></h5>
|
|
3
|
+
</div>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="./assets/logo.png" alt="crosscheck" width="160" />
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<p align="center"><em>用 crosscheck 构建 crosscheck。</em></p>
|
|
10
|
+
|
|
11
|
+
# crosscheck
|
|
12
|
+
|
|
13
|
+
**为使用 Claude Code 和 Codex 的开发者打造的自动化 AI Code Review——按你的方式配置,零额外基础设施。**
|
|
14
|
+
|
|
15
|
+
当你的 AI Agent 提交 PR 时,另一个 AI 负责审查。发现问题后,原作者 Agent 自动修复并提交跟进 PR。整个流程运行在你已有的订阅上,一条命令即可启动。
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 核心亮点
|
|
20
|
+
|
|
21
|
+
- **可定制的审查工作流** — 灵活配置完整流水线:仅审查、审查 + 自动修复,或审查 + 修复 + 复查。每个步骤均可定制审查指令,无需手动编辑 Prompt。
|
|
22
|
+
- **跨供应商模式与单供应商模式** — 跨供应商模式将每个 PR 路由给对手 AI 进行独立审查;单供应商模式则使用你拥有的任意一个 AI。一行配置即可切换。
|
|
23
|
+
- **订阅驱动,无需按 token 计费** — 通过 `claude` 和 `codex` 命令行工具运行,使用你已有的 Claude Pro/Max 和 ChatGPT Plus/Pro 订阅。无需 API Key,无额外审查费用。
|
|
24
|
+
- **`watch` 个人使用,`serve` 服务团队** — `crosscheck watch` 在本地笔记本运行并自动建立隧道,适合个人开发者。`crosscheck serve` 绑定到共享机器的固定端口,让整个团队无需任何人保持笔记本在线即可获得覆盖。
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 快速开始
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# 1. 安装 crosscheck 及 Agent CLI
|
|
32
|
+
npm install -g @humanbased/crosscheck
|
|
33
|
+
npm install -g @anthropic-ai/claude-code && claude # 需要 Claude Pro/Max 订阅
|
|
34
|
+
npm install -g @openai/codex && codex login --device-auth # 需要 ChatGPT Plus/Pro 订阅
|
|
35
|
+
brew install gh && gh auth login # GitHub CLI
|
|
36
|
+
|
|
37
|
+
# 2. 引导式配置——选择仓库、供应商模式、工作流流水线
|
|
38
|
+
crosscheck onboard
|
|
39
|
+
|
|
40
|
+
# 3. 启动监听
|
|
41
|
+
crosscheck watch # 个人笔记本
|
|
42
|
+
crosscheck serve # 团队常驻服务器
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`crosscheck onboard` 将引导你完成仓库选择、供应商模式、流水线步骤和隧道选择。完成后,运行 `watch` 或 `serve` 即可。
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 运行效果
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
$ crosscheck watch
|
|
53
|
+
|
|
54
|
+
"Move fast and review things."
|
|
55
|
+
|
|
56
|
+
profile personal · cross-vendor · balanced
|
|
57
|
+
users your-github-login (5 repos)
|
|
58
|
+
auto-fix on_issues · same-as-author · pull_request
|
|
59
|
+
config ./crosscheck.config.yml
|
|
60
|
+
|
|
61
|
+
✓ 隧道已就绪: https://abc123.lhr.life
|
|
62
|
+
✓ 已为 your-org/your-repo 注册 Webhook
|
|
63
|
+
等待 PR 事件 — 按 Ctrl+C 停止。
|
|
64
|
+
|
|
65
|
+
PR #47 opened: add retry logic for flaky network calls
|
|
66
|
+
origin=claude reviewer=codex
|
|
67
|
+
codex reviewing... (12s)
|
|
68
|
+
NEEDS WORK
|
|
69
|
+
auto-fix claude fixing...
|
|
70
|
+
fix PR #48 opened → github.com/your-org/your-repo/pull/48
|
|
71
|
+
|
|
72
|
+
PR #49 opened: implement caching layer
|
|
73
|
+
origin=codex reviewer=claude
|
|
74
|
+
claude reviewing... (18s)
|
|
75
|
+
APPROVE
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 命令列表
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
crosscheck init # 检查环境,生成初始配置文件
|
|
84
|
+
crosscheck onboard # 引导式配置——选择仓库、模式和流水线
|
|
85
|
+
crosscheck review <pr-url> # 对指定 PR 进行一次性审查
|
|
86
|
+
crosscheck watch # 个人使用——隧道 + 自动 Webhook + 本地监听
|
|
87
|
+
crosscheck serve # 团队使用——固定端口,一次性注册 Webhook
|
|
88
|
+
crosscheck status # 查看认证状态、配置摘要、CLI 版本
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**持续改进** *(实验性)*
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
crosscheck diagnose # 从审查日志中提取失败模式
|
|
95
|
+
crosscheck optimize [--apply] # 根据 diagnose 输出重写审查指令
|
|
96
|
+
crosscheck impact [--money] # 节省时间、发现问题、代码质量趋势报告
|
|
97
|
+
crosscheck issue # 从近期错误日志起草并提交 Bug 报告
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 配置说明
|
|
103
|
+
|
|
104
|
+
配置文件位于 `~/.crosscheck/config.yml`,一个文件覆盖所有仓库。运行 `crosscheck init` 生成,或通过 `crosscheck onboard` 自动写入。项目根目录下的 `crosscheck.config.yml` 或 `.crosscheck.yml` 仅在 home 配置缺失时作为回退使用。
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
orgs:
|
|
108
|
+
- your-org
|
|
109
|
+
|
|
110
|
+
routing:
|
|
111
|
+
allowed_authors:
|
|
112
|
+
- your-github-login
|
|
113
|
+
|
|
114
|
+
quality:
|
|
115
|
+
tier: balanced # fast(快速)| balanced(均衡)| thorough(深度)
|
|
116
|
+
|
|
117
|
+
post_review:
|
|
118
|
+
auto_fix:
|
|
119
|
+
enabled: true
|
|
120
|
+
trigger: on_issues # on_issues | always | never
|
|
121
|
+
fixer: same-as-author
|
|
122
|
+
delivery:
|
|
123
|
+
mode: pull_request
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
完整配置参考:[get-started.zh.md](./get-started.zh.md)
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 部署方式
|
|
131
|
+
|
|
132
|
+
**个人使用(`crosscheck watch`)** — 运行在你的笔记本上。通过 `localhost.run` 建立 SSH 隧道,无需端口转发,无需云账号。隧道断开时健康检查会自动重连。
|
|
133
|
+
|
|
134
|
+
**团队使用(`crosscheck serve`)** — 绑定到具有公网 IP 的机器上的固定端口,手动注册一次 Webhook,整个团队即可获得覆盖,无需任何人保持笔记本在线。
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 系统要求
|
|
139
|
+
|
|
140
|
+
| | 最低版本 |
|
|
141
|
+
|---|---|
|
|
142
|
+
| Node.js | 18+ |
|
|
143
|
+
| Claude Code CLI | 最新版 — `npm install -g @anthropic-ai/claude-code` |
|
|
144
|
+
| Codex CLI | 最新版 — `npm install -g @openai/codex` |
|
|
145
|
+
| GitHub CLI | 2.65+ — `brew install gh` |
|
|
146
|
+
|
|
147
|
+
运行 `gh auth login` 后,`GITHUB_TOKEN` 会自动获取,无需手动导出。
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 文档
|
|
152
|
+
|
|
153
|
+
| | |
|
|
154
|
+
|---|---|
|
|
155
|
+
| **[get-started.zh.md](./get-started.zh.md)** | 完整安装指南——前置条件、所有命令与参数、完整配置参考、常见问题 |
|
|
156
|
+
| **[crosscheck.config.example.yml](./crosscheck.config.example.yml)** | 带注释的配置文件示例(每个选项均有说明) |
|
|
157
|
+
| **[CHANGELOG.md](./CHANGELOG.md)** | 版本发布记录 |
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 参与贡献
|
|
162
|
+
|
|
163
|
+
欢迎提交 Issue 和 PR:[github.com/humanbased-ai/crosscheck](https://github.com/humanbased-ai/crosscheck)
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 许可证
|
|
168
|
+
|
|
169
|
+
[MIT](./LICENSE) — Copyright (c) 2025–2026 HumanBased AI.
|
package/assets/logo.png
ADDED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="940" height="494.2"><rect width="940" height="494.2" rx="5" ry="5" class="a"/><svg y="0%" x="0%"><circle cx="20" cy="20" r="6" fill="#ff5f58"/><circle cx="40" cy="20" r="6" fill="#ffbd2e"/><circle cx="60" cy="20" r="6" fill="#18c132"/></svg><svg height="434.2" viewBox="0 0 90 43.42" width="900" x="15" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="50"><style>@keyframes o{0%{transform:translateX(-90px)}5.3%{transform:translateX(-180px)}10.5%{transform:translateX(-270px)}15.8%{transform:translateX(-360px)}21.1%{transform:translateX(-450px)}26.3%{transform:translateX(-540px)}31.6%{transform:translateX(-630px)}36.8%{transform:translateX(-720px)}42.1%{transform:translateX(-810px)}47.4%{transform:translateX(-900px)}52.6%{transform:translateX(-990px)}57.9%{transform:translateX(-1080px)}63.2%{transform:translateX(-1170px)}68.4%{transform:translateX(-1260px)}73.7%{transform:translateX(-1350px)}78.9%{transform:translateX(-1440px)}84.2%{transform:translateX(-1530px)}89.5%{transform:translateX(-1620px)}94.7%{transform:translateX(-1710px)}to{transform:translateX(-1800px)}}.a{fill:#282d35}.f,.g,.h{fill:#b9c0cb;white-space:pre}.g,.h{fill:#a8cc8c}.h{fill:#b9c0cb;font-weight:700}.i,.j,.k,.l{fill:#b9bfca;white-space:pre}.j,.k,.l{fill:#dbab79}.k,.l{fill:#66c2cd}.l{fill:#71bef2}</style><g font-family="Monaco,Consolas,Menlo,'Bitstream Vera Sans Mono','Powerline Symbols',monospace" font-size="1.67"><defs><symbol id="1"><text y="1.67" class="f">────────────────────────────────────────────────────────────────────────────────────────</text></symbol><symbol id="2"><text y="1.67" class="g">●</text><text x="2.004" y="1.67" class="h">crosscheck</text><text x="14.028" y="1.67" class="f">cross-vendor</text><text x="27.054" y="1.67" class="f">·</text><text x="29.058" y="1.67" class="f">thorough</text></symbol><symbol id="3"><text x="39.078" y="1.67" class="f">workflow:</text><text x="49.098" y="1.67" class="f">review</text><text x="56.112" y="1.67" class="f">→</text><text x="58.116" y="1.67" class="f">fix</text><text x="62.124" y="1.67" class="f">→</text><text x="64.128" y="1.67" class="f">recheck</text></symbol><symbol id="4"><text x="73.146" y="1.67" class="f">vendors:</text><text x="83.166" y="1.67" class="f">claude</text></symbol><symbol id="5"><text y="1.67" class="f">·</text><text x="2.004" y="1.67" class="f">codex</text></symbol><symbol id="6"><text x="7.014" y="1.67" class="f">───────────────────────────────────────────────────────────────────────────────────</text></symbol><symbol id="7"><text y="1.67" class="f">─────</text></symbol><symbol id="8"><text x="7.014" y="1.67" class="f">PRs:</text><text x="12.024" y="1.67" class="f">4</text><text x="14.028" y="1.67" class="f">·</text><text x="16.032" y="1.67" class="f">CRs:</text><text x="21.042" y="1.67" class="f">3</text><text x="23.046" y="1.67" class="f">·</text><text x="25.05" y="1.67" class="f">fixes:</text><text x="32.064" y="1.67" class="f">2</text><text x="35.07" y="1.67" class="f">│</text><text x="38.076" y="1.67" class="f">avg</text><text x="42.084" y="1.67" class="f">CR:</text><text x="46.092" y="1.67" class="i">1m34s</text><text x="53.106" y="1.67" class="f">│</text><text x="56.112" y="1.67" class="f">↑</text><text x="58.116" y="1.67" class="f">18:42</text></symbol><symbol id="9"><text x="65.13" y="1.67" class="f">tunnel:</text><text x="75.15" y="1.67" class="f">e3f9a1.smee.io</text></symbol><symbol id="10"><text y="1.67" class="g">✓</text></symbol><symbol id="11"><text x="3.006" y="1.67" class="f">10:17</text><text x="9.018" y="1.67" class="f">PM</text><text x="13.026" y="1.67" class="f">PR</text><text x="16.032" y="1.67" class="f">#111</text><text x="21.042" y="1.67" class="f">opened</text><text x="29.058" y="1.67" class="f">feat/login</text><text x="43.086" y="1.67" class="f">origin=</text><text x="50.1" y="1.67" class="j">claude</text><text x="58.116" y="1.67" class="f">via=body</text><text x="68.136" y="1.67" class="f">reviewer=</text><text x="77.154" y="1.67" class="k">codex</text></symbol><symbol id="12"><text x="84.168" y="1.67" class="f">10:22</text></symbol><symbol id="13"><text y="1.67" class="f">PM</text><text x="4.008" y="1.67" class="f">PR</text><text x="7.014" y="1.67" class="f">#112</text><text x="12.024" y="1.67" class="f">opened</text><text x="20.04" y="1.67" class="f">fix/null-ptr</text><text x="34.068" y="1.67" class="f">origin=</text><text x="41.082" y="1.67" class="j">codex</text><text x="49.098" y="1.67" class="f">via=commits</text><text x="62.124" y="1.67" class="f">reviewer=</text><text x="71.142" y="1.67" class="k">claude</text></symbol><symbol id="14"><text x="77.154" y="1.67" class="f">─────────────</text></symbol><symbol id="15"><text y="1.67" class="f">───────────────────────────────────────────────────────────────────────────</text></symbol><symbol id="16"><text x="77.154" y="1.67" class="g">✓</text><text x="79.158" y="1.67" class="f">#109</text><text x="85.17" y="1.67" class="f">org/r</text></symbol><symbol id="17"><text y="1.67" class="f">epo</text><text x="5.01" y="1.67" class="f">feat/auth</text><text x="18.036" y="1.67" class="f">CR:</text><text x="22.044" y="1.67" class="g">APPROVE</text><text x="31.062" y="1.67" class="f">(43s)</text><text x="38.076" y="1.67" class="f">→</text><text x="40.08" y="1.67" class="k">https://github.com/org/repo/pull/109</text></symbol><symbol id="18"><text x="78.156" y="1.67" class="g">✓</text><text x="80.16" y="1.67" class="f">#110</text><text x="86.172" y="1.67" class="f">org/</text></symbol><symbol id="19"><text y="1.67" class="f">repo</text><text x="6.012" y="1.67" class="f">fix/crash</text><text x="19.038" y="1.67" class="f">CR:</text><text x="23.046" y="1.67" class="j">NEEDS</text><text x="29.058" y="1.67" class="j">WORK</text><text x="34.068" y="1.67" class="f">·</text><text x="36.072" y="1.67" class="f">fix</text><text x="40.08" y="1.67" class="f">2</text><text x="43.086" y="1.67" class="f">(2m08s)</text><text x="52.104" y="1.67" class="f">→</text><text x="54.108" y="1.67" class="k">https://github.com/org/repo/pull/110</text></symbol><symbol id="20"><text x="2.004" y="1.67" class="g">⠋</text><text x="4.008" y="1.67" class="h">#111</text><text x="10.02" y="1.67" class="i">org/repo</text><text x="20.04" y="1.67" class="f">feat/login</text><text x="46.092" y="1.67" class="f">started</text><text x="54.108" y="1.67" class="f">10:17</text><text x="60.12" y="1.67" class="f">PM</text><text x="64.128" y="1.67" class="f">4m05s</text><text x="71.142" y="1.67" class="g">⠋</text><text x="73.146" y="1.67" class="f">rechecking…</text></symbol><symbol id="21"><text x="86.172" y="1.67" class="f">PR</text><text x="89.178" y="1.67" class="l">█</text></symbol><symbol id="22"><text y="1.67" class="l">█████████</text><text x="10.02" y="1.67" class="f">711loc</text><text x="17.034" y="1.67" class="f">|</text><text x="19.038" y="1.67" class="f">CR</text><text x="22.044" y="1.67" class="j">████████</text><text x="31.062" y="1.67" class="j">2</text><text x="33.066" y="1.67" class="j">issues</text><text x="40.08" y="1.67" class="j">(NEEDS</text><text x="47.094" y="1.67" class="j">WORK,</text><text x="53.106" y="1.67" class="j">3.2K)</text><text x="59.118" y="1.67" class="f">codex</text><text x="65.13" y="1.67" class="f">·</text><text x="67.134" y="1.67" class="f">thorough</text><text x="76.152" y="1.67" class="f">|</text><text x="78.156" y="1.67" class="f">Fix</text><text x="82.164" y="1.67" class="k">███</text><text x="85.17" y="1.67" class="f">░░░</text><text x="89.178" y="1.67" class="k">✓</text></symbol><symbol id="23"><text x="1.002" y="1.67" class="k">1</text><text x="3.006" y="1.67" class="k">applied</text><text x="11.022" y="1.67" class="f">(2K)</text><text x="16.032" y="1.67" class="f">|</text><text x="18.036" y="1.67" class="f">Recheck</text><text x="26.052" y="1.67" class="f">░░░░░</text></symbol><symbol id="24"><text x="33.066" y="1.67" class="g">⠋</text><text x="35.07" y="1.67" class="h">#112</text><text x="41.082" y="1.67" class="i">org/repo</text><text x="51.102" y="1.67" class="f">fix/null-ptr</text><text x="83.166" y="1.67" class="f">started</text></symbol><symbol id="25"><text x="1.002" y="1.67" class="f">10:22</text><text x="7.014" y="1.67" class="f">PM</text><text x="11.022" y="1.67" class="f">8s</text><text x="15.03" y="1.67" class="g">⠋</text><text x="17.034" y="1.67" class="f">reviewing…</text></symbol><symbol id="26"><text x="29.058" y="1.67" class="f">PR</text><text x="32.064" y="1.67" class="l">███</text><text x="35.07" y="1.67" class="f">░░░░░░░</text><text x="43.086" y="1.67" class="f">42loc</text><text x="49.098" y="1.67" class="f">|</text><text x="51.102" y="1.67" class="f">CR</text><text x="54.108" y="1.67" class="f">░░░░░░░░</text><text x="63.126" y="1.67" class="f">queued</text><text x="70.14" y="1.67" class="f">|</text><text x="72.144" y="1.67" class="f">Fix</text><text x="76.152" y="1.67" class="f">░░░░░░</text><text x="83.166" y="1.67" class="f">queued</text></symbol><symbol id="27"><text x="89.178" y="1.67" class="f">─</text></symbol><symbol id="28"><text y="1.67" class="f">───────────────────────────────────────────────────────────────────────────────────────</text></symbol><symbol id="a"><path fill="transparent" d="M0 0h90v20H0z"/></symbol><symbol id="b"><path fill="#6f7683" d="M0 0h1.102v2.171H0z"/></symbol></defs><path class="a" d="M0 0h90v43.42H0z"/><g style="animation-duration:.9500000000000003s;animation-iteration-count:infinite;animation-name:o;animation-timing-function:steps(1,end)"><svg width="1890"><svg><use xlink:href="#a"/><use xlink:href="#b" x="-.004"/></svg><svg x="90"><use xlink:href="#a"/><use xlink:href="#b" x="87.996" y="2.146"/><use xlink:href="#1"/></svg><svg x="180"><use xlink:href="#a"/><use xlink:href="#b" x="36.996" y="6.488"/><use xlink:href="#1"/><use xlink:href="#2" y="4.342"/></svg><svg x="270"><use xlink:href="#a"/><use xlink:href="#b" x="70.996" y="8.659"/><use xlink:href="#1"/><use xlink:href="#2" y="4.342"/><use xlink:href="#3" y="6.513"/></svg><svg x="360"><use xlink:href="#a"/><use xlink:href="#b" x="6.996" y="13.001"/><use xlink:href="#1"/><use xlink:href="#2" y="4.342"/><use xlink:href="#3" y="6.513"/><use xlink:href="#4" y="8.684"/><use xlink:href="#5" y="10.855"/></svg><svg x="450"><use xlink:href="#a"/><use xlink:href="#b" x="4.996" y="17.343"/><use xlink:href="#1"/><use xlink:href="#2" y="4.342"/><use xlink:href="#3" y="6.513"/><use xlink:href="#4" y="8.684"/><use xlink:href="#5" y="10.855"/><use xlink:href="#6" y="13.026"/><use xlink:href="#7" y="15.197"/></svg><svg x="540"><use xlink:href="#a"/><use xlink:href="#b" x="62.996" y="19.514"/><use xlink:href="#1"/><use xlink:href="#2" y="4.342"/><use xlink:href="#3" y="6.513"/><use xlink:href="#4" y="8.684"/><use xlink:href="#5" y="10.855"/><use xlink:href="#6" y="13.026"/><use xlink:href="#7" y="15.197"/><use xlink:href="#8" y="17.368"/></svg><svg x="630"><use xlink:href="#a"/><use xlink:href="#b" x=".996" y="23.856"/><use xlink:href="#1"/><use xlink:href="#2" y="4.342"/><use xlink:href="#3" y="6.513"/><use xlink:href="#4" y="8.684"/><use xlink:href="#5" y="10.855"/><use xlink:href="#6" y="13.026"/><use xlink:href="#7" y="15.197"/><use xlink:href="#8" y="17.368"/><use xlink:href="#9" y="19.539"/><use xlink:href="#10" y="21.71"/></svg><svg x="720"><use xlink:href="#a"/><use xlink:href="#b" x="81.996" y="26.027"/><use xlink:href="#1"/><use xlink:href="#2" y="4.342"/><use xlink:href="#3" y="6.513"/><use xlink:href="#4" y="8.684"/><use xlink:href="#5" y="10.855"/><use xlink:href="#6" y="13.026"/><use xlink:href="#7" y="15.197"/><use xlink:href="#8" y="17.368"/><use xlink:href="#9" y="19.539"/><use xlink:href="#10" y="21.71"/><use xlink:href="#11" y="23.881"/></svg><svg x="810"><use xlink:href="#a"/><use xlink:href="#b" x="76.996" y="30.369"/><use xlink:href="#1"/><use xlink:href="#2" y="4.342"/><use xlink:href="#3" y="6.513"/><use xlink:href="#4" y="8.684"/><use xlink:href="#5" y="10.855"/><use xlink:href="#6" y="13.026"/><use xlink:href="#7" y="15.197"/><use xlink:href="#8" y="17.368"/><use xlink:href="#9" y="19.539"/><use xlink:href="#10" y="21.71"/><use xlink:href="#11" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/></svg><svg x="900"><use xlink:href="#a"/><use xlink:href="#b" x="74.996" y="34.711"/><use xlink:href="#1"/><use xlink:href="#2" y="4.342"/><use xlink:href="#3" y="6.513"/><use xlink:href="#4" y="8.684"/><use xlink:href="#5" y="10.855"/><use xlink:href="#6" y="13.026"/><use xlink:href="#7" y="15.197"/><use xlink:href="#8" y="17.368"/><use xlink:href="#9" y="19.539"/><use xlink:href="#10" y="21.71"/><use xlink:href="#11" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#15" y="32.565"/></svg><svg x="990"><use xlink:href="#a"/><use xlink:href="#b" x="75.996" y="39.053"/><use xlink:href="#1"/><use xlink:href="#2" y="4.342"/><use xlink:href="#3" y="6.513"/><use xlink:href="#4" y="8.684"/><use xlink:href="#5" y="10.855"/><use xlink:href="#6" y="13.026"/><use xlink:href="#7" y="15.197"/><use xlink:href="#8" y="17.368"/><use xlink:href="#9" y="19.539"/><use xlink:href="#10" y="21.71"/><use xlink:href="#11" y="23.881"/><use xlink:href="#12" y="26.052"/><use xlink:href="#13" y="28.223"/><use xlink:href="#14" y="30.394"/><use xlink:href="#15" y="32.565"/><use xlink:href="#16" y="34.736"/><use xlink:href="#17" y="36.907"/></svg><svg x="1080"><use xlink:href="#a"/><use xlink:href="#b" x="89.996" y="41.224"/><use xlink:href="#2" y="2.171"/><use xlink:href="#3" y="4.342"/><use xlink:href="#4" y="6.513"/><use xlink:href="#5" y="8.684"/><use xlink:href="#6" y="10.855"/><use xlink:href="#7" y="13.026"/><use xlink:href="#8" y="15.197"/><use xlink:href="#9" y="17.368"/><use xlink:href="#10" y="19.539"/><use xlink:href="#11" y="21.71"/><use xlink:href="#12" y="23.881"/><use xlink:href="#13" y="26.052"/><use xlink:href="#14" y="28.223"/><use xlink:href="#15" y="30.394"/><use xlink:href="#16" y="32.565"/><use xlink:href="#17" y="34.736"/><use xlink:href="#18" y="36.907"/><use xlink:href="#19" y="39.078"/></svg><svg x="1170"><use xlink:href="#a"/><use xlink:href="#b" x="89.996" y="41.224"/><use xlink:href="#2"/><use xlink:href="#3" y="2.171"/><use xlink:href="#4" y="4.342"/><use xlink:href="#5" y="6.513"/><use xlink:href="#6" y="8.684"/><use xlink:href="#7" y="10.855"/><use xlink:href="#8" y="13.026"/><use xlink:href="#9" y="15.197"/><use xlink:href="#10" y="17.368"/><use xlink:href="#11" y="19.539"/><use xlink:href="#12" y="21.71"/><use xlink:href="#13" y="23.881"/><use xlink:href="#14" y="26.052"/><use xlink:href="#15" y="28.223"/><use xlink:href="#16" y="30.394"/><use xlink:href="#17" y="32.565"/><use xlink:href="#18" y="34.736"/><use xlink:href="#19" y="36.907"/></svg><svg x="1260"><use xlink:href="#a"/><use xlink:href="#b" x="83.996" y="41.224"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#10" y="13.026"/><use xlink:href="#11" y="15.197"/><use xlink:href="#12" y="17.368"/><use xlink:href="#13" y="19.539"/><use xlink:href="#14" y="21.71"/><use xlink:href="#15" y="23.881"/><use xlink:href="#16" y="26.052"/><use xlink:href="#17" y="28.223"/><use xlink:href="#18" y="30.394"/><use xlink:href="#19" y="32.565"/><use xlink:href="#20" y="39.078"/></svg><svg x="1350"><use xlink:href="#a"/><use xlink:href="#b" x="30.996" y="41.224"/><use xlink:href="#7"/><use xlink:href="#8" y="2.171"/><use xlink:href="#9" y="4.342"/><use xlink:href="#10" y="6.513"/><use xlink:href="#11" y="8.684"/><use xlink:href="#12" y="10.855"/><use xlink:href="#13" y="13.026"/><use xlink:href="#14" y="15.197"/><use xlink:href="#15" y="17.368"/><use xlink:href="#16" y="19.539"/><use xlink:href="#17" y="21.71"/><use xlink:href="#18" y="23.881"/><use xlink:href="#19" y="26.052"/><use xlink:href="#20" y="32.565"/><use xlink:href="#21" y="34.736"/><use xlink:href="#22" y="36.907"/><use xlink:href="#23" y="39.078"/></svg><svg x="1440"><use xlink:href="#a"/><use xlink:href="#b" x="30.996" y="41.224"/><use xlink:href="#8"/><use xlink:href="#9" y="2.171"/><use xlink:href="#10" y="4.342"/><use xlink:href="#11" y="6.513"/><use xlink:href="#12" y="8.684"/><use xlink:href="#13" y="10.855"/><use xlink:href="#14" y="13.026"/><use xlink:href="#15" y="15.197"/><use xlink:href="#16" y="17.368"/><use xlink:href="#17" y="19.539"/><use xlink:href="#18" y="21.71"/><use xlink:href="#19" y="23.881"/><use xlink:href="#20" y="30.394"/><use xlink:href="#21" y="32.565"/><use xlink:href="#22" y="34.736"/><use xlink:href="#23" y="36.907"/></svg><svg x="1530"><use xlink:href="#a"/><use xlink:href="#b" x="26.996" y="41.224"/><use xlink:href="#10"/><use xlink:href="#11" y="2.171"/><use xlink:href="#12" y="4.342"/><use xlink:href="#13" y="6.513"/><use xlink:href="#14" y="8.684"/><use xlink:href="#15" y="10.855"/><use xlink:href="#16" y="13.026"/><use xlink:href="#17" y="15.197"/><use xlink:href="#18" y="17.368"/><use xlink:href="#19" y="19.539"/><use xlink:href="#20" y="26.052"/><use xlink:href="#21" y="28.223"/><use xlink:href="#22" y="30.394"/><use xlink:href="#23" y="32.565"/><use xlink:href="#24" y="36.907"/><use xlink:href="#25" y="39.078"/></svg><svg x="1620"><use xlink:href="#a"/><use xlink:href="#b" x="88.996" y="41.224"/><use xlink:href="#11"/><use xlink:href="#12" y="2.171"/><use xlink:href="#13" y="4.342"/><use xlink:href="#14" y="6.513"/><use xlink:href="#15" y="8.684"/><use xlink:href="#16" y="10.855"/><use xlink:href="#17" y="13.026"/><use xlink:href="#18" y="15.197"/><use xlink:href="#19" y="17.368"/><use xlink:href="#20" y="23.881"/><use xlink:href="#21" y="26.052"/><use xlink:href="#22" y="28.223"/><use xlink:href="#23" y="30.394"/><use xlink:href="#24" y="34.736"/><use xlink:href="#25" y="36.907"/><use xlink:href="#26" y="39.078"/></svg><svg x="1710"><use xlink:href="#a"/><use xlink:href="#b" x="86.996" y="41.224"/><use xlink:href="#13"/><use xlink:href="#14" y="2.171"/><use xlink:href="#15" y="4.342"/><use xlink:href="#16" y="6.513"/><use xlink:href="#17" y="8.684"/><use xlink:href="#18" y="10.855"/><use xlink:href="#19" y="13.026"/><use xlink:href="#20" y="19.539"/><use xlink:href="#21" y="21.71"/><use xlink:href="#22" y="23.881"/><use xlink:href="#23" y="26.052"/><use xlink:href="#24" y="30.394"/><use xlink:href="#25" y="32.565"/><use xlink:href="#26" y="34.736"/><use xlink:href="#27" y="36.907"/><use xlink:href="#28" y="39.078"/></svg><svg x="1800"><use xlink:href="#a"/><use xlink:href="#b" x="86.996" y="41.224"/><use xlink:href="#14"/><use xlink:href="#15" y="2.171"/><use xlink:href="#16" y="4.342"/><use xlink:href="#17" y="6.513"/><use xlink:href="#18" y="8.684"/><use xlink:href="#19" y="10.855"/><use xlink:href="#20" y="17.368"/><use xlink:href="#21" y="19.539"/><use xlink:href="#22" y="21.71"/><use xlink:href="#23" y="23.881"/><use xlink:href="#24" y="28.223"/><use xlink:href="#25" y="30.394"/><use xlink:href="#26" y="32.565"/><use xlink:href="#27" y="34.736"/><use xlink:href="#28" y="36.907"/></svg></svg></g></g></svg></svg>
|
|
Binary file
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# crosscheck.config.yml
|
|
2
|
+
# This file is designed to be easily read and modified by coding agents.
|
|
3
|
+
# All fields are optional — crosscheck uses sensible defaults.
|
|
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
|
+
|
|
12
|
+
# ─── Mode ────────────────────────────────────────────────────────────────────
|
|
13
|
+
# single-vendor: one AI reviews all PRs
|
|
14
|
+
# cross-vendor: each AI reviews the other's PRs (Claude ↔ Codex)
|
|
15
|
+
mode: cross-vendor
|
|
16
|
+
|
|
17
|
+
# ─── Clone protocol ──────────────────────────────────────────────────────────
|
|
18
|
+
# How crosscheck clones PR repos for review.
|
|
19
|
+
# ssh — git@github.com:owner/repo.git (uses your local SSH keys)
|
|
20
|
+
# https — https://github.com/owner/repo.git (uses GitHub token)
|
|
21
|
+
# Pick https if you have a multi-account SSH setup or your default SSH key
|
|
22
|
+
# cannot access target repos. Independent of `gh config get git_protocol`.
|
|
23
|
+
clone_protocol: ssh
|
|
24
|
+
|
|
25
|
+
# ─── Vendors ─────────────────────────────────────────────────────────────────
|
|
26
|
+
vendors:
|
|
27
|
+
codex:
|
|
28
|
+
enabled: true
|
|
29
|
+
model: o4-mini # o4-mini | o3 | gpt-4o (cost/quality tradeoff)
|
|
30
|
+
auth: subscription # subscription (device-auth OAuth) | api-key
|
|
31
|
+
|
|
32
|
+
claude:
|
|
33
|
+
enabled: true
|
|
34
|
+
model: sonnet # haiku | sonnet | opus
|
|
35
|
+
effort: medium # low | medium | high | max
|
|
36
|
+
|
|
37
|
+
# ─── Quality & Focus ─────────────────────────────────────────────────────────
|
|
38
|
+
quality:
|
|
39
|
+
tier: balanced # fast | balanced | thorough
|
|
40
|
+
#
|
|
41
|
+
# Tier determines the model and effort level used for each vendor:
|
|
42
|
+
#
|
|
43
|
+
# tier claude codex time cost
|
|
44
|
+
# ───────── ─────────────────── ─────────── ─────── ──────
|
|
45
|
+
# fast haiku · low o4-mini · low ~10s lowest
|
|
46
|
+
# balanced sonnet · medium o4-mini · med ~30s standard
|
|
47
|
+
# thorough sonnet · max o3 · high ~60s higher
|
|
48
|
+
#
|
|
49
|
+
# crosscheck onboard writes these automatically when you pick a tier.
|
|
50
|
+
# You can override individual vendor settings in the vendors: block below.
|
|
51
|
+
|
|
52
|
+
focus: # optional — narrows review scope
|
|
53
|
+
- security
|
|
54
|
+
- types
|
|
55
|
+
- performance
|
|
56
|
+
# - naming
|
|
57
|
+
# - test-coverage
|
|
58
|
+
# - documentation
|
|
59
|
+
|
|
60
|
+
custom_prompt: | # optional — appended to every review
|
|
61
|
+
Focus on correctness and security. Be concise.
|
|
62
|
+
|
|
63
|
+
# ─── Budget ──────────────────────────────────────────────────────────────────
|
|
64
|
+
budget:
|
|
65
|
+
codex_monthly_usd: 20 # null = unlimited (use if on subscription)
|
|
66
|
+
per_review_usd: 2.00 # hard stop per single review
|
|
67
|
+
|
|
68
|
+
# ── Orgs (watch/serve mode) ───────────────────────────────────────────────────
|
|
69
|
+
# Monitor entire orgs — all repos get covered with one webhook per org.
|
|
70
|
+
# Takes priority over `repos` when both are set.
|
|
71
|
+
orgs:
|
|
72
|
+
- motivation-labs
|
|
73
|
+
- codatta
|
|
74
|
+
|
|
75
|
+
# ─── Users ───────────────────────────────────────────────────────────────────
|
|
76
|
+
# Monitor all repos owned by personal GitHub accounts (non-org).
|
|
77
|
+
# At startup, crosscheck enumerates each user's repos and registers webhooks.
|
|
78
|
+
# Useful when your AI agents open PRs across many personal repos.
|
|
79
|
+
# Combines with `orgs` and `repos` — all configured sources are additive.
|
|
80
|
+
# users:
|
|
81
|
+
# - beingzy # your personal account
|
|
82
|
+
# - my-agent-login # a bot account that pushes to its own repos
|
|
83
|
+
|
|
84
|
+
# ─── Repos ───────────────────────────────────────────────────────────────────
|
|
85
|
+
# Omit entirely to auto-detect from `git remote` (useful in watch mode)
|
|
86
|
+
# repos: still works for monitoring specific repos only
|
|
87
|
+
# repos:
|
|
88
|
+
# - owner: acme
|
|
89
|
+
# name: specific-repo
|
|
90
|
+
repos:
|
|
91
|
+
- owner: codatta
|
|
92
|
+
name: my-repo
|
|
93
|
+
|
|
94
|
+
# ─── Routing ─────────────────────────────────────────────────────────────────
|
|
95
|
+
routing:
|
|
96
|
+
# Restrict reviews to PRs opened by these GitHub logins.
|
|
97
|
+
# Auto-filled with your login by `crosscheck init` or first `crosscheck watch`.
|
|
98
|
+
# Empty list = no author restriction (applies body-pattern check only).
|
|
99
|
+
# allowed_authors:
|
|
100
|
+
# - beingzy # your personal account (Claude Code runs as you)
|
|
101
|
+
# - my-org-bot # a dedicated bot account
|
|
102
|
+
|
|
103
|
+
# Author-based routing fallback — maps GitHub login → vendor origin.
|
|
104
|
+
# Used when no body / commit / branch pattern matches. Lets you skip the attribution
|
|
105
|
+
# footer requirement when an author consistently uses a single agent.
|
|
106
|
+
# beingzy: claude → PRs from beingzy treated as Claude-authored → Codex reviews them
|
|
107
|
+
# my-bot: codex → PRs from my-bot treated as Codex-authored → Claude reviews them
|
|
108
|
+
# NOTE: in `mode: cross-vendor` with BOTH vendors enabled, this map is bypassed —
|
|
109
|
+
# if the same author commits via both agents, a static route is structurally wrong.
|
|
110
|
+
# In that case, rely on attribution detection (body / commits / branch) and
|
|
111
|
+
# `fallback_reviewer` below for PRs with no attribution markers.
|
|
112
|
+
# author_routes:
|
|
113
|
+
# beingzy: claude
|
|
114
|
+
|
|
115
|
+
# Fallback reviewer when origin cannot be determined (no pattern/branch/route matched).
|
|
116
|
+
# 'auto' = pick whichever vendor is currently authenticated (codex first, then claude).
|
|
117
|
+
# 'codex' / 'claude' = always use that vendor.
|
|
118
|
+
# null = skip the PR (legacy cross-vendor behaviour).
|
|
119
|
+
fallback_reviewer: auto
|
|
120
|
+
|
|
121
|
+
# Branch-prefix routing — checked when body and commit patterns don't match.
|
|
122
|
+
# Agents should branch with these prefixes (claude/* and codex/*) so origin is
|
|
123
|
+
# always detectable even without attribution text in the PR body.
|
|
124
|
+
claude_branch_prefixes:
|
|
125
|
+
- "claude/"
|
|
126
|
+
codex_branch_prefixes:
|
|
127
|
+
- "codex/"
|
|
128
|
+
|
|
129
|
+
# Body and commit pattern matching — checked first, before branch prefix.
|
|
130
|
+
# Patterns are matched against both the PR body and commit messages (Co-Authored-By trailers).
|
|
131
|
+
codex_reviews_patterns:
|
|
132
|
+
- "Generated with \\[Claude Code\\]" # PR body attribution footer
|
|
133
|
+
- "Co-Authored-By: Claude" # commit trailer added by Claude Code
|
|
134
|
+
claude_reviews_patterns:
|
|
135
|
+
- "Generated with \\[OpenAI Codex\\]" # PR body attribution footer
|
|
136
|
+
- "Co-Authored-By: codex" # commit trailer added by Codex
|
|
137
|
+
|
|
138
|
+
# ─── Tunnel (watch mode only) ────────────────────────────────────────────────
|
|
139
|
+
# Controls how crosscheck watch receives GitHub webhook events on your laptop.
|
|
140
|
+
#
|
|
141
|
+
# localhost.run (default) — zero config, SSH tunnel, random URL each restart.
|
|
142
|
+
# No install required. URL changes on reconnect → webhook re-registered automatically.
|
|
143
|
+
# Limitation: events delivered while the tunnel is down are lost.
|
|
144
|
+
#
|
|
145
|
+
# smee — webhook relay via smee.io. Stable channel URL; events are queued and
|
|
146
|
+
# replayed even when your laptop is offline or watch is restarted.
|
|
147
|
+
# Setup:
|
|
148
|
+
# 1. npm install -g smee-client
|
|
149
|
+
# 2. Visit https://smee.io/new — copy the channel URL
|
|
150
|
+
# 3. Point your GitHub org/repo webhook Payload URL to the channel URL
|
|
151
|
+
# 4. Set tunnel.smee_channel below
|
|
152
|
+
#
|
|
153
|
+
# tunnel:
|
|
154
|
+
# backend: smee
|
|
155
|
+
# smee_channel: https://smee.io/your-channel-id
|
|
156
|
+
|
|
157
|
+
# ─── Server (serve mode only) ────────────────────────────────────────────────
|
|
158
|
+
server:
|
|
159
|
+
port: 7891
|
|
160
|
+
webhook_path: /webhook
|
|
161
|
+
# pid_file: ~/.crosscheck/crosscheck.pid # for daemon management
|
|
162
|
+
|
|
163
|
+
# ─── Post-Review Auto-Fix ────────────────────────────────────────────────────
|
|
164
|
+
# Controls HOW fixes are delivered after the agent applies them.
|
|
165
|
+
# Step sequencing (whether to run fix/recheck, trigger conditions, vendor assignment)
|
|
166
|
+
# is configured in ~/.crosscheck/workflow.yml.
|
|
167
|
+
#
|
|
168
|
+
post_review:
|
|
169
|
+
auto_fix:
|
|
170
|
+
delivery:
|
|
171
|
+
mode: pull_request # pull_request | commit | comment
|
|
172
|
+
# pull_request → fix PR targets the original branch; human approves before merge
|
|
173
|
+
# commit → fixes pushed directly onto the original PR branch
|
|
174
|
+
# comment → suggested fixes posted as review comments only
|
|
175
|
+
pr_title: "fix: address CR issues in #{original_pr_title}"
|
|
176
|
+
label: cr-autofix # GitHub label applied to the fix PR
|
|
177
|
+
|
|
178
|
+
# ─── Backtrace ───────────────────────────────────────────────────────────────
|
|
179
|
+
# On startup, scan all open PRs in the monitored scope and review any that have
|
|
180
|
+
# never received a [crosscheck] comment. Ensures coverage for PRs opened while
|
|
181
|
+
# crosscheck was offline or before it was first set up.
|
|
182
|
+
# Off by default — enable with the config below or pass --backtrace at startup.
|
|
183
|
+
# backtrace:
|
|
184
|
+
# enabled: true # set to true to enable the startup scan (or pass --backtrace)
|
|
185
|
+
|
|
186
|
+
# ─── Logs ────────────────────────────────────────────────────────────────────
|
|
187
|
+
# Structured debug logs written to ~/.crosscheck/logs/YYYY-MM-DD.ndjson
|
|
188
|
+
# Each line is a JSON object: { ts, level, event, ...context }
|
|
189
|
+
logs:
|
|
190
|
+
enabled: true
|
|
191
|
+
retention_days: 7 # delete files older than N days (min: 1, max: 30)
|
|
192
|
+
|
|
193
|
+
# ─── Display ─────────────────────────────────────────────────────────────────
|
|
194
|
+
# Terminal output theme for crosscheck watch.
|
|
195
|
+
# Override individual colors using chalk color names (red, green, blue, cyan,
|
|
196
|
+
# yellow, magenta, white, gray, dim, bold) or hex values (#rrggbb).
|
|
197
|
+
# display:
|
|
198
|
+
# theme:
|
|
199
|
+
# bar_fill: blue # filled █ segments on the PR size bar
|
|
200
|
+
# bar_empty: dim # empty ░ segments (all bars)
|
|
201
|
+
# cr_approve: green # CR bar + verdict label when APPROVE
|
|
202
|
+
# cr_needs_work: yellow # CR bar + verdict label when NEEDS WORK
|
|
203
|
+
# cr_block: red # CR bar + verdict label when BLOCK
|
|
204
|
+
# fix_fill: cyan # filled segments on the FIX bar
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# ─── Branding ────────────────────────────────────────────────────────────────
|
|
208
|
+
# Customize how crosscheck identifies itself in review comments.
|
|
209
|
+
# Useful for teams, shared services, or personal branding.
|
|
210
|
+
# brand:
|
|
211
|
+
# service_name: crosscheck # shown in comment headers (default: crosscheck)
|
|
212
|
+
# comment_header: "" # text prepended to every review comment
|
|
213
|
+
# comment_footer: "" # text appended to every review comment
|
|
214
|
+
# reviewer_attribution: "" # replaces "Reviewed by {vendor}" attribution line
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotation.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/annotation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { buildAnnotation, buildCommitTrailers, parseAnnotation, parseAnnotationFieldsFenced, } from '../lib/annotation.js';
|
|
3
|
+
describe('crosscheck annotation contract', () => {
|
|
4
|
+
const stepTypes = ['review', 'recheck', 'fix', 'conflict-resolve'];
|
|
5
|
+
for (const type of stepTypes) {
|
|
6
|
+
it(`round-trips ${type} annotations`, () => {
|
|
7
|
+
const annotation = {
|
|
8
|
+
origin: 'claude',
|
|
9
|
+
reviewer: 'codex',
|
|
10
|
+
model: 'gpt-5',
|
|
11
|
+
type,
|
|
12
|
+
round: 2,
|
|
13
|
+
verdict: 'NEEDS_WORK',
|
|
14
|
+
service: 'crosscheck',
|
|
15
|
+
};
|
|
16
|
+
expect(parseAnnotation(buildAnnotation(annotation))).toEqual(annotation);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
it('pins the emitted field order per type for snapshot stability', () => {
|
|
20
|
+
const snapshots = stepTypes.map(type => buildAnnotation({
|
|
21
|
+
origin: 'claude',
|
|
22
|
+
reviewer: 'codex',
|
|
23
|
+
model: 'gpt-5',
|
|
24
|
+
type,
|
|
25
|
+
round: 3,
|
|
26
|
+
verdict: 'BLOCK',
|
|
27
|
+
service: 'crosscheck',
|
|
28
|
+
}));
|
|
29
|
+
expect(snapshots).toEqual([
|
|
30
|
+
'<!-- crosscheck: origin=claude reviewer=codex model=gpt-5 type=review round=3 verdict=BLOCK service=crosscheck -->',
|
|
31
|
+
'<!-- crosscheck: origin=claude reviewer=codex model=gpt-5 type=recheck round=3 verdict=BLOCK service=crosscheck -->',
|
|
32
|
+
'<!-- crosscheck: origin=claude reviewer=codex model=gpt-5 type=fix round=3 verdict=BLOCK service=crosscheck -->',
|
|
33
|
+
'<!-- crosscheck: origin=claude reviewer=codex model=gpt-5 type=conflict-resolve round=3 verdict=BLOCK service=crosscheck -->',
|
|
34
|
+
]);
|
|
35
|
+
});
|
|
36
|
+
it('appends optional head sha after stable v2 fields', () => {
|
|
37
|
+
const annotation = buildAnnotation({
|
|
38
|
+
origin: 'claude',
|
|
39
|
+
reviewer: 'codex',
|
|
40
|
+
model: 'gpt-5',
|
|
41
|
+
type: 'review',
|
|
42
|
+
round: 3,
|
|
43
|
+
verdict: 'BLOCK',
|
|
44
|
+
service: 'crosscheck',
|
|
45
|
+
sha: 'abc1234',
|
|
46
|
+
});
|
|
47
|
+
expect(annotation).toBe('<!-- crosscheck: origin=claude reviewer=codex model=gpt-5 type=review round=3 verdict=BLOCK service=crosscheck sha=abc1234 -->');
|
|
48
|
+
expect(parseAnnotation(annotation)).toEqual({
|
|
49
|
+
origin: 'claude',
|
|
50
|
+
reviewer: 'codex',
|
|
51
|
+
model: 'gpt-5',
|
|
52
|
+
type: 'review',
|
|
53
|
+
round: 3,
|
|
54
|
+
verdict: 'BLOCK',
|
|
55
|
+
service: 'crosscheck',
|
|
56
|
+
sha: 'abc1234',
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
it('preserves bare marker handling when sha-like fields are absent', () => {
|
|
60
|
+
expect(parseAnnotation('<!-- crosscheck: fix_applied -->')).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
it('parses legacy annotations with documented defaults', () => {
|
|
63
|
+
expect(parseAnnotation('<!-- crosscheck: origin=claude reviewer=codex verdict=APPROVE type=review -->')).toEqual({
|
|
64
|
+
origin: 'claude',
|
|
65
|
+
reviewer: 'codex',
|
|
66
|
+
model: 'default',
|
|
67
|
+
type: 'review',
|
|
68
|
+
round: 1,
|
|
69
|
+
verdict: 'APPROVE',
|
|
70
|
+
service: 'crosscheck',
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
it('keeps verdict-less review annotations parseable for freshness detection', () => {
|
|
74
|
+
expect(parseAnnotation('<!-- crosscheck: origin=claude reviewer=codex type=review -->')).toEqual({
|
|
75
|
+
origin: 'claude',
|
|
76
|
+
reviewer: 'codex',
|
|
77
|
+
model: 'default',
|
|
78
|
+
type: 'review',
|
|
79
|
+
round: 1,
|
|
80
|
+
verdict: 'UNKNOWN',
|
|
81
|
+
service: 'crosscheck',
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
it('parses fields order-independently and ignores unknown fields', () => {
|
|
85
|
+
expect(parseAnnotation('<!-- crosscheck: service=custom verdict=BLOCK extra=yes round=4 type=recheck model=claude-opus reviewer=claude origin=codex -->')).toEqual({
|
|
86
|
+
origin: 'codex',
|
|
87
|
+
reviewer: 'claude',
|
|
88
|
+
model: 'claude-opus',
|
|
89
|
+
type: 'recheck',
|
|
90
|
+
round: 4,
|
|
91
|
+
verdict: 'BLOCK',
|
|
92
|
+
service: 'custom',
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
it('uses the footer annotation when the body quotes older markers', () => {
|
|
96
|
+
const body = 'Quoted marker `<!-- crosscheck: origin=claude reviewer=codex verdict=BLOCK type=review -->`\n\n'
|
|
97
|
+
+ '<!-- crosscheck: origin=claude reviewer=codex model=gpt-5 type=recheck round=2 verdict=APPROVE service=crosscheck -->';
|
|
98
|
+
expect(parseAnnotation(body)?.type).toBe('recheck');
|
|
99
|
+
});
|
|
100
|
+
it('returns null for bare summary markers', () => {
|
|
101
|
+
expect(parseAnnotation('<!-- crosscheck: fix_applied -->')).toBeNull();
|
|
102
|
+
});
|
|
103
|
+
it('skips fenced annotations and parses the footer annotation', () => {
|
|
104
|
+
const body = [
|
|
105
|
+
'Example:',
|
|
106
|
+
'```',
|
|
107
|
+
'<!-- crosscheck: origin=claude reviewer=codex type=review verdict=BLOCK -->',
|
|
108
|
+
'```',
|
|
109
|
+
'<!-- crosscheck: origin=codex reviewer=claude type=recheck verdict=APPROVE -->',
|
|
110
|
+
].join('\n');
|
|
111
|
+
expect(parseAnnotation(body)?.type).toBe('recheck');
|
|
112
|
+
expect(parseAnnotation(body)?.verdict).toBe('APPROVE');
|
|
113
|
+
});
|
|
114
|
+
it('exposes bare summary markers through the fenced field parser', () => {
|
|
115
|
+
const fields = parseAnnotationFieldsFenced('<!-- crosscheck: fix_applied -->');
|
|
116
|
+
expect(fields?.get('__marker__')).toBe('fix_applied');
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe('crosscheck commit trailers', () => {
|
|
120
|
+
it('emits reviewer, model, step, and service trailers', () => {
|
|
121
|
+
expect(buildCommitTrailers({
|
|
122
|
+
reviewer: 'claude',
|
|
123
|
+
model: 'default',
|
|
124
|
+
step: 'fix',
|
|
125
|
+
service: 'crosscheck',
|
|
126
|
+
})).toBe([
|
|
127
|
+
'Crosscheck-Reviewer: claude',
|
|
128
|
+
'Crosscheck-Model: default',
|
|
129
|
+
'Crosscheck-Step: fix',
|
|
130
|
+
'Crosscheck-Service: crosscheck',
|
|
131
|
+
].join('\n'));
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
//# sourceMappingURL=annotation.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotation.test.js","sourceRoot":"","sources":["../../src/__tests__/annotation.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backtrace.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/backtrace.test.ts"],"names":[],"mappings":""}
|