review-council 1.8.2 → 2.0.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.
Files changed (69) hide show
  1. package/README.md +145 -16
  2. package/dist/ci.js +7 -1
  3. package/dist/ci.js.map +1 -1
  4. package/dist/config/defaults.d.ts +40 -12
  5. package/dist/config/defaults.js +39 -16
  6. package/dist/config/defaults.js.map +1 -1
  7. package/dist/config/loader.js +15 -1
  8. package/dist/config/loader.js.map +1 -1
  9. package/dist/config/schema.d.ts +27 -0
  10. package/dist/config/schema.js +31 -0
  11. package/dist/config/schema.js.map +1 -1
  12. package/dist/consensus/deduper.d.ts +1 -1
  13. package/dist/consensus/deduper.js.map +1 -1
  14. package/dist/consensus/gating.d.ts +120 -0
  15. package/dist/consensus/gating.js +314 -0
  16. package/dist/consensus/gating.js.map +1 -0
  17. package/dist/consensus/parser.js +81 -0
  18. package/dist/consensus/parser.js.map +1 -1
  19. package/dist/consensus/types.d.ts +40 -1
  20. package/dist/consensus/voter.d.ts +1 -1
  21. package/dist/consensus/voter.js +17 -4
  22. package/dist/consensus/voter.js.map +1 -1
  23. package/dist/converge/attempt-budget.d.ts +57 -0
  24. package/dist/converge/attempt-budget.js +578 -0
  25. package/dist/converge/attempt-budget.js.map +1 -0
  26. package/dist/converge/finding-identity.d.ts +18 -0
  27. package/dist/converge/finding-identity.js +0 -0
  28. package/dist/converge/finding-identity.js.map +1 -0
  29. package/dist/converge/run-state.d.ts +104 -0
  30. package/dist/converge/run-state.js +267 -0
  31. package/dist/converge/run-state.js.map +1 -0
  32. package/dist/dispatch/adapter.d.ts +6 -0
  33. package/dist/dispatch/anthropic.js +3 -1
  34. package/dist/dispatch/anthropic.js.map +1 -1
  35. package/dist/dispatch/async-lane.d.ts +96 -0
  36. package/dist/dispatch/async-lane.js +264 -0
  37. package/dist/dispatch/async-lane.js.map +1 -0
  38. package/dist/dispatch/google.js +3 -1
  39. package/dist/dispatch/google.js.map +1 -1
  40. package/dist/dispatch/merge.js +3 -0
  41. package/dist/dispatch/merge.js.map +1 -1
  42. package/dist/dispatch/openai-compat.js +3 -1
  43. package/dist/dispatch/openai-compat.js.map +1 -1
  44. package/dist/dispatch/openai.js +3 -1
  45. package/dist/dispatch/openai.js.map +1 -1
  46. package/dist/dispatch/runner.d.ts +12 -0
  47. package/dist/dispatch/runner.js +78 -17
  48. package/dist/dispatch/runner.js.map +1 -1
  49. package/dist/dispatch/utils.d.ts +7 -0
  50. package/dist/dispatch/utils.js +17 -0
  51. package/dist/dispatch/utils.js.map +1 -1
  52. package/dist/index.js +607 -37
  53. package/dist/index.js.map +1 -1
  54. package/dist/models/seed.d.ts +44 -0
  55. package/dist/models/seed.js +175 -0
  56. package/dist/models/seed.js.map +1 -0
  57. package/dist/models/stats-store.d.ts +70 -0
  58. package/dist/models/stats-store.js +167 -0
  59. package/dist/models/stats-store.js.map +1 -0
  60. package/dist/output/github.js +3 -1
  61. package/dist/output/github.js.map +1 -1
  62. package/dist/output/markdown.js +20 -1
  63. package/dist/output/markdown.js.map +1 -1
  64. package/dist/output/progress.d.ts +51 -0
  65. package/dist/output/progress.js +116 -0
  66. package/dist/output/progress.js.map +1 -0
  67. package/dist/output/terminal.js +3 -1
  68. package/dist/output/terminal.js.map +1 -1
  69. package/package.json +3 -3
package/README.md CHANGED
@@ -153,17 +153,126 @@ rcl roles show <name> # Show system prompt and details for a role
153
153
 
154
154
  ---
155
155
 
