@mrciphersmith/keryx 0.3.83 → 0.3.85

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrciphersmith/keryx",
3
- "version": "0.3.83",
3
+ "version": "0.3.85",
4
4
  "description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -326,6 +326,12 @@ recording them is one copy rather than four decisions.
326
326
  remove.
327
327
  - **Do not ask the operator which model to use per dispatch.** Asking every time
328
328
  is what made adaptive selection impossible.
329
+ - **An interactive review round shows the computed plan once.** It is the third
330
+ start question of `review-orchestrator` (`model_strategy: ask`, the
331
+ interactive default): the complexity the round's signals give, each role's tier
332
+ and the model it resolves to here. The operator accepts it, takes every role to
333
+ `deep`, or sets it — for that round. An unattended round dispatches the
334
+ computed plan without asking (`adaptive`).
329
335
  - Never write a concrete model name into a skill, a rule, a dispatch template, or
330
336
  the resolution code.
331
337
  - Take the candidate set from runtime detection. Never from a literal list of
@@ -433,14 +433,14 @@ Before accepting implementation:
433
433
  1. Run focused tests for touched scope.
434
434
  2. Run `code-verifier`.
435
435
  3. Run `keryx health run` when Code Health is enabled.
436
- 4. Check the bounds, then run `review-orchestrator` with relevant domains.
437
-
436
+ 4. Check the bounds, then run `review-orchestrator` with relevant domains — in this session,
437
+ never handed whole to one subagent: one without a dispatch tool returns `STATUS: BLOCKED`.
438
438
  ```bash
439
439
  keryx review budget --spent <usd-so-far> --outstanding <subagents you already have in flight>
440
440
  ```
441
-
442
441
  A non-zero exit means the spend ceiling (3 USD by default) has been reached:
443
- **stop and ask the user** rather than dispatching another fan-out.
442
+ **stop and ask the user** rather than dispatching another fan-out — never shrink the fan-out to fit.
443
+ Dispatch prompts point at sources (files, SHAs, the PR) and never paraphrase a contract.
444
444
 
445
445
  `--outstanding` is the part that matters here. `review-orchestrator`
446
446
  dispatches reviewers in parallel and runs *nested* under this skill, and
@@ -368,3 +368,138 @@ inside) the findings they annotate — same separation the finding schema
368
368
  itself draws between a reviewer's claim (`severity`, `problem`, …) and what
369
369
  became of it (`disposition`), which a reviewer never states and this pass
370
370
  does not either.
