@mrciphersmith/keryx 0.3.94 → 0.3.109

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.94",
3
+ "version": "0.3.109",
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": {
@@ -242,7 +242,7 @@ Write or update:
242
242
  - `context.md` - compact links and findings, not raw dumps;
243
243
  - `plan.md` - chosen approach and trade-offs;
244
244
  - `tasks.md` - task definitions grouped by context, test, implement, review, docs;
245
- - `acceptance-criteria.md` - verifiable `ACn` criteria.
245
+ - `acceptance-criteria.md` - verifiable `ACn` criteria, each ending in one marker: [verify: exec `<command>`] or [verify: invariant `<command>`] (a backticked command), [verify: judged] (a human checks: live run, operator decision, text quality), or [verify: none — <reason>]. If a kind is unclear, ask the operator ONE question listing the criteria with proposed kinds, before `flow freeze`. Behaviour with an external dependency or a failure path gets its own failure-scenario criterion with an observable result (saved, error visible, retry creates no duplicate); a check claimed to catch a regression carries `· sensitive: revert|mutation|failure-scenario` and the confirm note carries `evidence: <ref>` (revert/mutation run or failure-scenario reference).
246
246
 
247
247
  ### A verification step in the plan is a task, not a sentence
248
248
 
@@ -283,13 +283,12 @@ did not exist and 24 completed flows shipped with an open task:
283
283
  keryx flow task done <id> <Tn> --disposition skipped --reason "<why it was not needed>"
284
284
  ```
285
285
 
286
- Read the `tasks` line in the `flow complete` output. If it says `skipped`, the
287
- gate did not run and the task list is yours to verify by hand.
286
+ Read the `tasks` line in the `flow complete` output. If it says `skipped`, the gate did not run and the task list is yours to verify by hand.
288
287
 
289
- Then freeze and start:
288
+ Then freeze and start (`--yes`: the operator already answered the kinds question, so the freeze must not prompt):
290
289
 
291
290
  ```bash
292
- keryx flow freeze <id>
291
+ keryx flow freeze <id> --yes
293
292
  keryx flow start <id>
294
293
  ```
295
294
 
@@ -692,3 +691,4 @@ Stop and re-read this skill if you are thinking:
692
691
  | "The worker returned BLOCKED twice — faster if I implement this task myself." | The implementer never self-accepts and the orchestrator never implements. Block the flow, escalate one concise question, then unblock and re-dispatch. Doing the work here erases the boundary the whole flow model rests on. |
693
692
  | "Verification is described in the plan, so it will happen." | A verification step in the plan is a task, not a sentence. If it is not a task with a status, nothing records whether it ran, and the flow reaches `implemented` with an unrun gate. |
694
693
  | "The review fan-out is cheap, so the budget check can wait." | `keryx review budget --spent … --outstanding …` gates the fan-out, and `review-orchestrator` nests under this skill where keryx cannot see the in-flight subagents. Skipping the check means the cap bounds nothing. |
694
+ | "I'll set the verification kind later." | An `unclassified` criterion cannot become data afterwards without a recorded rewrite: `keryx flow ac update <id> --criterion ACn --text "…" --reason "<why>"`. Put the `[verify: …]` marker on every criterion before `flow freeze`. |
@@ -63,22 +63,15 @@ Architecture Review Progress:
63
63
 
64
64
  See shared script: `.metaproject/skills/gdskills/shared/git-merge-base.md`
65
65
 
66
- Run the script to determine `BASE_SHA`, then collect the diff:
66
+ Review scope: **changes introduced in the current branch since merge-base only**.
67
+ Do not review pre-existing architectural problems unless they are directly touched by the diff.
67
68
 
69
+ **Supplied text first.** When the payload carries `slices`, `context_files`, `diff` or `file_contents`, review exactly that text: a read-only child has no shell, so run no git command and never rebuild the diff. Only with none supplied, collect it:
68
70
  ```bash
