@mrciphersmith/keryx 0.3.118 → 0.3.120
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 +104554 -96795
- package/dist/core.js +1767 -1061
- package/package.json +1 -1
- package/src/gdgraph/service.ts +4 -0
- package/src/gdgraph/symbol-reach.ts +1069 -0
- package/src/gdskills/bundled/skills/orchestration/feature-dev/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/orchestration/flow-orchestrator/SKILL.md +37 -40
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.md +6 -6
- 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 +8 -0
- package/src/gdskills/bundled/skills/orchestration/task-implementer/output-contract.schema.json +19 -0
- package/src/gdskills/bundled/skills/platform/scheduled-tasks/SKILL.md +2 -2
- package/src/gdskills/bundled/skills/review/review-architecture/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-backend/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-clean-code/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-core-boundaries/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-flow-graph/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-frontend/SKILL.md +3 -7
- package/src/gdskills/bundled/skills/review/review-frontend-conventions/SKILL.md +4 -6
- package/src/gdskills/bundled/skills/review/review-highload/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-logic/SKILL.md +2 -2
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.detail.md +82 -17
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.md +78 -111
- 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 +1 -1
- package/src/gdskills/bundled/skills/review/review-pr-feedback/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-regression/SKILL.md +2 -2
- package/src/gdskills/bundled/skills/review/review-security-code/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-style/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-testing-practices/SKILL.md +1 -1
- package/src/gdskills/bundled/skills/review/review-verifier/SKILL.md +3 -3
- package/src/gdskills/contracts/review-finding.schema.json +25 -0
|
@@ -113,7 +113,7 @@ Input: codebase_path=<project_root>, scope=changed, base_branch=<base>
|
|
|
113
113
|
- `git diff main...HEAD` — review the full diff
|
|
114
114
|
- Check for: TODOs left behind, console.logs, hardcoded values
|
|
115
115
|
- Verify all acceptance criteria from Phase 1 spec
|
|
116
|
-
3. Fix any findings (max 2 review-fix cycles)
|
|
116
|
+
3. Fix any findings (max 2 review-fix cycles). Each next round is `keryx review start` or `keryx review plan` on the new head: the round comes from `round.json`; no own range, no whole-branch re-review (the `git diff main...HEAD` above is round 1 only).
|
|
117
117
|
4. Re-run `code-verifier` after any fixes
|
|
118
118
|
|
|
119
119
|
### Phase 8: DELIVER + CHANGE REPORT
|
|
@@ -77,11 +77,12 @@ flowchart TD
|
|
|
77
77
|
C --> D["flow-init context enrichment"]
|
|
78
78
|
D --> E["freeze AC + start flow"]
|
|
79
79
|
E --> F["dispatch tests-creator / task-implementer"]
|
|
80
|
-
F -->
|
|
80
|
+
F --> FG{"first green: ask operator - open PR or harden first"}
|
|
81
|
+
FG --> G["code-verifier + review-orchestrator"]
|
|
81
82
|
G --> H{"All tasks, checks, review OK?"}
|
|
82
83
|
H -- "no" --> F
|
|
83
84
|
H -- "yes" --> I{"Ask user how to finish"}
|
|
84
|
-
I -- "create PR" --> J["create PR
|
|
85
|
+
I -- "create PR" --> J["create PR; each round = review start on the new head (delta)"]
|
|
85
86
|
J --> K{"review clean, PR mergeable?"}
|
|
86
87
|
K -- "no, attempts < 5" --> J
|
|
87
88
|
K -- "no, attempts = 5 or repetition detected" --> R["enrich context and change fix strategy"]
|
|
@@ -177,9 +178,7 @@ Record attempts as they happen, not only on resume:
|
|
|
177
178
|
keryx flow task attempt <id> <Tn> --outcome started|failed|blocked [--detail "<what happened>"]
|
|
178
179
|
```
|
|
179
180
|
|
|
180
|
-
`attempts.count` is append-only and lives in `flow.json`. A counter that lives
|
|
181
|
-
only in the orchestrator's context resets to zero exactly when the loop bound
|
|
182
|
-
matters most, which makes it not a counter.
|
|
181
|
+
`attempts.count` is append-only and lives in `flow.json`. A counter that lives only in the orchestrator's context resets to zero exactly when the loop bound matters most, which makes it not a counter.
|
|
183
182
|
|
|
184
183
|
### 0.1 Route
|
|
185
184
|
|
|
@@ -244,27 +243,26 @@ Write or update:
|
|
|
244
243
|
- `tasks.md` - task definitions grouped by context, test, implement, review, docs;
|
|
245
244
|
- `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
245
|
|
|
246
|
+
### UI or state scope: a state × event matrix in plan.md
|
|
247
|
+
|
|
248
|
+
When the scope touches UI, a store, or other code that holds state across events, `plan.md` carries a state × event matrix before `flow freeze`. Rows are the states the surface can be in (for example loading, loaded, empty, missing, first-load failed, refresh failed); columns are the events that reach it (for example the user switches selection, unmount, workspace or context change, retry). Each cell is one line: what the user sees and which state survives, citing the project's styling/UX rules where they decide it. Every non-trivial cell gets an `ACn` row, or one AC per group of cells with the same result; a cell that is genuinely "no change" needs none. List only the states and events the change reaches:
|
|
249
|
+
|
|
250
|
+
| state \ event | user switches selection | unmount | retry |
|
|
251
|
+
|---|---|---|---|
|
|
252
|
+
| loading | drop the stale response; loading shows for the new one | no state write after unmount | — |
|
|
253
|
+
| refresh failed | keep loaded data; the error does not follow to the new selection | — | re-fetch; error stays inline until success |
|
|
254
|
+
|
|
255
|
+
It does not apply when the scope holds no UI or state (CLI output, pure functions, docs, build config): write `State × event matrix: not applicable — <why>` in `plan.md`. The matrix is what workers and fix rounds check behavior against; a choice no cell decides is a `behavior_changes` entry for the operator (Phase 2).
|
|
256
|
+
|
|
247
257
|
### A verification step in the plan is a task, not a sentence
|
|
248
258
|
|
|
249
|
-
Every check the plan says must happen before the work is accepted - run the
|
|
250
|
-
thing end to end, confirm two components agree, exercise the path no test
|
|
251
|
-
covers - is added with `keryx flow task add` and closed with
|
|
252
|
-
`keryx flow task done`. Prose in `plan.md` blocks nothing, and an
|
|
253
|
-
orchestrator that wrote the step is the same one deciding whether to run it.
|
|
259
|
+
Every check the plan says must happen before the work is accepted - run the thing end to end, confirm two components agree, exercise the path no test covers - is added with `keryx flow task add` and closed with `keryx flow task done`. Prose in `plan.md` blocks nothing, and an orchestrator that wrote the step is the same one deciding whether to run it.
|
|
254
260
|
|
|
255
|
-
The failure this prevents is specific and has happened: a plan listed
|
|
256
|
-
"confirm both components agree on the same input" as step 5, the
|
|
257
|
-
implementation shipped without it, and review found that the two did not
|
|
258
|
-
agree at all - the change could not work in production. The check had been
|
|
259
|
-
identified correctly and then skipped, because nothing made skipping it
|
|
260
|
-
visible.
|
|
261
|
+
The failure this prevents is specific and has happened: a plan listed "confirm both components agree on the same input" as step 5, the implementation shipped without it, and review found that the two did not agree at all - the change could not work in production. The check had been identified correctly and then skipped, because nothing made skipping it visible.
|
|
261
262
|
|
|
262
|
-
Tasks are the mechanism for this. `keryx flow complete` runs a `tasks` gate
|
|
263
|
-
over them, so an unrun verification step keeps the flow open instead of being
|
|
264
|
-
quietly dropped.
|
|
263
|
+
Tasks are the mechanism for this. `keryx flow complete` runs a `tasks` gate over them, so an unrun verification step keeps the flow open instead of being quietly dropped.
|
|
265
264
|
|
|
266
|
-
Know the gate's exact scope, because for years this file claimed a gate that
|
|
267
|
-
did not exist and 24 completed flows shipped with an open task:
|
|
265
|
+
Know the gate's exact scope, because for years this file claimed a gate that did not exist and 24 completed flows shipped with an open task:
|
|
268
266
|
|
|
269
267
|
- the gate is **opt-in per flow package**, keyed on `gates.tasks` in
|
|
270
268
|
`flow.json`, which `keryx flow init` writes for every flow it creates. A
|
|
@@ -389,11 +387,7 @@ fi
|
|
|
389
387
|
keryx flow task done <id> <Tn>
|
|
390
388
|
```
|
|
391
389
|
|
|
392
|
-
Why each path is checked on its own: `git status --porcelain --` with no path
|
|
393
|
-
lists the whole tree, `git add` fails on a path that is neither on disk nor
|
|
394
|
-
tracked, and `git commit` with nothing staged exits 1. The trailing
|
|
395
|
-
`-- "${PENDING[@]}"` commits only these paths, so a file another lane staged is
|
|
396
|
-
not swept into this commit.
|
|
390
|
+
Why each path is checked on its own: `git status --porcelain --` with no path lists the whole tree, `git add` fails on a path that is neither on disk nor tracked, and `git commit` with nothing staged exits 1. The trailing `-- "${PENDING[@]}"` commits only these paths, so a file another lane staged is not swept into this commit.
|
|
397
391
|
|
|
398
392
|
If new work is discovered:
|
|
399
393
|
|
|
@@ -415,6 +409,8 @@ properly formatted `subagent-result`.
|
|
|
415
409
|
| `BLOCKED` | `keryx flow block <id> --reason "<worker reason>"`; resolve or escalate one concise question, then `flow unblock` and re-dispatch. |
|
|
416
410
|
| `FAILED` | Emitted by harness **child** workers (`src/harness/child/contract.ts`), never by skill workers — `task-implementer` maps its own `failed` onto `BLOCKED`. Retry once with the same dispatch. If it fails again, block the flow and surface the error to the user. |
|
|
417
411
|
|
|
412
|
+
**A `behavior_changes` entry with `needs_operator: true` is a question, not a concern to journal.** task-implementer lists every user-visible tradeoff it made (message wording, error placement, state reset) there. Before accepting that result, ask the operator with the question tool — one question per entry, the implemented choice and each of its `alternatives` as options — and record the answer in `journal.md`. An answer other than the implemented one is a fix task on the same `Tn` before the boundary commit, not a review finding later.
|
|
413
|
+
|
|
418
414
|
Carry `run_id`/`dispatch_id` across retries so the flow journal stays traceable,
|
|
419
415
|
and record every dispatch against the task's persisted counter so a session
|
|
420
416
|
restart does not reset the budget:
|
|
@@ -432,7 +428,8 @@ Before accepting implementation:
|
|
|
432
428
|
1. Run focused tests for touched scope.
|
|
433
429
|
2. Run `code-verifier`.
|
|
434
430
|
3. Run `keryx health run` when Code Health is enabled.
|
|
435
|
-
4.
|
|
431
|
+
4. **First-green gate, once per flow.** The first time every implement/test task is `done` and steps 1–3 pass, ask the operator one question (question tool, options) before any review round: `issue AC met — open the PR with the standard review`, or `harden first` with each extra matrix cell or failure path you would add as its own option. Record the answer in `journal.md`; picked hardening becomes `keryx flow task add` tasks (plus `keryx flow ac update` when it adds criteria) before review. A dispatched run has no operator: it takes the standard review and journals that the dispatch answered the gate.
|
|
432
|
+
5. Check the bounds, then run `review-orchestrator` with relevant domains — in this session,
|
|
436
433
|
never handed whole to one subagent: one without a dispatch tool returns `STATUS: BLOCKED`.
|
|
437
434
|
```bash
|
|
438
435
|
keryx review budget --spent <usd-so-far> --full --outstanding <subagents still running, 0 if none>
|
|
@@ -440,16 +437,15 @@ Before accepting implementation:
|
|
|
440
437
|
A non-zero exit means the spend ceiling (3 USD by default) has been reached:
|
|
441
438
|
**stop and ask the user** rather than dispatching another fan-out — never shrink the fan-out to fit.
|
|
442
439
|
Dispatch prompts point at sources (files, SHAs, the PR) and never paraphrase a contract.
|
|
440
|
+
Every round opens with `keryx review start` on the current head, never a hand-built range (Phase 4 loop, step 1).
|
|
443
441
|
|
|
444
|
-
`--outstanding` is the part that matters here. `review-orchestrator` runs inline
|
|
445
|
-
in this session and dispatches reviewers in parallel; keryx cannot observe other
|
|
446
|
-
subagents. Passing the count still running is the only thing that makes the
|
|
447
|
-
concurrency cap mean anything; omit it and the cap bounds the reviewer fan-out
|
|
448
|
-
alone, which the review record then states plainly. Add `--full` for `--all`.
|
|
442
|
+
`--outstanding` is the part that matters here. `review-orchestrator` runs inline in this session and dispatches reviewers in parallel; keryx cannot observe other subagents. Passing the count still running is the only thing that makes the concurrency cap mean anything; omit it and the cap bounds the reviewer fan-out alone, which the review record then states plainly. Add `--full` for `--all`.
|
|
449
443
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
444
|
+
6. If findings require code changes, run a fix round through `task-implementer`, recorded as a flow fix task:
|
|
445
|
+
- **Scope freeze.** A fix round fixes the round's findings and nothing else. Hardening, refactors or new cells a fix suggests go to the operator as a question (as in step 4); never grow scope inside a fix round.
|
|
446
|
+
- **Red probes → ONE implementer.** When reviewers left red probes (failing tests or commands on the findings), pass them as `test_case_specs` to one `task-implementer` dispatch — no separate `tests-creator` task. `tests-creator` runs only for a new contract no probe covers.
|
|
447
|
+
- **`suggested_fix` is a hypothesis.** Pass each finding's `id` and `suggested_fix` in `fix_context.review_feedback`; the implementer reproduces the finding (red), checks the suggestion against the state × event matrix, then fixes (task-implementer 1.3). Journal every `suggested_fix diverged` / `did not reproduce` note it returns.
|
|
448
|
+
7. Close the skill-learning loop (see `rules/core/skill-lifecycle.mdc`). Collect
|
|
453
449
|
the `skill_drift` fields from task-implementer results and the
|
|
454
450
|
`## Skill Learning` block from review-orchestrator. For each flagged
|
|
455
451
|
project-skill, dispatch a subagent — on a cheaper / non-flagship model if one
|
|
@@ -536,10 +532,8 @@ the bound plus an escalation — never an unbounded loop.
|
|
|
536
532
|
|
|
537
533
|
### PR review/fix loop
|
|
538
534
|
|
|
539
|
-
1.
|
|
540
|
-
|
|
541
|
-
2. If findings or required check failures remain, create or update a flow fix
|
|
542
|
-
task, dispatch `task-implementer`, push the fix, and run review again.
|
|
535
|
+
1. Each round — the first and every one after a fix — is `keryx review start` on the PR's current head, then `review-orchestrator` from that package. `review start` finds the previous round itself (local package, git history, the PR's round block, the flow package) and, when the previous reviewed head is an ancestor, reviews the delta: fix changes with a small roster (logic, regression, the findings' authors, the verifier) and the prior findings attached, new changes as round 1, unchanged code carried with its dispositions. Never pass a whole-branch range or `--all` per round; `<package>/round.json` records the round, its source and its mode.
|
|
536
|
+
2. If findings or required check failures remain, run a fix round under Phase 3 step 6 (flow fix task, `task-implementer`), push the fix, and run the next round as in step 1.
|
|
543
537
|
|
|
544
538
|
**A required check failure is not automatically a fix task.** When `review.jev.ci_triage` is on, run `keryx review ci-triage --run <id> --json` on each failed run first: `top: flaky` (or a `deterministic` override) → rerun once (`gh run rerun --failed <id>`), record it in `journal.md`, and treat a second failure as `real-regression` regardless; `top: real-regression` → investigate and fix as usual; `top: infra` → report it in the completion notes and leave the code alone. The verdict is advisory only — never the sole reason to skip a fix task.
|
|
545
539
|
|
|
@@ -628,7 +622,7 @@ keryx flow complete <id>
|
|
|
628
622
|
|
|
629
623
|
Completion is allowed only after the PR merge has been confirmed. The merge
|
|
630
624
|
target must be the base branch captured when the flow was created; do not
|
|
631
|
-
silently retarget or close against another branch. The flow folder is committed in the same PR as the code; the commit at closing is a rule to follow, not one the gate checks. `flow complete` fails the `folder-committed` gate while the flow's `flow.json` is not in `HEAD` (flows created from 0.3.53 on; commit it with `git add .metaproject/flows/<dir> && git commit`, then run `flow complete` again). `flow init` and `flow renumber` avoid numbers used on known remote branches, and `keryx flow check` reports a clash with a remote branch (repair with `keryx flow renumber <dir> --to <free id> --reason "<why>"`) and warns about a folder that is not committed. Flows created since the owner gate fail completion while no owner is set (`keryx flow owner set <id> --owner "<name>" --reason "<why>"`); `ac confirm` and `flow complete` append a signature — `--signed-by "<name>"` names the signer, otherwise `KERYX_ACTOR` or the local git identity is recorded, as a claim. A flow created with `--require-confirmation` needs one more gate — `--confirm-token <token>` from `keryx flow confirm <id>`, a short-lived single-use token
|
|
625
|
+
silently retarget or close against another branch. The flow folder is committed in the same PR as the code; the commit at closing is a rule to follow, not one the gate checks. `flow complete` fails the `folder-committed` gate while the flow's `flow.json` is not in `HEAD` (flows created from 0.3.53 on; commit it with `git add .metaproject/flows/<dir> && git commit`, then run `flow complete` again). `flow init` and `flow renumber` avoid numbers used on known remote branches, and `keryx flow check` reports a clash with a remote branch (repair with `keryx flow renumber <dir> --to <free id> --reason "<why>"`) and warns about a folder that is not committed. Flows created since the owner gate fail completion while no owner is set (`keryx flow owner set <id> --owner "<name>" --reason "<why>"`); `ac confirm` and `flow complete` append a signature — `--signed-by "<name>"` names the signer, otherwise `KERYX_ACTOR` or the local git identity is recorded, as a claim. A flow created with `--require-confirmation` needs one more gate — `--confirm-token <token>` from `keryx flow confirm <id>`, a short-lived single-use token. In keryx shell call the `flow_confirm` tool (the operator answers it as a card; never send the operator to a terminal); outside it, a typed challenge in a terminal mints it. It proves an interactive step ran, not that a human ran it. A flow left stuck in `completing` by a crash or interrupted attempt (never a normal gate failure) recovers with `keryx flow recover <id> --reason "<why>"`.
|
|
632
626
|
|
|
633
627
|
If gates fail, the CLI returns the flow to `in-progress`. Add a journal note,
|
|
634
628
|
create fix tasks, and repeat Phase 2.
|
|
@@ -691,4 +685,7 @@ Stop and re-read this skill if you are thinking:
|
|
|
691
685
|
| "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. |
|
|
692
686
|
| "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. |
|
|
693
687
|
| "The review fan-out is cheap, so the budget check can wait." | `keryx review budget --spent … --outstanding …` gates the fan-out, and `review-orchestrator` runs inline in this same main session, where keryx cannot see the in-flight subagents; declare them with `--outstanding`. Skipping the check means the cap bounds nothing. |
|
|
688
|
+
| "The reviewer wrote the fix; applying it is the fastest close." | A `suggested_fix` is a hypothesis. Most majors in a long fix loop are introduced by fixes: reproduce the finding red, check the suggestion against the state × event matrix, then fix (Phase 3 step 6). |
|
|
689
|
+
| "While I'm in this code, the fix round can also harden the empty state." | Scope freeze: a fix round fixes findings. New hardening is an operator decision at the first-green gate or as an explicit question, never silent growth. |
|
|
690
|
+
| "The implementer journaled its UX choice, so it is decided." | A `behavior_changes` entry with `needs_operator: true` is decided by the operator, asked with options before the result is accepted (Phase 2). A journal line decides nothing. |
|
|
694
691
|
| "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`. |
|
|
@@ -1125,12 +1125,12 @@ runs on the session model. That is a correct answer, not a failure.
|
|
|
1125
1125
|
|
|
1126
1126
|
```
|
|
1127
1127
|
flags: <selected flags, e.g. --backend --security --testing-practices>
|
|
1128
|
-
commit_range: <BASE_SHA>..HEAD
|
|
1128
|
+
commit_range: <BASE_SHA>..HEAD # round 1 only; a later round takes its range from round.json
|
|
1129
1129
|
issue_url: <issue URL, when the job has one — enables the Stage 1 spec gate>
|
|
1130
1130
|
context_doc: <JOBS_ROOT>/<job-name>/ai/context.md
|
|
1131
1131
|
verification_mode: annotate
|
|
1132
1132
|
managed_review: { mode: "review-flow", target: "branch", target_ref: "<feature-branch>" }
|
|
1133
|
-
is_fix_round: <true on any round after the first>
|
|
1133
|
+
is_fix_round: <true on any round after the first; the round, its range and prior_findings come from `review start`/`review plan`, never from your own range>
|
|
1134
1134
|
pr_comments: { enabled: <true when a PR exists> }
|
|
1135
1135
|
```
|
|
1136
1136
|
|
|
@@ -1298,11 +1298,11 @@ FOR iteration in [1, 2, 3]:
|
|
|
1298
1298
|
4. Run the sanity check (step 2.5.2 logic) — verify commits were made
|
|
1299
1299
|
5. Run the next managed round — the FULL 2.6.1 sequence, not a bare re-dispatch:
|
|
1300
1300
|
keryx review budget --spent <usd> --outstanding <n>
|
|
1301
|
-
keryx review
|
|
1301
|
+
keryx review plan --target branch --ref <feature-branch> --head <new-head>
|
|
1302
|
+
# start + scope + blast-radius + slice + required + estimate on the new head;
|
|
1303
|
+
# round.json names the delta, scope.json and blast-radius.json land in the package
|
|
1302
1304
|
keryx review comments collect --repo <r> --pr <n> --sha <new-head> --round <N+1> --out <file>
|
|
1303
|
-
|
|
1304
|
-
keryx review blast-radius --ref "$BASE_SHA" --previous blast-radius.json --json > blast-radius.json
|
|
1305
|
-
<run review-orchestrator inline, in this session, with is_fix_round: true>
|
|
1305
|
+
<run review-orchestrator inline, in this session; it takes the round from round.json>
|
|
1306
1306
|
keryx review ingest --report <new-report> --ref <feature-branch> --head <new-head> \
|
|
1307
1307
|
--scope scope.json --blast-radius blast-radius.json \
|
|
1308
1308
|
--verifications <file> --refuted <file> --outstanding <n>
|
|
@@ -179,7 +179,7 @@ If `blocker` or `major` findings exist:
|
|
|
179
179
|
1. Group by file
|
|
180
180
|
2. Launch task-implementer (`task_type: "fix"`) with the findings
|
|
181
181
|
3. Run the sanity check — verify commits were made
|
|
182
|
-
4. Run the NEXT managed round (the
|
|
182
|
+
4. Run the NEXT managed round: `keryx review plan --target branch --ref <feature-branch> --head <new-head>` (or `review start`) on the new head, then review-orchestrator. The round, range and prior findings come from `round.json`: no own range, no `--all` per round, no whole-branch re-review.
|
|
183
183
|
5. Disposition every finding of the previous round:
|
|
184
184
|
```bash
|
|
185
185
|
keryx review complete <review-id> --finding F-001 --disposition acted-on --evidence "<commit>"
|
|
@@ -98,11 +98,13 @@ For a description-based task, omit `issue_number` and issue references in commit
|
|
|
98
98
|
|
|
99
99
|
```
|
|
100
100
|
FIX_CONTEXT:
|
|
101
|
-
review_feedback: structured findings from reviewer (file, line, severity, message)
|
|
101
|
+
review_feedback: structured findings from reviewer (id, file, line, severity, message, suggested_fix)
|
|
102
102
|
original_task_ids: the tasks that introduced the findings (array)
|
|
103
103
|
iteration: fix iteration number, 1..3 — the same repair bound as 5.4
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
+
**A reviewer's `suggested_fix` is a hypothesis, not an instruction.** Per finding: reproduce it first — a test or probe that fails on the current head (red); check the suggested fix against the plan's state × event matrix (`plan.md`, when it has one) and every caller the change reaches; then fix and show the probe green. A finding that does not reproduce is reported, not fixed. Record each divergence in `notes`: `suggested_fix diverged: <id> — <what you did instead and why>` or `did not reproduce: <id>`.
|
|
107
|
+
|
|
106
108
|
**1.4 Validate the request against the contract:**
|
|
107
109
|
|
|
108
110
|
Write the request you were handed to a file and run:
|
|
@@ -143,7 +145,7 @@ git -C "<codebase_path>" rev-parse --abbrev-ref HEAD # must equal <branch>
|
|
|
143
145
|
|
|
144
146
|
**1.5 TDD Check (if `test_case_specs` is present):**
|
|
145
147
|
|
|
146
|
-
If the task object contains `test_case_specs` (provided by `tests-creator
|
|
148
|
+
If the task object contains `test_case_specs` (provided by `tests-creator`, or in a fix round the reviewers' red probes):
|
|
147
149
|
1. Read each test file listed in `test_case_specs.test_files`
|
|
148
150
|
2. Run the tests using `test_case_specs.run_command` — confirm they FAIL
|
|
149
151
|
3. If tests pass already → report `DONE_WITH_CONCERNS` (tests may not be testing the right thing)
|
|
@@ -427,6 +429,7 @@ Write full JSON to `<JOBS_ROOT>/<JOB_NAME>/results/<task_id>.json`:
|
|
|
427
429
|
"skill_drift": "<none | stale: <module>/<skill> — <what diverged> | missing: <module> should have a project-skill>",
|
|
428
430
|
"noticed_not_touched": [{ "what": "<problem>", "where": "<path|symbol>" }],
|
|
429
431
|
"assumptions": ["<what you assumed where the task did not say>"],
|
|
432
|
+
"behavior_changes": [{ "description": "<what now behaves differently>", "user_visible": true, "needs_operator": true, "alternatives": ["<option you did not take>"] }],
|
|
430
433
|
"not_touched": [{ "path": "src/path/file.ts", "reason": "<why left alone>" }],
|
|
431
434
|
"notes": "<any warnings, blockers, or additional context>"
|
|
432
435
|
}
|
|
@@ -434,23 +437,14 @@ Write full JSON to `<JOBS_ROOT>/<JOB_NAME>/results/<task_id>.json`:
|
|
|
434
437
|
|
|
435
438
|
Set `skill_drift` from Phase 2.0b: if the project-skill you used was not `fresh`, or the code you wrote diverged from what a skill documents, name the skill and the divergence. The orchestrator uses this to decide whether to trigger `skills learn` (do NOT run `learn` yourself — it is a mutating step the orchestrator dispatches; see `rules/core/skill-lifecycle.mdc`).
|
|
436
439
|
|
|
437
|
-
|
|
438
|
-
reader to skim all three. Omit one rather than pad it. The trio is adapted (MIT;
|
|
439
|
-
see THIRD_PARTY_NOTICES.md) as contract fields rather than a free-text template; the bars below are ours.
|
|
440
|
+
Four of those fields have a bar, and a field that collects noise trains the reader to skim all of them. Omit one rather than pad it. The first three are adapted (MIT; see THIRD_PARTY_NOTICES.md) as contract fields rather than a free-text template; the bars below are ours.
|
|
440
441
|
|
|
441
|
-
- `assumptions` — what you assumed where the task was silent AND acted on. If
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
- `
|
|
445
|
-
follow-up task could be written from it alone, with `where` it lives. Not a
|
|
446
|
-
dumping ground for every smell seen in passing, and not style opinion.
|
|
447
|
-
- `not_touched` — of the files this task was aimed at (`target_files`), the ones
|
|
448
|
-
absent from `files_modified`/`files_created`/`files_deleted`, each with why.
|
|
449
|
-
It answers that one question and no other: a reader subtracts those lists and
|
|
450
|
-
this one from `target_files`, and flags the remainder as an unexplained omission.
|
|
442
|
+
- `assumptions` — what you assumed where the task was silent AND acted on. If the assumption being wrong would not change a line you wrote, it is a hedge, not an assumption; leave it out.
|
|
443
|
+
- `noticed_not_touched` — a problem in code you actually read, stated so a follow-up task could be written from it alone, with `where` it lives. Not a dumping ground for every smell seen in passing, and not style opinion.
|
|
444
|
+
- `not_touched` — of the files this task was aimed at (`target_files`), the ones absent from `files_modified`/`files_created`/`files_deleted`, each with why. It answers that one question and no other: a reader subtracts those lists and this one from `target_files`, and flags the remainder as an unexplained omission.
|
|
445
|
+
- `behavior_changes` — behavior you chose where the task and the plan's state × event matrix did not decide it. **Every user-visible tradeoff goes here with `user_visible: true, needs_operator: true`** and the `alternatives` you rejected: message wording, where an error appears, which state resets or survives a switch, retry or reload. Never only in `assumptions`, `notes` or a journal line — the orchestrator asks the operator before it accepts a result carrying one, and a tradeoff it cannot see is accepted unasked.
|
|
451
446
|
|
|
452
|
-
Then check the shape and record the file — two commands, both of which refuse
|
|
453
|
-
rather than warn:
|
|
447
|
+
Then check the shape and record the file — two commands, both of which refuse rather than warn:
|
|
454
448
|
|
|
455
449
|
```bash
|
|
456
450
|
keryx skills contracts validate <JOBS_ROOT>/<JOB_NAME>/results/<task_id>.json \
|
|
@@ -489,7 +483,7 @@ The step's own status is the orchestrator's to write (`keryx job step <JOB_NAME>
|
|
|
489
483
|
|
|
490
484
|
Return a compact STATUS response following `rules/core/subagent-status-protocol.md`.
|
|
491
485
|
**Do NOT include the full JSON block inline** — the orchestrator reads the result file when it needs details.
|
|
492
|
-
The inline response must contain only: STATUS line + Completed bullets + Files changed + Verification summary.
|
|
486
|
+
The inline response must contain only: STATUS line + Completed bullets + Files changed + Verification summary + a `## Behavior changes` list (each entry's description, `user_visible`, `needs_operator`, alternatives) whenever `behavior_changes` is non-empty — a flow dispatch writes no result file, so this list is the only copy the orchestrator reads. Any `needs_operator: true` entry makes the status at best `DONE_WITH_CONCERNS`, never `DONE`.
|
|
493
487
|
|
|
494
488
|
**Status classification:**
|
|
495
489
|
- `success` → `STATUS: DONE`, or `DONE_WITH_CONCERNS` when work that cleared the
|
package/src/gdskills/bundled/skills/orchestration/task-implementer/input-contract.schema.json
CHANGED
|
@@ -149,6 +149,14 @@
|
|
|
149
149
|
"additionalProperties": false,
|
|
150
150
|
"required": ["file", "severity", "message"],
|
|
151
151
|
"properties": {
|
|
152
|
+
"id": {
|
|
153
|
+
"type": "string",
|
|
154
|
+
"description": "The finding's id in the review package, cited back in the result's `notes` when the fix diverged from `suggested_fix` or the finding did not reproduce"
|
|
155
|
+
},
|
|
156
|
+
"suggested_fix": {
|
|
157
|
+
"type": "string",
|
|
158
|
+
"description": "The reviewer's proposed fix. A hypothesis, not an instruction: SKILL.md 1.3 reproduces the finding first and checks this against the plan's state × event matrix before applying anything"
|
|
159
|
+
},
|
|
152
160
|
"file": {
|
|
153
161
|
"type": "string",
|
|
154
162
|
"description": "File path where the issue was found"
|
package/src/gdskills/bundled/skills/orchestration/task-implementer/output-contract.schema.json
CHANGED
|
@@ -65,6 +65,25 @@
|
|
|
65
65
|
"description": "What was assumed where the task did not say. A wrong assumption is the usual cause of a rejected result, so these are the first thing a reviewer should check. Read only by a human — nothing in the result or the request can confirm an assumption, so this is deliberately an array of sentences rather than a structure that would imply a check nobody performs.",
|
|
66
66
|
"items": { "type": "string", "minLength": 1 }
|
|
67
67
|
},
|
|
68
|
+
"behavior_changes": {
|
|
69
|
+
"type": "array",
|
|
70
|
+
"description": "Behavior the implementer chose where the task and the plan's state × event matrix did not decide it. Every user-visible tradeoff (message wording, error placement, which state resets or survives) is listed with `user_visible: true, needs_operator: true`; flow-orchestrator Phase 2 asks the operator before accepting a result carrying such an entry, so a tradeoff recorded only in `assumptions` or `notes` is one nobody decided.",
|
|
71
|
+
"items": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"additionalProperties": false,
|
|
74
|
+
"required": ["description", "user_visible", "needs_operator"],
|
|
75
|
+
"properties": {
|
|
76
|
+
"description": { "type": "string", "minLength": 1, "description": "What now behaves differently, stated as the user or caller would observe it" },
|
|
77
|
+
"user_visible": { "type": "boolean", "description": "A user of the product can see the difference" },
|
|
78
|
+
"needs_operator": { "type": "boolean", "description": "The choice is a product decision the operator must confirm before the result is accepted" },
|
|
79
|
+
"alternatives": {
|
|
80
|
+
"type": "array",
|
|
81
|
+
"description": "The options not taken, so the operator chooses between real alternatives rather than approving the one shown",
|
|
82
|
+
"items": { "type": "string", "minLength": 1 }
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
},
|
|
68
87
|
"not_touched": {
|
|
69
88
|
"type": "array",
|
|
70
89
|
"description": "Files a reader would expect in `files_modified` and will not find there, each with the reason. `path` is a separate field because this is machine-checkable: a reader holding the request can subtract `files_modified`/`files_created`/`files_deleted` and this list from `task.target_files` and flag whatever is left as an unexplained omission.",
|
|
@@ -55,7 +55,7 @@ operator reads in the shell's Schedules section.
|
|
|
55
55
|
Call `schedule_create`. The operator then sees a confirmation card: cadence and
|
|
56
56
|
next runs, prompt, runner, budget, network, every granted tool with its binary
|
|
57
57
|
and account, and exactly what gets installed. You do not confirm it. Only the
|
|
58
|
-
operator can, and every permission mode asks, `auto` included.
|
|
58
|
+
operator can, and every permission mode asks, `auto` included. Changing an existing schedule works the same way (`schedule_pause`, `schedule_resume`, `schedule_run`, `schedule_remove`): the operator answers a card; never send them to a terminal.
|
|
59
59
|
|
|
60
60
|
### Step 4: Report back
|
|
61
61
|
After the operator's answer, say what was scheduled and when it next runs, or
|
|
@@ -72,7 +72,7 @@ that nothing was written. Point to `/schedules` for the list and the reports.
|
|
|
72
72
|
- NEVER read or copy the schedule signing key (`schedule-hmac.key`), and never try to
|
|
73
73
|
reach the scheduler another way (quoting, `env -u`, a script). The text floor can be
|
|
74
74
|
worked around, and that is exactly why it is not the gate. `keryx schedule add|resume|run`
|
|
75
|
-
need the operator's own terminal, and a schedule without this machine's signature never runs.
|
|
75
|
+
need the operator's own terminal (inside keryx shell the operator answers the card instead), and a schedule without this machine's signature never runs.
|
|
76
76
|
- NEVER run `loginctl enable-linger`. If linger is off, tell the operator the
|
|
77
77
|
timer runs only while they are logged in and that the command is theirs to run.
|
|
78
78
|
- State the limits when they matter: the machine must be on; systemd and launchd
|
|
@@ -26,7 +26,7 @@ license: "MIT"
|
|
|
26
26
|
|
|
27
27
|
Specialized reviewer for **architectural patterns and structural decisions**.
|
|
28
28
|
Reviews only changes introduced in the current branch (merge-base to HEAD).
|
|
29
|
-
Focuses exclusively on verifiable structural violations — not style opinions or hypothetical concerns. Its inputs are the reviewer payload only; session memory and earlier conversation are not inputs.
|
|
29
|
+
Focuses exclusively on verifiable structural violations — not style opinions or hypothetical concerns. 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`.
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
@@ -26,7 +26,7 @@ license: "MIT"
|
|
|
26
26
|
|
|
27
27
|
Focused backend reviewer covering NestJS patterns, REST API design, database access patterns,
|
|
28
28
|
and TypeScript correctness for service-layer code. This skill does NOT duplicate security or
|
|
29
|
-
performance checks — those belong to `review-security-code` and `review-performance`. Its inputs are the reviewer payload only; session memory and earlier conversation are not inputs.
|
|
29
|
+
performance checks — those belong to `review-security-code` and `review-performance`. 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`.
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
@@ -27,7 +27,7 @@ license: "MIT"
|
|
|
27
27
|
# Review: Clean Code + SOLID
|
|
28
28
|
|
|
29
29
|
Specialized reviewer for **Clean Code principles** (Robert C. Martin) and **SOLID** at the
|
|
30
|
-
function and class level. Focuses on code in the current branch diff only. Its inputs are the reviewer payload only; session memory and earlier conversation are not inputs.
|
|
30
|
+
function and class level. Focuses on code in the current branch diff only. 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`.
|
|
31
31
|
|
|
32
32
|
The goal is not stylistic nitpicking — every finding here points to a concrete
|
|
33
33
|
maintainability, readability, or extensibility problem that will cause friction
|
|
@@ -24,7 +24,7 @@ license: "MIT"
|
|
|
24
24
|
# Review — Core Boundaries
|
|
25
25
|
|
|
26
26
|
Reviewer for shared infrastructure modules. A core module should provide stable foundations
|
|
27
|
-
used by feature modules; it should not accumulate feature-specific behaviour. Its inputs are the reviewer payload only; session memory and earlier conversation are not inputs.
|
|
27
|
+
used by feature modules; it should not accumulate feature-specific behaviour. 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`.
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
@@ -24,7 +24,7 @@ license: "MIT"
|
|
|
24
24
|
# Review — Flow Graph Abstractions
|
|
25
25
|
|
|
26
26
|
Reviewer for reusable ReactFlow/graph integration layers. Use it when a repository has a shared
|
|
27
|
-
graph surface consumed by domain modules. Its inputs are the reviewer payload only; session memory and earlier conversation are not inputs.
|
|
27
|
+
graph surface consumed by domain modules. 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`.
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
@@ -2,18 +2,14 @@
|
|
|
2
2
|
name: review-frontend
|
|
3
3
|
model_tier: standard
|
|
4
4
|
description: "Use when a frontend review is requested, checking React component patterns, MobX state management (observer, actions, computed, reactions, lifecycle), View-Store boundaries, and TypeScript safety in changed frontend code. NOT for backend patterns, security vulnerabilities, performance bottlenecks, or cross-layer architecture."
|
|
5
|
-
triggers:
|
|
6
|
-
- "frontend review"
|
|
7
|
-
- "component review"
|
|
8
|
-
- "ui review"
|
|
9
|
-
- "review React"
|
|
10
|
-
- "review components"
|
|
5
|
+
triggers: ["frontend review", "component review", "ui review", "review React", "review components"]
|
|
11
6
|
metadata:
|
|
12
7
|
author: "MrCipherSmith"
|
|
13
8
|
version: "1.1.0"
|
|
14
9
|
category: "review"
|
|
15
10
|
compatible_harnesses: "cursor,codex,zed,opencode,claude"
|
|
16
11
|
stack_requires: "react,mobx"
|
|
12
|
+
overlap_group: "frontend"
|
|
17
13
|
license: "MIT"
|
|
18
14
|
---
|
|
19
15
|
|
|
@@ -21,7 +17,7 @@ license: "MIT"
|
|
|
21
17
|
|
|
22
18
|
## Purpose
|
|
23
19
|
|
|
24
|
-
Validates frontend-specific patterns in the changed code of the current branch. Covers React component correctness (observer wrapping, MVVM boundary, useEffect misuse, accessibility basics, key props), full MobX store patterns (structure, member ordering, accessibility modifiers, observable collections, reactions, async actions, bidirectional sync, lifecycle, API placement), and TypeScript safety. Its inputs are the reviewer payload only; session memory and earlier conversation are not inputs.
|
|
20
|
+
Validates frontend-specific patterns in the changed code of the current branch. Covers React component correctness (observer wrapping, MVVM boundary, useEffect misuse, accessibility basics, key props), full MobX store patterns (structure, member ordering, accessibility modifiers, observable collections, reactions, async actions, bidirectional sync, lifecycle, API placement), and TypeScript safety. 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`.
|
|
25
21
|
|
|
26
22
|
This skill consolidates what was previously split between `code-style-review` (frontend parts) and `code-mobx-store-review`. It supersedes both for frontend changes.
|
|
27
23
|
|
|
@@ -11,16 +11,14 @@ description: |
|
|
|
11
11
|
NOT for: generic React and MobX correctness with no local rule behind it
|
|
12
12
|
(review-frontend), what the CSS actually renders (review-layout), or naming and
|
|
13
13
|
readability as a matter of taste (review-style).
|
|
14
|
-
triggers:
|
|
15
|
-
- "frontend conventions"
|
|
16
|
-
- "local frontend rules"
|
|
17
|
-
- "CLAUDE frontend"
|
|
18
|
-
- "review frontend conventions"
|
|
14
|
+
triggers: ["frontend conventions", "local frontend rules", "CLAUDE frontend", "review frontend conventions"]
|
|
19
15
|
metadata:
|
|
20
16
|
author: "MrCipherSmith"
|
|
21
17
|
version: "1.0.0"
|
|
22
18
|
category: "review"
|
|
23
19
|
stack_requires: "react,mobx"
|
|
20
|
+
overlap_group: "frontend"
|
|
21
|
+
overlap_rank: "generic"
|
|
24
22
|
license: "MIT"
|
|
25
23
|
---
|
|
26
24
|
|
|
@@ -28,7 +26,7 @@ license: "MIT"
|
|
|
28
26
|
|
|
29
27
|
Reviewer for frontend repository conventions that are more specific than generic React/MobX
|
|
30
28
|
correctness. Use it alongside `review-frontend`, `review-style`, `review-performance`, and
|
|
31
|
-
`review-logic`. Its inputs are the reviewer payload only; session memory and earlier conversation are not inputs.
|
|
29
|
+
`review-logic`. 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`.
|
|
32
30
|
|
|
33
31
|
Before reviewing, read the nearest project guide files if they exist: root `CLAUDE.md`,
|
|
34
32
|
`AGENTS.md`, `.junie/guidelines.md`, `ARCHITECTURE.md`, and module-level `CLAUDE.md` files.
|
|
@@ -28,7 +28,7 @@ license: "MIT"
|
|
|
28
28
|
|
|
29
29
|
Specialized reviewer for **code that will run under significant concurrent load**.
|
|
30
30
|
Focuses on correctness under concurrency, resource contention, back-pressure, failure
|
|
31
|
-
modes at scale, and distributed systems invariants — not general performance profiling. Its inputs are the reviewer payload only; session memory and earlier conversation are not inputs.
|
|
31
|
+
modes at scale, and distributed systems invariants — not general performance profiling. 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`.
|
|
32
32
|
|
|
33
33
|
Reviews only changes introduced in the current branch (merge-base to HEAD).
|
|
34
34
|
|
|
@@ -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`.
|
|
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.
|
|
@@ -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
|
|