@lcv-ideas-software/cross-review 4.0.1 → 4.0.2

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 CHANGED
@@ -7,6 +7,70 @@ standard `v00.00.00`; npm package versions remain SemVer.
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [v04.00.02] — 2026-05-15
11
+
12
+ **Patch — Codex second-pass audit close-out (6 findings).** v4.0.1 closed 8
13
+ findings from the first Codex parecer; this v4.0.2 closes 6 additional
14
+ items the second parecer flagged. None affects runtime semantics.
15
+
16
+ ### Fixed
17
+
18
+ - **AUDIT-1 (MEDIUM) — lockfile version drift.** v4.0.1 bumped
19
+ `package.json` to `4.0.1` but the lockfile root `.version` and
20
+ `.packages[""].version` stayed at `4.0.0` (the `npm install` ran
21
+ during v4.0.0 captured deps, then the version bump didn't trigger a
22
+ re-resolve). Full reinstall this release brings the lockfile back to
23
+ the current `package.json` version. **Plus: new anti-drift smoke
24
+ marker `package_version_consistency_test`** asserts the four
25
+ equalities `pkg.name === pkg-lock.name`, `pkg-lock.name ===
26
+ "@lcv-ideas-software/cross-review"`, `pkg.version === pkg-lock.version`,
27
+ `pkg.version === pkg-lock.packages[""].version`. Any future version
28
+ bump that forgets the `npm install` re-resolve fails smoke loudly
29
+ instead of slipping through to publish.
30
+ - **AUDIT-2 (MEDIUM) — model-selection wording aligned with no-fallback
31
+ policy.** Both `docs/model-selection.md` and `src/peers/model-selection.ts`
32
+ were still describing "automatic model selection", "priority list",
33
+ and "documented fallback" — terms from the pre-v3.7.2 multi-model era.
34
+ The runtime has used canonical pins (one model per peer, no auto-chain)
35
+ since v3.7.2 (operator directive "sem fallback é sem fallback").
36
+ Updated docs + the `selected/candidates/reason` messages in
37
+ `selectFromCandidates`, `overrideSelection`, and the no-API-key
38
+ path to use canonical-pin language consistently. The `confidence`
39
+ classification logic is unchanged.
40
+ - **AUDIT-3 (LOW) — SECURITY.md stub wording.** The doc said
41
+ `CROSS_REVIEW_STUB=1` alone is "ignored"; the code at
42
+ `src/peers/registry.ts:36-44` actually throws an explicit error
43
+ referencing the missing confirmation flag. Updated wording to
44
+ "rejected fail-fast" to match runtime behavior.
45
+ - **AUDIT-4 (LOW) — README MCP tools list completed.** The README
46
+ Section listing the available tools had 22 entries; the runtime
47
+ exposes 28. Added the 6 missing tools:
48
+ `session_evidence_checklist_update`,
49
+ `session_evidence_judge_pass`,
50
+ `session_evidence_judge_consensus_pass`,
51
+ `session_judgment_precision_report`,
52
+ `contest_verdict`,
53
+ `regenerate_caller_tokens`.
54
+ - **AUDIT-5 (LOW) — `docs/architecture.md` rename event.** The "Stable
55
+ Rename" section said the rename to `cross-review` happened at
56
+ `2.1.0`; the actual event is v4.0.0 on 2026-05-15 (this rename ship).
57
+ Rewrote the section to record v4.0.0 as the rename event and note
58
+ that prior names live only in dated changelog and memory.
59
+ - **AUDIT-6 (MEDIUM) — StepSecurity post-rename detections triaged.**
60
+ Two new org-level suppression rules created:
61
+ (a) `Source-Code-Overwritten` for `*/dist/*` in
62
+ `.github/workflows/publish.yml` under the `Pre-publish gate (test +
63
+ metadata)` job for repo `cross-review` (the prior cross-review-v2
64
+ rules no longer match after rename); (b)
65
+ `Action-Uses-Commit-From-Non-Default-Branch` for
66
+ `github/codeql-action*` (GitHub's release-branch model — tagged
67
+ versions cut from `releases/vN` not from default branch are
68
+ intended/audited by GitHub Security; rejecting would force less
69
+ secure tag-based usage). Plus 20 existing detections (19
70
+ Source-Code-Overwritten dist/\* + 1 codeql-action SHA) suppressed
71
+ per-detection via `update_detection_status` with rule-id citations
72
+ in the suppress reason.
73
+
10
74
  ## [v04.00.01] — 2026-05-15
11
75
 