69
- # Changed files — used for stack auto-detection
70
- git diff --name-status "${BASE_SHA}"
71
-
72
- # Full diff — used for finding exact violations
73
- git diff "${BASE_SHA}"
74
-
75
- # Untracked new files
76
- git ls-files --others --exclude-standard
71
+ git diff --name-status "${BASE_SHA}" && git diff "${BASE_SHA}" && git ls-files --others --exclude-standard
72
+ # explicit range: <FROM_SHA>..<TO_SHA> in place of "${BASE_SHA}"
77
73
  ```
78
74
 
79
- Review scope: **changes introduced in the current branch since merge-base only**.
80
- Do not review pre-existing architectural problems unless they are directly touched by the diff.
81
-
82
75
  ---
83
76
 
84
77
  ## Stack Auto-Detection
@@ -63,18 +63,14 @@ See shared script: `.metaproject/skills/gdskills/shared/git-merge-base.md`
63
63
 
64
64
  Run that script to determine `BASE_SHA` before collecting the diff.
65
65
 
66
- ```bash
67
- # Default mode — all changes from merge-base to working tree
68
- git diff --name-only "${BASE_SHA}"
69
- git diff "${BASE_SHA}"
66
+ Only review files changed in scope. Do not comment on legacy code outside the diff.
70
67
 
71
- # Explicit range mode
72
- git diff --name-only <FROM_SHA>..<TO_SHA>
73
- git diff <FROM_SHA>..<TO_SHA>
68
+ **Supplied text first.** When the payload carries `slices`, `context_files`, `diff` or `file_contents`, review exactly that text: a read-only child has no shell, so run no git command and never rebuild the diff. Only with none supplied, collect it:
69
+ ```bash
70
+ git diff --name-status "${BASE_SHA}" && git diff "${BASE_SHA}" && git ls-files --others --exclude-standard
71
+ # explicit range: <FROM_SHA>..<TO_SHA> in place of "${BASE_SHA}"
74
72
  ```
75
73
 
76
- Only review files changed in scope. Do not comment on legacy code outside the diff.
77
-
78
74
  ---
79
75
 
80
76
  ## Review Checklist
@@ -67,18 +67,16 @@ Clean Code Review Progress:
67
67
 
68
68
  See shared script: `.metaproject/skills/gdskills/shared/git-merge-base.md`
69
69
 
70
- Run the script to determine `BASE_SHA`, then collect the diff:
71
-
72
- ```bash
73
- git diff --name-status "${BASE_SHA}"
74
- git diff "${BASE_SHA}"
75
- git ls-files --others --exclude-standard
76
- ```
77
-
78
70
  Review scope: **only code introduced or modified in this branch since merge-base**.
79
71
  Pre-existing problems in unchanged lines are out of scope unless a change directly
80
72
  worsens them.
81
73
 
74
+ **Supplied text first.** When the payload carries `slices`, `context_files`, `diff` or `file_contents`, review exactly that text: a read-only child has no shell, so run no git command and never rebuild the diff. Only with none supplied, collect it:
75
+ ```bash
76
+ git diff --name-status "${BASE_SHA}" && git diff "${BASE_SHA}" && git ls-files --others --exclude-standard
77
+ # explicit range: <FROM_SHA>..<TO_SHA> in place of "${BASE_SHA}"
78
+ ```
79
+
82
80
  ---
83
81
 
84
82
  ## Iron Laws
@@ -102,25 +102,10 @@ See shared script: `.metaproject/skills/gdskills/shared/git-merge-base.md`
102
102
 
103
103
  Run the script from that file to determine `MERGE_BASE` (`BASE_SHA`) and `SCOPE` before proceeding.
104
104
 
105
- ### Commands to collect the review slice
106
-
107
- ```bash
108
- git status
109
- git log --oneline "${BASE_SHA}..HEAD"
110
- git diff --stat --name-status "${BASE_SHA}..HEAD"
111
- git diff "${BASE_SHA}..HEAD"
112
-
113
- # Include uncommitted changes (default mode):
114
- git diff --stat --name-status "${BASE_SHA}"
115
- git diff "${BASE_SHA}"
116
- git ls-files --others --exclude-standard
117
- ```
118
-
119
- For explicit hash/range mode:
120
-
105
+ **Supplied text first.** When the payload carries `slices`, `context_files`, `diff` or `file_contents`, review exactly that text: a read-only child has no shell, so run no git command and never rebuild the diff. Only with none supplied, collect it:
121
106
  ```bash
122
- git diff --stat --name-status <FROM_SHA>..<TO_SHA>
123
- git diff <FROM_SHA>..<TO_SHA>
107
+ git diff --name-status "${BASE_SHA}" && git diff "${BASE_SHA}" && git ls-files --others --exclude-standard
108
+ # explicit range: <FROM_SHA>..<TO_SHA> in place of "${BASE_SHA}"
124
109
  ```
