@mrciphersmith/keryx 0.3.85 → 0.3.87

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/core.js CHANGED
@@ -9995,7 +9995,6 @@ var init_route_tokens = __esm(() => {
9995
9995
  "them"
9996
9996
  ]);
9997
9997
  });
9998
-
9999
9998
  // src/gdskills/skill-frontmatter.ts
10000
9999
  function frontmatterLines(content) {
10001
10000
  const text = content.startsWith("\uFEFF") ? content.slice(1) : content;
@@ -10791,12 +10790,12 @@ var init_skill_length_ceilings = __esm(() => {
10791
10790
  "orchestration/flow-orchestrator": 694,
10792
10791
  "orchestration/issue-analyzer": 373,
10793
10792
  "orchestration/job-documenter": 414,
10794
- "orchestration/job-orchestrator": 2243,
10793
+ "orchestration/job-orchestrator": 2235,
10795
10794
  "orchestration/task-implementer": 668,
10796
10795
  "planning/autodoc-analyst": 180,
10797
10796
  "planning/autodoc-architect": 179,
10798
10797
  "planning/autodoc-assembler": 145,
10799
- "planning/autodoc-orchestrator": 343,
10798
+ "planning/autodoc-orchestrator": 342,
10800
10799
  "planning/autodoc-scanner": 183,
10801
10800
  "planning/autodoc-writer": 270,
10802
10801
  "planning/brainstorm": 115,
@@ -10853,7 +10852,7 @@ var init_skill_length_ceilings = __esm(() => {
10853
10852
  "review/review-jev-scenarios": 187,
10854
10853
  "review/review-layout": 238,
10855
10854
  "review/review-logic": 377,
10856
- "review/review-orchestrator": 1712,
10855
+ "review/review-orchestrator": 1614,
10857
10856
  "review/review-performance": 374,
10858
10857
  "review/review-pr-feedback": 895,
10859
10858
  "review/review-regression": 216,
@@ -11732,7 +11731,8 @@ var init_tools = __esm(() => {
11732
11731
  "apply_patch",
11733
11732
  "shell_exec",
11734
11733
  "web_fetch",
11735
- "web_search"
11734
+ "web_search",
11735
+ "spawn_subagent"
11736
11736
  ];
11737
11737
  TOOL_TARGET_MAPS = {
11738
11738
  claude: new Map([
@@ -25505,6 +25505,10 @@ function dispatchErrors(value) {
25505
25505
  errors.push(`${role}: missing or shared execution identity`);
25506
25506
  if (text(run.executionId))
25507
25507
  executions.add(run.executionId);
25508
+ if (run.status === "not-run") {
25509
+ errors.push(`${role}: not run${text(run.notRunReason) ? ` (${run.notRunReason})` : ""}; a reviewer that did not run is never a clean pass`);
25510
+ continue;
25511
+ }
25508
25512
  if (run.status !== "complete" || run.scopeComplete !== true)
25509
25513
  errors.push(`${role}: reviewer scope is incomplete`);
25510
25514
  if (!text(run.rawEvidence))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrciphersmith/keryx",
3
- "version": "0.3.85",
3
+ "version": "0.3.87",
4
4
  "description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -21,6 +21,10 @@ license: "MIT"
21
21
 
22
22
  # Flow Orchestrator
23
23
 
24
+ ## Preflight
25
+
26
+ Run in the main session: this skill dispatches workers. Without the `Agent` tool, or with the depth budget spent (Claude Code nests at most 3 deep), the whole output is this line, with no tool calls and no work of your own: `STATUS: BLOCKED nested_dispatch_unavailable — run this skill in the main session`
27
+
24
28
  ## Purpose
25
29
 
26
30
  Flow Orchestrator is the Task Manager-aware implementation orchestrator. Plan bridge: publish the tasks with `plan_set` under the ids `T1`…`Tn`, mirror each `keryx flow task done` with `plan_update`, and publish Phase 4's completion choice as `proposed` — see the `session-plan-bridge` rule.
@@ -28,8 +32,6 @@ It wraps the existing gdskills pipeline with `keryx flow` state.
28
32
 
29
33
  Use this skill instead of `job-orchestrator` when the user wants a managed story/issue lifecycle with frozen acceptance criteria, task state, an explicit completion choice, Code Health, and a durable flow package in `.metaproject/flows/`.
30
34
 
31
- Do not modify `job-orchestrator` or `task-implementer` behavior. They remain usable without Task Manager. This skill coordinates them through flow state.
32
-
33
35
  ## Hard Preconditions
34
36
 
35
37
  1. Read `.metaproject/index.md` and `.metaproject/metaproject.json`.
@@ -122,9 +124,8 @@ it already tried. The flow package does.
122
124
  keryx flow next <id> --json
123
125
  ```
124
126
 
125
- This is the first task whose `status` is not `done` and whose declared
126
- `dependsOn` are all `done` — the ordering computed from the package
127
- instead of re-derived by you from prose.
127
+ This is the first task not `done` whose declared `dependsOn` are all
128
+ `done` — computed from the package, not re-derived from prose.
128
129
 
129
130
  4. **Read the `resume` field before dispatching anything.** It has three
130
131
  answers and they are not interchangeable:
@@ -141,10 +142,9 @@ it already tried. The flow package does.
141
142
  or close the task (`keryx flow task done <id> <Tn>`). Re-dispatching
142
143
  over an unresolved attempt is how the same work gets done twice.
143
144
 
144
- `keryx flow next` also lists every OTHER not-done task carrying an
145
- unresolved attempt, under `unresolved`. Those are parallel dispatches that
146
- never reported back; resolve them the same way before assuming the flow is
147
- idle.
145
+ `keryx flow next` also lists every OTHER not-done task with an unresolved
146
+ attempt, under `unresolved`: parallel dispatches that never reported back.
147
+ Resolve them the same way before assuming the flow is idle.
148
148
 
149
149
  5. Before dispatching a worker for that task, record the attempt:
150
150
 
@@ -436,19 +436,17 @@ Before accepting implementation:
436
436
  4. Check the bounds, then run `review-orchestrator` with relevant domains — in this session,
437
437
  never handed whole to one subagent: one without a dispatch tool returns `STATUS: BLOCKED`.
438
438
  ```bash
439
- keryx review budget --spent <usd-so-far> --outstanding <subagents you already have in flight>
439
+ keryx review budget --spent <usd-so-far> --full --outstanding <subagents still running, 0 if none>
440
440
  ```
441
441
  A non-zero exit means the spend ceiling (3 USD by default) has been reached:
442
442
  **stop and ask the user** rather than dispatching another fan-out — never shrink the fan-out to fit.
443
443
  Dispatch prompts point at sources (files, SHAs, the PR) and never paraphrase a contract.
444
444
 
445
- `--outstanding` is the part that matters here. `review-orchestrator`
446
- dispatches reviewers in parallel and runs *nested* under this skill, and
447
- keryx cannot observe subagents in another process. Passing the count you
448
- already have in flight is the only thing that makes the concurrency cap mean
449
- anything across the nesting; omit it and the cap bounds the reviewer fan-out
450
- alone, which the review record then states plainly rather than implying
451
- otherwise.
445
+ `--outstanding` is the part that matters here. `review-orchestrator` runs inline
446
+ in this session and dispatches reviewers in parallel; keryx cannot observe other
447
+ subagents. Passing the count still running is the only thing that makes the
448
+ concurrency cap mean anything; omit it and the cap bounds the reviewer fan-out
449
+ alone, which the review record then states plainly. Add `--full` for `--all`.
452
450
 
453
451
  5. If findings require code changes, dispatch fix work through `task-implementer`
454
452
  and record the fix task in the flow.
@@ -586,7 +584,9 @@ the bound plus an escalation — never an unbounded loop.
586
584
  findings, affected graph, relevant wiki, and health/testing artifacts;
587
585
  identify the likely cycle cause; choose a materially different fix strategy
588
586
  or split the work into narrower tasks; record the decision in `journal.md`;
589
- then continue with the enriched context.
587
+ then continue with the enriched context. The review round count is not reset:
588
+ past `REVIEW_ROUND_CAP` rounds on one merge-base..HEAD, report to the operator
589
+ instead of running another round.
590
590
  6. Never merge while findings or required checks remain unresolved. If the
591
591
  re-planned approach still cannot produce a mergeable PR, leave the flow
592
592
  `in-progress` and report the blocker instead of forcing completion.
@@ -22,14 +22,12 @@ metadata:
22
22
  license: "MIT"
23
23
  ---
24
24
 
25
- <SUBAGENT-STOP>
26
- If you were dispatched as a subagent to execute a specific task, skip this skill entirely.
27
- This skill is for orchestrators and interactive session-level routing only.
28
- Proceed directly with your assigned task.
29
- </SUBAGENT-STOP>
30
-
31
25
  # Job Orchestrator
32
26
 
27
+ ## Preflight
28
+
29
+ Run in the main session: this skill dispatches sub-agents. Without the `Agent` tool, or with the depth budget spent (Claude Code nests at most 3 deep), the whole output is this line, with no tool calls and no work of your own: `STATUS: BLOCKED nested_dispatch_unavailable — run this skill in the main session`
30
+
33
31
  ## Purpose
34
32
 
35
33
  Dynamic orchestrator that builds execution plans based on user intent. Unlike a fixed pipeline, the orchestrator adapts its workflow to what the user actually needs — from "just analyze this issue" to "implement, review, and create a PR". It dispatches sub-agents (`issue-analyzer`, `context-collector`, `tests-creator`, `task-implementer`, `code-verifier`, `review-orchestrator`) and persists every step, document and retry through `keryx job`, which writes `.metaproject/jobs/<job-name>/`. Plan bridge: publish these steps with `plan_set` under the ids `keryx job status` reports, mirror each `keryx job step` with `plan_update`, and mark them `proposed` while the approval above is open — see the `session-plan-bridge` rule.
@@ -1059,16 +1057,14 @@ carried in the dispatch prompt and reported in 2.9.
1059
1057
  **Step 1 — check the budget before dispatching, while stopping is still possible.**
1060
1058
 
1061
1059
  ```bash
1062
- keryx review budget --spent <usd-so-far> --outstanding <subagents this orchestrator has in flight>
1060
+ keryx review budget --spent <usd-so-far> --full --outstanding <subagents still running, 0 if none>
1063
1061
  ```
1064
1062
 
1065
- `--outstanding` is not optional here. `src/review/caps.ts` names `job-orchestrator`
1066
- as the outermost of the three nesting levels — `job-orchestrator` →
1067
- `flow-orchestrator` → `review-orchestrator` — that its cap of 4 in-flight reviewers
1068
- was chosen to survive. keryx is a CLI invoked once per command; it cannot observe
1069
- subagents running inside another orchestrator's process. **The cap binds the nested
1070
- total only when the parent declares its own in-flight count.** Omit `--outstanding`
1071
- and the cap bounds the reviewer fan-out alone, which the record then states plainly.
1063
+ `--outstanding` is the number of subagents this session still has running while the
1064
+ round starts (0 when none). All three orchestrators run inline in the main session, so the
1065
+ reviewers are the only fan-out; keryx cannot observe other subagents, so **the wave size
1066
+ (at most 10 for `--all` or a full review; add `--full`) binds the total only when you
1067
+ declare that count.** Omit it and the record states that the cap bounds the reviewers alone.
1072
1068
 
1073
1069
  A non-zero exit means the spend ceiling (3 USD by default) is reached: stop and ask
1074
1070
  the user rather than dispatching another fan-out.
@@ -1122,30 +1118,26 @@ replaced. The command names no model — it ranks what the provider reports at r
1122
1118
  and, when it cannot rank anything, prints `inherit: true`, which means the dispatch
1123
1119
  runs on the session model. That is a correct answer, not a failure.
1124
1120
 
1125
- **Step 6 — dispatch `review-orchestrator`.**
1121
+ **Step 6 — run `review-orchestrator` inline, in this main session.** Load
1122
+ `skills/gdskills/review/review-orchestrator/SKILL.md` yourself; do **not** wrap it in a
1123
+ `Task` — a subagent cannot spawn the reviewers and the skill answers
1124
+ `STATUS: BLOCKED nested_dispatch_unavailable`. Give it these inputs:
1126
1125
 
1127
1126
  ```
1128
- Task({
1129
- description: "Review round <n>: <job-name>",
1130
- subagent_type: "general-purpose",
1131
- prompt: |
1132
- Load skill: skills/gdskills/review/review-orchestrator/SKILL.md
1133
-
1134
- flags: <selected flags, e.g. --backend --security --testing-practices>
1135
- commit_range: <BASE_SHA>..HEAD
1136
- issue_url: <issue URL, when the job has one — enables the Stage 1 spec gate>
1137
- context_doc: <JOBS_ROOT>/<job-name>/ai/context.md
1138
- verification_mode: annotate
1139
- managed_review: { mode: "review-flow", target: "branch", target_ref: "<feature-branch>" }
1140
- is_fix_round: <true on any round after the first>
1141
- pr_comments: { enabled: <true when a PR exists> }
1142
-
1143
- Emit the unified report AND the fenced ```json keryx:findings``` block.
1144
- Dispatch review-verifier (Wave C) over the consolidated findings and return
1145
- its verification claims as a file path.
1146
- })
1127
+ flags: <selected flags, e.g. --backend --security --testing-practices>
1128
+ commit_range: <BASE_SHA>..HEAD
1129
+ issue_url: <issue URL, when the job has one — enables the Stage 1 spec gate>
1130
+ context_doc: <JOBS_ROOT>/<job-name>/ai/context.md
1131
+ verification_mode: annotate
1132
+ managed_review: { mode: "review-flow", target: "branch", target_ref: "<feature-branch>" }
1133
+ is_fix_round: <true on any round after the first>
1134
+ pr_comments: { enabled: <true when a PR exists> }
1147
1135
  ```
1148
1136
 
1137
+ It emits the unified report AND the fenced ```json keryx:findings``` block, and runs
1138
+ `review-verifier` (Wave C) over the consolidated findings, returning its verification
1139
+ claims as a file path.
1140
+
1149
1141
  **Step 7 — verification is part of the round, not an extra.** `review-orchestrator`
1150
1142
  dispatches `review-verifier` in Wave C over the consolidated findings. The verifier
1151
1143
  **runs something** and can only delete — it never raises a severity, adds a finding,
@@ -1310,7 +1302,7 @@ FOR iteration in [1, 2, 3]:
1310
1302
  keryx review comments collect --repo <r> --pr <n> --sha <new-head> --round <N+1> --out <file>
1311
1303
  keryx review scope --ref "$BASE_SHA" --json > scope.json
1312
1304
  keryx review blast-radius --ref "$BASE_SHA" --previous blast-radius.json --json > blast-radius.json
1313
- <dispatch review-orchestrator with is_fix_round: true>
1305
+ <run review-orchestrator inline, in this session, with is_fix_round: true>
1314
1306
  keryx review ingest --report <new-report> --ref <feature-branch> --head <new-head> \
1315
1307
  --scope scope.json --blast-radius blast-radius.json \
1316
1308
  --verifications <file> --refuted <file> --outstanding <n>
@@ -1985,7 +1977,7 @@ What actually bounds this orchestrator:
1985
1977
  | review → fix rounds | 3 | 2.7, and `max_review_iterations` (`maximum: 3`) in the input contract |
1986
1978
  | repetition, whatever the count says | first repeat | the STUCK CHECK in 2.7, and `keryx review loop` against the durable record |
1987
1979
  | retries per step | recorded, not guessed | `metrics.steps[].retries`, incremented by `keryx job step --status in-progress` and read back with `keryx job status --json` |
1988
- | reviewer fan-out | 4 in flight | `keryx review budget --outstanding <n>` before every dispatch (2.6.1) |
1980
+ | reviewer fan-out | ≤10 per wave | `keryx review budget --outstanding <n>` before every dispatch (2.6.1) |
1989
1981
  | spend | 3 USD by default | `keryx review budget --spent <usd>` — a non-zero exit means stop and ask |
1990
1982
 
1991
1983
  Each of these is a number some command reads or writes. A guard no command can
@@ -20,8 +20,7 @@ metadata:
20
20
  version: 1.0.0
21
21
  ---
22
22
 
23
- <!-- SUBAGENT-STOP: If you are a subagent dispatched by another orchestrator, HALT.
24
- Return STATUS: BLOCKED — autodoc-orchestrator must run as top-level agent only. -->
23
+ **Preflight:** run in the main session. Without the `Agent` tool or depth budget, output only `STATUS: BLOCKED nested_dispatch_unavailable — run this skill in the main session`, with no tool calls.
25
24
 
26
25
  # autodoc-orchestrator
27
26
 
@@ -426,7 +426,7 @@ re-request after fixes. A gating round runs the composition the start questions
426
426
  selected.
427
427
 
428
428
  - **No dispatch tool, no review.** A host that cannot dispatch subagents — this
429
- engine running inside a subagent is the usual case — returns
429
+ engine running inside a subagent, say — returns
430
430
  `STATUS: BLOCKED` with reason `nested_dispatch_unavailable` and no verdict.
431
431
  It does not review the diff alone and call that a round. Measured (flow 405):
432
432
  a single-agent round on a 150-line frontend PR wrote "did not dispatch any
@@ -503,3 +503,173 @@ New managed packages carry `research.json`, initially pending. Before closing a
503
503
  Supply the ledger using `keryx review ingest --research <ledger.json>` alongside the report and findings. Format: `version: 1`, `scopeReviewed: true`, `rawReconciled: true`, `obligations: [...]`. Each obligation requires `id`, `source`, `question`, `status`, `evidence`, `reason`. Status `finding` additionally requires `finding` pointing to exactly one canonical finding ID or global ID. Other terminal statuses are `refuted` and `out-of-scope`, both requiring evidence and reason. Preserve distinct scenarios when deduplicating. Assert census/reconciliation flags only after performing those checks; an empty obligations array is valid only if the actual census found no open observations.
504
504
 
505
505
  Open, deferred and unverifiable obligations block completion. If context, runtime or budget prevents resolution, retain the obligation and report incomplete; do not relabel it refuted or out-of-scope. Completion and the flow gate re-read the ledger even when the manifest says closed. Legacy packages without this artifact remain compatible, not proven complete. This gate validates the declared ledger, not the truth or exhaustiveness of its census; independent source/raw audits remain necessary.
506
+
507
+ ## Why Wave C verifies instead of re-scoring
508
+
509
+ Wave C used to run `review-strict`: a meta-pass that re-read the consolidated
510
+ findings and **adjusted their severity with no new evidence**, under an elevation
511
+ table biased 3:1 toward escalation. It was **removed, not improved**, and the
512
+ reason is measured rather than stylistic:
513
+
514
+ - **GPT-4 on GSM8K across self-correction rounds: 95.5 → 91.5 → 89.0.**
515
+ **GPT-3.5 on CommonSenseQA: 75.8 → 38.1.** Among the answers that changed,
516
+ correct → incorrect exceeded incorrect → correct (Huang et al., *Large Language
517
+ Models Cannot Self-Correct Reasoning Yet*, ICLR 2024, arXiv:2310.01798).
518
+ - **Self-Refine (arXiv:2303.17651): +49.2 on dialogue response generation, +0.2
519
+ on maths.** Self-refinement gains are on subjective tasks and vanish on
520
+ verifiable reasoning. Judging whether a null-guard is missing is verifiable
521
+ reasoning.
522
+
523
+ Re-scoring a finding by re-reading it is therefore not a rigour pass; it is a
524
+ coin flip weighted toward more findings. **Do not restore it because it looks
525
+ obviously useful — it looked obviously useful the first time.**
526
+
527
+ `review-verifier` occupies the slot and differs in exactly one way that matters:
528
+ **it runs something.** Verification that executes rejects 85–96% of false reports
529
+ against 4–15% unaided while finding 30–44% more true bugs (AnyPoC,
530
+ arXiv:2604.11950); Meta's TestGen-LLM funnel discards 75% of its own output
531
+ (75% build → 57% build and pass → 25% improve coverage) and the surviving quarter
532
+ reaches 73% human acceptance (arXiv:2402.09171).
533
+
534
+ ## Scope B — bounds, rejections and recompute
535
+
536
+ It walks `gdgraph affected` outward from every changed file, ranks by edge
537
+ distance, keeps distance ≤ 2, cuts at 40 files closest-first, and adds a changed
538
+ file's naming-related tests when the graph did not already reach them. Requires a
539
+ built graph — run `keryx gdgraph build` if it refuses.
540
+
541
+ **Do not pick the files yourself, and do not widen it.** "Review the
542
+ functionality so nothing breaks" naively means "review the whole repository every
543
+ round", which is unaffordable *and* actively harmful: review quality decays as
544
+ context grows — measured F1 0.65 at round 2 falling to 0.29 at round 10. An
545
+ unbounded scope B makes later rounds worse than earlier ones.
546
+
547
+ The bounds are measured on this repository, not guessed: at depth 2 the set is a
548
+ median of 19 files (p90 65); depth 3 buys eight more in the median and doubles
549
+ the p90. The 40-file cap fires on 25% of commits and removes only hop-2 entries
550
+ on all but 2 of 80, so it almost never costs a direct dependent — and when it
551
+ does, it says so.
552
+
553
+ **Record the whole thing.** `--out "<review-package>/blast-radius.md"` writes the
554
+ set, the depth, and **every file the cap removed**. A truncation nobody can see
555
+ reads afterwards as "we checked everything", which is the claim this pipeline
556
+ exists to stop making. An empty radius is reported as `unresolved`, not as clean:
557
+ the graph indexes code, so a change to a skill, a rule or a schema has no blast
558
+ radius at all and that is a different fact from "nothing depends on it".
559
+
560
+ ### The scope-B question, and what is rejected
561
+
562
+ > Does this change break an existing behaviour **at these sites**?
563
+
564
+ Nothing else. The blast-radius set is **under regression check, not under
565
+ review**. A finding about style, naming or architecture in code the change did
566
+ not touch is refused **by the orchestrator in code** — not discouraged here —
567
+ under three rules, every one of them a fact about the claim rather than about who
568
+ made it:
569
+
570
+ | Rule | Refused because |
571
+ |---|---|
572
+ | `outside-set` | the file is neither in the computed set nor in the changed set; the reviewer went browsing |
573
+ | `non-regression-severity` | below `major`. Under the canonical rubric `minor` states the code behaves correctly and `info` names neither trigger nor outcome; neither can be a claim that something broke |
574
+ | `no-link-to-change` | nothing in the finding names a changed file, module or symbol. A regression claim says THE CHANGE broke this site |
575
+
576
+ Rejections are **recorded, not deleted** — raise the observation under scope A or
577
+ as a separate review. Pass `--brief` output verbatim into the scope-B dispatch:
578
+ the code rejection is the enforcement, but a reviewer told afterwards has already
579
+ spent the round producing findings that will all be refused.
580
+
581
+ `class_scope` on a scope-B finding names the **caller that breaks**, not the
582
+ changed line, because that is the site a human has to look at.
583
+
584
+ ### When it is recomputed
585
+
586
+ | Round | Scope A | Scope B |
587
+ |---|---|---|
588
+ | 1 (first after the draft PR) | yes | yes |
589
+ | 2..N | yes | recomputed only if the changed-file set moved |
590
+ | final | yes | **yes, always** |
591
+
592
+ Do not decide this by memory:
593
+
594
+ ```bash
595
+ keryx review blast-radius --ref "${BASE_SHA}" --previous blast-radius.json [--final]
596
+ ```
597
+
598
+ It prints the decision and the reason, and reuses the previous record when
599
+ nothing moved. The final round recomputes whatever the file set did — otherwise a
600
+ fix introduced in round 3 gets no regression check at all, and the round that
601
+ certifies the flow is the one that checked the least.
602
+
603
+ ## Fix rounds — dispositions, regressions, withdrawal
604
+
605
+ ### Every prior finding leaves the round with a disposition
606
+
607
+ A fix round that reports only new findings is unreadable: the author cannot tell
608
+ which of their fixes landed. Close the loop explicitly — one line per prior
609
+ finding, in the report, before the new findings:
610
+
611
+ | Disposition | Meaning |
612
+ |---|---|
613
+ | `closed` | Checked against the code, not against the commit message, and the defect is gone |
614
+ | `open` | The fix does not reach the defect; say what is still true |
615
+ | `partial` | One site of the class was fixed and the enumeration named others |
616
+ | `regressed` | The fix removed this defect and introduced another — file the new one separately |
617
+ | `withdrawn` | The finding was wrong. See below |
618
+
619
+ **Check the code, not the commit message.** A commit titled *"report an abandoned
620
+ sync as abandoned"* is a claim; the disposition is whether the branch it renamed
621
+ is reachable and pinned. On a recorded round, two such commits asserted behaviour
622
+ on lines no test could reach.
623
+
624
+ ### A fix is a change, and changes get reviewed
625
+
626
+ The most expensive class in a multi-round review is **the defect the fix
627
+ introduced**. It is systematically under-found, for a structural reason: the fix
628
+ arrives framed as the answer to a finding, so it is read as an answer rather than
629
+ as new code. It is new code.
630
+
631
+ So scope A of a fix round includes the fix, reviewed on its own merits, and the
632
+ report carries its own section:
633
+
634
+ ```markdown
635
+ ## Regressions the fixes introduced
636
+ <[F-NNN] — the finding it was answering, and the new defect it created>
637
+ ```
638
+
639
+ Recorded shapes, all from fixes that correctly closed the finding they answered:
640
+ an early return added to stop a fall-through, which then skipped the work the
641
+ caller needed; a persistence call added to save expanded state, which then
642
+ persisted the broken state on the error path too. Both were closed correctly and
643
+ both shipped a new bug in the same commit.
644
+
645
+ ### Withdrawing your own earlier finding
646
+
647
+ A finding from a previous round that this round disproves is **withdrawn**,
648
+ explicitly, at the top of the report, with the evidence — before any new finding.
649
+
650
+ This is not a courtesy. An uncorrected wrong finding costs the author a fix they
651
+ did not need, and it stays in `prior_findings` steering later rounds. Withdrawal
652
+ is also the one self-correction this pipeline permits, and it is permitted because
653
+ it is asymmetric: it *deletes* a claim, so it cannot inflate the finding count,
654
+ which is the failure mode that removed the re-scoring pass from Wave C.
655
+
656
+ State what made the original claim wrong, in one sentence, and if the same
657
+ reasoning error has now happened twice in one review, say that too. A reviewer
658
+ that names its own recurring error is calibrating; one that quietly drops a
659
+ finding is hiding a result.
660
+
661
+ ## Job Context Awareness
662
+
663
+ When dispatched by `job-orchestrator` or called with an explicit context path, the prompt MAY include:
664
+
665
+ ```
666
+ JOB_NAME: <job-name>
667
+ CONTEXT_PATH: .metaproject/jobs/<job-name>/ai/context.md
668
+ ```
669
+
670
+ If provided and the file exists, read the context document **before** running scope detection.
671
+ Use it to understand:
672
+ - Intentionally chosen libraries and patterns (do not flag as issues)
673
+ - Architectural decisions already agreed upon, and acceptance criteria driving the Stage 1 spec compliance gate
674
+
675
+ If absent, proceed normally — context is optional and non-blocking.