12
76
  **Patch — close-out of post-v4.0.0 audit (eight surfaces left stale by the
package/README.md CHANGED
@@ -193,7 +193,13 @@ these environment variables before running real sessions (example):
193
193
  - `session_report`
194
194
  - `session_check_convergence`
195
195
  - `session_attach_evidence`
196
+ - `session_evidence_checklist_update`
197
+ - `session_evidence_judge_pass`
198
+ - `session_evidence_judge_consensus_pass`
199
+ - `session_judgment_precision_report`
200
+ - `contest_verdict`
196
201
  - `escalate_to_operator`
202
+ - `regenerate_caller_tokens`
197
203
  - `session_sweep`
198
204
  - `session_finalize`
199
205
 
package/SECURITY.md CHANGED
@@ -37,7 +37,7 @@ This repository employs:
37
37
 
38
38
  - **Multi-host concurrency.** Running two MCP host instances of `cross-review` against the same `CROSS_REVIEW_DATA_DIR` is **not supported**. The per-session lock has TTL + PID-liveness fallbacks that close the common cases but leave a narrow TOCTOU window when two hosts contend for the same session. If you need multi-host operation, point each instance at a distinct `CROSS_REVIEW_DATA_DIR` (introduced in v2.0; tilde expansion since v2.4.0) or share one host across all clients.
39
39
  - **API keys in memory.** `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, `DEEPSEEK_API_KEY` are loaded into `AppConfig.api_keys` at boot. The persistence layer redacts secrets via [`redact()`](./src/security/redact.ts) before any meta.json/event log write, but the in-memory object is not opaque — do not log `config` directly. Stack traces from SDK errors are passed through `safeErrorMessage()` which redacts known key shapes.
40
- - **Stub adapters.** `CROSS_REVIEW_STUB=1` alone is **ignored** since v2.4.0. To activate stubs, also set `NODE_ENV=test` OR `CROSS_REVIEW_STUB_CONFIRMED=1`. This double-confirmation prevents a stray dotenv variable from invalidating a cross-review used as a pre-commit gate.
40
+ - **Stub adapters.** `CROSS_REVIEW_STUB=1` alone is **rejected fail-fast** since v2.4.0 — boot throws an explicit error referencing the missing confirmation flag, rather than silently demoting to real adapters. To deliberately activate stubs, set BOTH `CROSS_REVIEW_STUB=1` AND one of `NODE_ENV=test` OR `CROSS_REVIEW_STUB_CONFIRMED=1`. The double-confirmation prevents a stray dotenv variable from invalidating a cross-review used as a pre-commit gate.
41
41
  - **Dashboard HTTP.** The dashboard binds only to `127.0.0.1`. There is no authentication or rate-limit; same-machine processes can read all session metadata, costs and report markdown. Do not expose the dashboard port over a network without an authenticating reverse proxy.
42
42
  - **Untrusted callers.** The MCP `tools/list` schemas enforce per-field caps (`maxLength`, `pattern`) since v2.4.0 to defend against memory-exhaustion attempts via oversized `task`/`draft`/`prompt`. The trust boundary still assumes a cooperative caller — do not expose the stdio transport over a network socket without an authenticating proxy.
43
43
  - **Untrusted peers.** Peer streaming responses are capped at 16 MiB per call (`STREAM_TEXT_MAX_BYTES` since v2.4.0). The structured `<cross_review_status>` payload is rejected as malformed when it exceeds 64 KiB before `JSON.parse` runs.
@@ -6120,6 +6120,30 @@ assert.equal(Object.hasOwn(metrics.decision_quality, "undefined"), false);
6120
6120
  assert.ok(/pruneCorruptSessions\(minAgeMs: number\): \{ scanned: number; removed: number; kept: number \}/.test(storeSrcB1), "v3.7.5 / B1: store.pruneCorruptSessions must declare the {scanned, removed, kept} shape");
6121
6121
  console.log("[smoke] session_sweep_prune_corrupt_test: PASS");
6122
6122
  }
6123
+ // v4.0.2 (AUDIT-1, Codex audit close-out 2026-05-15): anti-drift check
6124
+ // that `package.json.version` === `package-lock.json.version` ===
6125
+ // `package-lock.json.packages[""].version`. The v4.0.1 ship bumped
6126
+ // package.json without re-running `npm install`, so the lockfile root
6127
+ // versions stayed at `4.0.0` while package.json said `4.0.1`. Codex's
6128
+ // audit caught it. This marker pins the consistency invariant so any
6129
+ // future bump that forgets to regenerate the lockfile fails smoke
6130
+ // loudly instead of slipping through to publish.
6131
+ {
6132
+ const pjPath = path.join(process.cwd(), "package.json");
6133
+ const plPath = path.join(process.cwd(), "package-lock.json");
6134
+ const pj = JSON.parse(fs.readFileSync(pjPath, "utf8"));
6135
+ const pl = JSON.parse(fs.readFileSync(plPath, "utf8"));
6136
+ const pjVer = pj.version;
6137
+ const plRootVer = pl.version;
6138
+ const plPackagesRootVer = pl.packages?.[""]?.version;
6139
+ assert.equal(plRootVer, pjVer, `v4.0.2 / AUDIT-1: package-lock.json root .version (${plRootVer}) must equal package.json .version (${pjVer}); run \`npm install\` after bumping the version.`);
6140
+ assert.equal(plPackagesRootVer, pjVer, `v4.0.2 / AUDIT-1: package-lock.json packages[""].version (${plPackagesRootVer}) must equal package.json .version (${pjVer}); run \`npm install\` after bumping the version.`);
6141
+ // Also verify package.json `name` matches the new canonical name; if
6142
+ // the rename ever needs to happen again, this fails fast.
6143
+ assert.equal(pj.name, "@lcv-ideas-software/cross-review", `v4.0.2 / AUDIT-1: package.json .name must be "@lcv-ideas-software/cross-review" (post-v4.0.0 rename); got "${pj.name}".`);
6144
+ assert.equal(pl.name, "@lcv-ideas-software/cross-review", `v4.0.2 / AUDIT-1: package-lock.json .name must be "@lcv-ideas-software/cross-review"; got "${pl.name}".`);
6145
+ console.log("[smoke] package_version_consistency_test: PASS");
6146
+ }
6123
6147
  // v2.6.1 NOTE: smoke coverage for `peer.fallback.budget_blocked` and
6124
6148
  // `peer.moderation_recovery.budget_blocked` is intentionally NOT
6125
6149
  // included. These two gates use the same arithmetic shape as preflight