125
110
 
126
111
  ---
@@ -68,17 +68,15 @@ High-Load Review Progress:
68
68
 
69
69
  See shared script: `.metaproject/skills/gdskills/shared/git-merge-base.md`
70
70
 
71
- Run the script to determine `BASE_SHA`, then collect the diff:
71
+ Review scope: **changes introduced in the current branch since merge-base only**.
72
+ Pre-existing problems in unchanged lines are out of scope unless the diff makes them worse.
72
73
 
74
+ **Supplied text first.** When the payload carries `slices`, `context_files`, `diff` or `file_contents`, review exactly that text: a read-only child has no shell, so run no git command and never rebuild the diff. Only with none supplied, collect it:
73
75
  ```bash
74
- git diff --name-status "${BASE_SHA}"
75
- git diff "${BASE_SHA}"
76
- git ls-files --others --exclude-standard
76
+ git diff --name-status "${BASE_SHA}" && git diff "${BASE_SHA}" && git ls-files --others --exclude-standard
77
+ # explicit range: <FROM_SHA>..<TO_SHA> in place of "${BASE_SHA}"
77
78
  ```
78
79
 
79
- Review scope: **changes introduced in the current branch since merge-base only**.
80
- Pre-existing problems in unchanged lines are out of scope unless the diff makes them worse.
81
-
82
80
  ---
83
81
 
84
82
  ## Iron Laws
@@ -66,22 +66,15 @@ Logic Review Progress:
66
66
 
67
67
  See shared script: `.metaproject/skills/gdskills/shared/git-merge-base.md`
68
68
 
69
- Run the script to determine `BASE_SHA`, then collect the diff:
69
+ Review scope: **changes introduced in the current branch since merge-base only**.
70
+ Do not review unrelated files.
70
71
 
72
+ **Supplied text first.** When the payload carries `slices`, `context_files`, `diff` or `file_contents`, review exactly that text: a read-only child has no shell, so run no git command and never rebuild the diff. Only with none supplied, collect it:
71
73
  ```bash
72
- # Committed + local changes (default mode)
73
- git diff --name-status "${BASE_SHA}"
74
- git diff "${BASE_SHA}"
75
- git ls-files --others --exclude-standard
76
-
77
- # Committed only (explicit range mode)
78
- git diff --name-status <FROM>..<TO>
79
- git diff <FROM>..<TO>
74
+ git diff --name-status "${BASE_SHA}" && git diff "${BASE_SHA}" && git ls-files --others --exclude-standard
75
+ # explicit range: <FROM_SHA>..<TO_SHA> in place of "${BASE_SHA}"
80
76
  ```
81
77
 
82
- Review scope: **changes introduced in the current branch since merge-base only**.
83
- Do not review unrelated files.
84
-
85
78
  ---
86
79
 
87
80
  ## Stage 1 — Spec Compliance (run first when issue/task is provided)
@@ -418,6 +418,22 @@ Context: <PR or branch>, <N> files / <N> lines, <domains>; risk: <class>
418
418
  > answers (default: 1A 2A 3A)