156
+ ### `rcl converge-attempt`
157
+
158
+ Machine-enforced safety guard used by the generated `rcl-converge` skill.
159
+ Each call atomically and durably consumes one per-target attempt under the
160
+ repository's common Git directory, so the budget survives sessions, linked
161
+ worktrees, and abrupt system restarts.
162
+ New targets default to seven attempts, but an explicit invocation can set any
163
+ positive cap with `--max-attempts`. Omitting the flag on resume preserves the
164
+ persisted cap. At the boundary, RCL refuses before provider calls and directs
165
+ the workflow to ask the user; an approved continuation explicitly supplies a
166
+ higher cap.
167
+
168
+ At the skill level, `--max-attempts N` controls this machine launch budget.
169
+ The separate `--max-rounds N` flag caps evidence rounds and is machine-enforced
170
+ by `rcl converge-report` (default 3, valid range 2–5; rounds past 5 are
171
+ impossible under any flag).
172
+
173
+ Full-fleet reviewer completion is not required. For the generated
174
+ `rcl-converge` skill, let `N = stats.totalReviews`; a round is conclusive only
175
+ when `stats.successfulReviews >= max(2, ceil(2 × N / 3))`. Every timeout or
176
+ error must be disclosed, and a result below that threshold is inconclusive.
177
+
178
+ Exit code 2 means the configured cap was exhausted and explicit continuation
179
+ approval is required. Exit code 3 means attempt accounting itself failed
180
+ (state, lock, Git, filesystem, or another infrastructure error); increasing
181
+ the cap is not the remedy. With `--json`, failures are emitted as structured
182
+ JSON on stderr. If the attempt is durably recorded but final lock release
183
+ fails, the claim still succeeds with a warning so retrying cannot spend a
184
+ second slot for the same intended launch.
185
+
186
+ The short accounting mutex is fully written as a private owner file and then
187
+ published with an exclusive hard link, which cannot replace an existing file
188
+ or legacy directory. State contents and, where supported, their directory
189
+ entry are synced before a claim succeeds. A dead owner is isolated through a
190
+ token-scoped hard-link tombstone before another claimant can proceed; inode
191
+ checks make that tombstone safe to remove after reclamation. Invalid or legacy
192
+ ownerless locks fail closed, and timeout errors include the manual recovery
193
+ path. When upgrading,
194
+ an evidence ledger seeds only its highest recorded round: historical failed or
195
+ missing-report launches cannot be reconstructed, while every claim after the
196
+ machine state is created is counted exactly. The state remains a same-user
197
+ local safety mechanism, not a tamper-proof store: deliberately deleting
198
+ `.git/rcl-converge-attempts` is an explicit policy bypass.
199
+
200
+ ```bash
201
+ rcl converge-attempt --target owner-repo-123 # default/persisted cap
202
+ rcl converge-attempt --target owner-repo-123 --max-attempts 10 # explicit override
203
+ ```
204
+
205
+ ---
206
+
207
+ ### `rcl converge-report` and `rcl converge-verdict`
208
+
209
+ The cross-round memory of a converge run, persisted in
210
+ `.git/rcl-converge-runs/<target>.json`.
211
+
212
+ `converge-report` dedupes one round's report JSON against every prior round of
213
+ the run using a location-anchored finding identity (hash of file + category +
214
+ line bucket, plus a line-overlap matcher — titles are deliberately ignored:
215
+ models rephrase ~98% of them between rounds). Each finding is classified
216
+ `new`, `repeat`, `suppressed` (previously dismissed, no new corroboration —
217
+ cannot re-gate), or `regating` (previously dismissed but now backed by ≥2
218
+ models or critical severity). The same call enforces the evidence-round cap:
219
+ default 3, `--max-rounds` accepts 2–5, and rounds past 5 are impossible. Exit
220
+ code 2 is the cap consent boundary; exit 3 is a state failure.
221
+
222
+ `converge-verdict` records triage outcomes per finding identity —
223
+ `--fixed <key>` and `--dismissed '<key>=<reason>'` (both repeatable) — which
224
+ drives later-round suppression and accrues the per-model precision history.
225
+
226
+ ```bash
227
+ rcl converge-report --target rcl-30 --report report-r2.json --round 2 --json
228
+ rcl converge-verdict --target rcl-30 --round 2 \
229
+ --fixed 9787c6ea72ae778c --dismissed 'd2baf9675eb450f0=guard already exists'
230
+ ```
231
+
232
+ ---
233
+
234
+ ### `rcl models`
235
+
236
+ The tool's own memory of which reviewers earn their seat. Every reviewer call
237
+ and every `converge-verdict` outcome accrues in a cross-run store at `~/.rcl`
238
+ (`RCL_DATA_DIR` overrides; deliberately not under /tmp, so history survives
239
+ converge-state cleanup). `rcl models` prints, per model over a trailing 90-day
240
+ window: triage precision (share of its supported findings the converge loop
241
+ verified and fixed rather than dismissed), triage volume, call volume,
242
+ dead-call rate, p50 latency — and the consensus **weight** the model earns:
243
+ `0.5 + precision`, clamped to [0.5, 1.5], neutral (1) below 20 triaged
244
+ outcomes. Weights scale each model's consensus vote in report confidence and
245
+ in consensus gating, so persistently noisy models lose gating power
246
+ automatically; the applied weights are visible per finding
247
+ (`consensus.weightedScore` / `consensus.modelWeights`) and per run
248
+ (`stats.modelWeights`) in the report JSON.
249
+
250
+ ```bash
251
+ rcl models # table over the trailing 90 days
252
+ rcl models show --window 30 --json
253
+ rcl models seed --from ~/recovered-rcl-artifacts # backfill from reports + converge ledgers
254
+ ```
255
+
256
+ ---
257
+
156
258
  ## Config File
