@applesnort/crosscheck 0.3.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,7 +19,42 @@ or your own wrapper. crosscheck owns prompt construction, routing, fan-out, dedu
19
19
  and output; you own the model. `--dry-run` prints the roster and prompts without
20
20
  spawning anything.
21
21
 
22
- No dependencies, no install step, 183 tests.
22
+ No dependencies, no install step, 267 tests.
23
+
24
+ ## Getting set up
25
+
26
+ ```bash
27
+ npx @applesnort/crosscheck init
28
+ ```
29
+
30
+ Scaffolds `.crosscheckrc.json`, a `.crosscheck/lenses/` directory with a note on
31
+ writing lenses, and a `.github/workflows/crosscheck.yml` that reviews each pull
32
+ request, uploads SARIF to code scanning, and posts a summary comment. Existing
33
+ files are left alone unless you pass `--force`.
34
+
35
+ Set `exec` to whatever runs your model, then:
36
+
37
+ ```bash
38
+ crosscheck run --diff --dry-run
39
+ ```
40
+
41
+ ## In CI
42
+
43
+ The scaffolded workflow reviews the diff against the base branch, and does two
44
+ things with the result:
45
+
46
+ - **SARIF to code scanning** — per-line annotations in the Files changed view,
47
+ which is where a reviewer is already looking.
48
+ - **A summary comment** via `--comment-file`, carrying what per-line annotations
49
+ cannot: which lenses were skipped and why, which died, what the baseline
50
+ suppressed, and how many findings verification refuted.
51
+
52
+ The comment embeds a marker so later runs **edit** it rather than stacking. A pull
53
+ request with eleven bot comments gets muted, and a muted reviewer finds nothing.
54
+
55
+ The workflow checks out with `fetch-depth: 0`, because reviewing a diff needs the
56
+ base commit. crosscheck itself never talks to a model — supply whatever your
57
+ `exec` command needs via the workflow's `env`.
23
58
 
24
59
  ## Configuration
25
60
 
@@ -50,7 +85,9 @@ and an unrecognised key is an error rather than a silent no-op, because a
50
85
  misspelled `exec` that quietly does nothing is worse than a crash.
51
86
 
52
87
  Accepted keys: `exec`, `lenses`, `concurrency`, `only`, `skip`, `mixed`, `out`,
53
- `sarif`, `baseline`, `overlap`. Keys beginning `//` are treated as comments.
88
+ `sarif`, `baseline`, `overlap`, `preflight`, `context`, `verify`, `since`,
89
+ `max-dispatches`, `no-cache`, `cache-dir`, `comment-file`. `exec` accepts a string
90
+ or a per-lens map. Keys beginning `//` are treated as comments.
54
91
 
55
92
  > **v0.x — the API is unstable.** The CLI commands and the `lib/` exports may
56
93
  > change shape before 1.0. Pin an exact version if you depend on it.
@@ -59,6 +96,100 @@ Accepted keys: `exec`, `lenses`, `concurrency`, `only`, `skip`, `mixed`, `out`,
59
96
  > similar to the (abandoned) `cross-check`. Installed, the command is
60
97
  > `crosscheck`.
61
98
 