419
419
  ```
420
420
 
421
+ ## Policy questions mid-round — the `policy` tag and the arbiter
422
+
423
+ A question the round raises with `ask_user` about scope, budget, partial coverage, a smaller slice, slice order or
424
+ which option to take carries a `policy` tag: `{ kind, facts }`. `kind` is one of `scope`, `budget`,
425
+ `option_choice`, `partial_coverage`, `smaller_slice`, `slice_order`. `facts` holds only numbers and booleans that
426
+ describe the **recommended** option (for `budget`: `budgetUsedPercent`, `raisesBudget`; the guide lists the rest).
427
+ Nothing from the diff, a finding or a PR comment goes into the facts: the arbiter builds its prompt from the tag and
428
+ nothing else, so a quote there is dropped, and a question that carries one is shaped by outside content, which the
429
+ arbiter does not decide.
430
+
431
+ In `review-auto` and in an unattended run the review arbiter answers a tagged question from its numbered rules and
432
+ writes `arbiter.log` into the package; `allow` takes the recommended option, `deny` and `escalate` refuse in an
433
+ unattended run and ask the operator in `review-auto`. An untagged question keeps the old behaviour. A release, a
434
+ merge, a credential, a destructive action or a publish is never tagged and never the arbiter's: those ask a person,
435
+ and in an unattended run they are refused. In an interactive `ask` round the operator is asked, tagged or not.
436
+
421
437
  ## Depth floor — a gating round does not degrade
422
438
 
423
439
  A round is **gating** when its verdict lets a change move: the review step of a
@@ -498,7 +514,7 @@ These apply to every round without a question:
498
514
 
499
515
  ### Runtime research-completion ledger
500
516
 
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.
517
+ 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. `keryx review ledger build` writes the ledger from the saved raw results and turns each raw finding into an obligation; it closes one only from a matching canonical finding or a `--dispositions` entry that carries evidence and a reason, and it leaves everything else `unresolved`.
502
518
 
503
519
  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
520
 
@@ -75,17 +75,17 @@ Publish this checklist with `plan_set` under the ids `step-0`…`step-14` once,
75
75
  - Use the reviewer's exact `subagent_type`. If the runtime has no such type, use `general-purpose` and name the reviewer's `SKILL.md` path in the prompt. Neither available: that reviewer is `BLOCKED`.
76
76
  - Prompts carry pointers, not pasted files — the diff, the SHAs, the PR, the schema paths — and never paraphrase a contract.
77
77
  - A reply is a result only if it starts with a `STATUS:` line and carries a `REVIEW_RESULT` block matching `reviewer-finding.schema.json`; anything else is `BLOCKED`.
78
- - The model comes from `keryx review tier` (Step 6).
78
+ - The model comes from `keryx review tier` (Step 6). On `spawn_subagent` pass its tier as `model_tier` on every reviewer — `review-verifier` and simple reviewers `light`, normal `standard`, complex `deep`; an omitted tier runs the child on your own model.
79
79
 
80
80
  ## Shell host (keryx shell, or any host with no file-reading subagent) — mandatory
81
81
 
82
82
  A reviewer on this host cannot open a path: its file tool reads inside its working directory only, and a pointer it cannot follow becomes a round spent on a refusal. So the pointer rule above does not apply; the TEXT travels in the prompt, in slices small enough to finish.
83
83
 
84
84
  0. **Publish the plan before anything else.** Your first tool call is `plan_set` with `step-0`…`step-14` all `pending`. A shell turn that has open plan items is continued by the host; a turn that ends on a text reply is over, and a message saying the review "cannot be honestly completed" ends the run with nothing reviewed. Never end the turn while a step is `pending` or `in_progress`: mark it `blocked` only with a cause you cannot fix with a command, and otherwise keep working. Step 6a then updates this plan rather than creating it.
85
- 1. **Slice first.** `keryx review slice --ref <base> --out <dir>` after `keryx review scope`. It writes `slice-NN.diff` files of at most 150000 bytes each and a `manifest.json`; ledgers (csv, lockfiles, snapshots, generated files) are listed under `omissions` with a reason — list them in the report as not reviewed, never as clean.
85
+ 1. **Slice first.** `keryx review slice --ref <base> --out <dir>` after `keryx review scope`. It writes `slice-NN.diff` files of at most 150000 bytes each and a `manifest.json` carrying a wave budget (`--wave-bytes`, default 60000 and never below the slice ceiling): what ONE reviewer dispatch may total, so a role owning many slices is dispatched in slice waves that each fit the child deadline. On a large diff pass a small `--max-bytes` (for example 18000) and `--wave-bytes` (for example 54000) so no wave outruns a reviewer's five minutes; ledgers (csv, lockfiles, snapshots, generated files) are listed under `omissions` with a reason — list them in the report as not reviewed, never as clean.
86
86
  2. **Slices travel by `context_files`.** Write the slices under the project (the default `--out`, `.metaproject/data/review/slices`, already is) and pass each reviewer its slice paths in `spawn_subagent`'s `context_files`: the host copies the text into that reviewer's task, so you never paste or retype a slice. Put the `slices` ids in its reviewer-input. A dispatch that names a git range but no slice and no `context_files` leaves the reviewer with nothing to read — that is `BLOCKED`, not a review.
87
- 3. **Check before dispatch.** `keryx review dispatch-check --payload <file> --manifest <dir>/manifest.json` for the wave; exit 1 means a payload names no slice, is over the ceiling, or breaks `reviewer-input.schema.json`. Fix it; do not dispatch around it.
88
- 4. **One batch.** Dispatch the whole wave — up to 10 reviewers — in one message, not one at a time. Give each reviewer `max_rounds` of at least 40 (the default); a reviewer that spends its rounds reading the skill and the schema returns nothing. **Incomplete means retry once, then Not run.** On `INCOMPLETE` or `BLOCKED`, `keryx review retry-plan --manifest <dir>/manifest.json --result <result.json>` decides: it cuts the assigned slices in half and names the one retry, and after that prints the `- **Not run:** …` line to paste into the report. An unfinished reviewer is never counted as a clean pass. **Persist every result.** Pass each reviewer `save_result_to: .metaproject/data/review/raw/<reviewer>.txt`: the host writes its full final text there, so `review complete` has raw evidence even after the transcript is cut. Build `research.json` from those files — the ledger fields from the detail file plus one more key, `dispatch: {version:1, selected:[names], unresolvedRules:[], runs:[{reviewer, executionId:<its sub:… id>, status:"complete", scopeComplete:true, rawEvidence:<saved path>, ruleEvidence:[<rule paths>], executionRequired:false, executionReason:<why>}]}` — and ingest once with `--research`, into the package `review start` created. A refused `review complete` names what is missing: fix that with a command and run it again; it is never `blocked`. `--head` wants a SHA (`git rev-parse HEAD`), not `HEAD`.
87
+ 3. **Check before dispatch.** `keryx review dispatch-check --payload <file> --manifest <dir>/manifest.json` for the wave; exit 1 means a payload names no slice, is over the wave ceiling (dispatch fewer slices, then the next wave), or breaks `reviewer-input.schema.json`. Fix it; do not dispatch around it.
88
+ 4. **One batch.** Dispatch the whole wave — up to 10 reviewers — in one message, not one at a time. Give each reviewer `max_rounds` of at least 40 (the default); a reviewer that spends its rounds reading the skill and the schema returns nothing. **Incomplete means the next wave while it makes progress, Not run when it stalls.** Every reviewer result lists the `slices` it covered. On `INCOMPLETE`, `BLOCKED` or `NEEDS_CONTEXT` (never accepted as a finished scope), and on a `DONE` that left slices open, `keryx review retry-plan --manifest <dir>/manifest.json --result <raw/reviewer.txt>` decides and hands out the next wave of only the slices still uncovered (`--next-wave` plans one without a result). A result that covered a new slice spends no attempt; two results in a row with nothing new, or six failed rounds, print the `- **Not run:** …` line to paste into the report, and a result with nothing new first has its open slices cut in half. Dispatch each wave, save its reply, and run `retry-plan` again until it says `accepted`. Only the operator can accept a smaller set than that, with their own quote. An unfinished reviewer is never counted as a clean pass. **Persist every result.** Pass each reviewer `save_result_to: .metaproject/data/review/raw/<reviewer>.txt`: the host writes its full final text there, so `review complete` has raw evidence even after the transcript is cut. Build `research.json` with `keryx review ledger build <input-dir> --package <review-dir>` — never by hand: it reads the saved results, `scope-files.json` and the retry state, marks a reviewer complete only when its result is finished and its payloads cover the scope, and prints each gap with the exact next command and the waves left (a `retry-plan --next-wave` call, or a `--dispositions` entry for a raw finding). Run `keryx review ingest --research <review-dir>/research.json` once it prints READY (exit 0). A refused `review complete` names what is missing: fix that with a command and run it again; it is never `blocked`. `--head` wants a SHA (`git rev-parse HEAD`), not `HEAD`.
89
89
  5. **Never print a scope or a slice.** The tool output of one call is cut at about 20 KB and `keryx review scope` of a large PR prints hundreds of KB. Run it as `keryx review scope --ref <base> --json > .metaproject/data/review/scope.json` and read the counts from the file (`keryx ctx read`, or `jq`); take `<base>` from `git symbolic-ref refs/remotes/origin/HEAD`, not a guessed `origin/main`. Create `.metaproject/data/review/` first (`mkdir -p`) — a missing directory is a command to run, not a blocker. **Machine artifacts by direct write.** Save slices, payloads and results by redirection or `keryx ctx run --raw -- <command>`; the summarized form of `keryx ctx run` drops the bytes a later step parses.
90
90
 
91
91
  ## Control
@@ -1102,7 +1102,7 @@ whoever reads the merge commit a year later reads the body. When `review.jev.con
1102
1102
 
