@open-agent-toolkit/cli 0.1.13 → 0.1.15

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.
Files changed (46) hide show
  1. package/assets/agents/oat-reviewer.md +54 -10
  2. package/assets/docs/workflows/projects/reviews.md +21 -2
  3. package/assets/docs/workflows/skills/index.md +2 -0
  4. package/assets/public-package-versions.json +4 -4
  5. package/assets/skills/oat-project-review-provide-remote/SKILL.md +354 -0
  6. package/assets/skills/oat-project-review-receive/SKILL.md +7 -10
  7. package/assets/skills/oat-project-review-receive-remote/SKILL.md +4 -4
  8. package/assets/skills/oat-review-provide/SKILL.md +2 -2
  9. package/assets/skills/oat-review-provide/scripts/resolve-review-output.sh +16 -6
  10. package/assets/skills/oat-review-provide-remote/SKILL.md +273 -0
  11. package/assets/skills/oat-review-receive/SKILL.md +6 -6
  12. package/assets/skills/oat-review-receive-remote/SKILL.md +5 -5
  13. package/dist/commands/init/tools/shared/skill-manifest.d.ts +2 -2
  14. package/dist/commands/init/tools/shared/skill-manifest.d.ts.map +1 -1
  15. package/dist/commands/init/tools/shared/skill-manifest.js +2 -0
  16. package/dist/commands/project/new/index.d.ts +1 -0
  17. package/dist/commands/project/new/index.d.ts.map +1 -1
  18. package/dist/commands/project/new/index.js +23 -0
  19. package/dist/commands/project/new/scaffold.d.ts +17 -0
  20. package/dist/commands/project/new/scaffold.d.ts.map +1 -1
  21. package/dist/commands/project/new/scaffold.js +74 -0
  22. package/dist/review-remote/body-builder.d.ts +79 -0
  23. package/dist/review-remote/body-builder.d.ts.map +1 -0
  24. package/dist/review-remote/body-builder.js +103 -0
  25. package/dist/review-remote/capability-probe.d.ts +61 -0
  26. package/dist/review-remote/capability-probe.d.ts.map +1 -0
  27. package/dist/review-remote/capability-probe.js +87 -0
  28. package/dist/review-remote/line-mapper.d.ts +81 -0
  29. package/dist/review-remote/line-mapper.d.ts.map +1 -0
  30. package/dist/review-remote/line-mapper.js +165 -0
  31. package/dist/review-remote/marker-parser.d.ts +44 -0
  32. package/dist/review-remote/marker-parser.d.ts.map +1 -0
  33. package/dist/review-remote/marker-parser.js +97 -0
  34. package/dist/review-remote/narrowing.d.ts +81 -0
  35. package/dist/review-remote/narrowing.d.ts.map +1 -0
  36. package/dist/review-remote/narrowing.js +90 -0
  37. package/dist/review-remote/project-resolver.d.ts +46 -0
  38. package/dist/review-remote/project-resolver.d.ts.map +1 -0
  39. package/dist/review-remote/project-resolver.js +60 -0
  40. package/dist/review-remote/reviewer-dispatch.d.ts +108 -0
  41. package/dist/review-remote/reviewer-dispatch.d.ts.map +1 -0
  42. package/dist/review-remote/reviewer-dispatch.js +153 -0
  43. package/dist/review-remote/worktree.d.ts +62 -0
  44. package/dist/review-remote/worktree.d.ts.map +1 -0
  45. package/dist/review-remote/worktree.js +117 -0
  46. package/package.json +2 -2
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: oat-reviewer
3
- version: 1.0.2
4
- description: Unified reviewer for OAT projects - mode-aware verification of requirements/design alignment and code quality. Writes review artifact to disk.
3
+ version: 1.1.0
4
+ description: Unified reviewer for OAT projects - mode-aware verification of requirements/design alignment and code quality. Writes a review artifact to disk by default, or returns structured findings in-memory when dispatched in structured-output mode.
5
5
  tools: Read, Bash, Grep, Glob, Write
6
6
  color: yellow
7
7
  ---
@@ -17,7 +17,12 @@ You may be asked to do either:
17
17
 
18
18
  **Critical mindset:** Assume you know nothing about this project. Trust only written artifacts and code. Do NOT trust summaries or claims - verify by reading actual files.
19
19
 
20
- Your job: Review thoroughly, write a review artifact, then return a brief confirmation.
20
+ Your job: Review thoroughly, then deliver the result via the output sink your dispatch selects:
21
+
22
+ - **Default (artifact mode):** write a review artifact to disk, then return a brief confirmation. This is the behavior when the dispatch payload does NOT set `oat_output_mode: structured`.
23
+ - **Structured-output mode:** when the dispatch payload sets `oat_output_mode: structured`, return a `StructuredFindings` object in-memory and write NO artifact file. See **Structured-Output Mode** below.
24
+
25
+ The review logic itself — checklist, severity model, requirements/design alignment, code-quality checks — is identical in both modes. Only the output sink changes.
21
26
 
22
27
  ## Why This Matters
23
28
 
@@ -46,6 +51,7 @@ You will be given a "Review Scope" block including:
46
51
  - **workflow_mode**: `spec-driven` | `quick` | `import` (default to `spec-driven` if absent)
47
52
  - **artifact_paths**: Paths to available artifacts (spec/design/plan/implementation/discovery/import reference)
48
53
  - **tasks_in_scope**: Task IDs being reviewed (if task/phase scope)
54
+ - **oat_output_mode**: Optional output-sink selector. Absent (or any value other than `structured`) means **artifact mode** — write the review artifact to disk per Step 8. `structured` means **structured-output mode** — return a `StructuredFindings` object in-memory and write NO artifact file (see **Structured-Output Mode**). This key parallels the existing `oat_review_invocation` dispatch-payload naming.
49
55
  - **model_axis**: Optional model dispatch state selected by the orchestrator (`selected:<value>`, `inherited`, `not-applicable`, or `host-auto`)
50
56
  - **effort_axis**: Optional effort dispatch state selected by the orchestrator (`selected:<value>`, `provider-default`, `inherited`, `not-applicable`, or `host-auto`)
51
57
  - **dispatch_ceiling**: Optional resolved provider ceiling that capped/selected this review dispatch
@@ -230,6 +236,8 @@ Group findings by severity:
230
236
 
231
237
  ### Step 8: Write Review Artifact
232
238
 