371
+
372
+ ## Start questions (Step 5) — once per round, after the context pack
373
+
374
+ The round asks its operator three questions, once, in one interaction, after
375
+ Step 1 (context pack) and Step 3 (scope) — never before them: the counterpart
376
+ question cannot be answered well until the context pack has looked for the
377
+ other side. On Claude Code that is one `AskUserQuestion` call carrying the
378
+ three questions; on any other host, the lettered prompt below. An unattended
379
+ round (job pipeline, trigger, schedule) asks nothing, applies the defaults and
380
+ records them under `### How this review was run`.
381
+
382
+ 1. **Reviewers** — default `--all`: every reviewer the engine detects plus every
383
+ project and convention reviewer its gates admit. Narrowing is an explicit
384
+ choice (tests only, one domain, a custom list). Flags the caller passed
385
+ answer this question and skip it. Convention reviewers are part of this
386
+ question; the job setting `convention_reviewers` still answers it in a
387
+ `job-orchestrator` pipeline.
388
+ 2. **Counterpart** — the other side of every contract the diff consumes or
389
+ mirrors: the backend for a frontend change, the frontend and other consumers
390
+ for a backend change. Before asking, the context pack looks for it:
391
+ endpoints, DTOs and rules the diff calls or mirrors, a paired PR
392
+ (`gh pr list --repo <counterpart> --search <branch-or-feature>`), the
393
+ producer at a freshly fetched SHA. The question shows what was found —
394
+ "no link found" included — and one checkbox, **verify the counterpart**, ON
395
+ by default even when nothing was found. Verification is not limited to a
396
+ paired PR: the other side's contracts and logic are re-read at a pinned SHA
397
+ every round. When the round cannot locate that code itself (repository,
398
+ handler, validator), it asks the operator where it is; it never records
399
+ `state: unavailable` on its own. Skipping verification takes a reason, and
400
+ the reason goes in the report.
401
+ 3. **Models** — the complexity the round already holds signals for (changed
402
+ files and lines, the risk class from Depth floor below, domains, scope B),
403
+ the per-role tier `keryx review tier` prints for each planned dispatch, and
404
+ the model each tier resolves to on this host. Choices: accept the plan (the
405
+ default), all `deep`, or custom. The plan is shown once per round, never per
406
+ dispatch (`rules/core/model-selection.mdc`). Skills, rules and this file name
407
+ tiers only; model ids appear in the rendered question and the report.
408
+
409
+ ```text
410
+ Context: <PR or branch>, <N> files / <N> lines, <domains>; risk: <class>
411
+
412
+ 1) Reviewers A) --all (default) B) tests only C) <domain> only D) choose
413
+ 2) Counterpart found: <endpoints, rules, paired PR — or "no link found">
414
+ A) verify <backend|frontend> (default) B) skip — give a reason
415
+ 3) Models complexity: <low|medium|high>; <role>: <tier> → <model>, …
416
+ A) accept (default) B) all deep C) custom
417
+
418
+ > answers (default: 1A 2A 3A)
419
+ ```
420
+
421
+ ## Depth floor — a gating round does not degrade
422
+
423
+ A round is **gating** when its verdict lets a change move: the review step of a
424
+ flow (`flow-orchestrator` Phase 3), a pre-merge or pre-ship review, a
425
+ re-request after fixes. A gating round runs the composition the start questions
426
+ selected.
427
+
428
+ - **No dispatch tool, no review.** A host that cannot dispatch subagents — this
429
+ engine running inside a subagent is the usual case — returns
430
+ `STATUS: BLOCKED` with reason `nested_dispatch_unavailable` and no verdict.
431
+ It does not review the diff alone and call that a round. Measured (flow 405):
432
+ a single-agent round on a 150-line frontend PR wrote "did not dispatch any
433
+ sub-reviewers", approved it with two cosmetic minors, and the next human round
434
+ filed six real findings, every one reachable from the diff and the backend at
435
+ a pinned SHA.
436
+ - **Size never lowers depth below the risk class.** The budget table sizes the
437
+ context, not the depth.
438
+ - **High-risk includes a client-side mirror of a server rule** — validation,
439
+ limits, permissions, uniqueness, reserved names — beside the triggers the main
440
+ file lists.
441
+
442
+ ## Counterpart verification — the contract is enumerated, not summarised
443
+
444
+ For an **input rule** the diff mirrors or depends on (what the server accepts
445
+ for a name, a value, a role), the `cross_repo` entry records the producer's
446
+ complete check set in `checks` and how that set was found in
447
+ `enumeration_method` (`review-context.schema.json`):
448
+
449
+ - every check the producer runs on that input: validators, restriction
450
+ utilities, uniqueness queries, reserved-name registries, and the storage bound
451
+ (column width, index, a downstream identifier);
452
+ - for each check: its `source` (`file:line` at the pinned SHA), whether it is
453
+ case-sensitive, and the `paths` it runs on (create, update, rename, copy,
454
+ import, move, …).
455
+
456
+ Put these rules in every reviewer dispatch:
457
+
458
+ - **The facts are a starting point, not a boundary.** A reviewer may read the
459
+ producer itself and file what the entry missed.
460
+ - **"The producer has no limit" is a question, not a fact.** Find what bounds
461
+ the value — that is where an over-long or unexpected value fails, usually as a
462
+ server error.
463
+ - **Build the surfaces × checks matrix**: every surface that sends the input
464
+ against every check, each cell `same`, `missing`, `stricter` or `looser`.
465
+ `missing` is a refusal the user meets late; `stricter` blocks legal input; a
466
+ check the producer lacks but storage enforces is a producer defect — filed as
467
+ pre-existing, or fixed by a paired change.
468
+ - **Every refusal the producer can return is shown where the user can act on
469
+ it** — next to the field, not as a generic toast.
470
+
471
+ ## Round obligations — always on, never asked
472
+
473
+ These apply to every round without a question:
474
+
475
+ 1. **Enumerate before concluding.** Every caller and surface of a changed value
476
+ is found with `keryx ctx rg` or gdgraph, and the query is recorded — never
477
+ taken from the diff's own list.
478
+ 2. **Quantified claims are checked.** "Every", "all", "only" and "never" in the
479
+ PR body or the commits are compared with that enumeration; an over-claim is a
480
+ `minor` finding, the same class as the description-versus-diff rule.
481
+ 3. **A verified-clean line names its sites.** Each line of the `Verified clean`
482
+ lane names the files, sites or commands it rests on; "the frontend does the
483
+ same" without them is not verified.
484
+ 4. **A pre-existing defect gets a disposition.** Every pre-existing defect the
485
+ round finds in the contract the change touches is recorded with one: fixed in
486
+ the change (small, same contract), named out of scope in the PR body, or a
487
+ recommended issue. Found and dropped is the failure this rule exists for.
488
+ 5. **Red on the parent, per test.** Every added test fails with the parent
489
+ commit's production files restored; the run is the evidence.
490
+ 6. **A threaded value is pinned per site.** A parameter, key or prop passed at
491
+ several render sites is asserted at each site, or centralised so there is
492
+ one.
493
+ 7. **One rule, one implementation.** The same check implemented twice is a
494
+ finding, even while both copies agree.
495
+ 8. **"Do not re-raise" needs a record.** A dispatch may exclude an item only by
496
+ citing the PR comment, issue or decision that settled it — never a whole
497
+ surface ("X has no test; covered elsewhere").
498
+
499
+ ### Runtime research-completion ledger
500
+
501
+ New managed packages carry `research.json`, initially pending. Before closing a round, enumerate unresolved observations from raw reviewers and the changed-file/consumer census, assign stable obligation IDs, and investigate them. Run the probe or inspect the relevant source and assertions: merely proposing a check does not resolve it. An unexecuted probe is not a verified claim.
502
+
503
+ Supply the ledger using `keryx review ingest --research <ledger.json>` alongside the report and findings. Format: `version: 1`, `scopeReviewed: true`, `rawReconciled: true`, `obligations: [...]`. Each obligation requires `id`, `source`, `question`, `status`, `evidence`, `reason`. Status `finding` additionally requires `finding` pointing to exactly one canonical finding ID or global ID. Other terminal statuses are `refuted` and `out-of-scope`, both requiring evidence and reason. Preserve distinct scenarios when deduplicating. Assert census/reconciliation flags only after performing those checks; an empty obligations array is valid only if the actual census found no open observations.
504
+
505
+ Open, deferred and unverifiable obligations block completion. If context, runtime or budget prevents resolution, retain the obligation and report incomplete; do not relabel it refuted or out-of-scope. Completion and the flow gate re-read the ledger even when the manifest says closed. Legacy packages without this artifact remain compatible, not proven complete. This gate validates the declared ledger, not the truth or exhaustiveness of its census; independent source/raw audits remain necessary.
@@ -18,15 +18,11 @@ metadata:
18
18
  compatible_harnesses: "cursor,codex,zed,opencode,claude"