157
259
 
158
260
  Place `.review-council.yml` in your project root (or any parent directory). All fields are optional.
159
261
 
160
262
  ```yaml
161
- # Models to use (provider-prefixed names)
263
+ # Blocking council (provider-prefixed names) — every round waits for these.
264
+ # Shown here: the actual defaults. Keep slow/aggregator-routed models out of
265
+ # this list; give them an async seat instead.
162
266
  models:
163
- - anthropic/claude-opus-4-6
164
- - openai/gpt-5.4
165
- - google/gemini-2.5-pro
166
- # Any model on https://openrouter.ai — keep the vendor segment after the prefix
267
+ - anthropic/claude-fable-5
268
+ - openai/gpt-5.6-sol
269
+ - google/gemini-3.6-flash
270
+
271
+ # Async bonus reviewers — fired with each round, never awaited. Results that
272
+ # have arrived by the next round of the same target are merged into that
273
+ # round's dedup and marked `async` in the report JSON.
274
+ # Any model on https://openrouter.ai works — keep the vendor segment after the prefix.
275
+ asyncModels:
167
276
  - openrouter/moonshotai/kimi-k3
168
277
 
169
278
  # Default roles to run
@@ -194,6 +303,17 @@ thresholds:
194
303
  dedupeLineWindow: 5 # lines within which findings are merged
195
304
  jaccardThreshold: 0.3 # weighted title+description similarity threshold for dedup
196
305
 
306
+ # Convergence gating: which findings block convergence / CI (RCL-23).
307
+ # A finding gates when multi-model, critical, or unrefuted by a cheap
308
+ # verification pass; refuted single-model claims stay in the report but
309
+ # stop blocking. Report JSON marks every finding with gating.reason
310
+ # (consensus | critical | verified | none).
311
+ gating:
312
+ mode: verified-consensus # or all-findings (legacy: severity alone decides)
313
+ minModels: 2 # distinct models for consensus gating
314
+ verificationModel: google/gemini-3.6-flash # direct-API only
315
+ verificationTimeout: 60000 # ms for the single batched refutation call
316
+
197
317
  # Output defaults
198
318
  output:
199
319
  markdown: true
@@ -202,7 +322,11 @@ output:
202
322
 
203
323
  # Concurrency and reliability
204
324
  concurrency: 6
205
- timeout: 600000 # ms per model call (reasoning models need headroom on real diffs)
325
+ timeout: 300000 # ms per blocking model call (every direct-API p90 is under 260s)
326
+ asyncTimeout: 900000 # ms per async-lane call (slow reasoning models get headroom; nothing waits on them)
327
+ # quorumFraction: 0.75 # round closes once this share of calls has completed; stragglers
328
+ # are canceled and recorded (core `models` are never canceled).
329
+ # Default: exactly 2/3 — leave unset for that; 1 disables.
206
330
  maxRetries: 3
207
331
 
208
332
  # Reasoning budget for providers that support it (currently OpenRouter).
@@ -225,6 +349,12 @@ spec: SPEC.md
225
349
 
226
350
  Supported config file names: `.review-council.yml`, `.review-council.yaml`, `.review-council.json`, `review-council.config.js`.
227
351
 
352
+ Before dispatch, RCL prints the expanded reviewer × chunk call count,
353
+ concurrency, wave count, timeout, and timeout-bound queue estimate. Interactive
354
+ runs update the spinner; redirected runs emit periodic heartbeat and bounded
355
+ completion lines with status counters, so a long queue is distinguishable from
356
+ a hung process.
357
+
228
358
  ---
229
359
 
230
360
  ## How Consensus Works
@@ -254,16 +384,15 @@ For the full algorithm, see [CONSENSUS_V2_SPEC.md](./CONSENSUS_V2_SPEC.md).
254
384
  | `RCL_DEBUG` | Set to any value to print full error stack traces |
255
385
  | `RCL_NO_HARNESS_KEYS` | Set to any value to disable Harness key distribution (below) |
256
386
 
257
- The default model fleet includes OpenRouter-hosted models. If `OPENROUTER_API_KEY`
258
- is not set, those entries are dropped from the defaults with a warning naming the
259
- surviving fleet (models you configure explicitly still fail loudly instead). The
260
- default secondary list is entirely OpenRouter-hosted, so without the key it is
261
- empty and specialist roles are spread across the primary models only — set
262
- `secondaryModels:` explicitly if you want a secondary tier without OpenRouter. Note that when the key is set,
263
- default reviews send diff and context content to OpenRouter — an aggregator and
264
- an additional data processor beyond the direct model providers — as well as to
265
- Anthropic, OpenAI, and Google. Configure `models:` explicitly if that matters
266
- for your repository.
387
+ The default blocking council is direct-API only (Anthropic, OpenAI, Google) —
388
+ no default review round ever waits on an OpenRouter-routed call. The default
389
+ async lane holds one OpenRouter-hosted bonus reviewer (`kimi-k3`); if
390
+ `OPENROUTER_API_KEY` is not set, it is dropped from the defaults with a warning
391
+ (models you configure explicitly still fail loudly instead). Note that when the
392
+ key is set, default reviews send diff and context content to OpenRouter — an
393
+ aggregator and an additional data processor beyond the direct model providers —
394
+ as well as to Anthropic, OpenAI, and Google. Configure `models:` and
395
+ `asyncModels:` explicitly if that matters for your repository.
267
396
 
268
397
  ### Key distribution via Harness
269
398
 
package/dist/ci.js CHANGED
@@ -13,7 +13,13 @@ export function evaluateCiGate(result) {
13
13
  message: `CI: 0/${result.stats.totalReviews} reviewers succeeded — nothing was reviewed. Exiting with code 1.`,
14
14
  };
15
15
  }
16
- const blocking = result.findings.filter((f) => f.severity === 'critical' || f.severity === 'important');
16
+ // Gating-annotated findings (RCL-23) block on their gating reason —
17
+ // consensus, critical, or verified — so a refuted single-model claim no
18
+ // longer fails CI. Legacy reports without annotations keep the pure
19
+ // severity gate.
20
+ const blocking = result.findings.filter((f) => f.gating
21
+ ? f.gating.reason !== 'none'
22
+ : f.severity === 'critical' || f.severity === 'important');
17
23
  if (blocking.length > 0) {
18
24
  return {
19
25
  exitCode: 1,
package/dist/ci.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ci.js","sourceRoot":"","sources":["../src/ci.ts"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,IAAI,MAAM,CAAC,KAAK,CAAC,iBAAiB,KAAK,CAAC,EAAE,CAAC;QACzC,OAAO;YACL,QAAQ,EAAE,CAAC;YACX,OAAO,EAAE,SAAS,MAAM,CAAC,KAAK,CAAC,YAAY,mEAAmE;SAC/G,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CACrC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,QAAQ,KAAK,WAAW,CAC/D,CAAC;IACF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,QAAQ,EAAE,CAAC;YACX,OAAO,EAAE,OAAO,QAAQ,CAAC,MAAM,kDAAkD;SAClF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AACzB,CAAC"}
1
+ {"version":3,"file":"ci.js","sourceRoot":"","sources":["../src/ci.ts"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,IAAI,MAAM,CAAC,KAAK,CAAC,iBAAiB,KAAK,CAAC,EAAE,CAAC;QACzC,OAAO;YACL,QAAQ,EAAE,CAAC;YACX,OAAO,EAAE,SAAS,MAAM,CAAC,KAAK,CAAC,YAAY,mEAAmE;SAC/G,CAAC;IACJ,CAAC;IAED,oEAAoE;IACpE,wEAAwE;IACxE,oEAAoE;IACpE,iBAAiB;IACjB,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC5C,CAAC,CAAC,MAAM;QACN,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM;QAC5B,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,QAAQ,KAAK,WAAW,CAC5D,CAAC;IACF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,QAAQ,EAAE,CAAC;YACX,OAAO,EAAE,OAAO,QAAQ,CAAC,MAAM,kDAAkD;SAClF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AACzB,CAAC"}
@@ -1,12 +1,27 @@
1
- /** SOTA models — run the general role + participate in specialized round-robin */
2
- export declare const DEFAULT_MODELS: readonly ["anthropic/claude-fable-5", "openai/gpt-5.6-sol", "google/gemini-3.6-flash", "openrouter/moonshotai/kimi-k3"];
1
+ /**
2
+ * Core (blocking) council — every round waits for these and only these.
3
+ * Direct-API models only: the RCL-21 audit (922 rounds, 15,268 calls) found
4
+ * the OpenRouter wing at p50 7–9.5 min per call with 19–39% dead calls,
5
+ * last-finisher in 97.6% of rounds; the direct trio answers in 45–70 s with
6
+ * ~0% dead calls. Replaying the corpus with this trio alone drops the median
7
+ * round from 14.4 to 2.0 min while 91% of multi-model findings still surface.
8
+ */
9
+ export declare const DEFAULT_MODELS: readonly ["anthropic/claude-fable-5", "openai/gpt-5.6-sol", "google/gemini-3.6-flash"];
10
+ /**
11
+ * Async bonus reviewers — fired with the round but never awaited; whatever
12
+ * has arrived by the NEXT round's dedup is merged then, marked async in the
13
+ * report. kimi-k3 keeps a seat here because it has the council's best
14
+ * corroboration rate (62%) but is ~6× slower than the core trio.
15
+ */
16
+ export declare const DEFAULT_ASYNC_MODELS: readonly ["openrouter/moonshotai/kimi-k3"];
3
17
  /**
4
18
  * Secondary models — specialized round-robin only, no general role.
5
- * Chosen for training-lineage diversity: with the four SOTA models above,
6
- * every default voter comes from a different lab, so cross-model consensus
7
- * always reflects independent confirmation.
19
+ * Empty by default since RCL-25: qwen3.8-max, deepseek-v4-flash and grok-4.5
20
+ * were removed after the audit (24–39% dead calls, worst finding-cost in the
21
+ * council). Before any slow model earns a seat back, try it via its direct
22
+ * provider API instead of OpenRouter and re-measure.
8
23
  */
9
- export declare const DEFAULT_SECONDARY_MODELS: readonly ["openrouter/qwen/qwen3.8-max", "openrouter/deepseek/deepseek-v4-flash-0731", "openrouter/x-ai/grok-4.5"];
24
+ export declare const DEFAULT_SECONDARY_MODELS: readonly [];
10
25
  export declare const DEFAULT_THRESHOLDS: {
11
26
  readonly minConsensusScore: 0.4;
12
27
  readonly minConfidence: 0.2;
@@ -23,13 +38,26 @@ export declare const DEFAULT_THRESHOLDS: {
23
38
  readonly jaccardThreshold: 0.3;
24
39
  };
25
40
  /**
26
- * Reasoning-heavy models (kimi-k3, qwen3.8-max, deepseek-v4, grok-4.5)
27
- * routinely need several minutes to review a real diff: at 120s the entire
28
- * OpenRouter wing of the default fleet timed out, and at 300s most
29
- * specialist runs still did (successful calls measured 217–291s, with no
30
- * headroom). Dogfooded on this repo's own diffs.
41
+ * Blocking-path per-call timeout. Every direct-API model's p90 in the
42
+ * RCL-21 corpus is under 260 s, so 300 s only ever cuts models that should
43
+ * not be on the blocking path in the first place (slow reasoning models
44
+ * belong in the async lane, which has its own longer cap below).
45
+ */
46
+ export declare const DEFAULT_TIMEOUT_MS = 300000;
47
+ /**
48
+ * Quorum round closure (RCL-26): a round closes once this fraction of its
49
+ * planned calls has completed; outstanding non-core calls are canceled and
50
+ * recorded. ⅔ matches the converge reviewer-health threshold, so a round
51
+ * closed exactly at quorum can still be conclusive. Corpus replay: −51%
52
+ * total review wall even with the pre-RCL-25 roster. Set to 1 to disable.
53
+ */
54
+ export declare const DEFAULT_QUORUM_FRACTION: number;
55
+ /**
56
+ * Per-call timeout for the async (non-blocking) lane. Async reviewers are
57
+ * slow by definition — kimi-k3's p50 is 7–9.5 min — and nothing waits on
58
+ * them, so they get more headroom than the blocking council.
31
59
  */
32
- export declare const DEFAULT_TIMEOUT_MS = 600000;
60
+ export declare const DEFAULT_ASYNC_TIMEOUT_MS = 900000;
33
61
  export declare const DEFAULT_MAX_RETRIES = 3;
34
62
  /**
35
63
  * Reasoning budget for OpenRouter-hosted models. Unbounded, they spend the
@@ -1,21 +1,31 @@
1
- /** SOTA models — run the general role + participate in specialized round-robin */
1
+ /**
2
+ * Core (blocking) council — every round waits for these and only these.
3
+ * Direct-API models only: the RCL-21 audit (922 rounds, 15,268 calls) found
4
+ * the OpenRouter wing at p50 7–9.5 min per call with 19–39% dead calls,
5
+ * last-finisher in 97.6% of rounds; the direct trio answers in 45–70 s with
6
+ * ~0% dead calls. Replaying the corpus with this trio alone drops the median
7
+ * round from 14.4 to 2.0 min while 91% of multi-model findings still surface.
8
+ */
2
9
  export const DEFAULT_MODELS = [
3
10
  'anthropic/claude-fable-5',
4
11
  'openai/gpt-5.6-sol',
5
12
  'google/gemini-3.6-flash',
6
- 'openrouter/moonshotai/kimi-k3',
7
13
  ];
14
+ /**
15
+ * Async bonus reviewers — fired with the round but never awaited; whatever
16
+ * has arrived by the NEXT round's dedup is merged then, marked async in the
17
+ * report. kimi-k3 keeps a seat here because it has the council's best
18
+ * corroboration rate (62%) but is ~6× slower than the core trio.
19
+ */
20
+ export const DEFAULT_ASYNC_MODELS = ['openrouter/moonshotai/kimi-k3'];
8
21
  /**
9
22
  * Secondary models — specialized round-robin only, no general role.
10
- * Chosen for training-lineage diversity: with the four SOTA models above,
11
- * every default voter comes from a different lab, so cross-model consensus
12
- * always reflects independent confirmation.
23
+ * Empty by default since RCL-25: qwen3.8-max, deepseek-v4-flash and grok-4.5
24
+ * were removed after the audit (24–39% dead calls, worst finding-cost in the
25
+ * council). Before any slow model earns a seat back, try it via its direct
26
+ * provider API instead of OpenRouter and re-measure.
13
27
  */
14
- export const DEFAULT_SECONDARY_MODELS = [
15
- 'openrouter/qwen/qwen3.8-max',
16
- 'openrouter/deepseek/deepseek-v4-flash-0731',
17
- 'openrouter/x-ai/grok-4.5',
18
- ];
28
+ export const DEFAULT_SECONDARY_MODELS = [];
19
29
  export const DEFAULT_THRESHOLDS = {
20
30
  minConsensusScore: 0.4,
21
31
  minConfidence: 0.2,
@@ -32,13 +42,26 @@ export const DEFAULT_THRESHOLDS = {
32
42
  jaccardThreshold: 0.3,
33
43
  };
34
44
  /**
35
- * Reasoning-heavy models (kimi-k3, qwen3.8-max, deepseek-v4, grok-4.5)
36
- * routinely need several minutes to review a real diff: at 120s the entire
37
- * OpenRouter wing of the default fleet timed out, and at 300s most
38
- * specialist runs still did (successful calls measured 217–291s, with no
39
- * headroom). Dogfooded on this repo's own diffs.
45
+ * Blocking-path per-call timeout. Every direct-API model's p90 in the
46
+ * RCL-21 corpus is under 260 s, so 300 s only ever cuts models that should
47
+ * not be on the blocking path in the first place (slow reasoning models
48
+ * belong in the async lane, which has its own longer cap below).
49
+ */
50
+ export const DEFAULT_TIMEOUT_MS = 300_000;
51
+ /**
52
+ * Quorum round closure (RCL-26): a round closes once this fraction of its
53
+ * planned calls has completed; outstanding non-core calls are canceled and
54
+ * recorded. ⅔ matches the converge reviewer-health threshold, so a round
55
+ * closed exactly at quorum can still be conclusive. Corpus replay: −51%
56
+ * total review wall even with the pre-RCL-25 roster. Set to 1 to disable.
57
+ */
58
+ export const DEFAULT_QUORUM_FRACTION = 2 / 3;
59
+ /**
60
+ * Per-call timeout for the async (non-blocking) lane. Async reviewers are
61
+ * slow by definition — kimi-k3's p50 is 7–9.5 min — and nothing waits on
62
+ * them, so they get more headroom than the blocking council.
40
63
  */
41
- export const DEFAULT_TIMEOUT_MS = 600_000;
64
+ export const DEFAULT_ASYNC_TIMEOUT_MS = 900_000;
42
65
  export const DEFAULT_MAX_RETRIES = 3;
43
66
  /**
44
67
  * Reasoning budget for OpenRouter-hosted models. Unbounded, they spend the
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,0BAA0B;IAC1B,oBAAoB;IACpB,yBAAyB;IACzB,+BAA+B;CACvB,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,6BAA6B;IAC7B,4CAA4C;IAC5C,0BAA0B;CAClB,CAAC;AAEX,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,iBAAiB,EAAE,GAAG;IACtB,aAAa,EAAE,GAAG;IAClB,gBAAgB,EAAE,CAAC;IACnB;;;;;;;;OAQG;IACH,gBAAgB,EAAE,GAAG;CACb,CAAC;AAEX;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAC1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,QAAQ,CAAC;AACjD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,UAAU;IACV,WAAW;IACX,OAAO;IACP,SAAS;CACD,CAAC;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,QAAQ,EAAE,GAAG;IACb,IAAI,EAAE,GAAG;IACT,MAAM,EAAE,GAAG;IACX,GAAG,EAAE,GAAG;CACA,CAAC"}
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,0BAA0B;IAC1B,oBAAoB;IACpB,yBAAyB;CACjB,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,+BAA+B,CAAU,CAAC;AAE/E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAW,CAAC;AAEpD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,iBAAiB,EAAE,GAAG;IACtB,aAAa,EAAE,GAAG;IAClB,gBAAgB,EAAE,CAAC;IACnB;;;;;;;;OAQG;IACH,gBAAgB,EAAE,GAAG;CACb,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAE1C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,GAAG,CAAC,CAAC;AAE7C;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,OAAO,CAAC;AAChD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,QAAQ,CAAC;AACjD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,UAAU;IACV,WAAW;IACX,OAAO;IACP,SAAS;CACD,CAAC;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,QAAQ,EAAE,GAAG;IACb,IAAI,EAAE,GAAG;IACT,MAAM,EAAE,GAAG;IACX,GAAG,EAAE,GAAG;CACA,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { cosmiconfig } from 'cosmiconfig';
2
2
  import { ConfigSchema } from './schema.js';
3
- import { DEFAULT_MODELS, DEFAULT_SECONDARY_MODELS, DEFAULT_THRESHOLDS, DEFAULT_TIMEOUT_MS, DEFAULT_MAX_RETRIES, DEFAULT_CONCURRENCY, DEFAULT_REASONING_EFFORT, } from './defaults.js';
3
+ import { DEFAULT_MODELS, DEFAULT_SECONDARY_MODELS, DEFAULT_ASYNC_MODELS, DEFAULT_THRESHOLDS, DEFAULT_TIMEOUT_MS, DEFAULT_ASYNC_TIMEOUT_MS, DEFAULT_QUORUM_FRACTION, DEFAULT_MAX_RETRIES, DEFAULT_CONCURRENCY, DEFAULT_REASONING_EFFORT, } from './defaults.js';
4
4
  /**
5
5
  * A config file was found but could not be used. Never silently recover
6
6
  * from this: falling back to defaults would send code to cloud providers
@@ -80,8 +80,11 @@ function buildDefaultConfig() {
80
80
  return {
81
81
  models: dropOpenRouterDefaultsWithoutKey(DEFAULT_MODELS, 'models'),
82
82
  secondaryModels: dropOpenRouterDefaultsWithoutKey(DEFAULT_SECONDARY_MODELS, 'secondary models'),
83
+ asyncModels: dropOpenRouterDefaultsWithoutKey(DEFAULT_ASYNC_MODELS, 'async models'),
83
84
  thresholds: { ...DEFAULT_THRESHOLDS },
84
85
  timeout: DEFAULT_TIMEOUT_MS,
86
+ asyncTimeout: DEFAULT_ASYNC_TIMEOUT_MS,
87
+ quorumFraction: DEFAULT_QUORUM_FRACTION,
85
88
  maxRetries: DEFAULT_MAX_RETRIES,
86
89
  concurrency: DEFAULT_CONCURRENCY,
87
90
  reasoningEffort: DEFAULT_REASONING_EFFORT,
@@ -94,6 +97,13 @@ function mergeWithDefaults(config) {
94
97
  (config.models
95
98
  ? []
96
99
  : dropOpenRouterDefaultsWithoutKey(DEFAULT_SECONDARY_MODELS, 'secondary models')),
100
+ // Same containment rule as secondaryModels: an explicit `models` list
101
+ // means "send code to exactly these providers" — default async reviewers
102
+ // must not leak the diff to a provider the user configured away from.
103
+ asyncModels: config.asyncModels ??
104
+ (config.models
105
+ ? []
106
+ : dropOpenRouterDefaultsWithoutKey(DEFAULT_ASYNC_MODELS, 'async models')),
97
107
  roles: config.roles,
98
108
  reviewers: config.reviewers,
99
109
  customRoles: config.customRoles,
@@ -101,8 +111,12 @@ function mergeWithDefaults(config) {
101
111
  ...DEFAULT_THRESHOLDS,
102
112
  ...config.thresholds,
103
113
  },
114
+ // Resolved (and validated) at use by resolveGatingConfig.
115
+ gating: config.gating,
104
116
  output: config.output,
105
117
  timeout: config.timeout ?? DEFAULT_TIMEOUT_MS,
118
+ asyncTimeout: config.asyncTimeout ?? DEFAULT_ASYNC_TIMEOUT_MS,
119
+ quorumFraction: config.quorumFraction ?? DEFAULT_QUORUM_FRACTION,
106
120
  maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,
107
121
  concurrency: config.concurrency ?? DEFAULT_CONCURRENCY,
108
122
  reasoningEffort: config.reasoningEffort ?? DEFAULT_REASONING_EFFORT,
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
@@ -42,9 +42,25 @@ export declare const ReasoningEffortSchema: z.ZodEnum<{
42
42
  medium: "medium";
43
43
  high: "high";
44
44
  }>;
45
+ /**
46
+ * Convergence gating (RCL-23). `verified-consensus` (default): a finding
47
+ * gates only when multi-model, critical, or unrefuted by the verification
48
+ * pass. `all-findings` restores the legacy behavior where every
49
+ * critical/important finding gates.
50
+ */
51
+ export declare const GatingSchema: z.ZodObject<{
52
+ mode: z.ZodOptional<z.ZodEnum<{
53
+ "verified-consensus": "verified-consensus";
54
+ "all-findings": "all-findings";
55
+ }>>;
56
+ minModels: z.ZodOptional<z.ZodNumber>;
57
+ verificationModel: z.ZodOptional<z.ZodString>;
58
+ verificationTimeout: z.ZodOptional<z.ZodNumber>;
59
+ }, z.core.$strip>;
45
60
  export declare const ConfigSchema: z.ZodObject<{
46
61
  models: z.ZodOptional<z.ZodArray<z.ZodString>>;
47
62
  secondaryModels: z.ZodOptional<z.ZodArray<z.ZodString>>;
63
+ asyncModels: z.ZodOptional<z.ZodArray<z.ZodString>>;
48
64
  roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
49
65
  reviewers: z.ZodOptional<z.ZodArray<z.ZodObject<{
50
66
  model: z.ZodString;
@@ -62,6 +78,15 @@ export declare const ConfigSchema: z.ZodObject<{
62
78
  dedupeLineWindow: z.ZodOptional<z.ZodNumber>;
63
79
  jaccardThreshold: z.ZodOptional<z.ZodNumber>;
64
80
  }, z.core.$strip>>;
81
+ gating: z.ZodOptional<z.ZodObject<{
82
+ mode: z.ZodOptional<z.ZodEnum<{
83
+ "verified-consensus": "verified-consensus";
84
+ "all-findings": "all-findings";
85
+ }>>;
86
+ minModels: z.ZodOptional<z.ZodNumber>;
87
+ verificationModel: z.ZodOptional<z.ZodString>;
88
+ verificationTimeout: z.ZodOptional<z.ZodNumber>;
89
+ }, z.core.$strip>>;
65
90
  output: z.ZodOptional<z.ZodObject<{
66
91
  terminal: z.ZodOptional<z.ZodBoolean>;
67
92
  json: z.ZodOptional<z.ZodBoolean>;
@@ -72,6 +97,8 @@ export declare const ConfigSchema: z.ZodObject<{
72
97
  belowThresholdAppendix: z.ZodOptional<z.ZodBoolean>;
73
98
  }, z.core.$strip>>;
74
99
  timeout: z.ZodOptional<z.ZodNumber>;
100
+ asyncTimeout: z.ZodOptional<z.ZodNumber>;
101
+ quorumFraction: z.ZodOptional<z.ZodNumber>;
75
102
  maxRetries: z.ZodOptional<z.ZodNumber>;
76
103
  concurrency: z.ZodOptional<z.ZodNumber>;
77
104
  reasoningEffort: z.ZodOptional<z.ZodEnum<{
@@ -38,15 +38,46 @@ export const OutputSchema = z.object({
38
38
  belowThresholdAppendix: z.boolean().optional(),
39
39
  });
40
40
  export const ReasoningEffortSchema = z.enum(['low', 'medium', 'high']);
41
+ /**
42
+ * Convergence gating (RCL-23). `verified-consensus` (default): a finding
43
+ * gates only when multi-model, critical, or unrefuted by the verification
44
+ * pass. `all-findings` restores the legacy behavior where every
45
+ * critical/important finding gates.
46
+ */
47
+ export const GatingSchema = z.object({
48
+ mode: z.enum(['verified-consensus', 'all-findings']).optional(),
49
+ /** Distinct supporting models that make a finding consensus-gated. */
50
+ minModels: z.number().int().min(2).optional(),
51
+ /** Direct-API model for the refutation pass (openrouter/ is rejected). */
52
+ verificationModel: z.string().optional(),
53
+ /** Per-call timeout (ms) for the verification pass. */
54
+ verificationTimeout: z.number().positive().optional(),
55
+ });
41
56
  export const ConfigSchema = z.object({
42
57
  models: z.array(z.string()).optional(),
43
58
  secondaryModels: z.array(z.string()).optional(),
59
+ /**
60
+ * Async bonus reviewers — fired with each round, never awaited. Results
61
+ * that have arrived by the next round's dedup are merged then and marked
62
+ * async in the report. Never on the blocking path.
63
+ */
64
+ asyncModels: z.array(z.string()).optional(),
44
65
  roles: z.array(z.string()).optional(),
45
66
  reviewers: z.array(ReviewerPairSchema).optional(),
46
67
  customRoles: z.array(RoleConfigSchema).optional(),
47
68
  thresholds: ThresholdsSchema.optional(),
69
+ gating: GatingSchema.optional(),
48
70
  output: OutputSchema.optional(),
49
71
  timeout: z.number().positive().optional(),
72
+ /** Per-call timeout (ms) for the async lane; defaults higher than `timeout`. */
73
+ asyncTimeout: z.number().positive().optional(),
74
+ /**
75
+ * Fraction of planned calls whose completion closes a review round;
76
+ * outstanding non-core calls are canceled. 1 disables early closure.
77
+ * Floored at ⅔ so a closed round can still pass the converge
78
+ * reviewer-health check (successful ≥ ⅔ of total).
79
+ */
80
+ quorumFraction: z.number().min(2 / 3).max(1).optional(),
50
81
  maxRetries: z.number().int().nonnegative().optional(),
51
82
  concurrency: z.number().int().positive().optional(),
52
83
  /** Reasoning budget for providers that support it (currently OpenRouter). */
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
@@ -37,5 +37,5 @@ export declare function hasOpposingSentiment(a: Finding, b: Finding, specificOnl
37
37
  * (the ungated code-council version added one).
38
38
  */
39
39
  export declare function conceptSimilarity(a: Finding, b: Finding): number;
40
- export declare function linesOverlap(a: Finding, b: Finding, window: number): boolean;
40
+ export declare function linesOverlap(a: Pick<Finding, 'startLine' | 'endLine'>, b: Pick<Finding, 'startLine' | 'endLine'>, window: number): boolean;
41
41
  export declare function deduplicateFindings(reviews: ModelReview[], jaccardThreshold?: number, lineWindow?: number, minConsensusScore?: number): DeduplicatedGroup[];