239
+ **Artifact mode only.** Skip this step entirely in structured-output mode (`oat_output_mode: structured`) — see **Structured-Output Mode** below.
240
+
233
241
  Write the review artifact to the specified path.
234
242
 
235
243
  **File path format:**
@@ -323,6 +331,9 @@ Run the `oat-project-review-receive` skill to convert findings into plan tasks.
323
331
 
324
332
 
325
333
  ### Step 9: Return Confirmation
334
+
335
+ **Artifact mode only.** In structured-output mode (`oat_output_mode: structured`), return the `StructuredFindings` object instead — see **Structured-Output Mode** below.
336
+
326
337
  Return a brief confirmation. DO NOT include full review contents.
327
338
 
328
339
  Format:
@@ -336,16 +347,47 @@ Format:
336
347
 
337
348
  Return to your main session and run the `oat-project-review-receive` skill.
338
349
 
339
- ```
350
+ ````
340
351
 
352
+ ## Structured-Output Mode
353
+
354
+ When the dispatch payload sets `oat_output_mode: structured`, the output sink changes — nothing else does. Run the full review (Steps 1-7) exactly as in artifact mode, then:
355
+
356
+ 1. **Do NOT write a review artifact.** Skip Step 8 entirely. In this mode you MUST NOT write to any path under `{project}/reviews/` (or anywhere else). The caller — the project-rail `oat-project-review-provide-remote` skill's Tier 1 dispatch — consumes your return value in-memory and posts it to GitHub itself; GitHub is the source of truth on that rail, so a local artifact would be redundant and is explicitly disallowed.
357
+ 2. **Instead of Step 9's confirmation, return a `StructuredFindings` object** as your response. Do not also return the artifact-mode confirmation block.
358
+
359
+ **`StructuredFindings` return shape** (canonical schema: `design.md` → Data Models → StructuredFindings):
360
+
361
+ ```typescript
362
+ interface StructuredFindings {
363
+ summary: string; // 2-3 sentence review summary
364
+ findings: Array<{
365
+ id: string; // C1, I1, M1, m1 — stable per dispatch (C/I/M/m prefix matches the severity model)
366
+ severity: 'critical' | 'important' | 'medium' | 'minor';
367
+ title: string;
368
+ file: string | null; // repo-relative path
369
+ line: number | null; // 1-based line in the post-image (new file)
370
+ body: string; // finding description and rationale
371
+ fix_guidance: string | null; // suggested fix (may be null)
372
+ }>;
373
+ verification_commands: string[]; // commands the caller can run to verify fixes — returned as an array, NOT appended to a file
374
+ }
375
+ ````
341
376
 
377
+ **Rules for the structured return:**
342
378
 
379
+ - `severity` MUST be one of the four enum values, mapped from the same Critical/Important/Medium/Minor buckets as Step 7.
380
+ - `file` and `line` MUST both be set or both be `null`. A finding with a concrete location sets both; a reviewer-level finding without a specific location sets both to `null` and is conveyed via the `summary` / its own `body`, not as an inline location.
381
+ - `id` prefixes follow the existing convention (`C`/`I`/`M`/`m`) and are stable within a single dispatch — no renumbering.
382
+ - `verification_commands` carries what Step 8's "Verification Commands" section would have carried, as an array of command strings.
383
+
384
+ Default behavior is unaffected: when `oat_output_mode` is absent or set to anything other than `structured`, follow Steps 8-9 and write the artifact exactly as before.
343
385
 
344
386
  ## Critical Rules
345
387
 
346
388
  **TRUST NOTHING.** Read actual files. Don't trust summaries, claims, or "I did X" statements.
347
389
 
348
- **WRITE THE REVIEW ARTIFACT.** Don't return findings to orchestrator - write to disk.
390
+ **WRITE THE REVIEW ARTIFACT (artifact mode).** In the default artifact mode, don't return findings to the orchestrator - write to disk. In structured-output mode (`oat_output_mode: structured`) the opposite holds: return the `StructuredFindings` object and write NO artifact.
349
391
 
350
392
  **STAY IN SCOPE.** Review only what's specified. Don't expand scope.
351
393
 
@@ -355,19 +397,21 @@ Return to your main session and run the `oat-project-review-receive` skill.
355
397
 
356
398
  **INCLUDE VERIFICATION COMMANDS.** How can we verify the fix works?
357
399
 
358
- **RETURN ONLY CONFIRMATION.** Your response should be brief. Full findings are in the artifact.
359
-
360
-
400
+ **RETURN ONLY CONFIRMATION (artifact mode).** In artifact mode your response should be brief full findings are in the artifact. In structured-output mode, return the full `StructuredFindings` object (it is the deliverable, not a summary).
361
401
 
362
402
  ## Success Criteria
403
+
363
404
  - [ ] All project artifacts loaded and read
364
405
  - [ ] Scope respected (not reviewing out-of-scope changes)
365
406
  - [ ] Spec/design alignment verified
366
407
  - [ ] Code quality checked at pragmatic level
367
408
  - [ ] Findings categorized by severity
368
- - [ ] Review artifact written to correct path
409
+ - [ ] Output delivered via the dispatch-selected sink: artifact written to correct path (artifact mode) OR `StructuredFindings` returned with NO artifact written (structured-output mode)
369
410
  - [ ] Findings have file:line references
370
411
  - [ ] Findings have actionable fix guidance
371
412
  - [ ] Verification commands included
372
- - [ ] Brief confirmation returned
413
+ - [ ] Brief confirmation returned (artifact mode) / `StructuredFindings` object returned (structured-output mode)
414
+
415
+ ```
416
+
373
417
  ```
@@ -31,6 +31,8 @@ The commit is scoped and explicit — it stages only the project's tracking file
31
31
 
32
32
  - `oat-project-review-provide` is project-scoped and requires active project state (resolved via `oat config get activeProject` / `.oat/config.local.json`) plus project `state.md`.
33
33
  - `oat-review-provide` is for non-project commit-range reviews (ad-hoc, no project state required).