19
19
  license: "MIT"
20
20
  ---
21
-
22
21
  # Review Orchestrator
23
-
24
22
  Entry point for the entire review domain. This skill is a thin router: it detects scope,
25
23
  dispatches specialized reviewers in parallel, then consolidates their findings into one
26
24
  unified report sorted by severity. It does not perform any review logic itself.
27
-
28
25
  ---
29
-
30
26
  ## Workflow
31
27
 
32
28
  ```
@@ -38,7 +34,7 @@ Review Orchestrator Progress:
38
34
  - [ ] Step 3: Build the bounded scope with `keryx review scope` — never by hand
39
35
  - [ ] Step 3b: On a deep round, compute scope B with `keryx review blast-radius` — never by browsing — and KEEP the `--json` file; `review ingest --blast-radius <file>` is refused without it
40
36
  - [ ] Step 4: Parse flags / auto-detect domain from scope
41
- - [ ] Step 5: Ask user to confirm optional convention reviewers (legacy/profile reviewers are flag-only, never prompted)
37
+ - [ ] Step 5: Start questions, once, after Steps 1 and 3 — reviewers (default `--all`), counterpart verification (default on), model plan; unattended takes the defaults (SKILL.detail.md § "Start questions"; legacy/profile reviewers stay flag-only)
42
38
  - [ ] Step 5c: When `review.jev.select` is on, run `keryx review jev-select` over the finalized candidate set and drop its `skip` decisions from Wave A/B — see "Reviewer selection with Jev"
43
39
  - [ ] Step 6: Plan sub-agent dispatch and token budgets, and compute each dispatch's model with `keryx review tier` — never by hand
44
40
  - [ ] Step 7: Stage 1 gate - spec compliance check (if issue/task provided)
@@ -144,7 +140,7 @@ which of its inputs were recovered and which were never written down.
144
140
  | `context_doc` | string | no | Path to job context document (e.g., `.metaproject/jobs/<job>/ai/context.md`). |
145
141
  | `context_mode` | string | no | `none`, `light`, or `full`. Default: `light` for PR review, `none` for small path reviews. `full` may call `context-collector` before dispatch. |
146
142
  | `token_budget` | object | no | Optional budget controls: `{total, per_reviewer, diff_max_chars, file_max_chars}`. |
147
- | `model_strategy` | string | no | `ask` or `adaptive`. Default: `adaptive`; the model per dispatch is computed by `keryx review tier`, never chosen by hand (see Step 6). |
143
+ | `model_strategy` | string | no | `ask` or `adaptive`. Default: `ask` in an interactive round (shown once as Start question 3), `adaptive` unattended; the model per dispatch is computed by `keryx review tier`, never chosen by hand (see Step 6). |
148
144
  | `managed_review` | object | no | Optional managed review mode: `{mode, target, target_ref, flow_id, reviewers}` where mode is `lightweight`, `attach-review`, `review-flow`, or `ingest`. |
149
145
  | `verification_mode` | string | no | `off`, `annotate`, or `filter`. Default `annotate` — verdicts are recorded and nothing is removed. See Wave C. |
150
146
  | `pr_comments` | object | no | `{enabled, max_replies_total, max_sentences_per_reply}`. Defaults: enabled when a PR exists, `30`, `2`. Collect every round, reply once at the end. See External PR comments. |
@@ -522,9 +518,9 @@ The rule that follows for reviewers, and that belongs in the dispatch prompt:
522
518
  > producer disproves, and a defect missed because the producer's actual default was
523
519
  > assumed rather than read.
524
520
 
525
- If the other repository is not available to you, record it as
526
- `state: unavailable` in `cross_repo` and leave the dependent findings at `info`.
527
- An unavailable producer is a result. Assuming one is not.
521
+ If you cannot locate the producer, ask the operator where it is (Start question 2); record `state: unavailable` only when it cannot be read, and leave the dependent findings at `info`.
522
+ An unavailable producer is a result. Assuming one is not. An input rule records the producer's full check set and is verified every round,
523
+ paired PR or not — SKILL.detail.md § "Counterpart verification".
528
524
 
529
525
  A finding whose evidence lives in the producer sets `repo` on the finding itself.
530
526
  `file` and `line` alone name a path in the repository under review, so without
@@ -600,8 +596,8 @@ Context modes:
600
596
  - `full`: for large/high-risk PRs or user request. Invoke `context-collector` first, then pass the resulting context path and summary to reviewers.
601
597
 
602
598
  High-risk triggers for `full` recommendation:
603
- - Auth, permissions, API contracts, migrations, shared core, state management, graph/flow, security, performance-critical paths.
604
- - More than 20 changed source files or more than 2,000 changed lines.
599
+ - Auth, permissions, API contracts, a client-side mirror of a server rule (validation, limit, permission, uniqueness, reserved names), migrations, shared core, state management, graph/flow, security, performance-critical paths.
600
+ - More than 20 changed source files or more than 2,000 changed lines. Size never lowers depth below the risk class (SKILL.detail.md § "Depth floor").
605
601
  - Missing or ambiguous linked requirements.
606
602
 
607
603
  If `full` context would be useful but was not explicitly requested, ask once:
@@ -655,8 +651,8 @@ whether it is computed:
655
651
 
656
652
  | `model_strategy` | Behavior |
657
653
  |---|---|
658
- | `ask` | Present the `keryx review tier` model plan once before dispatch. |
659
- | `adaptive` (default) | Dispatch on the computed model directly; record the chosen model per reviewer in the final report metadata. |
654
+ | `ask` (default, interactive) | Present the `keryx review tier` model plan once before dispatch — Start question 3; the operator may accept it, take all `deep`, or set it. |
655
+ | `adaptive` (default, unattended) | Dispatch on the computed model directly; record the chosen model per reviewer in the final report metadata. |
660
656
 
661
657
  Rules:
662
658
  - Never write a model id into a dispatch by hand — paste the `model` block `keryx review tier` printed.
@@ -1052,30 +1048,30 @@ what to do with it: `SKILL.detail.md` beside this file, section "Project-local
1052
1048
  reviewers". A description saying another entry point dispatches it is its
1053
1049
  author's routing note, not a restriction.
1054
1050
 
1055
- ### Convention Reviewer Confirmation
1051
+ ### Start questions (Step 5)
1056
1052
 
1057
- When convention reviewers are auto-detected and the user did not explicitly pass
1058
- `--project-conventions`, `--frontend-conventions`, `--testing-practices`, `--core-boundaries`,
1059
- `--flow-graph`, or `--all`, ask before dispatch:
1053
+ Ask once, after the context pack (Step 1) and the scope (Step 3), in one interaction — one
1054
+ `AskUserQuestion` call on Claude Code, the lettered prompt in SKILL.detail.md elsewhere:
1060
1055
 
1061
- ```text
1062
- I found local convention reviewers that match this review scope:
1056
+ 1. **Reviewers** — default `--all`; detected convention reviewers are included. Narrowing
1057
+ (tests only, one domain, custom) is the operator's explicit choice. Passed flags answer it.
1058
+ Legacy/profile reviewers stay flag-only and are never prompted.
1059
+ 2. **Counterpart** — show what the context pack found for the other side of the contract
1060
+ (endpoints, mirrored rules, a paired PR, or "no link found") and a checkbox to verify it,
1061
+ ON by default even with no link. If the round cannot locate that code, it asks where it is.
1062
+ Verification is not limited to a paired PR: contracts and logic are re-read every round.
1063
+ 3. **Models** — complexity, the per-role tier from `keryx review tier`, the model each tier
1064
+ resolves to on this host; accept (default), all `deep`, or custom. Once per round.
1063
1065
 