1103
1103
  **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.
1104
1104
 
1105
- 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).
1105
+ **The reviewer set is not yours to shrink.** Run `keryx review required --mode all|diff --scope <scope.json>` (`all` for `--all` or no narrowing flag; `diff` only when the operator named a narrower mode), dispatch every reviewer it prints, and declare `mode` in `dispatch`; pass the same `--scope` to `keryx review start|ingest` so the package keeps the file list. Closure refuses a smaller set unless `dispatch.override = { operatorQuote, reason }` carries the operator's own words. New managed packages declare `reviewerDispatch: "research.json"`. Alongside the research ledger, provide `dispatch: { version: 1, mode: "all"|"diff", 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).
1106
1106
 
1107
1107
  Dispatch selected reviewers in parallel when independent — this engine dispatches them itself (see "How to spawn"); a host without a dispatch tool returns `STATUS: BLOCKED` (`nested_dispatch_unavailable`) and never reviews alone — Preflight 1. Waves follow the diff domains in "Control" and keep their dependency order:
1108
1108
 
@@ -1255,7 +1255,7 @@ Before consolidation, validate every reviewer result:
1255
1255
  | `DONE` | Consolidate. |
1256
1256
  | `DONE_WITH_CONCERNS` | Consolidate and carry the concerns into the report. |