34
+ - `oat-project-review-provide-remote` reviews a GitHub PR from a different machine within project context and posts the review back to GitHub (see [Remote provide](#remote-provide)).
35
+ - `oat-review-provide-remote` reviews a GitHub PR from a different machine in ad-hoc mode and posts the review back to GitHub.
34
36
 
35
37
  **Receive** (process review findings):
36
38
 
@@ -39,6 +41,20 @@ The commit is scoped and explicit — it stages only the project's tracking file
39
41
  - `oat-review-receive` processes local review artifacts in ad-hoc mode (standalone task-list output, no project state mutation).
40
42
  - `oat-review-receive-remote` processes GitHub PR comment feedback in ad-hoc mode (standalone task-list output, optional reply posting).
41
43
 
44
+ The `*-provide-remote` and `*-receive-remote` skills are the two halves of the cross-machine loop: one agent posts a review to a PR; an agent on the PR's own machine receives it and turns it into fix tasks.
45
+
46
+ ## Remote provide
47
+
48
+ `oat-review-provide-remote` (ad-hoc) and `oat-project-review-provide-remote` (project-scoped) let an agent on one machine review a GitHub PR opened from another machine and post the review back to GitHub. They mirror the existing `*-receive-remote` skills, closing the local-vs-remote × provide-vs-receive matrix.
49
+
50
+ - **GitHub is the source of truth.** No local review artifact is written on the reviewing machine, and the project rail makes no `plan.md`/bookkeeping mutations there — the originating machine's `*-receive-remote` owns those. The posted PR review carries metadata markers (`oat_provide_remote`, `oat_review_head_sha`, and on the project rail `oat_project` + `oat_review_scope`) so a subsequent provide-remote pass can find the prior review for re-review narrowing.
51
+ - **Hybrid read strategy.** The skill checks the PR out into an ephemeral worktree for full-context review by default, and falls back to diff-only mode (`gh pr diff`, or when `--no-checkout` is set / checkout fails) with a degraded-context warning.
52
+ - **Single posted review.** Findings are posted as one PR review via `gh api` with inline `comments[]`; the verdict is `REQUEST_CHANGES` when any Critical/Important finding exists, otherwise `COMMENT` (including clean reviews — never an automatic `APPROVE`). Findings whose line is outside the PR diff are downgraded into the top-level review body rather than dropped.
53
+ - **Project rail is project-aware but read-only.** It resolves the project by scanning the PR diff for `.oat/projects/*/*/state.md` (with a `--project <path>` override), reads project artifacts to drive mode-aware review quality, and uses Tier 1/2/3 dispatch (`oat-reviewer` structured-output mode → fresh session → inline). The ad-hoc rail runs inline only.
54
+ - **Re-review narrowing** scopes a follow-up pass to commits since the prior matching review, guarded against a stale/force-pushed prior SHA (existence + ancestry checks; falls back to full scope when the prior SHA is unreachable). Project-rail narrowing matches on the `(project, scope)` tuple so a `p02` re-review never narrows against a prior `final` review.
55
+
56
+ > The posting backend is `gh api` directly: the bundled `agent-reviews` CLI is read/reply-only and has no review-posting flow, so the skills probe for a posting capability (forward-compatible) and fall through to `gh api`.
57
+
42
58
  ## Status model
43
59
 
44
60
  Status progression in `plan.md` Reviews table:
@@ -53,8 +69,9 @@ Status progression in `plan.md` Reviews table:
53
69
 
54
70
  - Critical/Important: address before pass.
55
71
  - Medium: address by default; defer only with explicit approval and recorded rationale/disposition.
56
- - Minor (non-final scopes): do not auto-defer by default. Convert when likely future cleanup or when the fix is trivial; defer only with recorded rationale.
57
- - Minor (final scope): not auto-deferred; require explicit user disposition (defer vs convert), and recommend convert when likely future cleanup or trivial to fix.
72
+ - Minor: **default to `convert`** (fix inline). Small non-blocking findings are usually cheaper to fix than to track as backlog items, so the receive skills convert them by default rather than deferring.
73
+ - Deferring (or dismissing) a finding **at any severity, including minor**, requires a concrete recorded rationale (duplicate, blocked dependency, explicit out-of-scope follow-up, or disproportionate churn now). This brings the manual receive path in line with the auto-review path, which already converts minors.
74
+ - Minor (final scope): still require explicit per-finding user disposition after a plain-language explanation, with `convert` as the recommended default.
58
75
 
59
76
  ## Auto-review at HiLL checkpoints
60
77
 
@@ -117,8 +134,10 @@ Final review `passed` gate requires:
117
134
  - `.oat/projects/local/orphan-reviews/` (default local-only storage for ad-hoc review artifacts)
118
135
  - `.oat/repo/reviews/` (tracked storage convention when explicitly desired)
119
136
  - `.agents/skills/oat-review-provide/SKILL.md`
137
+ - `.agents/skills/oat-review-provide-remote/SKILL.md`
120
138
  - `.agents/skills/oat-review-receive/SKILL.md`
121
139
  - `.agents/skills/oat-review-receive-remote/SKILL.md`
122
140
  - `.agents/skills/oat-project-review-provide/SKILL.md`
141
+ - `.agents/skills/oat-project-review-provide-remote/SKILL.md`
123
142
  - `.agents/skills/oat-project-review-receive/SKILL.md`
124
143
  - `.agents/skills/oat-project-review-receive-remote/SKILL.md`
@@ -61,6 +61,7 @@ Use this section when you want to choose the right OAT skill for a task. If you
61
61
  - `oat-project-capture`
62
62
  - `oat-project-reconcile`
63
63
  - `oat-project-review-provide`
64
+ - `oat-project-review-provide-remote`
64
65
  - `oat-project-review-receive`
65
66
  - `oat-project-review-receive-remote`
66
67
  - `oat-project-pr-progress`
@@ -91,6 +92,7 @@ Use this section when you want to choose the right OAT skill for a task. If you
91
92
  === "Review, backlog, and maintenance"
92
93
 
93
94
  - `oat-review-provide`
95
+ - `oat-review-provide-remote`
94
96
  - `oat-review-receive`
95
97
  - `oat-review-receive-remote`
96
98
  - `oat-repo-knowledge-index`
@@ -1,6 +1,6 @@
1
1
  {
2
- "cli": "0.1.13",
3
- "docs-config": "0.1.13",
4
- "docs-theme": "0.1.13",
5
- "docs-transforms": "0.1.13"
2
+ "cli": "0.1.15",
3
+ "docs-config": "0.1.15",
4
+ "docs-theme": "0.1.15",
5
+ "docs-transforms": "0.1.15"
6
6
  }
@@ -0,0 +1,354 @@
1
+ ---
2
+ name: oat-project-review-provide-remote
3
+ version: 1.0.2
4
+ description: Use when reviewing a GitHub PR opened on another machine for an active OAT project and posting findings back as a single PR review. Resolves the project from the PR diff, reads project artifacts for mode-aware review, and posts via gh api.
5
+ disable-model-invocation: true
6
+ user-invocable: true
7
+ allowed-tools: Read, Write, Bash, Glob, Grep, Task, AskUserQuestion
8
+ ---
9
+
10
+ # Remote Review Provide (Project-Scoped GitHub PR)
11
+
12
+ Review a GitHub PR opened by an agent on another machine for an active OAT project, and post the findings back as a single GitHub PR review. The project is located from the PR diff (or an explicit `--project <path>` override), its artifacts are read for mode-aware review quality, and the posted review carries project metadata markers so `oat-project-review-receive-remote` can round-trip the findings into plan tasks on the originating machine.
13
+
14
+ GitHub is the source of truth on this rail: no local artifact is written, no `plan.md` / `state.md` / `implementation.md` bookkeeping happens here, and no commits or pushes are made from this machine. The receive-remote skill on machine A owns every project-state mutation.
15
+
16
+ This is the project-scoped sibling of `oat-review-provide-remote` (ad-hoc rail). It adds project resolution, mode-aware review context, and a Tier 1/2/3 dispatch model that matches `oat-project-review-provide`.
17
+
18
+ ## Prerequisites
19
+
20
+ - `gh` CLI is installed and authenticated (`gh auth status`).
21
+ - The PR to review exists on GitHub and is reachable from the current repo's remote.
22
+ - The PR diff includes `state.md` for exactly one OAT project (project-flow commit discipline), OR you pass `--project <path>` to disambiguate.
23
+ - Optionally `npx agent-reviews` for posting symmetry (capability-probed at startup; `gh api` is the fallback).
24
+
25
+ ## Mode Assertion
26
+
27
+ **OAT MODE: Project Remote Review Provide**
28
+
29
+ **Purpose:** Fetch a GitHub PR, locate the OAT project it belongs to, run a mode-aware review against the project artifacts + review checklist + severity model, and post a single PR review (summary + severity counts + inline comments + project metadata markers) back to GitHub.
30
+
31
+ **BLOCKED Activities:**
32
+
33
+ - No `plan.md`, `state.md`, or `implementation.md` lifecycle mutations on this machine (machine A's `oat-project-review-receive-remote` owns those).
34
+ - No local review artifact written on this machine (GitHub is the source of truth; the Tier 1 reviewer runs in structured-output mode and writes NO artifact).
35
+ - No commits and no pushes from this machine.
36
+ - No mutation of the caller's working tree — all checkout happens in an ephemeral worktree.
37
+ - No implementing fixes (this skill reviews; it does not fix).
38
+ - No posting a review to GitHub without explicit user confirmation.
39
+
40
+ **ALLOWED Activities:**
41
+
42
+ - Resolve the PR number and the target OAT project (diff scan + `--project` override).
43
+ - Acquire PR content via ephemeral worktree + `gh pr checkout` (or `gh pr diff` fallback).
44
+ - Read project artifacts (`state.md`, `spec.md`, `design.md`, `plan.md`, `implementation.md`, `discovery.md`) from the checkout — read-only.
45
+ - Detect prior provide-remote reviews and narrow re-review scope (with the stale-SHA guard), filtered to this `(project, scope)`.
46
+ - Run the review via Tier 1 (`oat-reviewer` structured-output) / Tier 2 (fresh session) / Tier 3 (inline).
47
+ - Build the posted-review body with project markers + inline-comment array.
48
+ - Post a single PR review via `agent-reviews` (if probed supported) else `gh api` (with user confirmation).
49
+
50
+ **Self-Correction Protocol:**
51
+ If you catch yourself:
52
+
53
+ - Running `gh pr checkout` in the caller's working tree instead of an ephemeral worktree -> STOP, acquire the worktree first, and check out inside it.
54
+ - Writing a review artifact file on this machine (including the Tier 1 reviewer writing under `reviews/`) -> STOP; the posted PR review is the only output. The reviewer MUST run in structured-output mode.
55
+ - Editing or committing project lifecycle artifacts (`plan.md`, `state.md`, `implementation.md`) -> STOP and revert to review-and-post only.
56
+ - Pushing or committing anything from this machine -> STOP; machine A's receive-remote owns all project-state mutations.
57
+ - Posting the review to GitHub without explicit user confirmation -> STOP and present the body + verdict for approval first.
58
+ - Narrowing against a prior review SHA without running the existence + ancestry guard -> STOP and run the guard first.
59
+ - Narrowing against a prior review for a different project or a different scope -> STOP; only the same `(project, scope)` prior review narrows this one.
60
+ - Forgetting to remove the ephemeral worktree after posting (or on failure) -> STOP and release it in a `finally`.
61
+
62
+ ## Progress Indicators (User-Facing)
63
+
64
+ Print this banner once at start:
65
+
66
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
67
+ OAT ▸ PROJECT REMOTE REVIEW PROVIDE
68
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
69
+
70
+ Use step indicators:
71
+
72
+ - `[1/8] Resolving PR...`
73
+ - `[2/8] Checking out PR (ephemeral worktree)...`
74
+ - `[3/8] Resolving OAT project + reading artifacts...`
75
+ - `[4/8] Detecting prior reviews + narrowing scope...`
76
+ - `[5/8] Running review (Tier 1/2/3)...`
77
+ - `[6/8] Mapping inline comments to the diff...`
78
+ - `[7/8] Building review body + verdict...`
79
+ - `[8/8] Posting review + cleanup...`
80
+
81
+ ## Arguments
82
+
83
+ ```
84
+ oat-project-review-provide-remote [code <scope>|artifact <scope>]
85
+ [--pr <N>] [--project <path>]
86
+ [--no-checkout] [--narrow|--no-narrow]
87
+ ```
88
+
89
+ - `code <scope>` / `artifact <scope>`: review type and scope token. Scope tokens: `pNN`, `pNN-tNN`, `pNN-pMM`, `final`, or `artifact <name>`. When omitted, infer from PR state (default `code` with the phase scope; `final` when the implementation is complete).
90
+ - `--pr <N>`: target PR number. When omitted, auto-detect from the current branch.
91
+ - `--project <path>`: explicit OAT project directory. Takes precedence over the diff scan. Required when the diff touches zero or multiple projects' `state.md`.
92
+ - `--no-checkout`: skip the ephemeral worktree and review from `gh pr diff` only (degraded context; project artifacts read from `gh` blob fetches instead of the checkout).
93
+ - `--narrow` / `--no-narrow`: force or forbid re-review narrowing against a prior provide-remote review for this `(project, scope)`. When neither is passed, honor `workflow.autoNarrowReReviewScope` (no prompt when `true`; confirm prompt otherwise).
94
+
95
+ Inputs are CLI-style args parsed from `$ARGUMENTS`. No file inputs. No file outputs on this machine.
96
+
97
+ ## Findings Model
98
+
99
+ Normalize every finding to this shape (matches the `oat-reviewer` `StructuredFindings` schema and the `oat-project-review-receive-remote` model):
100
+
101
+ ```yaml
102
+ finding:
103
+ id: "C1" | "I1" | "M1" | "m1"
104
+ severity: critical | important | medium | minor
105
+ title: string
106
+ file: string | null
107
+ line: number | null
108
+ body: string
109
+ fix_guidance: string | null
110
+ ```
111
+
112
+ Severity conventions:
113
+
114
+ - `critical`: Broken behavior, security risk, or missing P0 requirement.
115
+ - `important`: Missing P1 requirement, major robustness issue.
116
+ - `medium`: Meaningful but non-blocking quality/maintainability issue.
117
+ - `minor`: Cosmetic/style/documentation issue.
118
+
119
+ `file` and `line` are both set (inline finding) or both `null` (reviewer-level finding that lands in the top-level body). Checklist + severity model + the `StructuredFindings` schema source of truth: `.agents/agents/oat-reviewer.md` and `design.md` → Data Models → StructuredFindings.
120
+
121
+ ## Process
122
+
123
+ ### Step 1: Resolve PR Number
124
+
125
+ PR resolution order:
126
+
127
+ 1. `--pr <N>` from `$ARGUMENTS`.
128
+ 2. Auto-detect from the current branch: `gh pr view --json number -q .number`.
129
+
130
+ Confirm `gh auth status` succeeds. Ask the user to confirm the resolved PR number before checkout. Capture the PR HEAD SHA (full 40-char) for the marker block and the narrowing guard:
131
+
132
+ ```bash
133
+ PR_HEAD_SHA=$(gh pr view "$PR" --json headRefOid -q .headRefOid)
134
+ ```
135
+
136
+ ### Step 2: Check Out the PR (Hybrid Read)
137
+
138
+ Acquire an ephemeral worktree FIRST, then run `gh pr checkout` inside it so the caller's working tree is never mutated. Use repo-scoped git commands so the skill works regardless of the caller's CWD (design.md → Data Flow step 2). This shell flow parallels the tested TypeScript helper at `packages/cli/src/review-remote/worktree.ts` (`acquireWorktree` / `runInWorktree` / `releaseWorktree`) — keep the two in sync if you change either:
139
+
140
+ ```bash
141
+ REPO_ROOT=$(git rev-parse --show-toplevel)
142
+ EPHEMERAL_PATH=$(mktemp -d)
143
+ rmdir "$EPHEMERAL_PATH" # git worktree add requires a non-existent target
144
+ git -C "$REPO_ROOT" worktree add --detach "$EPHEMERAL_PATH" HEAD
145
+ ( cd "$EPHEMERAL_PATH" && gh pr checkout "$PR" )
146
+ ```
147
+
148
+ The `-C "$REPO_ROOT"` flag is load-bearing — it lets the command run even when the caller's CWD is not inside the repository.
149
+
150
+ Fallback to diff-only mode when `--no-checkout` is set, or when worktree creation / `gh pr checkout` fails (capture exit code + stderr; distinguish auth from network from branch-state failures). On checkout failure, clean up the partial worktree (`git -C "$REPO_ROOT" worktree remove --force "$EPHEMERAL_PATH"`), then warn the user that context is degraded and continue with:
151
+
152
+ ```bash
153
+ gh pr diff "$PR" > "$DIFF_FILE"
154
+ gh pr view "$PR" --json title,body,headRefOid,baseRefName,state
155
+ ```
156
+
157
+ In diff-only mode the project artifacts are read by fetching individual blobs from the PR HEAD (`gh api /repos/{owner}/{repo}/contents/<path>?ref=$PR_HEAD_SHA`) rather than from a checkout.
158
+
159
+ ### Step 3: Resolve the OAT Project + Read Artifacts
160
+
161
+ Determine the changed-file list for the PR, then resolve the target project. This mirrors the tested helper at `packages/cli/src/review-remote/project-resolver.ts` (`resolveProject`):
162
+
163
+ ```bash
164
+ # Changed files for the PR (rich-context: from the checkout; diff-only: from gh).
165
+ CHANGED_FILES=$(gh api "/repos/{owner}/{repo}/pulls/$PR/files" --jq '.[].filename')
166
+ ```
167
+
168
+ Resolution rules:
169
+
170
+ 1. **`--project <path>` override wins.** Validate that the path resolves to a directory containing `state.md`; if not, surface a clear error and stop (do not post).
171
+ 2. Otherwise, scan `CHANGED_FILES` for two-level `.oat/projects/<scope>/<project>/state.md` paths.
172
+ - Exactly one match -> use it.
173
+ - Multiple matches -> error out with the candidate list and require `--project <path>`.
174
+ - Zero matches -> require `--project <path>`.
175
+
176
+ Once resolved to `PROJECT_PATH`, read the project artifacts read-only for mode-aware review context (from the checkout in rich-context mode, or via blob fetch in diff-only mode):
177
+
178
+ - `state.md`, `spec.md`, `design.md`, `plan.md`, `implementation.md`, `discovery.md` (whichever exist for the project's workflow mode).
179
+
180
+ Resolve the workflow mode and the scope token:
181
+
182
+ - Read `state.md` frontmatter for the workflow mode and current phase/status.
183
+ - Parse the scope token from `$ARGUMENTS` (`code <scope>` / `artifact <scope>`), or infer it from PR state (default `code` with the current phase; `final` when the implementation is complete). For `final` scope, also gather the deferred-findings ledger from `implementation.md`.
184
+
185
+ NEVER mutate, commit, or push any project artifact. This is a read-only project context on machine B.
186
+
187
+ ### Step 4: Detect Prior Reviews + Narrow Scope
188
+
189
+ List prior PR reviews and parse each body's marker block. Filter to reviews where `oat_provide_remote: true` AND `oat_project == "$PROJECT_PATH"` AND `oat_review_scope == "<current-scope-token>"`. Different-project or different-scope prior reviews do NOT narrow this one (mirrors the tested helper at `packages/cli/src/review-remote/narrowing.ts`, `pickNarrowingTarget` with `rail: "project"`).
190
+
191
+ ```bash
192
+ gh api "/repos/{owner}/{repo}/pulls/$PR/reviews"
193
+ ```
194
+
195
+ Take the most recent matching review (by submitted timestamp). Before narrowing to `<prior_sha>..<HEAD>`, run the stale-SHA guard (design.md → Error Handling → Stale prior-review SHA):
196
+
197
+ Run the guard in the available git context `$GIT_CTX` — `$EPHEMERAL_PATH` in rich-context (checkout) mode, or `$REPO_ROOT` in diff-only mode (where no worktree exists):
198
+
199
+ 1. **Existence:** `git -C "$GIT_CTX" cat-file -e <prior_sha>` (diff-only mode: `git -C "$REPO_ROOT" fetch origin <prior_sha>:refs/oat-prior-review` first, then re-check; if that fetch fails, fall back to full PR scope).
200
+ 2. **Ancestry:** `git -C "$GIT_CTX" merge-base --is-ancestor <prior_sha> "$PR_HEAD_SHA"`.
201
+
202
+ Guard outcomes:
203
+
204
+ - Both pass -> narrow to `<prior_sha>..<HEAD>`.
205
+ - Either fails -> fall back to full PR scope and warn that the prior SHA is unreachable (likely rebase/force-push).
206
+ - `--narrow` set AND guard fails -> hard error; surface unreachability and stop.
207
+ - `workflow.autoNarrowReReviewScope == true` -> never prompt; guard failure auto-falls back to full scope with the warning as the auto-fallback notice.
208
+ - No matching prior review (for this `(project, scope)`) -> use full PR diff.
209
+
210
+ ### Step 5: Run the Review (Tier 1/2/3 Dispatch)
211
+
212
+ Mode-aware review against the project artifacts + the `oat-reviewer` checklist + severity model. Scope to the narrowing range when one was chosen; otherwise the full PR diff. Assign finding IDs per severity bucket (`C1`, `I1`, `M1`, `m1`), stable within the dispatch.
213
+
214
+ **Step 5a: Probe subagent availability** (mirrors `oat-project-review-provide` Step 6a):
215
+
216
+ ```
217
+ [5/8] Checking subagent availability…
218
+ → oat-reviewer: {available | authorization required | not resolved} ({reason})
219
+ → Selected: Tier {1|2|3} — {Subagent (structured output) | Fresh session (recommended) | Inline review}
220
+ ```
221
+
222
+ Detection:
223
+
224
+ - Claude Code: Task-style subagent dispatch with `subagent_type: "oat-reviewer"` (resolves from `.claude/agents/oat-reviewer.md`).
225
+ - Cursor: explicit invocation `/oat-reviewer` (or natural mention), resolved from `.cursor/agents/oat-reviewer.md` or the `.claude/agents/oat-reviewer.md` compatibility path.
226
+ - Codex multi-agent: verify `[features] multi_agent = true`; if the host requires explicit authorization before `spawn_agent`, announce `authorization required` and ask one concise confirmation before selecting a lower tier. If authorized -> Tier 1; if declined -> Tier 2/3 fallback.
227
+ - If the runtime can dispatch reviewer work -> Tier 1. If subagent dispatch is unavailable -> Tier 2. If the user requests inline / confirms a fresh session -> Tier 3.
228
+
229
+ **Step 5b: Tier 1 — `oat-reviewer` in structured-output mode (preferred).**
230
+
231
+ Build the dispatch payload and spawn the reviewer in structured-output mode. This mirrors the tested wrapper at `packages/cli/src/review-remote/reviewer-dispatch.ts` (`buildDispatchPayload` / `dispatchStructuredReview`):
232
+
233
+ - Set `oat_output_mode: structured` in the dispatch payload (the flag `.agents/agents/oat-reviewer.md` recognizes). In this mode the reviewer returns a `StructuredFindings` object in-memory and writes NO artifact under `reviews/`.
234
+ - Include the project context (`oat_project`, `oat_review_scope`, `oat_review_head_sha`), the Review Scope metadata block, a pointer to the posted-review-body schema (`design.md` → Data Models → Posted-review-body), and the resolved narrowing range (`<prior_sha>..<HEAD>` or none).
235
+ - If a worktree was resolved in Step 2, include its path so the reviewer reads from the checkout.
236
+ - The reviewer returns `StructuredFindings` (summary + findings array + `verification_commands`). On a dispatcher error, do NOT retry at Tier 1 — fall through to Tier 2/3. On malformed structured output, surface the validation error and fall through to Tier 2/3.
237
+
238
+ **Step 5c: Tier 2 — Fresh session (recommended fallback).** If subagent dispatch is unavailable and the user is not already in a fresh session, provide fresh-session instructions and exit. (If Codex reported `authorization required` and the user later authorizes, return to Tier 1.)
239
+
240
+ **Step 5d: Tier 3 — Inline review (fallback).** If the user insists on inline review in the current session, run the reset protocol: re-read the required project artifacts, read all files in the review scope, apply the `oat-reviewer` checklist inline, and produce the findings set in the same `StructuredFindings` shape. Write NO artifact.
241
+
242
+ ### Step 6: Map Inline Comments to the Diff
243
+
244
+ For each finding with non-null `file` + `line`, classify it against the PR diff BEFORE adding it to the inline `comments[]` payload (design.md → Error Handling → Inline-comment line mapping; mirrors `packages/cli/src/review-remote/line-mapper.ts`):
245
+
246
+ - Rich-context mode: parse hunk ranges from `gh api /repos/{owner}/{repo}/pulls/$PR/files` (per-file `patch` field).
247
+ - Diff-only mode: parse hunk headers (`@@ -a,b +c,d @@`) from the `gh pr diff` output.
248
+ - `side: RIGHT` for additions/context; `side: LEFT` only when the finding is explicitly about removed code.
249
+ - **Renamed files:** a `gh api .../files` entry carries the pre-rename path in a sibling `previous_filename` field (not in `patch`). When a finding references the pre-rename path, remap it to the entry's post-rename `filename` before classifying, or it will be treated as out-of-diff.
250
+ - If `line` falls outside the diff: downgrade the finding to a top-level "Findings outside the PR diff" subsection with its `file:line` reference. NEVER silently drop it and NEVER shift the line to the nearest in-diff line.
251
+
252
+ > **Reference implementation:** the canonical, tested logic for this step lives in `packages/cli/src/review-remote/line-mapper.ts` (`parsePullFilesPatch` / `parseUnifiedDiff` / `classifyFinding`). The bash/`jq` flow here mirrors it — keep the two in sync. See `packages/cli/src/review-remote/README.md`; `bl-a7cd` tracks wiring this skill to call the helpers directly. The same applies to the marker block (`marker-parser.ts`), body/verdict (`body-builder.ts`), re-review narrowing (`narrowing.ts`), project resolution (`project-resolver.ts`), and the `oat-reviewer` dispatch (`reviewer-dispatch.ts`) used elsewhere in this skill.
253
+
254
+ ### Step 7: Build the Review Body + Verdict
255
+
256
+ Build the posted-review body with project markers (design.md → Data Models → Posted-review-body; mirrors `packages/cli/src/review-remote/body-builder.ts`): a leading HTML-comment marker block, then summary, severity counts, the minor-fix "Notes" nudge (only when minor findings are present), and the verification commands.
257
+
258
+ Markers (project rail — both `oat_project` and `oat_review_scope` present):
259
+
260
+ ```
261
+ <!-- oat-review-metadata
262
+ oat_provide_remote: true
263
+ oat_review_head_sha: <PR_HEAD_SHA>
264
+ oat_review_scope: <scope token, e.g. p02 | final>
265
+ oat_project: <PROJECT_PATH>
266
+ oat_review_invocation: manual
267
+ -->
268
+ ```
269
+
270
+ `oat_project` carries the resolved project path so machine A's `oat-project-review-receive-remote` routes findings into the right project's plan tasks. Verdict: `REQUEST_CHANGES` when any critical or important finding exists; `COMMENT` otherwise (including a clean, zero-findings review — never auto-`APPROVE`).
271
+
272
+ ### Step 8: Post the Review + Clean Up
273
+
274
+ Probe `agent-reviews` for a posting flow with a non-mutating check (`npx agent-reviews --help`), cached for the run:
275
+
276
+ - If a posting flow is supported -> prefer `agent-reviews` for tooling symmetry.
277
+ - Otherwise (or if the probe is inconclusive) -> post via `gh api`. As of the current `agent-reviews` release there is no review-posting flow, so `gh api` is the expected path.
278
+
279
+ Present the body + verdict + inline-comment count to the user and get explicit confirmation, then post a single review.
280
+
281
+ `gh api --field`/`-f`/`-F` only set top-level scalar values; they CANNOT build the nested `comments[]` array of objects the reviews endpoint requires for inline comments. Construct the complete review payload as JSON and pipe it through `--input -` instead. Each in-diff finding (from Step 6) becomes one `comments[]` entry `{ path, line, side, body }`; out-of-diff findings are NOT added here — they were already downgraded into `$REVIEW_BODY` in Step 6. `event` is the Step 7 verdict. A body-only review (zero in-diff findings) uses an empty `comments` array:
282
+
283
+ ```bash
284
+ # Build the payload as JSON. `comments` is the in-diff findings array; jq
285
+ # assembles it safely (escaping body text, numbers as numbers). For a
286
+ # body-only review, COMMENTS_JSON is `[]`.
287
+ jq -n \
288
+ --arg event "$VERDICT" \
289
+ --arg body "$REVIEW_BODY" \
290
+ --argjson comments "$COMMENTS_JSON" \
291
+ '{event: $event, body: $body, comments: $comments}' \
292
+ | gh api --method POST "/repos/{owner}/{repo}/pulls/$PR/reviews" --input -
293
+
294
+ # COMMENTS_JSON is a JSON array, one object per in-diff finding, e.g.:
295
+ # [
296
+ # { "path": ".oat/projects/foo/bar/plan.md", "line": 42, "side": "RIGHT", "body": "..." },
297
+ # { "path": "src/bar.ts", "line": 17, "side": "LEFT", "body": "..." }
298
+ # ]
299
+ # `side` is RIGHT for additions/context, LEFT only for explicit removed-code
300
+ # findings (Step 6). Use `[]` when there are no in-diff findings.
301
+ ```
302
+
303
+ Posting failure handling (design.md → Error Handling → Posting failures): on auth failure, surface `gh auth status` and stop (findings kept in memory). On PR closed/merged, surface a clear message and present findings inline. On inline-comment rejection, re-map against the current file list and retry once; if still rejected, downgrade the offending finding(s) and retry. On rate limit, surface the window and stop. NEVER silently drop a finding.
304
+
305
+ Always release the ephemeral worktree in a `finally`, even when review or posting fails:
306
+
307
+ ```bash
308
+ git -C "$REPO_ROOT" worktree remove --force "$EPHEMERAL_PATH" || git -C "$REPO_ROOT" worktree prune
309
+ rm -rf "$EPHEMERAL_PATH"
310
+ ```
311
+
312
+ ## Troubleshooting
313
+
314
+ - Auth failure: run `gh auth status`; re-authenticate, then retry.
315
+ - No PR detected: pass explicit `--pr <N>`.
316
+ - Project not resolved (zero or multiple `state.md` mods in the diff): pass explicit `--project <path>`.
317
+ - `--project` path invalid (no `state.md`): the skill stops without posting; pass a directory containing `state.md`.
318
+ - Checkout fails: the skill auto-falls back to diff-only mode with a degraded-context warning; pass `--no-checkout` to force it.
319
+ - Prior-review SHA unreachable: re-invoke without `--narrow` to review full scope.
320
+ - Inline comment rejected at a file:line: the finding is downgraded to the top-level body, not dropped.
321
+ - Subagent unavailable: the skill falls through Tier 2 (fresh session) / Tier 3 (inline).
322
+ - Network / rate-limit errors: retry after backoff; report blocked state if persistent.
323
+
324
+ ## Output Contract
325
+
326
+ At completion, report:
327
+
328
+ - PR number and HEAD SHA reviewed.
329
+ - Resolved project path and how it was resolved (diff scan vs `--project` override).
330
+ - Review type and scope token.
331
+ - Read mode (worktree checkout vs diff-only).
332
+ - Dispatch tier used (Tier 1 structured-output / Tier 2 fresh session / Tier 3 inline).
333
+ - Narrowing decision (full scope vs `<prior_sha>..<HEAD>`, and why).
334
+ - Severity counts and total findings.
335
+ - Inline-comment count posted vs findings downgraded to the body (out-of-diff).
336
+ - Verdict (`REQUEST_CHANGES` or `COMMENT`).
337
+ - Posting mechanism (`agent-reviews` or `gh api`) and whether the review was posted.
338
+ - Confirmation that the ephemeral worktree was removed.
339
+ - Confirmation that NO project artifact was mutated, committed, or pushed on this machine.
340
+
341
+ ## Success Criteria
342
+
343
+ - PR scope resolved and confirmed.
344
+ - OAT project resolved from the diff (or `--project` override) and validated; project artifacts read read-only for mode-aware context.
345
+ - PR content acquired via ephemeral worktree (or diff-only fallback) without mutating the caller's working tree.
346
+ - Prior provide-remote reviews detected and filtered to this `(project, scope)`; re-review narrowing applied only after the stale-SHA guard passes.
347
+ - Review executed via Tier 1 (`oat-reviewer` structured-output, NO artifact) / Tier 2 (fresh session) / Tier 3 (inline), with graceful fallthrough.
348
+ - Findings produced with consistent 4-tier severities and file:line references.
349
+ - Inline comments mapped to in-diff positions; out-of-diff findings downgraded to the body, never dropped.
350
+ - Posted-review body carries the marker block first (with `oat_project` + `oat_review_scope`), correct severity counts, and the minor-fix nudge when minors are present.
351
+ - Verdict matches the C/I rule (`REQUEST_CHANGES` vs `COMMENT`; never auto-`APPROVE`).
352
+ - Single PR review posted (with user confirmation) via `agent-reviews` if supported, else `gh api`.
353
+ - Ephemeral worktree removed on success and on failure.
354
+ - No local artifact, no `plan.md` / `state.md` / `implementation.md` updates, no commits, no pushes on this machine.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-review-receive
3
- version: 1.4.3
3
+ version: 1.5.1
4
4
  description: Use when review findings from oat-project-review-provide need closure. Converts review artifacts into actionable plan tasks.
5
5
  disable-model-invocation: true
6
6
  user-invocable: true
@@ -249,7 +249,7 @@ Read `oat_review_type` and `oat_review_invocation` from review artifact frontmat
249
249
  - If `oat_review_type == code` AND `oat_review_invocation == auto`:
250
250
  - **Auto-disposition mode.** This review was spawned by the auto-review checkpoint trigger in `oat-project-implement`. Apply relaxed disposition defaults:
251
251
  - Critical/Important/Medium: convert to fix tasks (same as manual mode)
252
- - Minor: auto-convert to fix tasks unless clearly out of scope (e.g., cosmetic polish unrelated to changed code). In manual mode, minors are auto-deferred for non-final scopes in auto mode, the goal is to fix everything while context is fresh.
252
+ - Minor: auto-convert to fix tasks unless clearly out of scope (e.g., cosmetic polish unrelated to changed code). Manual mode now also defaults minors to `convert` (see Step 9); auto mode keeps the same intent fix everything while context is fresh — but without any user prompts.
253
253
  - **No user prompts for disposition decisions.** The auto-review path runs fully autonomously.
254
254
  - Genuinely ambiguous findings (e.g., a medium the agent disagrees with) are deferred with a note explaining why, rather than pausing for interactive resolution.
255
255
  - Follow the task-conversion flow in Steps 3-10 with these adjusted defaults.
@@ -526,11 +526,8 @@ Design drift handling applies before Medium/Minor convenience deferrals:
526
526
  Minor findings handling is scope-aware:
527
527
 
528
528
  - If `scope != final`:
529
- - Minor findings are not auto-deferred just because they are non-functional.
530
- - Default to converting a Minor finding to a task when either of these is true:
531
- - it is likely future cleanup (better than even chance that the team will need to address it later), or
532
- - the fix scope is `Negligible` or `Minor`.
533
- - Only propose deferral when the finding is genuinely low-probability cleanup, blocked by another change, duplicated elsewhere, explicitly out of scope, or fixing now would create disproportionate churn/risk.
529
+ - Minor findings default to `convert`, not `defer`. Small findings are usually cheaper to fix inline than to track as backlog items, so converting is the baseline disposition for every Minor.
530
+ - `defer` (and `dismiss`) at Minor severity requires explicit, concrete rationale — the same gate that applies to Medium and above. Only propose deferral when the finding is genuinely low-probability cleanup, blocked by another change, duplicated elsewhere, explicitly out of scope, or fixing now would create disproportionate churn/risk.
534
531
  - If deferred, record rationale in implementation.md under "Deferred Findings".
535
532
  - Do not block review completion on minor disposition once each finding has been converted or explicitly deferred with rationale.
536
533
 
@@ -541,8 +538,8 @@ Minor findings handling is scope-aware:
541
538
  - potential user/maintainer impact,
542
539
  - why fixing now vs deferring is reasonable.
543
540
  - Recommendation default:
544
- - recommend `convert` when the finding is likely future cleanup or the fix scope is `Negligible`/`Minor`;
545
- - recommend `defer` only when the finding is unlikely to matter soon, blocked, duplicated, or high-churn to address now.
541
+ - default to recommending `convert` fixing a non-blocking minor inline is usually cheaper than tracking it as a backlog item, and this is especially true for `Negligible`/`Minor`-scope fixes;
542
+ - recommend `defer` only when the finding is unlikely to matter soon, blocked, duplicated, or high-churn to address now, and capture that concrete rationale.
546
543
  - Keep explanations concise (1-3 sentences per minor) and include file/line when available.
547
544
  - Ask user explicitly:
548
545
 
@@ -633,7 +630,7 @@ Actions taken:
633
630
  - Updated implementation.md with review notes
634
631
  - Archived review artifact to `reviews/archived/{filename}.md`
635
632
  - Deferred/accepted Medium findings: {N}
636
- - Deferred {N} minor findings (auto for non-final, explicit decision for final)
633
+ - Minor findings dispositioned: {N} converted (default), {N} deferred-with-rationale (explicit user decision required for final scope)
637
634
  - Finding disposition map: {ID -> converted|deferred|accepted + rationale summary}
638
635
 
639
636
  Review cycle: {N} of 3