1064
- A) Include all detected convention reviewers (recommended)
1065
- B) Choose individually
1066
- C) Skip convention reviewers for this run
1066
+ Unattended rounds ask nothing: `--all`, counterpart verified, computed models — recorded in
1067
+ `### How this review was run`. In a `job-orchestrator` pipeline the job setting
1068
+ `convention_reviewers` still answers question 1 (unresolved: include all detected reviewers
1069
+ and record that choice in the review scope).
1067
1070
 
1068
- Detected:
1069
- - review-frontend-conventions: <why detected, or omit if not detected>
1070
- - review-testing-practices: <why detected, or omit if not detected>
1071
- - review-core-boundaries: <why detected, or omit if not detected>
1072
- - review-flow-graph: <why detected, or omit if not detected>
1073
- ```
1074
-
1075
- If the user chooses B, list only detected reviewers and ask for names to include/exclude.
1076
- If the user does not answer and the review is part of an automated `job-orchestrator` pipeline,
1077
- use the job setting `convention_reviewers` (default: `"ask"`; if still unresolved, include all
1078
- detected reviewers and record that choice in the review scope).
1071
+ A gating round runs what these answers selected; a host that cannot dispatch subagents
1072
+ returns `STATUS: BLOCKED` (`nested_dispatch_unavailable`) instead of reviewing alone. Every
1073
+ round also carries the always-on obligations — SKILL.detail.md § "Depth floor",
1074
+ § "Counterpart verification", § "Round obligations".
1079
1075
 
1080
1076
  ### Reviewer selection with Jev (`jev-select`) — advisory, before dispatch (Step 5c)
1081
1077
 
@@ -1185,7 +1181,11 @@ whoever reads the merge commit a year later reads the body. When `review.jev.con
1185
1181
 