1257
1257
  | `NEEDS_CONTEXT` | One targeted context refill; if still unresolved, keep it as an explicit open question, not a blocker. |
1258
- | `BLOCKED` | Re-dispatch once; if it fails again, list the pass under **Not run**. |
1258
+ | `BLOCKED` | `retry-plan` hands out the next wave of the uncovered slices; progress keeps the reviewer, two results in a row with nothing new list the pass under **Not run**. |
1259
1259
  | `RATE_LIMITED` | Halve the wave and requeue (Control). |
1260
1260
  | anything else, or no result | Treat as `BLOCKED`. |
1261
1261
 
@@ -1603,7 +1603,7 @@ When a prompt carries `JOB_NAME` and `CONTEXT_PATH`, read that context document
1603
1603
  | "The blast radius came back empty, so nothing can break" | Empty and unresolved are different facts. The graph indexes code — a Markdown or JSON change has no radius at all, and the record says which one you got |
1604
1604
  | "The changed files are the same as last round, so scope B can be skipped on the final round" | The final round always recomputes. A fix landed in round 3 is the change; skipping means the certifying round checked the least |
1605
1605
  | "This scope-B file has an obvious naming problem, I'll report it" | Rejected in code: a naming problem is `minor` at best, and the floor is `major`. The set is under regression check, not under review — raise it under scope A |
1606
- | "The reviewer ran out of budget but I saw enough of the diff to write its findings" | Then the report names a review that did not happen. It is `BLOCKED`: one re-dispatch with a larger budget, else **Not run** |
1606
+ | "The reviewer ran out of budget but I saw enough of the diff to write its findings" | Then the report names a review that did not happen. It is `BLOCKED`: `retry-plan` hands out the uncovered slices in waves that fit the budget, else **Not run** |
1607
1607
  | "The verifier returned nothing, so I'll confirm the findings myself" | The orchestrator never verifies. No verdict means `unverified`, stated in the stage counts |
1608
1608
  | "The spec-gate finding is mine, so `reviewer: review-orchestrator`" | That name makes the finding unroutable in Wave C. File it under the reviewer that ran the comparison |
1609
1609
  | "Steps 8–10 are done, I'll tick them now and ingest later" | `completed` means the ingest record exists. A plan that runs ahead of the artifacts is how an unrun review looked finished |
@@ -66,25 +66,10 @@ See shared script: `.metaproject/skills/gdskills/shared/git-merge-base.md`
66
66
 
67
67
  Run the script from that file to determine `MERGE_BASE` (`BASE_SHA`) and `SCOPE` before proceeding.
68
68
 
