@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.
- package/README.md +2 -1
- package/crosscheck.config.example.yml +23 -2
- package/dist/__tests__/adoption.test.d.ts +2 -0
- package/dist/__tests__/adoption.test.d.ts.map +1 -0
- package/dist/__tests__/adoption.test.js +175 -0
- package/dist/__tests__/adoption.test.js.map +1 -0
- package/dist/__tests__/auto-fix-branch.test.d.ts +2 -0
- package/dist/__tests__/auto-fix-branch.test.d.ts.map +1 -0
- package/dist/__tests__/auto-fix-branch.test.js +143 -0
- package/dist/__tests__/auto-fix-branch.test.js.map +1 -0
- package/dist/__tests__/board.test.js +2 -0
- package/dist/__tests__/board.test.js.map +1 -1
- package/dist/__tests__/codex-env.test.d.ts +2 -0
- package/dist/__tests__/codex-env.test.d.ts.map +1 -0
- package/dist/__tests__/codex-env.test.js +70 -0
- package/dist/__tests__/codex-env.test.js.map +1 -0
- package/dist/__tests__/codex.test.js +89 -1
- package/dist/__tests__/codex.test.js.map +1 -1
- package/dist/__tests__/commit-subject.test.d.ts +2 -0
- package/dist/__tests__/commit-subject.test.d.ts.map +1 -0
- package/dist/__tests__/commit-subject.test.js +72 -0
- package/dist/__tests__/commit-subject.test.js.map +1 -0
- package/dist/__tests__/credential-free-origin.test.d.ts +2 -0
- package/dist/__tests__/credential-free-origin.test.d.ts.map +1 -0
- package/dist/__tests__/credential-free-origin.test.js +59 -0
- package/dist/__tests__/credential-free-origin.test.js.map +1 -0
- package/dist/__tests__/detector.test.js +87 -1
- package/dist/__tests__/detector.test.js.map +1 -1
- package/dist/__tests__/error-classification.test.js +34 -0
- package/dist/__tests__/error-classification.test.js.map +1 -1
- package/dist/__tests__/fix.test.js +37 -1
- package/dist/__tests__/fix.test.js.map +1 -1
- package/dist/__tests__/harness-section.test.d.ts +2 -0
- package/dist/__tests__/harness-section.test.d.ts.map +1 -0
- package/dist/__tests__/harness-section.test.js +46 -0
- package/dist/__tests__/harness-section.test.js.map +1 -0
- package/dist/__tests__/kickass.test.js +31 -0
- package/dist/__tests__/kickass.test.js.map +1 -1
- package/dist/__tests__/linear-worker.test.js.map +1 -1
- package/dist/__tests__/loader.test.js +2 -2
- package/dist/__tests__/loader.test.js.map +1 -1
- package/dist/__tests__/onboard-preservation.test.js +0 -1
- package/dist/__tests__/onboard-preservation.test.js.map +1 -1
- package/dist/__tests__/optimize.test.js +1 -1
- package/dist/__tests__/optimize.test.js.map +1 -1
- package/dist/__tests__/pr-status.test.js +213 -3
- package/dist/__tests__/pr-status.test.js.map +1 -1
- package/dist/__tests__/pr-workflow-state.test.js +247 -7
- package/dist/__tests__/pr-workflow-state.test.js.map +1 -1
- package/dist/__tests__/repository-guidance.test.js +21 -21
- package/dist/__tests__/repository-guidance.test.js.map +1 -1
- package/dist/__tests__/reviewed-sha.test.d.ts +2 -0
- package/dist/__tests__/reviewed-sha.test.d.ts.map +1 -0
- package/dist/__tests__/reviewed-sha.test.js +116 -0
- package/dist/__tests__/reviewed-sha.test.js.map +1 -0
- package/dist/__tests__/runner.test.js +178 -2
- package/dist/__tests__/runner.test.js.map +1 -1
- package/dist/__tests__/skill-broker.test.js +44 -2
- package/dist/__tests__/skill-broker.test.js.map +1 -1
- package/dist/__tests__/superseded-fix-pr.test.d.ts +2 -0
- package/dist/__tests__/superseded-fix-pr.test.d.ts.map +1 -0
- package/dist/__tests__/superseded-fix-pr.test.js +225 -0
- package/dist/__tests__/superseded-fix-pr.test.js.map +1 -0
- package/dist/__tests__/webhook.test.js +60 -0
- package/dist/__tests__/webhook.test.js.map +1 -1
- package/dist/cli.js +8 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/adoption.d.ts +6 -0
- package/dist/commands/adoption.d.ts.map +1 -0
- package/dist/commands/adoption.js +132 -0
- package/dist/commands/adoption.js.map +1 -0
- package/dist/commands/detect-step.d.ts.map +1 -1
- package/dist/commands/detect-step.js +5 -1
- package/dist/commands/detect-step.js.map +1 -1
- package/dist/commands/diagnose.d.ts.map +1 -1
- package/dist/commands/diagnose.js +2 -2
- package/dist/commands/diagnose.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +1 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/issue.js +1 -1
- package/dist/commands/issue.js.map +1 -1
- package/dist/commands/kickass.d.ts +1 -1
- package/dist/commands/kickass.d.ts.map +1 -1
- package/dist/commands/kickass.js +36 -22
- package/dist/commands/kickass.js.map +1 -1
- package/dist/commands/linear-test.js.map +1 -1
- package/dist/commands/onboard.d.ts.map +1 -1
- package/dist/commands/onboard.js +30 -3
- package/dist/commands/onboard.js.map +1 -1
- package/dist/commands/optimize.d.ts.map +1 -1
- package/dist/commands/optimize.js +1 -0
- package/dist/commands/optimize.js.map +1 -1
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +1 -1
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +40 -4
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/scan.d.ts.map +1 -1
- package/dist/commands/scan.js +6 -0
- package/dist/commands/scan.js.map +1 -1
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js +132 -61
- package/dist/commands/watch.js.map +1 -1
- package/dist/config/loader.js +6 -6
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +8 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +19 -2
- package/dist/config/schema.js.map +1 -1
- package/dist/github/detector.d.ts.map +1 -1
- package/dist/github/detector.js +28 -1
- package/dist/github/detector.js.map +1 -1
- package/dist/github/merge.d.ts +0 -5
- package/dist/github/merge.d.ts.map +1 -1
- package/dist/github/merge.js +0 -9
- package/dist/github/merge.js.map +1 -1
- package/dist/github/reviewed-sha.d.ts +13 -0
- package/dist/github/reviewed-sha.d.ts.map +1 -0
- package/dist/github/reviewed-sha.js +62 -0
- package/dist/github/reviewed-sha.js.map +1 -0
- package/dist/github/superseded-fix-pr.d.ts +19 -0
- package/dist/github/superseded-fix-pr.d.ts.map +1 -0
- package/dist/github/superseded-fix-pr.js +97 -0
- package/dist/github/superseded-fix-pr.js.map +1 -0
- package/dist/github/webhook.d.ts +4 -1
- package/dist/github/webhook.d.ts.map +1 -1
- package/dist/github/webhook.js +8 -1
- package/dist/github/webhook.js.map +1 -1
- package/dist/lib/adoption.d.ts +64 -0
- package/dist/lib/adoption.d.ts.map +1 -0
- package/dist/lib/adoption.js +165 -0
- package/dist/lib/adoption.js.map +1 -0
- package/dist/lib/annotation.js +0 -7
- package/dist/lib/annotation.js.map +1 -1
- package/dist/lib/auto-fix-branch.d.ts +35 -0
- package/dist/lib/auto-fix-branch.d.ts.map +1 -0
- package/dist/lib/auto-fix-branch.js +88 -0
- package/dist/lib/auto-fix-branch.js.map +1 -0
- package/dist/lib/clone.d.ts +1 -0
- package/dist/lib/clone.d.ts.map +1 -1
- package/dist/lib/clone.js +38 -1
- package/dist/lib/clone.js.map +1 -1
- package/dist/lib/comment-bodies.d.ts.map +1 -1
- package/dist/lib/comment-bodies.js +6 -3
- package/dist/lib/comment-bodies.js.map +1 -1
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +17 -1
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/pr-picker.d.ts +1 -1
- package/dist/lib/pr-picker.d.ts.map +1 -1
- package/dist/lib/pr-picker.js +10 -5
- package/dist/lib/pr-picker.js.map +1 -1
- package/dist/lib/pr-status.d.ts +2 -1
- package/dist/lib/pr-status.d.ts.map +1 -1
- package/dist/lib/pr-status.js +70 -6
- package/dist/lib/pr-status.js.map +1 -1
- package/dist/lib/pr-workflow-state.d.ts +17 -1
- package/dist/lib/pr-workflow-state.d.ts.map +1 -1
- package/dist/lib/pr-workflow-state.js +110 -5
- package/dist/lib/pr-workflow-state.js.map +1 -1
- package/dist/lib/repo-picker.d.ts.map +1 -1
- package/dist/lib/repo-picker.js +0 -1
- package/dist/lib/repo-picker.js.map +1 -1
- package/dist/lib/runner.d.ts +31 -1
- package/dist/lib/runner.d.ts.map +1 -1
- package/dist/lib/runner.js +460 -58
- package/dist/lib/runner.js.map +1 -1
- package/dist/lib/vendor.d.ts +1 -0
- package/dist/lib/vendor.d.ts.map +1 -1
- package/dist/lib/vendor.js +6 -0
- package/dist/lib/vendor.js.map +1 -1
- package/dist/lib/workflow.d.ts +4 -0
- package/dist/lib/workflow.d.ts.map +1 -1
- package/dist/lib/workflow.js +4 -1
- package/dist/lib/workflow.js.map +1 -1
- package/dist/linear/comment.d.ts.map +1 -1
- package/dist/linear/comment.js.map +1 -1
- package/dist/reviewers/address.d.ts +1 -1
- package/dist/reviewers/address.d.ts.map +1 -1
- package/dist/reviewers/address.js +1 -1
- package/dist/reviewers/address.js.map +1 -1
- package/dist/reviewers/codex-env.d.ts +12 -0
- package/dist/reviewers/codex-env.d.ts.map +1 -0
- package/dist/reviewers/codex-env.js +54 -0
- package/dist/reviewers/codex-env.js.map +1 -0
- package/dist/reviewers/codex.d.ts +16 -1
- package/dist/reviewers/codex.d.ts.map +1 -1
- package/dist/reviewers/codex.js +110 -33
- package/dist/reviewers/codex.js.map +1 -1
- package/dist/reviewers/fix.d.ts +1 -1
- package/dist/reviewers/fix.d.ts.map +1 -1
- package/dist/reviewers/fix.js +16 -6
- package/dist/reviewers/fix.js.map +1 -1
- package/dist/skills/broker.d.ts +2 -1
- package/dist/skills/broker.d.ts.map +1 -1
- package/dist/skills/broker.js +28 -2
- package/dist/skills/broker.js.map +1 -1
- package/docs/metrics.md +115 -0
- package/docs/trust.md +159 -0
- package/get-started.md +115 -5
- package/package.json +3 -1
package/docs/metrics.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Metrics: what Crosscheck records, and where it stays
|
|
2
|
+
|
|
3
|
+
Crosscheck records what it did so you can tell whether it is working. Every number comes from local log files, and **nothing is transmitted**: there is no endpoint, no account, no upload, and no network call in any of the code that produces or reads these metrics. Telemetry is opt-in in the strongest available sense — it does not exist yet.
|
|
4
|
+
|
|
5
|
+
This document is the field-by-field inventory. If you find a field written to disk that is not listed here, that is a bug worth reporting.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Where it lives
|
|
10
|
+
|
|
11
|
+
| | |
|
|
12
|
+
|---|---|
|
|
13
|
+
| Location | `~/.crosscheck/logs/<YYYY-MM-DD>.ndjson` — one JSON object per line |
|
|
14
|
+
| On by default | Yes (`logs.enabled: true`) |
|
|
15
|
+
| Retention | `logs.retention_days`, default 30 — older files are deleted at startup |
|
|
16
|
+
| Turn it off | `logs.enabled: false` in `crosscheck.config.yml` |
|
|
17
|
+
|
|
18
|
+
Turning logging off is supported and costs you the reader commands: `crosscheck adoption`, `impact`, `diagnose`, and `optimize` all read these files and have nothing else to read.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Reading it
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
crosscheck adoption # activation, usage, weekly active repos, latency, first-run failures
|
|
26
|
+
crosscheck adoption --json # the same report as JSON
|
|
27
|
+
crosscheck adoption --since 2026-07-01 # narrow the window
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`crosscheck adoption` answers "is this being used, and does a PR get a verdict fast enough to matter". Its sibling `crosscheck impact` prices reviews that already happened. Both read the same files and neither makes a network call.
|
|
31
|
+
|
|
32
|
+
What the report shows:
|
|
33
|
+
|
|
34
|
+
| Metric | Derived from |
|
|
35
|
+
|---|---|
|
|
36
|
+
| onboard started / completed / abandoned | `onboard_started`, `onboard_completed` |
|
|
37
|
+
| reviews started / completed | `review_started`, `review_complete` |
|
|
38
|
+
| rechecks completed | `review_complete` with `step_type: recheck` |
|
|
39
|
+
| blocking findings posted | `blocking_finding_posted` |
|
|
40
|
+
| fixes applied | `fix_complete` with `applied_count > 0` |
|
|
41
|
+
| active repos, weekly active repos | distinct `repo` on `review_complete`, bucketed by ISO week |
|
|
42
|
+
| PR open → verdict (median, p90, slowest) | `open_to_verdict_ms` on `review_complete` |
|
|
43
|
+
| first-run failures | first `error` in a session that never logged a `review_complete` |
|
|
44
|
+
|
|
45
|
+
Two honest limits worth knowing before you quote a number:
|
|
46
|
+
|
|
47
|
+
- **Latency is only measured when the PR event carried an open time.** Hand-built events and some third-party webhook redeliveries do not. Those verdicts are excluded and counted separately as `unmeasured` rather than being given an invented start time.
|
|
48
|
+
- **Everything is bounded by the retention window.** A 30-day default means a "total" is a 30-day total. Raise `logs.retention_days` if you need a longer baseline.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## What is recorded
|
|
53
|
+
|
|
54
|
+
Identifying fields, on every event that has them:
|
|
55
|
+
|
|
56
|
+
| Field | Example | Why |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| `ts` | `2026-07-08T10:00:00.000Z` | ordering, weekly bucketing |
|
|
59
|
+
| `event` | `review_complete` | what happened |
|
|
60
|
+
| `repo` | `acme/web` | which repo — this is a name, and it is the most identifying field written |
|
|
61
|
+
| `pr` | `245` | which PR number |
|
|
62
|
+
|
|
63
|
+
Everything else is a count, an enum, a duration, or a commit sha:
|
|
64
|
+
|
|
65
|
+
| Field | Shape |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `verdict` | `APPROVE` / `NEEDS WORK` / `BLOCK` |
|
|
68
|
+
| `reviewer`, `model`, `effort` | vendor and model identifiers |
|
|
69
|
+
| `step_type`, `step_name`, `round`, `trigger` | which step ran, and why |
|
|
70
|
+
| `duration_ms` | how long the reviewer ran |
|
|
71
|
+
| `open_to_verdict_ms` | PR open → verdict, in ms |
|
|
72
|
+
| `tokens_used`, `input_tokens`, `output_tokens` | integer counts |
|
|
73
|
+
| `applied_count`, `commentCount` | integer counts |
|
|
74
|
+
| `sha`, `head_sha` | commit shas |
|
|
75
|
+
| `category` | error class: `auth`, `permission`, `rate_limit`, `overloaded`, `budget`, `timeout`, `network`, `git`, `subprocess`, `unknown` |
|
|
76
|
+
| `message`, `stack`, `stderr` | on error events only — the failure text, truncated |
|
|
77
|
+
| `outcome`, `stage` | on `onboard_completed`: `completed` / `abandoned`, and where it stopped |
|
|
78
|
+
| `deployment`, `repos`, `orgs`, `quality_tier`, `quality_mode`, `pipeline`, `tunnel`, `linear` | on `onboard_completed`: the **shape** of the setup — counts and enums, never repo or org names |
|
|
79
|
+
|
|
80
|
+
## What is not recorded
|
|
81
|
+
|
|
82
|
+
Standard logs never contain:
|
|
83
|
+
|
|
84
|
+
- **source code or diffs**
|
|
85
|
+
- **reviewer prompts**
|
|
86
|
+
- **review text** — the verdict is recorded; the prose is not
|
|
87
|
+
- **PR titles or bodies**
|
|
88
|
+
- **PR author logins**
|
|
89
|
+
- **tokens, keys, or secrets** — the one place a token could appear is the clone URL, which is redacted to `x-access-token:[REDACTED]` on every path that could log it
|
|
90
|
+
|
|
91
|
+
Error events are the one place free text lands, because a failure you cannot read is a failure you cannot fix. `message`, `stack`, and `stderr` come from the failing subprocess or API call and are truncated. They can quote a file path or a git ref. They are local files, like everything else here.
|
|
92
|
+
|
|
93
|
+
### The extended tier
|
|
94
|
+
|
|
95
|
+
Richer fields — PR title, body, file paths, review text, author — exist behind `logs.extended.enabled`, which is:
|
|
96
|
+
|
|
97
|
+
- **off by default**,
|
|
98
|
+
- **not settable from any CLI flag** and not offered by `crosscheck onboard`, so it can only be turned on by hand-editing config, and
|
|
99
|
+
- **tagged** — every line it writes carries `"_extended": true`, so it can be filtered or scrubbed independently of standard logs.
|
|
100
|
+
|
|
101
|
+
If you have not deliberately edited your config, this tier is off and nothing in the product will nudge you toward it.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Transmission
|
|
106
|
+
|
|
107
|
+
There is none. To be specific about what that means:
|
|
108
|
+
|
|
109
|
+
- No Crosscheck-operated server exists, so there is nowhere for a payload to go.
|
|
110
|
+
- No code in `src/lib/adoption.ts` or `src/commands/adoption.ts` opens a socket.
|
|
111
|
+
- Reporting is a local CLI command that prints to your terminal.
|
|
112
|
+
|
|
113
|
+
If opt-in transmission is ever built, it will be per-category, individually documented, off unless you turn it on, and it will print the payload that leaves your machine. Until then, "opt-in telemetry" describes a design in `prd.md`, not shipped behaviour — and the metrics above are yours alone.
|
|
114
|
+
|
|
115
|
+
Related: [docs/trust.md](./trust.md) covers what leaves your machine during normal operation, which is a different question from what gets logged.
|
package/docs/trust.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Trust: what Crosscheck reaches, sends, and changes
|
|
2
|
+
|
|
3
|
+
Crosscheck runs on your machine, holds your GitHub token, clones your code, and pushes commits. This document says exactly what that means, so you can decide whether to run it without reading the source.
|
|
4
|
+
|
|
5
|
+
Everything below is behaviour of the current release. Where a default is risky, it is called out as a default rather than buried.
|
|
6
|
+
|
|
7
|
+
**The short version.** Crosscheck has no server. There is no Crosscheck-operated endpoint, no telemetry, no account, no phone-home, and no analytics — install it and nothing is reported anywhere. It talks to GitHub with your token, and it runs the Claude Code and Codex CLIs on your machine under *their* credentials and *their* privacy terms. On a default `watch` setup, one third party you may not expect is in the path: the webhook tunnel. See [What leaves your machine](#what-leaves-your-machine).
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## What leaves your machine
|
|
12
|
+
|
|
13
|
+
Five destinations, and nothing else.
|
|
14
|
+
|
|
15
|
+
| Destination | What goes there | When | Avoidable? |
|
|
16
|
+
|---|---|---|---|
|
|
17
|
+
| `api.github.com`, `github.com` | Your token; PR reads; git clone/fetch; the comments, commit statuses, commits, branches and PRs Crosscheck writes | Every command | No — this is the product |
|
|
18
|
+
| Claude Code CLI → Anthropic | The reviewer prompt, plus whatever the agent reads from the clone (it is allowed `git diff` and `git log`) — so in practice your diff and relevant source | Review, fix, recheck, conflict-resolve steps | Yes — disable the vendor in config |
|
|
19
|
+
| Codex CLI → OpenAI | Same, for Codex-assigned steps | Same | Yes — disable the vendor in config |
|
|
20
|
+
| Tunnel relay — `localhost.run` (default) or `smee.io` | GitHub's webhook deliveries for your monitored repos: PR metadata, author, branch, head sha, and PR body as GitHub sends it | `crosscheck watch` only | Yes — see below |
|
|
21
|
+
| `api.linear.app` | Issue reads (enrichment) and verdict comments | Only when Linear is configured; off by default | Yes — leave it off |
|
|
22
|
+
|
|
23
|
+
Two things to be precise about, because they are the parts people get wrong:
|
|
24
|
+
|
|
25
|
+
**Crosscheck does not upload your code. The vendor CLIs do.** Crosscheck clones your repo to a temp directory and runs `claude` or `codex` as a subprocess pointed at that directory. Your diff reaches Anthropic or OpenAI through those CLIs, under the credentials you already logged into them with and under their data-handling terms — the same exposure you have when you run `claude` in your own checkout. Crosscheck adds no separate upload path. If a repo cannot go to a model vendor, Crosscheck is not the tool that changes that.
|
|
26
|
+
|
|
27
|
+
**The webhook tunnel is a third party in the path.** `crosscheck watch` needs a public URL for GitHub to POST to, and by default it opens an SSH tunnel through `localhost.run`. GitHub's webhook payloads for your monitored repos therefore transit a relay operated by someone else. Deliveries are HMAC-signed and Crosscheck rejects anything whose signature does not verify (`webhook_sig_invalid`), so a relay cannot *forge* events — but it can *see* payloads, which include PR titles, bodies, branch names and author logins. Payloads carry no source diff and no token.
|
|
28
|
+
|
|
29
|
+
To avoid the relay entirely, don't run `watch`. Everything Crosscheck does is available as a one-shot command that needs no inbound connection:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
crosscheck run https://github.com/acme/web/pull/245
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Run that from cron, from CI, or by hand. Or use `tunnel.backend: smee` with your own [smee.io](https://smee.io/new) channel if you prefer a named relay that queues events while you are offline — same trade, different operator. Self-hosting the relay is not supported today.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## GitHub permissions
|
|
40
|
+
|
|
41
|
+
Crosscheck uses whatever token `gh auth login` already produced — it does not mint its own, and it never asks you to paste one into a config file.
|
|
42
|
+
|
|
43
|
+
| Scope | Needed for | Required? |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `repo` | Clone, fetch, push; read PRs; post comments; write the `crosscheck/review` commit status | Yes |
|
|
46
|
+
| `admin:repo_hook` | Register the webhook on individual repos | `watch` with repo-level scopes only |
|
|
47
|
+
| `admin:org_hook` (`write:org`) | Register one webhook per org instead of per repo | `watch` with org-level scopes only |
|
|
48
|
+
|
|
49
|
+
`repo` is a coarse scope, and it is coarse because git push over HTTPS needs it. If that is more than you want to grant, the narrow path is a fine-grained PAT limited to the specific repositories you intend to review, exported as `GITHUB_TOKEN`. Crosscheck reads the token from `gh`'s keyring first and falls back to `GITHUB_TOKEN` / `GH_TOKEN`, so a scoped PAT in your shell is a drop-in.
|
|
50
|
+
|
|
51
|
+
Without the hook scopes, `watch` still runs — it just cannot register its own webhook, and you point one at the tunnel URL yourself.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Webhooks: registration and removal
|
|
56
|
+
|
|
57
|
+
`crosscheck watch` registers hooks at startup and removes them at shutdown.
|
|
58
|
+
|
|
59
|
+
**Registered:** one hook per monitored org (preferred) or per monitored repo, `active: true`, events `pull_request` and `issue_comment` only, `content_type: json`, pointed at your tunnel URL, with an HMAC secret. If a Crosscheck hook already exists, the existing one is reused and its event list patched rather than a second one created — restarts do not accumulate hooks.
|
|
60
|
+
|
|
61
|
+
**Removed:** on `Ctrl-C` or `SIGTERM`, `watch` deletes every hook it registered in that session before exiting.
|
|
62
|
+
|
|
63
|
+
**The gap you should know about:** an abnormal exit — uncaught exception, `SIGKILL`, power loss — skips that cleanup, and the hook stays registered and pointed at a tunnel URL that no longer answers. GitHub will retry deliveries, fail, and eventually show the hook as failing. Nothing leaks (the endpoint is gone, and the payload was going to your machine), but the hook is orphaned. Two ways to clear it:
|
|
64
|
+
|
|
65
|
+
- Start `watch` again. It finds the existing hook and reuses it, which also repoints it at the new tunnel URL.
|
|
66
|
+
- Delete it by hand: repo or org **Settings → Webhooks**, remove the entry whose payload URL is your old tunnel.
|
|
67
|
+
|
|
68
|
+
Note that with `tunnel.backend: smee`, the channel URL is stable and hooks are *meant* to outlive the session — that is the point of using smee. They persist until you delete them.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## What Crosscheck can change
|
|
73
|
+
|
|
74
|
+
The workflow is a sequence of steps, and each step's mutations are listed below. What runs is `~/.crosscheck/workflow.yml`, narrowable per repo — so this table is also the menu of what you can switch off.
|
|
75
|
+
|
|
76
|
+
| Step | What it writes to your repo |
|
|
77
|
+
|---|---|
|
|
78
|
+
| **review** | One PR comment (the review, with a hidden `<!-- crosscheck: ... -->` annotation). One commit status, context `crosscheck/review`: `pending` while running, then `success` or `failure`. Optionally one Linear comment. **No code.** |
|
|
79
|
+
| **recheck** | Same as review — a second comment, and release of the pending status. **No code.** |
|
|
80
|
+
| **fix** | Code. Commits to the PR's own branch and pushes there, plus a "fix applied" comment. If that push cannot land (protected branch, deleted branch, fork), it pushes the same commit to `fix/cr-<pr>-review-issues`, opens a follow-up PR targeting the original branch, and labels it `cr-autofix`. In `delivery.mode: comment` it pushes nothing and posts the diff as a suggestion instead. |
|
|
81
|
+
| **conflict-resolve** | Code. Merges the base branch into the PR branch, resolves conflicts, and pushes the merge commit to the PR branch, plus a comment. Skipped for fork PRs. |
|
|
82
|
+
|
|
83
|
+
Boundaries that hold across every step:
|
|
84
|
+
|
|
85
|
+
- **Never merges.** No command merges a pull request — there is no code path from any verdict to a merge. `crosscheck scan` will tell you a PR looks merge-ready; a human or your own automation acts on that.
|
|
86
|
+
- **Never touches your base branch.** Pushes go to the PR's head branch or to a new `fix/cr-*` branch. `main` and `staging` are only ever read.
|
|
87
|
+
- **Never force-pushes over your work.** A rejected non-fast-forward push is retried by rebasing onto the remote branch; if that fails it gives up and falls back to the follow-up PR.
|
|
88
|
+
- **Never edits outside the clone.** All work happens in a `mkdtemp` directory that is deleted when the step finishes, pass or fail.
|
|
89
|
+
- **Repo review guidance is read from the base branch,** not from the PR — a PR cannot rewrite the rules it will be reviewed under.
|
|
90
|
+
- **Automation triggers are authenticated.** The comment bridge that advances a workflow only fires for annotations posted by the token's own account; a comment from anyone else carrying the same hidden marker is ignored and logged as `annotation_injection_blocked`.
|
|
91
|
+
|
|
92
|
+
One boundary is *not* Crosscheck's to enforce, and you should know which: **what the reviewer agent may execute inside the clone is the vendor CLI's decision, not Crosscheck's.** Crosscheck itself never runs your project's code — no install, no test, no build. For Claude steps it passes an explicit tool allowlist of `Bash(git diff)` and `Bash(git log)`, so a review is confined to reading history. For Codex steps it invokes `codex exec` and passes no sandbox override, so the agent operates under Codex's own default policy for non-interactive runs — which necessarily permits writing files in the clone, since that is how a Codex fix lands. If your threat model requires a specific sandbox for agent execution, set it in the Codex CLI's own configuration; Crosscheck will not override it.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Trying it on one PR first
|
|
97
|
+
|
|
98
|
+
Fully read-only. Clones the repo, runs the review, prints the comment it *would* post, and exits. No comment, no commit status, no Linear write, no lock:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
crosscheck run https://github.com/acme/web/pull/245 --dry-run
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
When you want the comment but still no code changes:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
crosscheck run https://github.com/acme/web/pull/245 --review-only
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Neither command needs a webhook, a tunnel, or `watch`. There is also a [public fixture PR](./fixture-pr.md) if you would rather not point a first run at your own code.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Turning off auto-fix
|
|
115
|
+
|
|
116
|
+
Three levels, from narrowest to broadest.
|
|
117
|
+
|
|
118
|
+
**One repo, permanently** — review and recheck only, no code ever pushed to it:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
crosscheck alter acme/legacy-service --review-only
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The override lands in `~/.crosscheck/workflows/acme__legacy-service.yml` and is read per PR event, so it takes effect without restarting `watch`. `crosscheck alter acme/legacy-service --show` prints what is in force.
|
|
125
|
+
|
|
126
|
+
**Everywhere, but keep the suggestions** — fixes are posted as a diff in a comment instead of pushed:
|
|
127
|
+
|
|
128
|
+
```yaml
|
|
129
|
+
post_review:
|
|
130
|
+
auto_fix:
|
|
131
|
+
delivery:
|
|
132
|
+
mode: comment
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Everywhere, entirely** — remove the `fix` and `recheck` steps from `~/.crosscheck/workflow.yml`, or narrow each repo with `crosscheck alter <repo> --steps review`.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Secrets and local logs
|
|
140
|
+
|
|
141
|
+
**Secrets are never written to config.** `crosscheck.config.yml` stores environment variable *names* (`api_key_env: LINEAR_API_KEY`), never values. The GitHub token comes from `gh`'s keyring or your environment at call time. The webhook HMAC secret is read from your environment.
|
|
142
|
+
|
|
143
|
+
**The one place a token is embedded is the clone URL** (`https://x-access-token:<token>@github.com/...`), which is how git authenticates over HTTPS. Every log and error path that could carry that URL runs it through a redactor first, so it appears as `x-access-token:[REDACTED]`. Use `clone_protocol: ssh` if you would rather it never be constructed.
|
|
144
|
+
|
|
145
|
+
**Logs are local files, and that is the only place they go.** `~/.crosscheck/logs/<date>.ndjson`, one JSON object per line, enabled by default (`logs.enabled`), pruned by age (`logs.retention_days`, default 30). They power `crosscheck diagnose`, `optimize`, and `impact` — all of which read these files and make no network calls.
|
|
146
|
+
|
|
147
|
+
What a standard log line contains: repo and PR number, event name, verdict, vendor and model, token counts, durations, commit shas, error category. What it deliberately does not contain: **source code, diffs, prompts, review text, PR titles or bodies, or author logins.**
|
|
148
|
+
|
|
149
|
+
Those richer fields exist behind `logs.extended.enabled`, which is **off by default and not exposed by any CLI flag or by `onboard`** — it can only be turned on by hand-editing config, and every line it writes is tagged `"_extended": true` so it can be filtered or scrubbed separately. Turning it on is a deliberate act; nothing in the product nudges you toward it.
|
|
150
|
+
|
|
151
|
+
To keep no local history at all, set `logs.enabled: false`. `diagnose`, `optimize` and `impact` will have nothing to read, which is the whole trade.
|
|
152
|
+
|
|
153
|
+
Other state under `~/.crosscheck/`: your config, per-repo workflow overrides, and small caches of already-seen commit shas and diff hashes (used to avoid re-reviewing the same code). Shas and hashes, no content.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Reporting a security issue
|
|
158
|
+
|
|
159
|
+
Email <yi@inductive.network> rather than opening a public issue.
|
package/get-started.md
CHANGED
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
- [diagnose](#crosscheck-diagnose)
|
|
27
27
|
- [optimize](#crosscheck-optimize)
|
|
28
28
|
- [impact](#crosscheck-impact)
|
|
29
|
+
- [adoption](#crosscheck-adoption)
|
|
29
30
|
- [issue](#crosscheck-issue)
|
|
30
31
|
- [Configuration](#configuration)
|
|
31
32
|
- [How it works](#how-it-works)
|
|
@@ -235,6 +236,8 @@ crosscheck review https://github.com/owner/repo/pull/123 --reviewer codex
|
|
|
235
236
|
|
|
236
237
|
If this step fails, fix the specific auth, clone, reviewer, or comment-posting error before enabling `watch`.
|
|
237
238
|
|
|
239
|
+
If you'd rather nothing be written to the PR on a first run, use `crosscheck run <pr-url> --dry-run` instead: it clones, reviews, and prints the comment it would post without touching GitHub. (`--dry-run` lives on `run`, `fix`, `recheck`, and `resolve` — not on `review`, which always posts.) [docs/trust.md](./docs/trust.md) covers what leaves your machine at each step, which permissions each command needs, and exactly what `watch` can change.
|
|
240
|
+
|
|
238
241
|
## Step 3 — Choose a deployment mode
|
|
239
242
|
|
|
240
243
|
After one-shot review works, run the guided setup:
|
|
@@ -528,6 +531,8 @@ crosscheck alter humanbased-ai/xny-monorepo --reset # remove th
|
|
|
528
531
|
|
|
529
532
|
The depths differ in what happens after the initial review:
|
|
530
533
|
|
|
534
|
+
In every depth, an `APPROVE` stops all work on the commit it covers, and a later push re-opens the PR — see [What happens after a PR is approved?](#what-happens-after-a-pr-is-approved).
|
|
535
|
+
|
|
531
536
|
- **`review`** — review each new SHA; never modify code.
|
|
532
537
|
- **`review,fix`** — crosscheck auto-applies fixes when the verdict isn't `APPROVE`, and stops there; its own fix commit is not re-reviewed.
|
|
533
538
|
- **`review,fix,recheck`** — same, then rechecks its own fix commit. `max_rounds` in `~/.crosscheck/workflow.yml` bounds that fix→recheck cycle.
|
|
@@ -679,7 +684,7 @@ crosscheck scan --json
|
|
|
679
684
|
|
|
680
685
|
### `crosscheck kickass`
|
|
681
686
|
|
|
682
|
-
Selects all actionable PRs (any PR where a next step is needed: review, fix, recheck) and advances each one. Stale PRs are shown first. APPROVE PRs appear as a read-only "needs merge (manual)" section — visible so you know what's ready, but not dispatched automatically. The command revalidates the PR head before each mutation and prints an execution summary when it finishes.
|
|
687
|
+
Selects all actionable PRs (any PR where a next step is needed: resolve, review, fix, recheck) and advances each one. A PR with merge conflicts is dispatched as a `resolve` leg first — conflicts block everything downstream, and a base-branch move that conflicts a PR fires no webhook, so a scan is the only thing that notices. Stale PRs are shown first. APPROVE PRs appear as a read-only "needs merge (manual)" section — visible so you know what's ready, but not dispatched automatically. The command revalidates the PR head before each mutation and prints an execution summary when it finishes.
|
|
683
688
|
|
|
684
689
|
Each PR dispatch uses `detect-step` to read live PR comment history and advances **exactly the next needed step** — kickass drives one step per PR, then `watch` picks up continuation via the webhooks that step produces.
|
|
685
690
|
|
|
@@ -976,6 +981,65 @@ crosscheck impact (all time · 47 reviews)
|
|
|
976
981
|
| `--json` | Output the full report as JSON |
|
|
977
982
|
| `-c, --config <path>` | Config file path |
|
|
978
983
|
|
|
984
|
+
---
|
|
985
|
+
|
|
986
|
+
### `crosscheck adoption`
|
|
987
|
+
|
|
988
|
+
Reports whether crosscheck is actually being used, and how long a PR waits for a verdict. Where `impact` prices reviews that happened, `adoption` measures activation and reach. Reads from `~/.crosscheck/logs/` — no network calls, nothing transmitted.
|
|
989
|
+
|
|
990
|
+
```bash
|
|
991
|
+
crosscheck adoption
|
|
992
|
+
crosscheck adoption --since 2026-07-01
|
|
993
|
+
crosscheck adoption --json
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
```
|
|
997
|
+
crosscheck adoption (2026-06-15 → 2026-07-14)
|
|
998
|
+
|
|
999
|
+
Activation
|
|
1000
|
+
──────────────────────────────────────────────
|
|
1001
|
+
onboard started 3
|
|
1002
|
+
onboard completed 2
|
|
1003
|
+
abandoned 1
|
|
1004
|
+
|
|
1005
|
+
Usage
|
|
1006
|
+
──────────────────────────────────────────────
|
|
1007
|
+
reviews started 51
|
|
1008
|
+
reviews completed 47
|
|
1009
|
+
rechecks completed 12
|
|
1010
|
+
blocking findings posted 19
|
|
1011
|
+
fixes applied 11
|
|
1012
|
+
active repos 6
|
|
1013
|
+
|
|
1014
|
+
Weekly active repos
|
|
1015
|
+
──────────────────────────────────────────────
|
|
1016
|
+
2026-06-22 ████████ 3 repos 14 reviews
|
|
1017
|
+
2026-06-29 ████████████ 4 repos 18 reviews
|
|
1018
|
+
2026-07-06 ████████████████ 6 repos 15 reviews
|
|
1019
|
+
|
|
1020
|
+
PR open → verdict
|
|
1021
|
+
──────────────────────────────────────────────
|
|
1022
|
+
median 22m
|
|
1023
|
+
p90 1.8h
|
|
1024
|
+
slowest 2d
|
|
1025
|
+
measured on 41 verdicts
|
|
1026
|
+
ⓘ 6 verdicts had no PR open time in the event — excluded
|
|
1027
|
+
|
|
1028
|
+
First-run failures (sessions that never reached a verdict)
|
|
1029
|
+
──────────────────────────────────────────────
|
|
1030
|
+
auth 2
|
|
1031
|
+
|
|
1032
|
+
ⓘ derived from local logs only (30d retention) — nothing is transmitted. See docs/metrics.md
|
|
1033
|
+
```
|
|
1034
|
+
|
|
1035
|
+
| Flag | Description |
|
|
1036
|
+
|---|---|
|
|
1037
|
+
| `--since <YYYY-MM-DD>` | Limit the analysis to logs from this date onward |
|
|
1038
|
+
| `--json` | Output the full report as JSON |
|
|
1039
|
+
| `-c, --config <path>` | Config file path |
|
|
1040
|
+
|
|
1041
|
+
Every field these numbers are derived from is inventoried in **[docs/metrics.md](./docs/metrics.md)**, including what is deliberately never written to disk.
|
|
1042
|
+
|
|
979
1043
|
The monetary estimate formula: `(hours_saved × hourly_rate_usd) + (issues_caught × defect_cost_usd)`. Defaults: `$150/hr`, `$150/issue`. Both configurable in `crosscheck.config.yml` under `impact`.
|
|
980
1044
|
|
|
981
1045
|
---
|
|
@@ -1138,6 +1202,17 @@ skills:
|
|
|
1138
1202
|
# - code-review # preloaded, opt-in · @mattpocock, MIT
|
|
1139
1203
|
# - codebase-design # preloaded, opt-in · @mattpocock, MIT
|
|
1140
1204
|
|
|
1205
|
+
# Codex only. Codex reaches the skill broker (an MCP server) only when its
|
|
1206
|
+
# sandbox is disabled: under -s read-only, -s workspace-write, -a never and
|
|
1207
|
+
# --full-auto alike it cancels every tool call, so skills silently do nothing.
|
|
1208
|
+
# Turning this on lets codex run unsandboxed against the PR checkout — which is
|
|
1209
|
+
# untrusted code — in exchange for skills actually working. Crosscheck removes
|
|
1210
|
+
# the git credential from the checkout and passes codex an allowlisted
|
|
1211
|
+
# environment (no GITHUB_TOKEN) either way, but a prompt injection can still
|
|
1212
|
+
# read the working tree and reach the network. Claude needs none of this: its
|
|
1213
|
+
# broker works sandboxed.
|
|
1214
|
+
codex_full_access: false
|
|
1215
|
+
|
|
1141
1216
|
# ── Budget ────────────────────────────────────────────────────────────────────
|
|
1142
1217
|
budget:
|
|
1143
1218
|
codex_monthly_usd: 20 # null = unlimited; only applies when auth: api-key
|
|
@@ -1174,6 +1249,13 @@ routing:
|
|
|
1174
1249
|
# 2. Commit message Co-Authored-By: trailers (API call, non-fatal if it fails)
|
|
1175
1250
|
# 3. Branch prefix (claude/ or codex/)
|
|
1176
1251
|
# 4. author_routes fallback (last resort)
|
|
1252
|
+
# These say who WROTE the code, not who reviewed it.
|
|
1253
|
+
#
|
|
1254
|
+
# Crosscheck's own attribution — its fix-PR footer and `Crosscheck-Reviewer`
|
|
1255
|
+
# commit trailers — is recognised ALWAYS, whatever you put here. Setting either
|
|
1256
|
+
# list replaces the defaults, so if these markers lived in the list a pinned
|
|
1257
|
+
# config would misread crosscheck's own fix PRs as human-authored. Your patterns
|
|
1258
|
+
# are checked first and still win.
|
|
1177
1259
|
codex_reviews_patterns:
|
|
1178
1260
|
- "Generated with \\[Claude Code\\]" # Claude Code attribution footer
|
|
1179
1261
|
- "Co-Authored-By: Claude" # commit trailer
|
|
@@ -1222,8 +1304,9 @@ post_review:
|
|
|
1222
1304
|
auto_fix:
|
|
1223
1305
|
delivery:
|
|
1224
1306
|
mode: pull_request # pull_request | commit | comment
|
|
1225
|
-
# pull_request →
|
|
1226
|
-
#
|
|
1307
|
+
# pull_request → fixes land on the original PR branch; a separate fix PR is
|
|
1308
|
+
# opened only if that push can't land (branch merged/deleted/protected)
|
|
1309
|
+
# commit → fixes pushed directly onto the original PR branch (no fallback)
|
|
1227
1310
|
# comment → suggested fixes posted as review comments only
|
|
1228
1311
|
pr_title: "fix: address CR issues in #{original_pr_title}"
|
|
1229
1312
|
label: cr-autofix # GitHub label applied to the fix PR
|
|
@@ -1529,7 +1612,7 @@ agent opens PR #42 → opposite vendor reviews → issues found?
|
|
|
1529
1612
|
| Setting | Default | Why |
|
|
1530
1613
|
|---|---|---|
|
|
1531
1614
|
| `fixer: same-as-author` | the vendor that wrote the PR also fixes it | The authoring agent knows its own code and style best |
|
|
1532
|
-
| `delivery: pull_request` | opens a
|
|
1615
|
+
| `delivery: pull_request` | pushes the fix onto the PR's own branch, so the fix, recheck, and approval stay on one PR; opens a separate fix PR only when that push can't land | Keeps everything on the original PR while still covering merged/protected branches |
|
|
1533
1616
|
| `trigger: on_issues` | only fires when the reviewer found warnings or worse | Skips the fix step on clean PRs |
|
|
1534
1617
|
| `min_severity: warning` | ignores info/cosmetic findings | Avoids noisy fix PRs for style-only comments |
|
|
1535
1618
|
|
|
@@ -1644,11 +1727,38 @@ Each cycle is one `[crosscheck]` fix commit followed by one recheck. The loop st
|
|
|
1644
1727
|
|
|
1645
1728
|
`max_rounds` is respected by both `crosscheck watch` and `crosscheck run`. `watch` re-triggers on each pushed fix commit; `run` loops inline within the same session.
|
|
1646
1729
|
|
|
1730
|
+
### My PR became conflicted — will crosscheck resolve it?
|
|
1731
|
+
|
|
1732
|
+
Yes, if your workflow has a `conflict-resolve` step (the `onboard` default does). Conflicts are handled independently of the review ladder, because a PR usually conflicts when the **base branch** moves — which changes nothing about the code that was reviewed.
|
|
1733
|
+
|
|
1734
|
+
The catch is that a base-branch move fires no webhook on your PR, so `watch` never hears about it. `crosscheck scan` and `crosscheck kickass` are what notice: a conflicted PR shows `next=resolve` and is dispatched ahead of review, fix, and recheck. An approved PR that can no longer merge is resolved too — the merge commit then moves HEAD off the approved SHA, so the merged code gets a fresh review.
|
|
1735
|
+
|
|
1736
|
+
```bash
|
|
1737
|
+
crosscheck kickass # picks up conflicted PRs along with everything else
|
|
1738
|
+
crosscheck resolve <pr-url> # or force just the conflict-resolve step
|
|
1739
|
+
```
|
|
1740
|
+
|
|
1741
|
+
Fork PRs are skipped, same as with auto-fix — crosscheck cannot push to them. Repos narrowed to `review` or `review,recheck` never resolve conflicts either, since that would modify code.
|
|
1742
|
+
|
|
1743
|
+
### What happens after a PR is approved?
|
|
1744
|
+
|
|
1745
|
+
Crosscheck stops working on that commit. Once the newest verdict is `APPROVE` and it covers the PR's current HEAD, no further step runs — not a recheck, not a re-review. `watch` skips further events on that SHA, `crosscheck run` prints `this commit is already approved — nothing to do until new commits land`, and `kickass` lists the PR under "needs merge (manual)" instead of dispatching it.
|
|
1746
|
+
|
|
1747
|
+
**A push re-opens it.** New commits materially change what was approved, so the approval no longer applies: the next event runs a fresh review (round *n*+1) on the new code, and the full fix/recheck loop resumes from there. An `APPROVE` posted before the annotation carried a `sha=` field can't prove which commit it covers, so it is treated the same way — one review re-establishes it.
|
|
1748
|
+
|
|
1749
|
+
To force another pass on the approved commit itself, name the steps explicitly — that bypasses history detection:
|
|
1750
|
+
|
|
1751
|
+
```bash
|
|
1752
|
+
crosscheck run https://github.com/owner/repo/pull/123 --steps review
|
|
1753
|
+
```
|
|
1754
|
+
|
|
1755
|
+
`crosscheck detect-step <pr-url>` shows the stop reason for any PR.
|
|
1756
|
+
|
|
1647
1757
|
### Can I disable the auto-fix step?
|
|
1648
1758
|
|
|
1649
1759
|
Yes. Set `post_review.auto_fix.enabled: false` in your config, or set `trigger: never`. You can also raise `min_severity` to `error` to limit fixes to blocking issues only.
|
|
1650
1760
|
|
|
1651
|
-
|
|
1761
|
+
Both `delivery: pull_request` (the default) and `delivery: commit` push the fix directly onto the PR's own branch. The only difference is the fallback: `pull_request` opens a separate fix PR if that push can't land (branch merged, deleted, or protected), whereas `commit` surfaces the push failure instead. To get suggested fixes as review comments without any code push, use `delivery: comment`.
|
|
1652
1762
|
|
|
1653
1763
|
### Why does the fixer use the same vendor that wrote the PR?
|
|
1654
1764
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@humanbased/crosscheck",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0-beta.100",
|
|
4
4
|
"description": "AI code review pipeline that turns agent-written PRs into merge-ready patches",
|
|
5
5
|
"bin": {
|
|
6
6
|
"crosscheck": "dist/cli.js",
|
|
@@ -43,8 +43,10 @@
|
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/js-yaml": "^4.0.9",
|
|
45
45
|
"@types/node": "^22.0.0",
|
|
46
|
+
"eslint": "^9.39.5",
|
|
46
47
|
"tsx": "^4.16.0",
|
|
47
48
|
"typescript": "^5.5.0",
|
|
49
|
+
"typescript-eslint": "^8.67.0",
|
|
48
50
|
"vitest": "^3.2.4"
|
|
49
51
|
},
|
|
50
52
|
"keywords": [
|