1186
1182
  ## Dispatching Reviewers
1187
1183
 
1188
- Dispatch selected reviewers in parallel when independent. Use waves when token budget is tight or when one reviewer needs another result:
1184
+ **Dispatch integrity is a completion prerequisite.** Use one distinct execution per selected reviewer role; do not combine multiple roles in one child or count sections of one response as independent runs. When budgets are tight, use sequential waves, not role batching. Resolve every project-rule anchor before dispatch; missing rules require context recovery or a blocked result, never silently skipped checks. A read-only pass cannot discharge executable obligations: dispatch a capable execution pass and retain its evidence. Partial scope and NEEDS_CONTEXT remain incomplete until rerun over the outstanding scope.
1185
+
1186
+ New managed packages declare `reviewerDispatch: "research.json"`. Alongside the research ledger, provide `dispatch: { version: 1, selected: [...], unresolvedRules: [], runs: [...] }`. Preserve the actual computed reviewer inventory. Each run has `reviewer`, unique `executionId`, `status: "complete"`, `scopeComplete: true`, `rawEvidence`, nonempty `ruleEvidence`, and boolean `executionRequired`. Required execution needs nonempty `executionEvidence` (command/output references); a source-only scope requires `executionReason`. Do not fabricate IDs or mark truncated responses complete. Runtime validates these declarations at closure and the flow gate, not their truth: independently audit evidence and inventory before freezing. Legacy artifact absence is compatibility, not proof of a correct launch. Research closure is mandatory: see [Runtime research-completion ledger](SKILL.detail.md#runtime-research-completion-ledger).
1187
+
1188
+ Dispatch selected reviewers in parallel when independent — this engine dispatches them itself; a host without a dispatch tool returns `STATUS: BLOCKED` (`nested_dispatch_unavailable`) and never reviews alone. Use waves when token budget is tight or when one reviewer needs another result:
1189
1189
 
1190
1190
  1. Wave A - core correctness/risk reviewers: logic, architecture, security/highload when selected.
1191
1191
  2. Wave B - domain reviewers: frontend/backend/testing/convention reviewers filtered to relevant files. `review-jev-rules` (flow 330), `review-jev-risk`/`review-jev-scenarios` (flow 332), `review-jev-docs`/`review-jev-comments` (flow 333), `review-jev-contract` (flow 335) also run here, CLI-engine not sub-agent, `"engine": "jev"` in `keryx review reviewers --json`, gated on their own opt-in and a resolvable Jev/OpenRouter credential — measured verdicts per reviewer (keep off by default, experimental, etc.) in `SKILL.detail.md` § "CLI-engine reviewers".
@@ -205,6 +205,51 @@
205
205
  "null"
206
206
  ],