69
- ### Commands to collect the review slice
70
-
71
- ```bash
72
- git status
73
- git log --oneline "${BASE_SHA}..HEAD"
74
- git diff --stat --name-status "${BASE_SHA}..HEAD"
75
- git diff "${BASE_SHA}..HEAD"
76
-
77
- # Include uncommitted changes (default mode):
78
- git diff --stat --name-status "${BASE_SHA}"
79
- git diff "${BASE_SHA}"
80
- git ls-files --others --exclude-standard
81
- ```
82
-
83
- For explicit hash/range mode:
84
-
69
+ **Supplied text first.** When the payload carries `slices`, `context_files`, `diff` or `file_contents`, review exactly that text: a read-only child has no shell, so run no git command and never rebuild the diff. Only with none supplied, collect it:
85
70
  ```bash
86
- git diff --stat --name-status <FROM_SHA>..<TO_SHA>
87
- git diff <FROM_SHA>..<TO_SHA>
71
+ git diff --name-status "${BASE_SHA}" && git diff "${BASE_SHA}" && git ls-files --others --exclude-standard
72
+ # explicit range: <FROM_SHA>..<TO_SHA> in place of "${BASE_SHA}"
88
73
  ```
89
74
 
90
75
  ---
@@ -163,8 +163,8 @@ rejected anyway, so in practice every finding you report carries one.
163
163
  - **Fix**: concrete suggestion
164
164
  ```
165
165
 
166
- Severity comes from **Severity (canonical)** in `review-orchestrator/SKILL.md`.
167
- This reviewer keeps no table of its own.
166
+ Severity comes from **Severity (canonical)** in `review-orchestrator/SKILL.md`; no table here. When dispatched, follow the `reviewer-input.schema.json` payload and return a `REVIEW_RESULT` object compatible with
167
+ `.metaproject/skills/gdskills/review/review-orchestrator/reviewer-finding.schema.json`, then a short summary; `NEEDS_CONTEXT` rather than a guess.
168
168
 
169
169
  ### Shared laws (every reviewer)
170
170
 
@@ -67,25 +67,10 @@ See shared script: `.metaproject/skills/gdskills/shared/git-merge-base.md`
67
67
 
68
68
  Run the script from that file to determine `MERGE_BASE` (`BASE_SHA`) and `SCOPE` before proceeding.
69
69
 
70
- ### Commands to collect the review slice
71
-
72
- ```bash
73
- git status
74
- git log --oneline "${BASE_SHA}..HEAD"
75
- git diff --stat --name-status "${BASE_SHA}..HEAD"
76
- git diff "${BASE_SHA}..HEAD"
77
-
78
- # Include uncommitted changes (default mode):
79
- git diff --stat --name-status "${BASE_SHA}"
80
- git diff "${BASE_SHA}"
81
- git ls-files --others --exclude-standard
82
- ```
83
-
84
- For explicit hash/range mode:
85
-
70
+ **Supplied text first.** When the payload carries `slices`, `context_files`, `diff` or `file_contents`, review exactly that text: a read-only child has no shell, so run no git command and never rebuild the diff. Only with none supplied, collect it:
86
71
  ```bash
87
- git diff --stat --name-status <FROM_SHA>..<TO_SHA>
88
- git diff <FROM_SHA>..<TO_SHA>
72
+ git diff --name-status "${BASE_SHA}" && git diff "${BASE_SHA}" && git ls-files --others --exclude-standard
73
+ # explicit range: <FROM_SHA>..<TO_SHA> in place of "${BASE_SHA}"
89
74
  ```
90
75
 
91
76
  ---
@@ -64,18 +64,14 @@ See shared script: `.metaproject/skills/gdskills/shared/git-merge-base.md`
64
64
 
65
65
  Run that script to determine `BASE_SHA` before collecting the diff.
66
66
 
67
- ```bash
68
- # Default mode — all changes from merge-base to working tree
69
- git diff --name-only "${BASE_SHA}"
70
- git diff "${BASE_SHA}"
67
+ Only review code changed in scope. Do not flag style issues in lines outside the diff.
71
68
 
72
- # Explicit range mode
73
- git diff --name-only <FROM_SHA>..<TO_SHA>
74
- git diff <FROM_SHA>..<TO_SHA>
69
+ **Supplied text first.** When the payload carries `slices`, `context_files`, `diff` or `file_contents`, review exactly that text: a read-only child has no shell, so run no git command and never rebuild the diff. Only with none supplied, collect it:
70
+ ```bash
71
+ git diff --name-status "${BASE_SHA}" && git diff "${BASE_SHA}" && git ls-files --others --exclude-standard
72
+ # explicit range: <FROM_SHA>..<TO_SHA> in place of "${BASE_SHA}"
75
73
  ```
76
74
 
77
- Only review code changed in scope. Do not flag style issues in lines outside the diff.
78
-
79
75
  ---
80
76
 
81
77
  ## Review Checklist