@applesnort/crosscheck 0.6.0 → 0.7.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/CHANGELOG.md ADDED
@@ -0,0 +1,83 @@
1
+ # Changelog
2
+
3
+ Notable changes to `@applesnort/crosscheck`. Format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning is
5
+ [semver](https://semver.org/), pre-1.0, so a minor bump is where behaviour
6
+ changes land.
7
+
8
+ Entries before 0.7.0 were reconstructed from commit history after the fact, so
9
+ they name what each version did rather than itemising every change in it.
10
+
11
+ **Published to npm: 0.2.0, 0.2.1, 0.2.2, 0.3.0, 0.6.0.** 0.4.0, 0.5.0, 0.6.1 and
12
+ 0.6.2 exist as versions in this repository but were never published, so a
13
+ consumer resolving `@0.6` gets 0.6.0 and none of the fixes after it.
14
+
15
+ ## [0.7.0] — unreleased
16
+
17
+ ### Fixed
18
+
19
+ - The `check`, `architect`, `security-check` and `taint` lenses now route
20
+ `.vue` and `.svelte` files. They globbed `.js`/`.ts` and friends but not
21
+ single-file components, so only `ux` matched one — a 2437-line Vue component
22
+ in a real review was read by the usability lens and by nothing else, with no
23
+ correctness, security or architecture pass over the largest file in the
24
+ project.
25
+
26
+ The run still reported as complete, because each lens that skipped the
27
+ component did so via "nothing in scope matches", which reads as a routing
28
+ decision rather than a hole.
29
+
30
+ This is a **behaviour change, not just a fix**: every lens now receives more
31
+ files on any project containing components, so runs there are slower and cost
32
+ more. That is why it is a minor bump rather than a patch.
33
+
34
+ - `test/lenses.test.mjs` asserts the shipped lenses route both extensions. The
35
+ existing routing test only ever checked a plain `.js` file, which is why the
36
+ gap survived.
37
+
38
+ Stylesheets remain deliberately unrouted; the CLI naming an unmatched `.css`
39
+ file in its `UNREVIEWED` line is intended behaviour, not a further instance of
40
+ this bug.
41
+
42
+ ## [0.6.2] — unpublished
43
+
44
+ - Install the model CLI in the scaffolded workflow.
45
+
46
+ ## [0.6.1] — unpublished
47
+
48
+ - Do not load the same lens directory twice.
49
+
50
+ ## [0.6.0] — 2026
51
+
52
+ - Adoption in one command (`crosscheck init`): scaffold config, lenses and
53
+ workflow.
54
+
55
+ ## [0.5.0] — unpublished
56
+
57
+ - Cost work: make a standing panel cheap enough to leave switched on.
58
+
59
+ ## [0.4.0] — unpublished
60
+
61
+ - Review a change rather than a tree; verify findings before reporting them;
62
+ gate before dispatch.
63
+ - Cancel superseded CI runs instead of queueing them.
64
+
65
+ ## [0.3.0] — 2026
66
+
67
+ - Layer lens sources, so adding one lens costs one file instead of forking all
68
+ of them.
69
+ - Document that a project's own lenses stay in that project.
70
+
71
+ ## [0.2.2] — 2026
72
+
73
+ - `.crosscheckrc.json`, so a team shares one panel definition instead of a shell
74
+ alias nobody else can see.
75
+
76
+ ## [0.2.1] — 2026
77
+
78
+ - Disclose unreviewed files; stop sending lens frontmatter to the model.
79
+ - CLI smoke tests, and two bugs they found.
80
+
81
+ ## [0.2.0] — 2026
82
+
83
+ - Publish under the `@applesnort` scope.
@@ -183,9 +183,18 @@ function lensSources(option, { includeBuiltin = true } = {}) {
183
183
  if (dirs.length === 0) {
184
184
  fail('no lens directories to load (--no-builtin with no --lenses?)');
185
185
  }
186
- const sources = dirs.map(dir => ({ origin: dir, lenses: loadLenses(dir) }));
186
+ // The same directory can arrive twice ./lenses is auto-detected, and running
187
+ // from that project also names it via --lenses. Loading it twice makes every
188
+ // lens in it shadow itself, which reads as a configuration mistake that is not
189
+ // one. Keep the last occurrence, so an explicit --lenses still wins on order.
190
+ const seen = new Map();
191
+ for (const dir of dirs) {
192
+ seen.set(dir, true);
193
+ }
194
+ const uniqueDirs = [...seen.keys()];
195
+ const sources = uniqueDirs.map(dir => ({ origin: dir, lenses: loadLenses(dir) }));
187
196
  if (sources.every(source => source.lenses.length === 0)) {
188
- fail(`no usable lens definitions found in: ${dirs.join(', ')}`);
197
+ fail(`no usable lens definitions found in: ${uniqueDirs.join(', ')}`);
189
198
  }
190
199
  return sources;
191
200
  }
@@ -502,10 +511,20 @@ jobs:
502
511
  with:
503
512
  node-version: '22.x'
504
513
 
514
+ # EDIT THIS STEP. crosscheck never talks to a model, so whatever your
515
+ # \`exec\` command names has to exist on the runner. Nothing here is
516
+ # installed for you, and a missing command fails every lens with ENOENT.
517
+ #
518
+ # Claude Code: npm i -g @anthropic-ai/claude-code (exec: claude -p)
519
+ # llm: pipx install llm (exec: llm -m ...)
520
+ # your own: whatever installs it
521
+ - name: Install the model CLI
522
+ run: npm i -g @anthropic-ai/claude-code
523
+
505
524
  - name: Review the change
506
525
  env:
507
- # Provide whatever your --exec command needs. crosscheck itself never
508
- # talks to a model.
526
+ # Whatever your exec command needs to authenticate. crosscheck reads no
527
+ # credentials of its own.
509
528
  ANTHROPIC_API_KEY: \${{ secrets.ANTHROPIC_API_KEY }}
510
529
  run: |
511
530
  npx @applesnort/crosscheck run \\
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: architect
3
3
  summary: structure, data shape, coupling, and reversibility of decisions
4
- when: [**/*.{js,mjs,cjs,ts,tsx,py,go,rb,java,cs,rs,sql,prisma,graphql}, "**/migrations/**", "**/schema*"]
4
+ when: [**/*.{js,mjs,cjs,ts,tsx,py,go,rb,java,cs,rs,sql,prisma,graphql,vue,svelte}, "**/migrations/**", "**/schema*"]
5
5
  owns: couplings and lock-in that make later change expensive
6
6
  not-owns: line-level correctness, style, security categories, usability
7
7
  cites: []
package/lenses/check.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: check
3
3
  summary: correctness — boundaries, absent values, error paths, concurrency
4
- when: [**/*.{js,mjs,cjs,jsx,ts,tsx,py,go,rb,java,cs,rs,php,kt,swift}]
4
+ when: [**/*.{js,mjs,cjs,jsx,ts,tsx,py,go,rb,java,cs,rs,php,kt,swift,vue,svelte}]
5
5
  owns: defects that produce wrong behavior at runtime
6
6
  not-owns: style, naming, architecture, security categories, usability
7
7
  cites: []
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: security-check
3
3
  summary: application security — trust boundaries, injection, secrets, exposure
4
- when: [**/*.{js,mjs,cjs,ts,tsx,py,go,rb,java,cs,rs,php,kt,swift,sql}]
4
+ when: [**/*.{js,mjs,cjs,ts,tsx,py,go,rb,java,cs,rs,php,kt,swift,sql,vue,svelte}]
5
5
  owns: exploitable weaknesses reachable by an untrusted or under-privileged caller
6
6
  not-owns: general correctness, architecture preference, usability, styling
7
7
  cites: ["OWASP Top 10 (2021)", "OWASP ASVS", "CWE"]
package/lenses/taint.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: taint
3
3
  summary: data flow from untrusted origin to dangerous operation, and what sanitises it
4
- when: [**/*.{js,mjs,cjs,ts,tsx,py,go,rb,java,cs,rs,php,kt,swift}]
4
+ when: [**/*.{js,mjs,cjs,ts,tsx,py,go,rb,java,cs,rs,php,kt,swift,vue,svelte}]
5
5
  owns: untrusted values reaching an operation that interprets them, unsanitised
6
6
  not-owns: security policy, authentication design, crypto choice, correctness, architecture, usability
7
7
  cites: []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applesnort/crosscheck",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Run independent review lenses in parallel and merge their findings into one deduped, consensus-ranked report \u2014 with SARIF output.",
5
5
  "license": "MIT",
6
6
  "author": "Joel Mangin",
@@ -34,6 +34,7 @@
34
34
  "foreman.md",
35
35
  "PROVENANCE.md",
36
36
  "README.md",
37
+ "CHANGELOG.md",
37
38
  "LICENSE"
38
39
  ],
39
40
  "scripts": {