207
207
  "description": "The last round the producer was re-read. An entry with `state: open` that was pinned in round 1 and never revalidated is stale by round 3: a parallel pull request is precisely the thing that moves between rounds."
208
+ },
209
+ "checks": {
210
+ "type": "array",
211
+ "minItems": 1,
212
+ "description": "For an input rule the diff mirrors or depends on (what the producer accepts for a name, a value, a role): the producer's COMPLETE check set, not a summary of it. Flow 405: a dispatch that carried only the producer's regex let two rounds approve a change that missed a case-sensitive prefix check, a case-sensitive uniqueness check and a column-width bound. The set is a starting point for reviewers, never a boundary.",
213
+ "items": {
214
+ "type": "object",
215
+ "required": [
216
+ "check",
217
+ "source",
218
+ "paths"
219
+ ],
220
+ "properties": {
221
+ "check": {
222
+ "type": "string",
223
+ "minLength": 1,
224
+ "description": "What the producer refuses, in one line — including a storage bound such as a column width."
225
+ },
226
+ "source": {
227
+ "type": "string",
228
+ "minLength": 1,
229
+ "description": "`file:line` at the pinned ref."
230
+ },
231
+ "case_sensitive": {
232
+ "type": [
233
+ "boolean",
234
+ "null"
235
+ ]
236
+ },
237
+ "paths": {
238
+ "type": "array",
239
+ "minItems": 1,
240
+ "items": {
241
+ "type": "string"
242
+ },
243
+ "description": "The producer paths this check runs on — create, update, rename, copy, import, move, …"
244
+ }
245
+ },
246
+ "additionalProperties": true
247
+ }
248
+ },
249
+ "enumeration_method": {
250
+ "type": "string",
251
+ "minLength": 1,
252
+ "description": "How `checks` was found to be complete — the producer entry points read and the searches run. Required whenever `checks` is present."
208
253
  }
