@mrciphersmith/keryx 0.3.119 → 0.3.121
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/dist/cli.js +9730 -5314
- package/dist/core.js +1162 -812
- package/package.json +1 -1
- package/src/gdskills/bundled/install-manifest.json +2 -1
- package/src/gdskills/bundled/rules/core/session-plan-bridge.mdc +1 -1
- package/src/gdskills/bundled/skills/orchestration/feature-dev/SKILL.md +4 -4
- package/src/gdskills/bundled/skills/orchestration/flow-orchestrator/SKILL.md +47 -59
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.detail.md +70 -0
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.md +42 -79
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/orchestrator-prompt.md +1 -1
- package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.md +12 -18
- package/src/gdskills/bundled/skills/orchestration/task-implementer/input-contract.schema.json +25 -2
- package/src/gdskills/bundled/skills/orchestration/task-implementer/output-contract.schema.json +19 -0
- package/src/gdskills/bundled/skills/review/review-architecture/SKILL.md +6 -11
- package/src/gdskills/bundled/skills/review/review-backend/SKILL.md +6 -11
- package/src/gdskills/bundled/skills/review/review-clean-code/SKILL.md +6 -11
- package/src/gdskills/bundled/skills/review/review-core-boundaries/SKILL.md +5 -10
- package/src/gdskills/bundled/skills/review/review-flow-graph/SKILL.md +5 -10
- package/src/gdskills/bundled/skills/review/review-frontend/SKILL.md +8 -17
- package/src/gdskills/bundled/skills/review/review-frontend-conventions/SKILL.md +8 -15
- package/src/gdskills/bundled/skills/review/review-highload/SKILL.md +6 -11
- package/src/gdskills/bundled/skills/review/review-jev-comments/SKILL.md +4 -9
- package/src/gdskills/bundled/skills/review/review-jev-contract/SKILL.md +4 -9
- package/src/gdskills/bundled/skills/review/review-jev-docs/SKILL.md +4 -9
- package/src/gdskills/bundled/skills/review/review-jev-risk/SKILL.md +4 -9
- package/src/gdskills/bundled/skills/review/review-jev-rules/SKILL.md +4 -9
- package/src/gdskills/bundled/skills/review/review-jev-scenarios/SKILL.md +4 -9
- package/src/gdskills/bundled/skills/review/review-layout/SKILL.md +8 -9
- package/src/gdskills/bundled/skills/review/review-logic/SKILL.md +7 -12
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.detail.md +39 -2
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.md +49 -92
- package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-finding.schema.json +13 -0
- package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-input.schema.json +38 -0
- package/src/gdskills/bundled/skills/review/review-performance/SKILL.md +6 -11
- package/src/gdskills/bundled/skills/review/review-pr-contract/SKILL.md +2 -2
- package/src/gdskills/bundled/skills/review/review-pr-feedback/SKILL.md +8 -10
- package/src/gdskills/bundled/skills/review/review-premise/SKILL.md +180 -0
- package/src/gdskills/bundled/skills/review/review-regression/SKILL.md +4 -4
- package/src/gdskills/bundled/skills/review/review-security-code/SKILL.md +6 -11
- package/src/gdskills/bundled/skills/review/review-style/SKILL.md +6 -11
- package/src/gdskills/bundled/skills/review/review-testing-practices/SKILL.md +2 -2
- package/src/gdskills/contracts/review-finding.schema.json +88 -0
|
@@ -205,15 +205,10 @@ other reviewer's: same Quality Gate, same dedup, same Wave C verification.
|
|
|
205
205
|
|
|
206
206
|
### Shared laws (every reviewer)
|
|
207
207
|
|
|
208
|
-
1. **A claim of runtime harm with no reproducible path is `info`.** If you cannot
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
under review. Do not report a safe API because it could be misused, or a
|
|
213
|
-
pattern because it is often wrong elsewhere.
|
|
214
|
-
3. **One finding per class, not one per occurrence.** When the same shape appears
|
|
215
|
-
at several sites, report it once and list every site. Ten findings that are one
|
|
216
|
-
finding hide the other nine problems.
|
|
208
|
+
1. **A claim of runtime harm with no reproducible path is `info`.** If you cannot name the input, call, or condition that reaches the code, you have an observation, not a finding. Report it as `info` and say what would settle it.
|
|
209
|
+
2. **Never flag the theoretical.** The path you describe must exist in the code under review. Do not report a safe API because it could be misused, or a pattern because it is often wrong elsewhere.
|
|
210
|
+
3. **One finding per class, not one per occurrence.** When the same shape appears at several sites, report it once and list every site. Ten findings that are one finding hide the other nine problems.
|
|
211
|
+
4. **A deliberate choice is not a defect until its reason is read and shown wrong.** An explicit override, suppression or exemption, a comment or commit giving a reason, or a sibling doing the same is a decision: read its reason (the comment, `git log -L` or `git blame`, the sibling) before you report it, and report it only when you can show that reason wrong. A project rule is checked against accepted platform practice and its known exceptions before a deviation from it is reported.
|
|
217
212
|
|
|
218
213
|
This reviewer already satisfies all three by construction: `evidence` always
|
|
219
214
|
names the hunk and quotes it (never an unreproducible claim), a finding is
|
|
@@ -129,15 +129,10 @@ same dedup, same Wave C verification.
|
|
|
129
129
|
|
|
130
130
|
### Shared laws (every reviewer)
|
|
131
131
|
|
|
132
|
-
1. **A claim of runtime harm with no reproducible path is `info`.** If you cannot
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
under review. Do not report a safe API because it could be misused, or a
|
|
137
|
-
pattern because it is often wrong elsewhere.
|
|
138
|
-
3. **One finding per class, not one per occurrence.** When the same shape appears
|
|
139
|
-
at several sites, report it once and list every site. Ten findings that are one
|
|
140
|
-
finding hide the other nine problems.
|
|
132
|
+
1. **A claim of runtime harm with no reproducible path is `info`.** If you cannot name the input, call, or condition that reaches the code, you have an observation, not a finding. Report it as `info` and say what would settle it.
|
|
133
|
+
2. **Never flag the theoretical.** The path you describe must exist in the code under review. Do not report a safe API because it could be misused, or a pattern because it is often wrong elsewhere.
|
|
134
|
+
3. **One finding per class, not one per occurrence.** When the same shape appears at several sites, report it once and list every site. Ten findings that are one finding hide the other nine problems.
|
|
135
|
+
4. **A deliberate choice is not a defect until its reason is read and shown wrong.** An explicit override, suppression or exemption, a comment or commit giving a reason, or a sibling doing the same is a decision: read its reason (the comment, `git log -L` or `git blame`, the sibling) before you report it, and report it only when you can show that reason wrong. A project rule is checked against accepted platform practice and its known exceptions before a deviation from it is reported.
|
|
141
136
|
|
|
142
137
|
This reviewer satisfies all three by construction: severity is fixed at
|
|
143
138
|
`minor` — never higher — and `evidence` always names the scenario's linked
|
|
@@ -119,6 +119,10 @@ name instead.
|
|
|
119
119
|
LTR is toward the end in RTL. State both.
|
|
120
120
|
- [ ] A physical gradient, shadow, or transform in a component that otherwise uses
|
|
121
121
|
logical properties does **not** flip. Name the direction it points in each.
|
|
122
|
+
- [ ] Some surfaces usually do **not** mirror, by platform practice (Material Bidirectionality,
|
|
123
|
+
Apple HIG): media playback controls and their progress or seek bar, numbers, code, phone
|
|
124
|
+
numbers. A forced `dir="ltr"` there is usually deliberate: read its signals (law 4) before
|
|
125
|
+
reporting. An event timeline, calendar row or chart axis often does mirror; judge by the product.
|
|
122
126
|
- [ ] Text length differs by locale. A component sized by its own labels renders
|
|
123
127
|
**different geometry for identical data** across locales. Measure with the
|
|
124
128
|
longest real translation in the catalog, never the English one.
|
|
@@ -146,15 +150,10 @@ name instead.
|
|
|
146
150
|
|
|
147
151
|
### Shared laws (every reviewer)
|
|
148
152
|
|
|
149
|
-
1. **A claim of runtime harm with no reproducible path is `info`.** If you cannot
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
under review. Do not report a safe API because it could be misused, or a
|
|
154
|
-
pattern because it is often wrong elsewhere.
|
|
155
|
-
3. **One finding per class, not one per occurrence.** When the same shape appears
|
|
156
|
-
at several sites, report it once and list every site. Ten findings that are one
|
|
157
|
-
finding hide the other nine problems.
|
|
153
|
+
1. **A claim of runtime harm with no reproducible path is `info`.** If you cannot name the input, call, or condition that reaches the code, you have an observation, not a finding. Report it as `info` and say what would settle it.
|
|
154
|
+
2. **Never flag the theoretical.** The path you describe must exist in the code under review. Do not report a safe API because it could be misused, or a pattern because it is often wrong elsewhere.
|
|
155
|
+
3. **One finding per class, not one per occurrence.** When the same shape appears at several sites, report it once and list every site. Ten findings that are one finding hide the other nine problems.
|
|
156
|
+
4. **A deliberate choice is not a defect until its reason is read and shown wrong.** An explicit override, suppression or exemption, a comment or commit giving a reason, or a sibling doing the same is a decision: read its reason (the comment, `git log -L` or `git blame`, the sibling) before you report it, and report it only when you can show that reason wrong. A project rule is checked against accepted platform practice and its known exceptions before a deviation from it is reported.
|
|
158
157
|
|
|
159
158
|
Severity levels are defined once, in `review-orchestrator/SKILL.md` →
|
|
160
159
|
**Severity (canonical)**. This reviewer keeps no rubric of its own; below is only
|
|
@@ -27,7 +27,7 @@ license: "MIT"
|
|
|
27
27
|
|
|
28
28
|
Specialized reviewer for **logic correctness and algorithmic soundness**.
|
|
29
29
|
Inherits from the original `code-ai-review` + `code-learned-review` correctness phases
|
|
30
|
-
and unifies them into a single focused pass. Its inputs are the reviewer payload only; session memory and earlier conversation are not inputs.
|
|
30
|
+
and unifies them into a single focused pass. Its inputs are the reviewer payload only; session memory and earlier conversation are not inputs. It runs no command unless its payload's `allowed_tools` says `run-tests`, except the read-only `git log`, `git blame` and `git show` where its host gives a read-only child git (keryx shell does not: there the payload supplies the history).
|
|
31
31
|
|
|
32
32
|
This reviewer does not care about formatting, naming, or architecture opinions.
|
|
33
33
|
Every finding must describe an observable, reproducible defect or a spec gap.
|
|
@@ -69,7 +69,7 @@ See shared script: `.metaproject/skills/gdskills/shared/git-merge-base.md`
|
|
|
69
69
|
Review scope: **changes introduced in the current branch since merge-base only**.
|
|
70
70
|
Do not review unrelated files.
|
|
71
71
|
|
|
72
|
-
**Supplied text first.** When the payload carries `slices`, `context_files`, `diff` or `file_contents`, review exactly that text
|
|
72
|
+
**Supplied text first.** When the payload carries `slices`, `context_files`, `diff` or `file_contents`, review exactly that text and never rebuild the diff. A choice's history (law 4) is read with `git log`, `git blame` and `git show` only where the host gives a read-only child git; on keryx shell a read-only child has no shell and no git tool, so read the `git log -L`/`git blame` excerpts the payload supplies, or say the history was not read. Only with none supplied, collect it:
|
|
73
73
|
```bash
|
|
74
74
|
git diff --name-status "${BASE_SHA}" && git diff "${BASE_SHA}" && git ls-files --others --exclude-standard
|
|
75
75
|
# explicit range: <FROM_SHA>..<TO_SHA> in place of "${BASE_SHA}"
|
|
@@ -193,7 +193,7 @@ earlier review round, because there the finding is recorded as closed and is not
|
|
|
193
193
|
|
|
194
194
|
## Orchestrated Review Contract
|
|
195
195
|
|
|
196
|
-
When dispatched by `review-orchestrator`, follow the provided `reviewer-input.schema.json` payload. Return a `REVIEW_RESULT` object compatible with `.metaproject/skills/gdskills/review/review-orchestrator/reviewer-finding.schema.json`, then a concise markdown summary. Keep findings evidence-based, include concrete `suggested_fix` for every blocker/major, and return `NEEDS_CONTEXT` instead of guessing when required context is missing.
|
|
196
|
+
When dispatched by `review-orchestrator`, follow the provided `reviewer-input.schema.json` payload. Return a `REVIEW_RESULT` object compatible with `.metaproject/skills/gdskills/review/review-orchestrator/reviewer-finding.schema.json`, then a concise markdown summary. Keep findings evidence-based, include concrete `suggested_fix` for every blocker/major, and return `NEEDS_CONTEXT` instead of guessing when required context is missing. On a FIX slice, also return `prior_dispositions: [{id, disposition}]` for every attached finding id.
|
|
197
197
|
|
|
198
198
|
---
|
|
199
199
|
|
|
@@ -260,15 +260,10 @@ conditions land under that rubric, not a second rubric.
|
|
|
260
260
|
|
|
261
261
|
### Shared laws (every reviewer)
|
|
262
262
|
|
|
263
|
-
1. **A claim of runtime harm with no reproducible path is `info`.** If you cannot
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
under review. Do not report a safe API because it could be misused, or a
|
|
268
|
-
pattern because it is often wrong elsewhere.
|
|
269
|
-
3. **One finding per class, not one per occurrence.** When the same shape appears
|
|
270
|
-
at several sites, report it once and list every site. Ten findings that are one
|
|
271
|
-
finding hide the other nine problems.
|
|
263
|
+
1. **A claim of runtime harm with no reproducible path is `info`.** If you cannot name the input, call, or condition that reaches the code, you have an observation, not a finding. Report it as `info` and say what would settle it.
|
|
264
|
+
2. **Never flag the theoretical.** The path you describe must exist in the code under review. Do not report a safe API because it could be misused, or a pattern because it is often wrong elsewhere.
|
|
265
|
+
3. **One finding per class, not one per occurrence.** When the same shape appears at several sites, report it once and list every site. Ten findings that are one finding hide the other nine problems.
|
|
266
|
+
4. **A deliberate choice is not a defect until its reason is read and shown wrong.** An explicit override, suppression or exemption, a comment or commit giving a reason, or a sibling doing the same is a decision: read its reason (the comment, `git log -L` or `git blame`, the sibling) before you report it, and report it only when you can show that reason wrong. A project rule is checked against accepted platform practice and its known exceptions before a deviation from it is reported.
|
|
272
267
|
|
|
273
268
|
Severity levels are defined once, in `review-orchestrator/SKILL.md` →
|
|
274
269
|
**Severity (canonical)**. This reviewer does not restate them: `blocker` is the
|
|
@@ -651,7 +651,7 @@ certifies the flow is the one that checked the least.
|
|
|
651
651
|
|
|
652
652
|
## Readiness — the checklist behind `completed` and behind publishing
|
|
653
653
|
|
|
654
|
-
`keryx review readiness <review-id-or-path> [--json]` reads the package and prints
|
|
654
|
+
`keryx review readiness <review-id-or-path> [--json]` reads the package and prints eleven items, READY or NOT READY, each with the evidence and the command that repairs it. It writes nothing, and exits non-zero when the verdict is NOT READY. Only item 9 reaches GitHub (the PR's own file list); the TUI and `review status` read the package alone.
|
|
655
655
|
|
|
656
656
|
1. `files-covered` — every changed file is in a wave or carries a recorded waiver.
|
|
657
657
|
2. `blast-radius` — no file the blast radius cut is left unreviewed. A cut radius writes `chunks.json`; run `keryx review chunks plan`, `estimate`, `next`/`record`, `merge`. In an unattended run every wave runs without a question, up to the 25-pass ceiling; in an interactive run the operator is asked once: in keryx shell call `review_chunks_answer` (a card, never a terminal); elsewhere the operator runs `keryx review chunks estimate --package <dir> --answer yes --quote "<their words>"` in their terminal; unattended, record Not run.
|
|
@@ -663,8 +663,9 @@ certifies the flow is the one that checked the least.
|
|
|
663
663
|
8. `report-names` — pending mutation candidates and parity warnings are named in the report.
|
|
664
664
|
9. `pr-files` — the changed-file count equals the PR's own file list. A recount more than 3x the recorded scope is refused: it came from the wrong base. Recount with `keryx review blast-radius --package <ref> --changed <the PR's files>`.
|
|
665
665
|
10. `memory-outside-stage` — the orchestrator read memory only in its memory stage ("Clean context" above). Outside keryx shell it reads "not observable on this host" unless this session's keryx calls carry the caller token `keryx review start` printed.
|
|
666
|
+
11. `premise-decisions` — every finding `review-premise` held (`challenged` or `owner-decision`) has an operator decision: in keryx shell the card `review_decide_premise`; elsewhere the operator runs `keryx review decide-premise --package <dir> --finding <global_id> --answer uphold|dismiss --reason "<why>"` in their terminal (SKILL.md "Wave D"). Not waivable: each held finding needs its own answer, and `review_waive_readiness` / `--waive` refuse this item.
|
|
666
667
|
|
|
667
|
-
`keryx review complete` refuses status `completed` while any item fails. A failing item is waived only by the operator. In keryx shell call `review_waive_readiness` for the item: the operator answers it as a card, the waiver is recorded with the card text and the time, and then you run `keryx review complete`. Never send the operator to a terminal. Outside keryx shell the operator runs `keryx review complete --waive <item> "<their own words>"` in a terminal, repeatable. Unattended, record the item as Not run. `keryx review publish` is held by the same checklist. Publishing is the operator's decision too: in keryx shell call `review_publish` (a card shows the target and the body; never send the operator to a terminal). A not-ready package goes to GitHub only as a partial review (`review_publish` with `partial: true`, or `keryx review publish --partial`), which puts a "Partial review" header on the post and never approves. The shell guard stops a publish command that runs through the keryx shell; a publisher outside it (CI, another agent, a script file) is not stopped, and that limit is named, not hidden.
|
|
668
|
+
`keryx review complete` refuses status `completed` while any item fails. A failing item other than `premise-decisions` is waived only by the operator. In keryx shell call `review_waive_readiness` for the item: the operator answers it as a card, the waiver is recorded with the card text and the time, and then you run `keryx review complete`. Never send the operator to a terminal. Outside keryx shell the operator runs `keryx review complete --waive <item> "<their own words>"` in a terminal, repeatable. Unattended, record the item as Not run. `keryx review publish` is held by the same checklist. Publishing is the operator's decision too: in keryx shell call `review_publish` (a card shows the target and the body; never send the operator to a terminal). A not-ready package goes to GitHub only as a partial review (`review_publish` with `partial: true`, or `keryx review publish --partial`), which puts a "Partial review" header on the post and never approves. The shell guard stops a publish command that runs through the keryx shell; a publisher outside it (CI, another agent, a script file) is not stopped, and that limit is named, not hidden.
|
|
668
669
|
|
|
669
670
|
## Fix rounds — dispositions, regressions, withdrawal
|
|
670
671
|
|
|
@@ -687,6 +688,20 @@ sync as abandoned"* is a claim; the disposition is whether the branch it renamed
|
|
|
687
688
|
is reachable and pinned. On a recorded round, two such commits asserted behaviour
|
|
688
689
|
on lines no test could reach.
|
|
689
690
|
|
|
691
|
+
### Delta rounds — what `review start` hands you
|
|
692
|
+
|
|
693
|
+
`keryx review start` detects the round and writes `<package>/round.json` and `<package>/prior_findings.json`. It searches every source, because the earlier round may have run on another machine: the local package, git history (tracked package files), the PR's `keryx round` block, PR comments, and the flow's packages. `round.json` carries `round`, `source`, `sourcesTried`, `previous`, `mode`, `range`, `fixHunks`, `newHunks` and `carried`.
|
|
694
|
+
|
|
695
|
+
| `mode` | `range` | Review |
|
|
696
|
+
|---|---|---|
|
|
697
|
+
| `first` | merge-base..head | A first round. `sourcesTried` records what was searched when nothing was found. |
|
|
698
|
+
| `delta` | previous head..head | `fix` slices (a hunk that answers a prior finding): `review-logic`, `review-regression`, the authors of the attached findings and the verifier, each with its `prior_findings`. `new` slices: round 1, with the roles the slice names. Unchanged code: not re-reviewed. `carried` findings keep their dispositions. |
|
|
699
|
+
| `fallback-first` | merge-base..head | The previous head is not an ancestor (force-push, rebase). Review the whole range with the prior findings attached. |
|
|
700
|
+
|
|
701
|
+
A fix hunk still has a radius: enumerate what names the thing it changed (`review_context.scope.files`), as in any fix round. The attached findings are the contract: each leaves the round with a disposition, below.
|
|
702
|
+
|
|
703
|
+
A reviewer on a FIX slice reports those dispositions itself: its `REVIEW_RESULT` carries `prior_dispositions: [{id, disposition}]` with one entry for every attached finding id (`disposition` is `closed`, `open`, `partial`, `regressed` or `withdrawn`), judged against the code. `keryx review ingest` reads the array into the ledger; an attached id with no entry stays undisposed.
|
|
704
|
+
|
|
690
705
|
### A fix is a change, and changes get reviewed
|
|
691
706
|
|
|
692
707
|
The most expensive class in a multi-round review is **the defect the fix
|
|
@@ -903,3 +918,25 @@ Default budget guidance:
|
|
|
903
918
|
| medium | <= 20 files or <= 2,000 changed lines | `light` | per-domain filtered diff |
|
|
904
919
|
| large | > 20 files or > 2,000 changed lines | ask `full` | staged waves by domain |
|
|
905
920
|
| high-risk | auth/API/core/security/data migrations | ask `full` | staged waves, verifier included |
|
|
921
|
+
|
|
922
|
+
## Everything written to GitHub is brief
|
|
923
|
+
|
|
924
|
+
One rule, applied to every outward surface: **PR bodies, PR comments, review
|
|
925
|
+
replies, issue comments, and commit messages going to a PR.**
|
|
926
|
+
|
|
927
|
+
- Lead with the conclusion. No preamble, no restating the question, no apology,
|
|
928
|
+
no summary of the flow.
|
|
929
|
+
- Say what changed and where. **Link, do not paste.**
|
|
930
|
+
- The reasoning, the evidence, the rejected alternatives and the round history live
|
|
931
|
+
in the flow package — `journal.md`, `context.md`, the review artifacts — which is
|
|
932
|
+
durable, searchable, and costs a reader nothing to skip.
|
|
933
|
+
- A GitHub artifact that needs more than a short paragraph is a signal that the
|
|
934
|
+
detail belongs in the flow with a link out, **not** that the paragraph should
|
|
935
|
+
grow.
|
|
936
|
+
- No orchestrator-written PR comment or reply exceeds two sentences without
|
|
937
|
+
carrying a link to the artifact holding the detail. The reply pass enforces
|
|
938
|
+
this; for anything else you write outward, hold yourself to it.
|
|
939
|
+
|
|
940
|
+
This is deliberately asymmetric: **verbose in the flow, terse on GitHub.** The
|
|
941
|
+
flow is written for whoever resumes the work; GitHub is read by someone who did
|
|
942
|
+
not ask for our reasoning and is reading between other tasks.
|
|
@@ -27,7 +27,7 @@ license: "MIT"
|
|
|
27
27
|
1. **Can it spawn?** The round needs a subagent-spawn tool (`Agent`, `spawn_subagent` or the host's equivalent) and depth budget left: Claude Code nests subagents at most 3 deep, and at the limit `Agent` is withheld. A host with no spawn tool at all (Codex and other AGENTS.md hosts) does not stop here and does not review alone: it runs the round through the autonomous runner, `keryx review run --autonomous --target pr --ref <pull request URL>` (no pull request: `--target branch --ref <base> [--head <commit>]`), and relays its verdict and exit code (see "Hosts"). Only a session that has spent the depth budget (a nested subagent) stops; its whole output is this line, with no tool calls and no review of your own:
|
|
28
28
|
`STATUS: BLOCKED nested_dispatch_unavailable — run this skill in the main session`
|
|
29
29
|
2. **Is a round needed?** List the files with `git diff --name-status --no-renames <base>...HEAD`, so a rename shows both paths. A diff where EVERY file is prose or machine-written data ends here with one line, `round not needed: <reason>`, and no reviewer. Prose is exactly: README or CHANGELOG at any depth; CONTRIBUTING, LICENSE, SECURITY or CODE_OF_CONDUCT at the top level; and under `docs/`, `.metaproject/wiki`, `.metaproject/reviews` or a flow's `journal.md`, a file with extension md, rst or adoc whose name holds a lowercase letter (an all-uppercase name such as AGENT or WARP is steering by convention). Machine-written data is a file under `coverage/` or `__generated__/` with extension lcov, info or map only; json, txt, html and md there are code. Steering is code wherever it sits, `docs/` included: a directory (singular or plural) named agent, skill, command, rule, prompt, instruction, persona, steering or hook, any path segment starting with a dot (`.claude`, `.cursorrules`, `.mcp.json`), a file name starting with SKILL, AGENT, CLAUDE, GEMINI, QWEN, CODEX, WARP, CRUSH, JULES, KNOWLEDGE, GUIDELINES, CONVENTIONS or copilot-instructions, ending in .local, .override, .instructions, .prompt, .agent or .chatmode before the extension, or containing prompt, instruction or system. A flow's `description.md`, `acceptance-criteria.md` and `tasks/` are gate inputs, so they are code. Every other file counts as code too, including lockfiles, committed `dist/` output, CI, auth, migrations, config JSON, and any path with `..`, a backslash, a leading `./` or `//`. `classifyRoundNeed` in `src/review/round-need.ts` is the tested reference of this rule; the host executes this text, and nothing in the CLI calls the function yet. `--all`, an explicit reviewer list or a gating round forces a round.
|
|
30
|
-
3. **Round ceiling.** 5 rounds (`REVIEW_ROUND_CAP`) over the same
|
|
30
|
+
3. **Round ceiling.** 5 rounds (`REVIEW_ROUND_CAP`) over the same change. Past it: interactive, ask the operator; unattended, `STATUS: BLOCKED round_cap`.
|
|
31
31
|
4. **PR state, shown before dispatch.** On a PR target read its state (merged, approved, CI) and tell the operator the risk that it merges before the round ends: a verdict ready at minute 55 and held to minute 119 lost the race to the merge. Depth and the estimate need the package and the slice manifest, so they come later: after `review scope`, `review start` and `review slice`, before the first reviewer starts ("Round plan" steps 5-6; `SKILL.detail.md` § "Preflight 4").
|
|
32
32
|
|
|
33
33
|
## Hosts — the same round, different tools
|
|
@@ -44,19 +44,19 @@ license: "MIT"
|
|
|
44
44
|
- **Every host keeps the same files, per package** (`<package>` is the directory `keryx review start` created): slices in `<package>/slices/`, one reply per dispatch in `<package>/raw/<reviewer>.txt` (reviewer replies only), one driver per dispatch in `<package>/drivers/<reviewer>.json`, and `research.json` from `keryx review ledger build --package <package>` — never by hand. `retry-plan --package`, `verdict` and `ledger build` read `<package>/raw` by default; the shared `.metaproject/data/review/raw` holds other rounds' replies and is read only when named, so never write there.
|
|
45
45
|
- **The result is the file, never the spawn tool's output.** keryx shell cuts a child's summary at 16000 characters and Claude Code returns only the last message: parse `<package>/raw/<reviewer>.txt`. A missing file is no result (`BLOCKED`).
|
|
46
46
|
- **Caller token.** `keryx review start` prints `export KERYX_REVIEW_CALLER_TOKEN=…`; outside keryx shell export it on this session's keryx calls, or readiness item 10 reads "not observable on this host".
|
|
47
|
-
- **Operator decisions.** In keryx shell the operator answers a card: `review_confirm_plan`, `review_waive_readiness`, `review_waive_coverage`, `review_waive_mutation`, `review_override_reviewers`, `review_chunks_answer`, `review_publish`, `review_comments_reply`. Elsewhere give the operator the exact command to run in their own terminal — `keryx review confirm-plan --package <package>`, `keryx review complete <package> --waive <item> "<their words>"` or `--waive-coverage "<their words>"`, `keryx review waive-mutation --package <package> --reason "<why>"`, `keryx review override-reviewers --package <package> --reason "<why>"`, `keryx review chunks estimate --package <package> --answer yes --quote "<their words>"`, `keryx review publish <package>`, `keryx review comments reply … --final` — and wait. You never run `--mode automatic` or `--yes`, and never write an operator quote yourself; unattended, the item is Not run.
|
|
47
|
+
- **Operator decisions.** In keryx shell the operator answers a card: `review_confirm_plan`, `review_waive_readiness`, `review_waive_coverage`, `review_waive_mutation`, `review_override_reviewers`, `review_chunks_answer`, `review_publish`, `review_comments_reply`, `review_decide_premise`. Elsewhere give the operator the exact command to run in their own terminal — `keryx review confirm-plan --package <package>`, `keryx review complete <package> --waive <item> "<their words>"` or `--waive-coverage "<their words>"`, `keryx review waive-mutation --package <package> --reason "<why>"`, `keryx review override-reviewers --package <package> --reason "<why>"`, `keryx review chunks estimate --package <package> --answer yes --quote "<their words>"`, `keryx review publish <package>`, `keryx review comments reply … --final`, `keryx review decide-premise --package <package> --finding <id> --answer uphold|dismiss --reason "<why>"` — and wait. You never run `--mode automatic` or `--yes`, and never write an operator quote yourself; unattended, the item is Not run.
|
|
48
48
|
|
|
49
49
|
## Round plan — the order on every host
|
|
50
50
|
|
|
51
|
-
1. `keryx review
|
|
52
|
-
2. `keryx review start --target <kind> --ref <ref> --scope .metaproject/data/review/scope.json --memory-query "<query>" --host <host
|
|
51
|
+
1. `keryx review plan --target <pr-url|branch> [--ref <base>] [--head <sha>] --host <host> [--memory-query "<query>"] [--unattended]` is the one command: it runs start, scope (Step 3), blast-radius (Step 3b), slice, required and estimate, writes `<package>/plan.json` and dispatches nothing. Read the round first (Step 1a), then dispatch from step 7.
|
|
52
|
+
2. Without `plan`, run those stages one by one in this order: `keryx review scope --ref <base> --json > .metaproject/data/review/scope.json`, then `keryx review start --target <kind> --ref <ref> --scope .metaproject/data/review/scope.json --memory-query "<query>" --host <host>` (plus `--unattended` when nobody is at the keyboard); `start` searches every prior-round source (local package, git history, the PR's keryx round block, PR comments, flow) and writes `round.json`.
|
|
53
53
|
3. `keryx review blast-radius --ref <base> --package <package> --json > blast-radius.json` (Step 3b). Reasoned omissions (`unrelated-symbol`, `hub-damped`, `text-hub`, `test-consumer`) are context, not scope; only cap drops become chunks. Run the tests in `<package>/tests-to-run.json` with the command the radius prints, instead of reading them, and hand the output to the reviewers as context.
|
|
54
54
|
4. `keryx review slice --ref <base> --package <package> --host <host>`: each slice carries `roles`, `depth` (deep or light) and `audit`.
|
|
55
55
|
5. `keryx review required --mode all --scope .metaproject/data/review/scope.json --depth auto --package <package>`.
|
|
56
56
|
6. `keryx review estimate --package <package>`. Over threshold, the operator confirms (card `review_confirm_plan`, or `keryx review confirm-plan --package <package>` in their terminal); `dispatch-check` and `ledger build` refuse an unconfirmed plan, so never dispatch one. Unattended: report the estimate and stop with `STATUS: BLOCKED plan_over_threshold`.
|
|
57
|
-
7. Dispatch by slice roles: each role gets the slices that name it; a deep slice names every roster role its path gates allow, an `audit` one the whole core set. A major or worse on a light slice comes back from `
|
|
58
|
-
8. Verifier on the first blocker or major (Step 10). It runs no command itself: run `keryx review verify-run --package <package> --finding <id> -- <command>` and hand it the saved `research-evidence/verify-<id>-<n>.txt` as context.
|
|
59
|
-
9. `keryx review verdict <package>` to the operator, then the tail: mutation pass, `ledger build`, `ingest
|
|
57
|
+
7. Dispatch by slice roles: each role gets the slices that name it; a deep slice names every roster role its path gates allow, an `audit` one the whole core set. A major or worse on a light slice comes back from `review next` as an `escalated` dispatch: dispatch the core roles on it.
|
|
58
|
+
8. Verifier on the first blocker or major (Step 10). It runs no command itself: run `keryx review verify-run --package <package> --finding <id> -- <command>` and hand it the saved `research-evidence/verify-<id>-<n>.txt` as context. After it (no verifier ran: after the last reviewer), Wave D: `review-premise` (Step 10b).
|
|
59
|
+
9. `keryx review verdict <package>` to the operator, then the tail: mutation pass, `ledger build`, `ingest` (with `--premises`), the operator's answer to each held finding (Wave D), `readiness`, `complete`.
|
|
60
60
|
|
|
61
61
|
## Clean context — the round starts empty
|
|
62
62
|
|
|
@@ -85,9 +85,10 @@ Review Orchestrator Progress:
|
|
|
85
85
|
- [ ] Step 9: Collect reviewer-finding schema results and handle NEEDS_CONTEXT
|
|
86
86
|
- [ ] Step 9b: `jev-triage` — advisory, annotate-only severity/duplicate/verify-order annotations over the consolidated findings (opt-in `review.jev.triage`)
|
|
87
87
|
- [ ] Step 10: Wave C — when blockers/majors exist, `--verify` is set, or the PR is high-risk, dispatch `review-verifier` on the first blocker/major without waiting for other reviewers, then once per later pass over the findings held at that point
|
|
88
|
+
- [ ] Step 10b: Wave D — after the last verifier pass (none ran: after the last reviewer), dispatch `review-premise` (deep tier) over the canonical findings of severity ≥ minor (delta round: only those without a carried premise); pass its claims with `review ingest --premises <file>`; once that ingest wrote `findings.json` (the tail), ask the operator about each held finding (see "Wave D")
|
|
88
89
|
- [ ] Step 11: Sort by severity, deduplicate, emit unified report
|
|
89
90
|
- [ ] Step 12: Emit the machine-readable `keryx:findings` block alongside the report
|
|
90
|
-
- [ ] Step 13: Report the stage counts: dropped by pre-filter, refuted by the verifier, retained
|
|
91
|
+
- [ ] Step 13: Report the stage counts: dropped by pre-filter, refuted by the verifier, downgraded and held by the premise judge, retained
|
|
91
92
|
- [ ] Step 14: Managed rounds only (not `lightweight`, which is report-only), after the final round, on an open pull request at the head you reviewed — answer every external comment once with `keryx review comments reply --final` (render with `--dry-run`; the post itself is the operator's: the `review_comments_reply` card in keryx shell, else they run it in their terminal; unattended: do not publish, hand the rendered body back) — never against a pull request the dispatch named as the caller's
|
|
92
93
|
```
|
|
93
94
|
|
|
@@ -101,25 +102,26 @@ It names a model only if you gave it your session (`--session-provider`/`--sessi
|
|
|
101
102
|
|
|
102
103
|
### Step 6a — the plan bridge
|
|
103
104
|
|
|
104
|
-
Publish this checklist with `plan_set` under the ids `step-0`…`step-14` once, here, when scope and dispatch are fixed (keryx shell already published it as `pending` at the start — update it with `plan_update` instead; another host uses its own plan tool, "Hosts"). Publish each of steps 0–5 that ran as `completed` and each that did not run as `skipped`; publish steps 6–14 as `pending` (`in_progress` for the one starting now). From then on move each item with `plan_update` as its step completes — see the `session-plan-bridge` rule. `completed` means the step's artifact exists: steps 8–10 become `completed` (in the plan and in the report) only after `keryx review ingest` has recorded their results, and a step whose reviewers were `BLOCKED` is `blocked`.
|
|
105
|
+
Publish this checklist with `plan_set` under the ids `step-0`…`step-14` and `step-10b` once, here, when scope and dispatch are fixed (keryx shell already published it as `pending` at the start — update it with `plan_update` instead; another host uses its own plan tool, "Hosts"). Publish each of steps 0–5 that ran as `completed` and each that did not run as `skipped`; publish steps 6–14 and 10b as `pending` (`in_progress` for the one starting now). From then on move each item with `plan_update` as its step completes — see the `session-plan-bridge` rule. `completed` means the step's artifact exists: steps 8–10 and 10b become `completed` (in the plan and in the report) only after `keryx review ingest` has recorded their results (10b: `--premises`), and a step whose reviewers were `BLOCKED` is `blocked`.
|
|
105
106
|
|
|
106
107
|
## How to spawn (Steps 8 and 10)
|
|
107
108
|
|
|
108
109
|
- One `Agent` call per reviewer, all calls of a wave in a single message, so the wave runs in parallel.
|
|
110
|
+
- Reviewers are read-only: they read the diff and the files and run no command, except the read-only history commands `git log`, `git blame` and `git show` (law 4; `review-premise` too) where the host gives a read-only child git. keryx shell does not: a `spawn_subagent` child has no shell and no git tool, so you run `git log -L <start>,<end>:<file>` and `git blame -L <start>,<end> <file>` for each deliberate-looking site a reviewer must judge and pass the output in `context_files`; with neither, the reviewer says the history was not read. Only you (through `keryx review verify-run --timeout <seconds>`), the verifier and at most one testing reviewer run other commands, inside a time budget. Each payload carries `allowed_tools` (`read-only` or `run-tests`) and `exec_budget_s`.
|
|
109
111
|
- 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`.
|
|
110
112
|
- Prompts carry pointers, not pasted files — the diff, the SHAs, the PR, the schema paths — and never paraphrase a contract. On keryx shell the slices travel in `context_files` instead (below). Run `keryx review dispatch-check --payload <file> --manifest <package>/slices/manifest.json --package <package>` on every payload before a mass dispatch; it fails `REVIEWER_INPUT_PATH_MISSING` on a missing `skill_path` or `context_doc`.
|
|
111
113
|
- 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`. The one exception: a reply or dispatch error of `STATUS: RATE_LIMITED` is handled by the Rate limits rule under Control, never marked `BLOCKED`.
|
|
112
|
-
- 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
|
|
114
|
+
- 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 reviewers and `review-premise` `deep` (`keryx review tier --premise`); an omitted tier runs the child on your own model.
|
|
113
115
|
|
|
114
116
|
## Slices, waves and results — every host; keryx shell specifics marked
|
|
115
117
|
|
|
116
118
|
A reviewer starts in the project root and reads project files; a path outside the project root is unreadable to it. On keryx shell its `context_files` content reaches it wrapped as DATA, and slices and measurements travel only there (never pasted or retyped); elsewhere the prompt names the slice paths. `skill_path` and `pr_context` stay payload fields. The text reaches the reviewer in slices small enough to finish.
|
|
117
119
|
|
|
118
|
-
0. **Publish the plan before anything else (keryx shell).** 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.
|
|
120
|
+
0. **Publish the plan before anything else (keryx shell).** Your first tool call is `plan_set` with `step-0`…`step-14` and `step-10b` 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.
|
|
119
121
|
1. **Slice first.** `keryx review slice --ref <base> --package <package> --host <host>` after `keryx review start`. It writes `<package>/slices/slice-NN.diff` files of at most 150000 bytes each and a `manifest.json` carrying a wave budget (`--wave-bytes`, never below the slice ceiling; default by `--host`: 60000 on keryx-shell, 150000 elsewhere): what ONE reviewer dispatch may total, so a role owning many slices is dispatched in slice waves that each fit the child deadline. On keryx shell with 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.
|
|
120
122
|
2. **Slices travel by path; on keryx shell, only by `context_files`.** The slices sit under the project (`<package>/slices`). On keryx shell 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. Elsewhere name the slice paths in the prompt. Put the `slices` ids in its reviewer-input. A dispatch that names a git range but no slice leaves the reviewer with nothing to read — that is `BLOCKED`, not a review.
|
|
121
123
|
3. **Check before dispatch, every payload.** `keryx review dispatch-check --payload <file> --manifest <package>/slices/manifest.json --package <package>` for the wave; exit 1 means a payload names no slice, is over the wave ceiling (dispatch fewer slices, then the next wave), names a `skill_path` or `context_doc` that does not exist (`REVIEWER_INPUT_PATH_MISSING`), belongs to an unconfirmed over-threshold plan (`REVIEWER_INPUT_PLAN_UNCONFIRMED`), or breaks `reviewer-input.schema.json`. Fix it; do not dispatch around it.
|
|
122
|
-
4. **One batch.** Dispatch the whole wave — up to 10 reviewers — in one message, not one at a time. On keryx shell every round reviewer's `spawn_subagent` carries `review_wave: {"package": "<package>", "pass": "round"}` (a wave outside it counts against the turn's 32 children) and a `timeout_ms` that fits its wave: the default 300000 is sized for a wave of 60000 bytes, so a larger `--wave-bytes` needs a larger `timeout_ms`. 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, in its `REVIEW_RESULT` object, as ids (`"slices": ["slice-01", "slice-02"]`); an object with an `id` and an optional `coverage` note (`{"id": "slice-01", "coverage": "read in full"}`) is read the same way. An object with a `status` counts only when it is DONE, COMPLETE, COVERED or OK (any case); a slice marked NOT_READ, INCOMPLETE, SKIPPED or PARTIAL is not covered, so give a slice you did not read no `status` of that kind and leave it out. An entry with no id counts for nothing. **One driver file per dispatch.** Write `<package>/drivers/<reviewer>.json` with `{"reviewer": "<name>", "slices": [<ids dispatched>], "result": "raw/<reviewer>.txt", "definition": "<path of the reviewer's SKILL.md>"}`: `ledger build` takes the reviewer's rule file from `definition` (a `skill_path` there, or inside a `payload` object, is read too) and the slices it was handed from `slices`. Only reviewer replies belong in `raw/`; a verification payload or a note filed there is reported as set aside and left in place, but it still costs a step. 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 <package>/slices/manifest.json --result <package>/raw/<reviewer>.txt --package <package>` 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.
|
|
124
|
+
4. **One batch.** Dispatch the whole wave — up to 10 reviewers — in one message, not one at a time. On keryx shell every round reviewer's `spawn_subagent` carries `review_wave: {"package": "<package>", "pass": "round"}` (a wave outside it counts against the turn's 32 children) and a `timeout_ms` that fits its wave: the default 300000 is sized for a wave of 60000 bytes, so a larger `--wave-bytes` needs a larger `timeout_ms`. 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, in its `REVIEW_RESULT` object, as ids (`"slices": ["slice-01", "slice-02"]`); an object with an `id` and an optional `coverage` note (`{"id": "slice-01", "coverage": "read in full"}`) is read the same way. An object with a `status` counts only when it is DONE, COMPLETE, COVERED or OK (any case); a slice marked NOT_READ, INCOMPLETE, SKIPPED or PARTIAL is not covered, so give a slice you did not read no `status` of that kind and leave it out. An entry with no id counts for nothing. **One driver file per dispatch.** Write `<package>/drivers/<reviewer>.json` with `{"reviewer": "<name>", "slices": [<ids dispatched>], "result": "raw/<reviewer>.txt", "definition": "<path of the reviewer's SKILL.md>"}`: `ledger build` takes the reviewer's rule file from `definition` (a `skill_path` there, or inside a `payload` object, is read too) and the slices it was handed from `slices`. Only reviewer replies belong in `raw/`; a verification payload or a note filed there is reported as set aside and left in place, but it still costs a step. 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 <package>/slices/manifest.json --result <package>/raw/<reviewer>.txt --package <package>` 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. `keryx review slice --package <package>` already wrote one driver per reviewer x wave (`drivers/<reviewer>-w<n>.json`: slice ids, absolute slice paths, `result` path; the dispatcher adds `model`). Dispatch each wave in one batch, save each reply to its driver's `result`, and after each batch run `keryx review next --package <package>` (never `retry-plan` once per reviewer): it returns every reviewer's next wave at once, with reason `missing`, `retry`, `stalled` or `escalated`, or `done`. After a crash or timeout run it first: it collects late results from `<package>/raw/` and never re-hands a finished slice. Only the operator can accept a smaller set than that (`review_override_reviewers`, or `keryx review override-reviewers` in their terminal). An unfinished reviewer is never counted as a clean pass. **Persist every result, on every host.** On keryx shell pass each reviewer `save_result_to: <package>/raw/<reviewer>.txt`: the host writes its full final text there. Elsewhere the prompt tells the reviewer to write its whole reply to `<package>/raw/<reviewer>.txt` before it answers. Either way `review complete` has raw evidence after the transcript is cut, and you parse that file, never the tool output. Build `research.json` with `keryx review ledger build --package <package>` — 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 <package>/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`.
|
|
123
125
|
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.
|
|
124
126
|
6. **Write mutants whole.** A testing reviewer's `mutant_candidates` cover every changed branch, code downstream of the diff included. Write them to `research-evidence/mutants.json` unchanged; you may not narrow them, and a candidate no pass has run still blocks the coverage gate (`SKILL.detail.md`, mutation pass).
|
|
125
127
|
7. **Measure before `review-layout`.** Run the browser measurements (Playwright/Storybook) yourself and pass them in its first dispatch (`context_files` on keryx shell, by path elsewhere); they count as evidence when the command and viewport are named. A second `NEEDS_CONTEXT` from one role is Not run (`layout: no engine`), not another refill (`SKILL.detail.md`).
|
|
@@ -127,11 +129,11 @@ A reviewer starts in the project root and reads project files; a path outside th
|
|
|
127
129
|
## Control
|
|
128
130
|
|
|
129
131
|
- **Profiles.** The default is read-only: one round, no edits. `--fix` hands the findings to `flow-orchestrator` or `task-implementer`; the orchestrator never edits code. Control returns to this main session after each hand-off, which loads this skill again (never the implementer, which would nest); each re-review counts toward the ceiling (it adds 1 to the count).
|
|
130
|
-
- **Waves.** Split by diff domain (`core` = logic, security, architecture; `domain` = frontend, backend, conventions; `support` = style, tests), in that order; A/B/C below keep their dependency order, except Wave C, which starts early and overlaps A and B (see Wave C). A full or `--all` round runs at most 10 reviewers per wave (`MAX_REVIEWERS_PER_WAVE_FULL`).
|
|
132
|
+
- **Waves.** Split by diff domain (`core` = logic, security, architecture; `domain` = frontend, backend, conventions; `support` = style, tests), in that order; A/B/C/D below keep their dependency order, except Wave C, which starts early and overlaps A and B (see Wave C); Wave D runs after the last verifier pass. A full or `--all` round runs at most 10 reviewers per wave (`MAX_REVIEWERS_PER_WAVE_FULL`).
|
|
131
133
|
- **Rate limits.** On a reviewer dispatch that fails with a rate-limit or overloaded error (reported as `STATUS: RATE_LIMITED`, a harness signal, not a schema status), halve the wave, requeue the rest and honour `retry-after`, at most 300 seconds (`MAX_RETRY_AFTER_SECONDS`). After at most two halvings (`MAX_RATE_HALVINGS`) stop with `STATUS: BLOCKED rate_limited`, naming the queue left.
|
|
132
|
-
- **Early verdict.** When every reviewer and the verifier are done, save every verifier pass to `research-evidence/verifications.json`, then run `keryx review verdict <package>` (it reads `<package>/raw`; the shared `.metaproject/data/review/raw` only when passed as `--raw`, which mixes in other rounds) and give the operator the verdict then; refuted findings are excluded only once `verifications.json` exists. The mutation pass, ledger and `keryx review complete` continue as the tail, and every managed round finishes them. The verdict is interim: the round is not done until `complete` (`SKILL.detail.md` § "Early verdict").
|
|
133
|
-
- **Recovery.** After a timeout or crash: collect, validate, ingest, then dispatch only what is missing with `keryx review
|
|
134
|
-
- **Done when** the consolidated report and the `keryx:findings` block are emitted and the stage counts and **Not run** are stated. A managed round (not `lightweight`, which is report-only) is also done only when every dispatched reviewer's result is recorded with `keryx review ingest` and `keryx review complete` has run. `completed` means `keryx review readiness` passed, or each failing item is waived by the operator: in keryx shell call `review_waive_readiness` (a card, never a terminal), then run `keryx review complete`; elsewhere the operator runs `keryx review complete <package> --waive <item> "<their words>"` in their terminal; unattended, record Not run; publishing to GitHub is held by the same checklist, and a not-ready package goes out only through `keryx review publish --partial` (in keryx shell: `review_publish` with `partial: true`).
|
|
134
|
+
- **Early verdict.** When every reviewer and the verifier are done, save every verifier pass to `research-evidence/verifications.json`, then run `keryx review verdict <package>` (it reads `<package>/raw`; the shared `.metaproject/data/review/raw` only when passed as `--raw`, which mixes in other rounds) and give the operator the verdict then; refuted findings are excluded only once `verifications.json` exists, held ones only once Wave D's claims are saved to `research-evidence/premises.json`. A verdict given before Wave D ran is provisional, and you say so: it counts as open the findings the judge may still hold or lower. The mutation pass, ledger and `keryx review complete` continue as the tail, and every managed round finishes them. The verdict is interim: the round is not done until `complete` (`SKILL.detail.md` § "Early verdict").
|
|
135
|
+
- **Recovery.** After a timeout or crash: collect, validate, ingest, then dispatch only what is missing with `keryx review next --package <package>` (all reviewers at once). Never re-dispatch a wave whose results are on disk; after a second timeout of the same reviewer change the task (fewer slices, narrower focus), not only the diff size (`SKILL.detail.md` § "Recovery").
|
|
136
|
+
- **Done when** the consolidated report and the `keryx:findings` block are emitted and the stage counts and **Not run** are stated. A managed round (not `lightweight`, which is report-only) is also done only when every dispatched reviewer's result is recorded with `keryx review ingest` and `keryx review complete` has run. `completed` means `keryx review readiness` passed, or each failing item but `premise-decisions` (answered per finding, never waived) is waived by the operator: in keryx shell call `review_waive_readiness` (a card, never a terminal), then run `keryx review complete`; elsewhere the operator runs `keryx review complete <package> --waive <item> "<their words>"` in their terminal; unattended, record Not run; publishing to GitHub is held by the same checklist, and a not-ready package goes out only through `keryx review publish --partial` (in keryx shell: `review_publish` with `partial: true`).
|
|
135
137
|
|
|
136
138
|
---
|
|
137
139
|
|
|
@@ -237,7 +239,7 @@ keryx review start --target <kind> --ref <ref>
|
|
|
237
239
|
keryx review ingest --report <path> [--flow <id>] --ref <ref>
|
|
238
240
|
[--verifications <file>] [--verification-mode off|annotate|filter]
|
|
239
241
|
[--scope <scope.json>] [--blast-radius <blast-radius.json>]
|
|
240
|
-
[--refuted <file>]
|
|
242
|
+
[--refuted <file>] [--premises <file>]
|
|
241
243
|
# --blast-radius is REQUIRED whenever this round dispatched a
|
|
242
244
|
# scope-B reviewer (review-regression). See below.
|
|
243
245
|
keryx review status <review-id-or-path>
|
|
@@ -480,25 +482,7 @@ Read each run's verdict (`flaky` | `regression` | `infra`) into the report: `fla
|
|
|
480
482
|
|
|
481
483
|
## Everything written to GitHub is brief
|
|
482
484
|
|
|
483
|
-
|
|
484
|
-
replies, issue comments, and commit messages going to a PR.**
|
|
485
|
-
|
|
486
|
-
- Lead with the conclusion. No preamble, no restating the question, no apology,
|
|
487
|
-
no summary of the flow.
|
|
488
|
-
- Say what changed and where. **Link, do not paste.**
|
|
489
|
-
- The reasoning, the evidence, the rejected alternatives and the round history live
|
|
490
|
-
in the flow package — `journal.md`, `context.md`, the review artifacts — which is
|
|
491
|
-
durable, searchable, and costs a reader nothing to skip.
|
|
492
|
-
- A GitHub artifact that needs more than a short paragraph is a signal that the
|
|
493
|
-
detail belongs in the flow with a link out, **not** that the paragraph should
|
|
494
|
-
grow.
|
|
495
|
-
- No orchestrator-written PR comment or reply exceeds two sentences without
|
|
496
|
-
carrying a link to the artifact holding the detail. The reply pass enforces
|
|
497
|
-
this; for anything else you write outward, hold yourself to it.
|
|
498
|
-
|
|
499
|
-
This is deliberately asymmetric: **verbose in the flow, terse on GitHub.** The
|
|
500
|
-
flow is written for whoever resumes the work; GitHub is read by someone who did
|
|
501
|
-
not ask for our reasoning and is reading between other tasks.
|
|
485
|
+
PR bodies, comments, replies and commit messages lead with the conclusion, say what changed and where, and link rather than paste; verbose in the flow, terse on GitHub (`SKILL.detail.md` § "Everything written to GitHub is brief").
|
|
502
486
|
|
|
503
487
|
## Review Context Pack
|
|
504
488
|
|
|
@@ -696,49 +680,15 @@ record `model_assignment: adaptive` with the model you chose.
|
|
|
696
680
|
|
|
697
681
|
### Fix round check (Step 1a)
|
|
698
682
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
the
|
|
702
|
-
|
|
703
|
-
**
|
|
704
|
-
|
|
705
|
-
**
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
is no point at which a malformed dispatch could be rejected. `reviewer-input` is
|
|
709
|
-
also absent from the `CONTRACTS` registry (`src/gdskills/contracts.ts`), so
|
|
710
|
-
`keryx skills contracts validate` cannot be pointed at it either.
|
|
711
|
-
|
|
712
|
-
So this is a requirement on you, unenforced, and the only evidence it was met is
|
|
713
|
-
the `prior_findings` array the reviewer actually receives. A reviewer that cannot
|
|
714
|
-
see what the fix was answering cannot tell whether the fix is complete.
|
|
715
|
-
|
|
716
|
-
Two scope rules apply, and they exist because breaking them is what produced
|
|
717
|
-
seven rounds on PR #215 and four on PR #216:
|
|
718
|
-
|
|
719
|
-
1. **Review `merge-base..HEAD`, never the fix commit alone.** Narrowing to the
|
|
720
|
-
newest commit is the intuitive move and it is wrong: it hides the blast
|
|
721
|
-
radius. A fix that changes a guard, an instruction, a refusal or a helper
|
|
722
|
-
makes every *other* site that names it wrong, and those sites are outside the
|
|
723
|
-
fix commit by construction.
|
|
724
|
-
|
|
725
|
-
2. **Enumerate what NAMES the thing the fix changed.** For each guard,
|
|
726
|
-
instruction, message, refusal or helper the fix touched, grep for its callers
|
|
727
|
-
and for the text that recommends it, and record the result in
|
|
728
|
-
`review_context.scope.files`. On PR #216 a round corrected one operator
|
|
729
|
-
instruction of four; the correction silently broke the other three, and
|
|
730
|
-
nothing looked for them because nothing was asked to.
|
|
731
|
-
|
|
732
|
-
Recording the enumeration matters as much as doing it: a round that searched and
|
|
733
|
-
found nothing is a different fact from a round that never searched, and only the
|
|
734
|
-
recorded list distinguishes them.
|
|
735
|
-
|
|
736
|
-
Every prior finding leaves the round with a disposition — `closed`, `open`, `partial`,
|
|
737
|
-
`regressed` or `withdrawn` — one line each in the report before the new findings, checked against
|
|
738
|
-
the code and not the commit message. A fix is new code: scope A includes it, and the report carries
|
|
739
|
-
a `## Regressions the fixes introduced` section. A finding this round disproves is withdrawn at the
|
|
740
|
-
top of the report with its evidence. The table, recorded shapes and rationale:
|
|
741
|
-
`SKILL.detail.md` § "Fix rounds — dispositions, regressions, withdrawal".
|
|
683
|
+
`keryx review start` (or `keryx review plan`) decides the round; you never pick a range. `<package>/round.json` says round N, the mode (`first`, `delta`, `fallback-first`), the source that found the previous round and the `range`; `<package>/prior_findings.json` holds the earlier findings. "Round 1 — no previous round found (sources tried …)" is a valid outcome: review as a first round and say which sources were tried.
|
|
684
|
+
|
|
685
|
+
- **`delta` round.** A FIX slice (`kind: fix`, a hunk that answers a prior finding) gets `review-logic`, `review-regression`, the authors of the findings attached to it and the verifier. Set `is_fix_round: true` and attach those findings as `prior_findings` on each of those reviewer inputs. A NEW slice (`kind: new`) is reviewed as round 1, with the roles its slice names. Code of `merge-base..head` that did not change since the previous round gets one cheap second look: SECOND-LOOK slices (`kind: second-look`, listed in `round.json` `secondLookHunks`) are read once per round by `review-logic` and `review-security-code` only, and their findings are ordinary findings. When round.json says "previous round weak: …" (the previous round did not complete, left uncovered slices, skipped required reviewers, had "Not run" lines, or reviewed a narrower scope) that code is `kind: new` instead and gets the full round-1 treatment. `review plan` prints "second-look: N slices / M dispatches". Carried findings keep their dispositions. An empty range (base equals head: a merged pull request read against its own target branch) is refused; pass the recorded base with `review start --base` / `review plan --ref`. A reviewer on a FIX slice returns `prior_dispositions: [{id, disposition}]` in its `REVIEW_RESULT`, one entry for every attached finding id.
|
|
686
|
+
- **`fallback-first` round** (force-push or rebase: the previous head is not an ancestor). Review `merge-base..head` in full, with the prior findings attached.
|
|
687
|
+
- **Every attached prior finding leaves the round with a disposition** — `closed`, `open`, `partial`, `regressed` or `withdrawn` — one line each in the report before the new findings, checked against the code and not the commit message. A fix is new code: the report carries a `## Regressions the fixes introduced` section. A finding this round disproves is withdrawn at the top of the report with its evidence. Table, recorded shapes and rationale: `SKILL.detail.md` § "Fix rounds — dispositions, regressions, withdrawal".
|
|
688
|
+
- **Duplicates.** `keryx review ingest` merges duplicate findings; later waves receive `known_findings` and do not report them again.
|
|
689
|
+
- **Enumerate what NAMES the thing the fix changed.** For each guard, instruction, message, refusal or helper a fix hunk touched, find its callers and the text that recommends it, and record the result in `review_context.scope.files`. On PR #216 a round corrected one operator instruction of four and silently broke the other three, because nothing looked. A round that searched and found nothing is a different fact from one that never searched; only the recorded list tells them apart.
|
|
690
|
+
|
|
691
|
+
**The Jev edit guard is a FIX-phase tool.** `keryx review jev-edit-guard` runs in the author's agent while it applies fixes; this skill never runs it. Nothing refuses a dispatch that omits them (the `prior_findings`): `reviewer-input.schema.json` states the rule, no production code loads it, and the `prior_findings` array a reviewer receives is the only evidence it was met.
|
|
742
692
|
|
|
743
693
|
### Step 2: Determine Review Mode
|
|
744
694
|
|
|
@@ -932,7 +882,7 @@ Three bounds keep it from deleting coverage:
|
|
|
932
882
|
|
|
933
883
|
- **Only path-triggered reviewers.** A reviewer selected by an explicit flag, or
|
|
934
884
|
one whose scope is the whole change rather than a path set — `review-logic`,
|
|
935
|
-
`review-regression`, `review-verifier` — is never path-gated. One exception, for project reviewers only: a flag that more than one project reviewer carries is a **family flag** (the inventory lists it in that reviewer's `familyFlags`). It selects the whole family, and each member stays path-gated — `--<family>` over a diff touching one member's paths dispatches that member, not all of them.
|
|
885
|
+
`review-regression`, `review-verifier`, `review-premise` — is never path-gated. One exception, for project reviewers only: a flag that more than one project reviewer carries is a **family flag** (the inventory lists it in that reviewer's `familyFlags`). It selects the whole family, and each member stays path-gated — `--<family>` over a diff touching one member's paths dispatches that member, not all of them.
|
|
936
886
|
- **Scope A only.** Scope B is the blast radius; it is *supposed* to name files the
|
|
937
887
|
diff never touched.
|
|
938
888
|
- **Ambiguity includes.** If you cannot decide whether a path matches, dispatch.
|
|
@@ -1061,6 +1011,7 @@ Review Plan Preview must include an `Optional legacy/profile reviewers` group (e
|
|
|
1061
1011
|
| `--pr-contract` | `review-pr-contract` |
|
|
1062
1012
|
| `--all` | all reviewers above (including `review-clean-code`, `review-highload`, and project convention reviewers when local convention docs exist); never the legacy/profile reviewers, which stay flag-only |
|
|
1063
1013
|
| `--verify` | `review-verifier`, started on the first blocker or major and re-run for each later one (`SKILL.detail.md` § "Early verifier"); checks the findings by running something. Delete-only. |
|
|
1014
|
+
| (always, Wave D) | `review-premise` after the verifier, over the canonical findings of severity ≥ minor; judges whether each is a defect at all; lowers or holds, never adds. Not a fan-out flag |
|
|
1064
1015
|
| (auto) | detected from diff file extensions — see Auto-detection table |
|
|
1065
1016
|
|
|
1066
1017
|
Multiple flags may be combined: `review --backend --security` dispatches `review-logic` + `review-backend` + `review-architecture` + `review-security-code`; `review --frontend --frontend-conventions` dispatches the generic frontend set plus the local frontend conventions reviewer.
|
|
@@ -1113,6 +1064,7 @@ Dispatch selected reviewers in parallel when independent — this engine dispatc
|
|
|
1113
1064
|
1. Wave A - core correctness/risk reviewers: logic, architecture, security/highload when selected.
|
|
1114
1065
|
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".
|
|
1115
1066
|
3. Wave C - **verification**: `review-verifier` over the findings, started on the first blocker/major while other reviewers still run and re-run for each later one (`SKILL.detail.md` § "Early verifier"), or when `--verify` is set or the PR is high-risk. Exception to the A, B, C order: Wave C overlaps A and B and gets the findings held when each pass starts; Step 9b's `verify_order` applies to the later passes; each verifier pass is its own run. See below.
|
|
1067
|
+
4. Wave D - **premise**: `review-premise` after the last verifier pass (see "Wave D" below).
|
|
1116
1068
|
|
|
1117
1069
|
**Execution belongs to both B and C, and they execute for opposite reasons.** Wave C runs a command to *decide the fate of a finding that exists*; it is delete-only and can produce nothing. Wave B runs commands to *make findings* — `review-testing-practices` deletes each gate the diff added and records whether the suite goes red, and `review-layout` measures rendered geometry in a real engine.
|
|
1118
1070
|
|
|
@@ -1168,6 +1120,14 @@ Dispatch rules:
|
|
|
1168
1120
|
rewritten finding, the merge discards that whole claim and records the attempt.
|
|
1169
1121
|
Do not "help" by applying it.
|
|
1170
1122
|
|
|
1123
|
+
### Wave D — the premise judge, after the verifier
|
|
1124
|
+
|
|
1125
|
+
A finding can reproduce and still not be a defect: one against a timeline pinned LTR on purpose, as platform practice advises, passed the verifier because the `dir="ltr"` really was there. `review-premise` asks the other question, on the deep tier and a clean context: intent, accepted practice, consistency, fix soundness.
|
|
1126
|
+
- Before dispatch, renumber any display id that another finding, carried or new, already has, in the saved reviewer results, so the judge, its claims and ingest all see the same ids. A new finding has no `global_id` yet (ingest mints `<reviewId>#<id>` after Wave D); ingest refuses two findings under one key, and a claim naming an id two findings share is rejected as `ambiguous-finding`.
|
|
1127
|
+
- Dispatch it once after the last verifier pass (no verifier ran: after the last reviewer), over the canonical findings of severity ≥ minor, each with its display `id`, the **real** `reviewer` and `source`, and, for a finding carried from an earlier round, its `global_id`. External (PR-comment, `source: external`) findings are included: they can be challenged, never downgraded. In a delta round only findings without a carried premise. On keryx shell the judge has no shell and no git tool: run `git log -L` and `git blame -L` for each cited site first and pass the output in `context_files`.
|
|
1128
|
+
- The judge's claims name the `id`, or a carried finding's `global_id`. Save its claims object unchanged to `research-evidence/premises.json` (the verdict reads it there) and pass that file with `keryx review ingest --premises <file>`; never apply verdicts by hand. The merge is delete-only: `upheld` changes nothing, `downgraded` lowers the severity, and a claim that adds, raises or rewrites is rejected and listed in `scope.md`.
|
|
1129
|
+
- `challenged` and `owner-decision` **hold** a finding: it is neither fixable nor clean — not an open blocker or major, never in a fix loop's `fix_context.review_feedback`, and it blocks until answered; the verdict lists it as awaiting the operator. **Asking about a held finding** (every skill that meets one points here): at the tail, after `ingest --premises` wrote `findings.json` (never during Wave D, before the ingest: the answer commands read `findings.json`), in keryx shell call the card `review_decide_premise`, which records the answer; elsewhere put its `question` and `options` to the operator with the host's question tool, then give them the exact command to run in their own terminal, `keryx review decide-premise --package <package> --finding <global_id> --answer uphold|dismiss --reason "<why>"`, and wait. Never run it yourself (it needs a terminal) and never write their reason. In a flow, journal the recorded answer. Readiness and the flow review gate fail while a held finding has no decision. Unattended: leave it held and report it.
|
|
1130
|
+
|
|
1171
1131
|
### `verification_mode`
|
|
1172
1132
|
|
|
1173
1133
|
`off` | `annotate` | `filter`. **Default `annotate`, and it stays `annotate` for
|
|
@@ -1236,6 +1196,7 @@ Each reviewer must return a `REVIEW_RESULT` object matching `.metaproject/skills
|
|
|
1236
1196
|
| Performance anti-patterns | NO | `review-performance` |
|
|
1237
1197
|
| Style / naming / import order | NO | `review-style` |
|
|
1238
1198
|
| Checking whether a reported finding is real | NO | `review-verifier` |
|
|
1199
|
+
| Judging whether a finding is a defect at all | NO | `review-premise` |
|
|
1239
1200
|
| Clean Code principles + SOLID at code level | NO | `review-clean-code` |
|
|
1240
1201
|
| Concurrency, resource pools, caching, queues, idempotency | NO | `review-highload` |
|
|
1241
1202
|
| Frontend repository conventions | NO | `review-frontend-conventions` |
|
|
@@ -1350,17 +1311,12 @@ inventing a fifth level to express it would put us back where we started.
|
|
|
1350
1311
|
|
|
1351
1312
|
### Shared laws (every reviewer)
|
|
1352
1313
|
|
|
1353
|
-
1. **A claim of runtime harm with no reproducible path is `info`.** If you cannot
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
3. **One finding per class, not one per occurrence.** When the same shape appears
|
|
1360
|
-
at several sites, report it once and list every site. Ten findings that are one
|
|
1361
|
-
finding hide the other nine problems.
|
|
1362
|
-
|
|
1363
|
-
`review-security-code` carries a fourth — every security finding states its attack
|
|
1314
|
+
1. **A claim of runtime harm with no reproducible path is `info`.** If you cannot name the input, call, or condition that reaches the code, you have an observation, not a finding. Report it as `info` and say what would settle it.
|
|
1315
|
+
2. **Never flag the theoretical.** The path you describe must exist in the code under review. Do not report a safe API because it could be misused, or a pattern because it is often wrong elsewhere.
|
|
1316
|
+
3. **One finding per class, not one per occurrence.** When the same shape appears at several sites, report it once and list every site. Ten findings that are one finding hide the other nine problems.
|
|
1317
|
+
4. **A deliberate choice is not a defect until its reason is read and shown wrong.** An explicit override, suppression or exemption, a comment or commit giving a reason, or a sibling doing the same is a decision: read its reason (the comment, `git log -L` or `git blame`, the sibling) before you report it, and report it only when you can show that reason wrong. A project rule is checked against accepted platform practice and its known exceptions before a deviation from it is reported.
|
|
1318
|
+
|
|
1319
|
+
`review-security-code` carries a fifth — every security finding states its attack
|
|
1364
1320
|
vector — which does not generalise and stays there.
|
|
1365
1321
|
|
|
1366
1322
|
## Finding Format
|
|
@@ -1503,7 +1459,7 @@ file and must include the wire-contract line.
|
|
|
1503
1459
|
|
|
1504
1460
|
## Stage counts
|
|
1505
1461
|
|
|
1506
|
-
Required in **How this review was run**, copied from `scope.md`, not re-counted by hand. State what each stage removed. Never state it as a precision improvement: no precision baseline exists to improve on. The line carries `verification_mode` (`off | annotate | filter`), confirmed / refuted / unverifiable / unverified, and retained.
|
|
1462
|
+
Required in **How this review was run**, copied from `scope.md`, not re-counted by hand. State what each stage removed. Never state it as a precision improvement: no precision baseline exists to improve on. The line carries `verification_mode` (`off | annotate | filter`), confirmed / refuted / unverifiable / unverified, the premise verdicts (upheld / downgraded / held), and retained.
|
|
1507
1463
|
|
|
1508
1464
|
`## Checked and cleared` is now **Verified clean**. Same rule: a hypothesis
|
|
1509
1465
|
that was tested and died, with the evidence, not a list of virtues. There is
|
|
@@ -1595,6 +1551,7 @@ When a prompt carries `JOB_NAME` and `CONTEXT_PATH`, read that context document
|
|
|
1595
1551
|
| "A strict re-read of the findings will sharpen them" | That pass existed and was removed: self-correction without new evidence measured 95.5 → 91.5 → 89.0 on GSM8K and 75.8 → 38.1 on CommonSenseQA. Run something instead |
|
|
1596
1552
|
| "Three reviewers agree, so the finding is verified" | Consensus is not evidence. 80+ agents unanimously endorsed a vulnerability that did not exist; one empirical test killed it |
|
|
1597
1553
|
| "The verifier suggested a higher severity, I'll apply it" | It cannot suggest one. A claim carrying a severity is discarded whole and the attempt is recorded |
|
|
1554
|
+
| "The verifier confirmed it, so the fixer gets it" | Confirmed means the fact reproduces, not that it is a defect. Wave D judges the premise; a held finding waits for the operator |
|
|
1598
1555
|
| "This finding has no `verification`, so it can be dropped" | Absent means nobody checked. All 83 recorded findings are in that state; none of them is thereby wrong |
|
|
1599
1556
|
| "Precision went up after the verifier landed" | There is no precision baseline to have gone up from. State stage counts: dropped, refuted, retained |
|
|
1600
1557
|
| "I'll widen the blast radius, this change looks risky" | It is bounded because review quality decays with context: F1 0.65 at round 2 → 0.29 at round 10. Widening makes the later rounds worse, not safer |
|
|
@@ -193,6 +193,19 @@
|
|
|
193
193
|
"minLength": 1
|
|
194
194
|
}
|
|
195
195
|
},
|
|
196
|
+
"prior_dispositions": {
|
|
197
|
+
"title": "Dispositions of prior findings (FIX slices)",
|
|
198
|
+
"description": "Returned by a reviewer on a FIX slice: one entry for every attached prior finding id, giving its disposition checked against the code. The ledger reads it.",
|
|
199
|
+
"type": "array",
|
|
200
|
+
"items": {
|
|
201
|
+
"type": "object",
|
|
202
|
+
"required": ["id", "disposition"],
|
|
203
|
+
"properties": {
|
|
204
|
+
"id": {"type": "string", "minLength": 1},
|
|
205
|
+
"disposition": {"type": "string", "enum": ["closed", "open", "partial", "regressed", "withdrawn"]}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
},
|
|
196
209
|
"slices": {
|
|
197
210
|
"title": "Slices this result covered",
|
|
198
211
|
"description": "The ids of the dispatched slices the reviewer read. An entry is an id string, or an object with an `id`, an optional `coverage` note and an optional `status`. `keryx review retry-plan` and `ledger build` read both. An object counts as covered only when its `status` is absent or one of DONE, COMPLETE, COMPLETED, COVERED, OK (any case); any other status (NOT_READ, INCOMPLETE, SKIPPED, PARTIAL, …) leaves the slice uncovered and is named in the plan reason or the ledger gap. An entry with no id counts for nothing.",
|