99
+ ## Reviewing a change, not a directory
100
+
101
+ Nobody reviews a whole tree — they review a diff. Auditing paths makes cost scale
102
+ with repository size instead of change size, and re-reads code nobody touched.
103
+
104
+ ```bash
105
+ crosscheck run --diff # everything uncommitted
106
+ crosscheck run --staged # what you are about to commit
107
+ crosscheck run --since origin/main # the branch, for a PR
108
+ ```
109
+
110
+ Each lens is told which lines moved:
111
+
112
+ ```
113
+ - src/a.js (changed lines: 5-27, 61-84)
114
+ ```
115
+
116
+ Ranges are widened by `--context` lines (20 by default) so a lens sees the code
117
+ around a change, and the prompt is explicit that changed lines are the *priority*
118
+ rather than the boundary — a defect elsewhere that the change causes or depends on
119
+ is still worth reporting, while a pre-existing one it never touches is not what the
120
+ review is for. An empty diff exits cleanly rather than falling back to reviewing
121
+ everything.
122
+
123
+ ## Verification is on by default
124
+
125
+ `BLOCK` findings are refuted before they are reported. Each one gets a skeptic that
126
+ is handed **the file** rather than the finding's account of it, told to default to
127
+ refuted when it cannot name a concrete trigger. Refuted findings are removed and
128
+ **the count is always printed, including zero** — a finding that vanished without a
129
+ number is indistinguishable from one that was never found.
130
+
131
+ ```
132
+ crosscheck: verifying 3 finding(s)
133
+ ✓ confirmed src/session.js:44
134
+ ✗ refuted src/cache.js:12
135
+ Refuted in verification: 1.
136
+ ```
137
+
138
+ False positives cost more than misses: a panel that cries wolf twice stops being
139
+ read, and its true findings go unread with the rest. `--verify` extends the pass to
140
+ every severity; `--no-verify` skips it, at that cost.
141
+
142
+ A verifier that fails to run is **not** treated as agreement — the finding stands
143
+ and the failure is reported.
144
+
145
+ ## Your own gate, before anything is dispatched
146
+
147
+ ```json
148
+ { "preflight": "scripts/check-clean-worktree.sh" }
149
+ ```
150
+
151
+ A non-zero exit aborts before a single model call. That lets a project enforce a
152
+ rule crosscheck knows nothing about — data classification, branch policy, a clean
153
+ worktree — without the rule having to exist upstream.
154
+
155
+ ## Cost control
156
+
157
+ A tool that costs real money per run gets switched off, and a switched-off tool
158
+ finds nothing.
159
+
160
+ **A cheap lens should not pay for an expensive model.** `exec` may be a map:
161
+
162
+ ```json
163
+ {
164
+ "exec": {
165
+ "default": "claude -p",
166
+ "conventions": "llm -m claude-haiku-4-5"
167
+ }
168
+ }
169
+ ```
170
+
171
+ Precedence is the lens's own `exec` in its frontmatter, then the map entry, then
172
+ `default`. A rostered lens with no command anywhere fails loudly and names itself
173
+ — it is never quietly skipped.
174
+
175
+ **Unchanged files are not re-reviewed.** Results are cached under
176
+ `.crosscheck/cache`, keyed on the lens definition, the files, and their contents.
177
+ The definition is part of the key deliberately: editing a lens must invalidate its
178
+ results, or you would be served answers from the previous prompt with no way to
179
+ tell. `--no-cache` disables it, `--cache-dir` relocates it. A failed lens is never
180
+ cached, so it is retried rather than permanently wrong.
181
+
182
+ **`--max-dispatches N` caps the run, and says what it dropped:**
183
+
184
+ ```
185
+ crosscheck: BUDGET REACHED — 3 lens(es) not run: check, security-check, taint
186
+ ```
187
+
188
+ The unit is dispatches, not dollars. crosscheck cannot see tokens or cost —
189
+ `--exec` is an arbitrary command — so a monetary budget would be a number invented
190
+ from nothing. Truncation is always named, because a run that quietly stopped early
191
+ looks exactly like a run that found nothing.
192
+
62
193
  ## SARIF output
63
194
 
64
195
  Findings are emitted as [SARIF 2.1.0](https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html),
@@ -200,8 +331,11 @@ lib/
200
331
  prompt.mjs lens prompt construction
201
332
  run.mjs roster planning and bounded fan-out
202
333
  config.mjs .crosscheckrc.json discovery and validation
203
- bin/crosscheck.mjs CLI: run | lenses | report | sarif | baseline |
204
- overlap | calibrate
334
+ target.mjs diff parsing, changed line ranges
335
+ cache.mjs content-addressed result cache
336
+ comment.mjs pull-request summary comment
337
+ bin/crosscheck.mjs CLI: init | run | lenses | report | sarif |
338
+ baseline | overlap | calibrate
205
339
  fixtures/calibration/ planted defects, ground truth, and the calibration record
206
340
  fixtures/deception/ 20 modules that look safe and are not, or the reverse
207
341
  PROVENANCE.md where all of this came from