209
254
  },
210
255
  "allOf": [
@@ -241,6 +286,18 @@
241
286
  "pr"
242
287
  ]
243
288
  }
289
+ },
290
+ {
291
+ "if": {
292
+ "required": [
293
+ "checks"
294
+ ]
295
+ },
296
+ "then": {
297
+ "required": [
298
+ "enumeration_method"
299
+ ]
300
+ }
244
301
  }
245
302
  ],
246
303
  "additionalProperties": true
@@ -160,7 +160,7 @@ a tool, skill or model is unavailable; use `none` only when the run proves none.
160
160
  - **Subagents:** <dispatched subagents, their reviewer roles and actual models; or none when confirmed, otherwise not recorded>.
161
161
  - **Fallback:** <reviewer> via `general-purpose` because <native agent type unavailable | no bundled agent>. Or `none`.
162
162
  - **Not run:** <reviewer> — <short reason>. Or `none`.
163
- - **Selection:** <auto-detected scope | explicit flags | optional groups the user picked>
163
+ - **Selection:** <explicit flags | start questions: reviewers <`--all` | narrowed to …>, counterpart <verified at <sha> | skipped: reason>, models <accepted | all deep | custom> | defaults (unattended)>
164
164
  - **Verification:** <mode>. Confirmed N, refuted N, unverifiable N, unverified N. Removed N (always 0 outside `filter`).
165
165
  - **Stage counts:** pre-filter dropped <files>/<blocks>/<lines> (or `not recorded`). Retained N.
166
166
  - **Context:** <job/context path, or none>