pi-orchestrator-config 4.1.5

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 (175) hide show
  1. package/README.md +808 -0
  2. package/agents/api-documenter.md +32 -0
  3. package/agents/bash-expert.md +53 -0
  4. package/agents/code-reviewer-docs.md +145 -0
  5. package/agents/code-reviewer-guidelines.md +97 -0
  6. package/agents/code-reviewer-quality.md +142 -0
  7. package/agents/code-reviewer-security.md +107 -0
  8. package/agents/code-reviewer-spec.md +164 -0
  9. package/agents/debugger.md +63 -0
  10. package/agents/docker-expert.md +40 -0
  11. package/agents/docs-fetcher.md +48 -0
  12. package/agents/git-expert.md +63 -0
  13. package/agents/github-expert.md +83 -0
  14. package/agents/go-expert.md +62 -0
  15. package/agents/issue-reviewer-feasibility.md +60 -0
  16. package/agents/issue-reviewer-scope.md +63 -0
  17. package/agents/issue-reviewer-spec.md +77 -0
  18. package/agents/java-expert.md +31 -0
  19. package/agents/jenkins-expert.md +38 -0
  20. package/agents/kubernetes-expert.md +40 -0
  21. package/agents/planner.md +42 -0
  22. package/agents/python-expert.md +61 -0
  23. package/agents/reviewer.md +26 -0
  24. package/agents/scout.md +40 -0
  25. package/agents/security-auditor.md +254 -0
  26. package/agents/technical-documentation-writer.md +37 -0
  27. package/agents/test-automator.md +55 -0
  28. package/agents/test-runner.md +47 -0
  29. package/agents/ts-expert.md +23 -0
  30. package/agents/worker.md +30 -0
  31. package/extensions/acpx-provider/index.ts +104 -0
  32. package/extensions/acpx-provider/load-runtime.ts +99 -0
  33. package/extensions/acpx-provider/runtime-models.ts +40 -0
  34. package/extensions/cli-provider/agents/claude.ts +128 -0
  35. package/extensions/cli-provider/agents/cursor.ts +84 -0
  36. package/extensions/cli-provider/agents/gemini.ts +100 -0
  37. package/extensions/cli-provider/discover.ts +77 -0
  38. package/extensions/cli-provider/index.ts +57 -0
  39. package/extensions/cli-provider/parsers.ts +304 -0
  40. package/extensions/cli-provider/providers.ts +58 -0
  41. package/extensions/cli-provider/runner.ts +225 -0
  42. package/extensions/cli-provider/runtime-models.ts +32 -0
  43. package/extensions/cli-provider/session-reaper.ts +122 -0
  44. package/extensions/cli-provider/sessions.ts +533 -0
  45. package/extensions/cli-provider/shared/discover-cache.ts +235 -0
  46. package/extensions/cli-provider/types.ts +48 -0
  47. package/extensions/coms/coms-net-server.ts +1642 -0
  48. package/extensions/coms/coms-net-wrapper.ts +521 -0
  49. package/extensions/coms/coms-net.ts +1589 -0
  50. package/extensions/coms/coms-p2p.ts +1879 -0
  51. package/extensions/coms/coms-shared.ts +510 -0
  52. package/extensions/coms/coms-wrapper.ts +138 -0
  53. package/extensions/coms/index.ts +20 -0
  54. package/extensions/coms/themeMap.ts +147 -0
  55. package/extensions/image-gen/image-gen.ts +332 -0
  56. package/extensions/image-gen/index.ts +14 -0
  57. package/extensions/orchestrator/agents.ts +134 -0
  58. package/extensions/orchestrator/ask-user.ts +293 -0
  59. package/extensions/orchestrator/async-agents.ts +1037 -0
  60. package/extensions/orchestrator/async-capability.ts +129 -0
  61. package/extensions/orchestrator/async-runner.ts +324 -0
  62. package/extensions/orchestrator/async-status-parse.ts +31 -0
  63. package/extensions/orchestrator/async-status-ui.ts +201 -0
  64. package/extensions/orchestrator/async-wait.ts +36 -0
  65. package/extensions/orchestrator/btw.ts +210 -0
  66. package/extensions/orchestrator/cron-status-format.ts +126 -0
  67. package/extensions/orchestrator/cron-status-ui.ts +132 -0
  68. package/extensions/orchestrator/cron.ts +730 -0
  69. package/extensions/orchestrator/dreaming.ts +355 -0
  70. package/extensions/orchestrator/enforcement-helpers.ts +530 -0
  71. package/extensions/orchestrator/enforcement-rules.ts +329 -0
  72. package/extensions/orchestrator/enforcement.ts +828 -0
  73. package/extensions/orchestrator/extended-autocomplete.ts +593 -0
  74. package/extensions/orchestrator/git-helpers.ts +420 -0
  75. package/extensions/orchestrator/github-autocomplete.ts +250 -0
  76. package/extensions/orchestrator/icons.ts +17 -0
  77. package/extensions/orchestrator/index.ts +100 -0
  78. package/extensions/orchestrator/memory-embeddings.ts +281 -0
  79. package/extensions/orchestrator/memory-promotion.ts +449 -0
  80. package/extensions/orchestrator/memory-provenance.ts +80 -0
  81. package/extensions/orchestrator/memory-query-class.ts +90 -0
  82. package/extensions/orchestrator/memory-scoring.ts +434 -0
  83. package/extensions/orchestrator/memory-tools.ts +883 -0
  84. package/extensions/orchestrator/memory-tree.ts +212 -0
  85. package/extensions/orchestrator/nvim.ts +169 -0
  86. package/extensions/orchestrator/overlay-dashboard-utils.ts +25 -0
  87. package/extensions/orchestrator/overlay-dashboard.ts +512 -0
  88. package/extensions/orchestrator/pi-config-review-state.ts +303 -0
  89. package/extensions/orchestrator/preference-extractor.ts +106 -0
  90. package/extensions/orchestrator/project-settings.ts +468 -0
  91. package/extensions/orchestrator/promotion-queue.ts +311 -0
  92. package/extensions/orchestrator/resolve-agent-model.ts +32 -0
  93. package/extensions/orchestrator/review-ui.ts +204 -0
  94. package/extensions/orchestrator/rule-placeholders.ts +12 -0
  95. package/extensions/orchestrator/rules.ts +481 -0
  96. package/extensions/orchestrator/session-search.ts +243 -0
  97. package/extensions/orchestrator/session-validation.ts +374 -0
  98. package/extensions/orchestrator/situation-report.ts +370 -0
  99. package/extensions/orchestrator/status-bar.ts +31 -0
  100. package/extensions/orchestrator/status-line.ts +192 -0
  101. package/extensions/orchestrator/status.ts +110 -0
  102. package/extensions/orchestrator/subagent-tool.ts +1748 -0
  103. package/extensions/orchestrator/task-lifecycle.ts +88 -0
  104. package/extensions/orchestrator/utils.ts +227 -0
  105. package/extensions/pidash/index.ts +15 -0
  106. package/extensions/pidash/pidash.ts +941 -0
  107. package/extensions/pidiff/index.ts +13 -0
  108. package/extensions/pidiff/pidiff.ts +369 -0
  109. package/extensions/providers/acpx-driver.ts +479 -0
  110. package/extensions/providers/built-in-drivers.ts +52 -0
  111. package/extensions/providers/claude-driver.ts +319 -0
  112. package/extensions/providers/cursor-acpx-driver.ts +398 -0
  113. package/extensions/providers/cursor-cli-driver.ts +484 -0
  114. package/extensions/providers/gemini-driver.ts +302 -0
  115. package/extensions/providers/index.ts +513 -0
  116. package/extensions/shared/build-system-prompt.ts +57 -0
  117. package/extensions/shared/create-runtime-provider.ts +190 -0
  118. package/extensions/shared/daemon-manager.ts +248 -0
  119. package/extensions/shared/file-logger.ts +115 -0
  120. package/extensions/shared/managed-refresh.ts +211 -0
  121. package/extensions/shared/provider-driver.ts +295 -0
  122. package/extensions/shared/provider-errors.ts +305 -0
  123. package/extensions/shared/provider-registry.ts +388 -0
  124. package/extensions/shared/stream-builder.ts +275 -0
  125. package/extensions/shared/types.ts +20 -0
  126. package/extensions/shared/ui/README.md +10 -0
  127. package/extensions/shared/ui/badge.tsx +52 -0
  128. package/extensions/shared/ui/button.tsx +58 -0
  129. package/extensions/shared/ui/collapsible.tsx +21 -0
  130. package/extensions/shared/ui/dropdown-menu.tsx +266 -0
  131. package/extensions/shared/ui/input.tsx +20 -0
  132. package/extensions/shared/ui/popover.tsx +114 -0
  133. package/extensions/shared/ui/resizable.tsx +48 -0
  134. package/extensions/shared/ui/scroll-area.tsx +53 -0
  135. package/extensions/shared/ui/select.tsx +201 -0
  136. package/extensions/shared/ui/separator.tsx +25 -0
  137. package/extensions/shared/ui/tooltip.tsx +64 -0
  138. package/extensions/shared/ws-client.ts +74 -0
  139. package/package.json +59 -0
  140. package/prompts/coderabbit-rate-limit.md +95 -0
  141. package/prompts/create-coms-feature-manager.md +186 -0
  142. package/prompts/create-skill.md +128 -0
  143. package/prompts/domain-model.md +109 -0
  144. package/prompts/external-ai.md +665 -0
  145. package/prompts/implement-and-review.md +25 -0
  146. package/prompts/implement.md +26 -0
  147. package/prompts/issue-review.md +256 -0
  148. package/prompts/pr-review.md +753 -0
  149. package/prompts/query-db.md +154 -0
  150. package/prompts/refine-review.md +208 -0
  151. package/prompts/release.md +235 -0
  152. package/prompts/remember.md +33 -0
  153. package/prompts/review-handler-status.md +27 -0
  154. package/prompts/review-handler.md +677 -0
  155. package/prompts/review-local.md +159 -0
  156. package/prompts/scout-and-plan.md +21 -0
  157. package/rules/00-orchestrator-core.md +42 -0
  158. package/rules/05-issue-first-workflow.md +119 -0
  159. package/rules/10-agent-routing.md +58 -0
  160. package/rules/15-mcp-launchpad.md +46 -0
  161. package/rules/20-code-review-loop.md +234 -0
  162. package/rules/25-documentation-updates.md +15 -0
  163. package/rules/30-prompt-templates.md +19 -0
  164. package/rules/35-memory.md +240 -0
  165. package/rules/40-critical-rules.md +124 -0
  166. package/rules/45-file-preview.md +29 -0
  167. package/rules/50-agent-bug-reporting.md +90 -0
  168. package/rules/55-coms-protocol.md +63 -0
  169. package/rules/60-task-tracking.md +66 -0
  170. package/skills/conflict-resolver/SKILL.md +213 -0
  171. package/skills/skill-creator/SKILL.md +85 -0
  172. package/skills/systematic-debugging/SKILL.md +353 -0
  173. package/skills/test-driven-development/SKILL.md +335 -0
  174. package/skills/update-agents-md/SKILL.md +282 -0
  175. package/templates/coms-feature-manager-prompt.md +313 -0
@@ -0,0 +1,753 @@
1
+ ---
2
+ description: Review a GitHub PR and post inline comments on selected findings
3
+ argument-hint: "[PR number or URL]"
4
+ ---
5
+
6
+ ## Raw Arguments
7
+
8
+ ```text
9
+ $ARGUMENTS
10
+ ```
11
+
12
+ # GitHub PR Review Command
13
+
14
+ > **Bug Reporting Policy:** If you encounter ANY error, unexpected behavior, or reproducible bug
15
+ > while executing this command — DO NOT work around it silently. Ask the user:
16
+ > "Should I create a GitHub issue for this?" Route to:
17
+ > `myk-org/pi-config` for plugin/command spec or `myk-pi-tools` CLI issues.
18
+ > Do not silently skip steps or apply manual fixes that hide the root cause.
19
+
20
+ Reviews a GitHub PR and posts inline review comments on selected findings.
21
+
22
+ ## Prerequisites Check (MANDATORY)
23
+
24
+ Before starting, verify the tools are available:
25
+
26
+ ### Step 0: Check uv
27
+
28
+ ```bash
29
+ uv --version
30
+ ```
31
+
32
+ If not found, install from <https://docs.astral.sh/uv/getting-started/installation/>
33
+
34
+ ### Step 1: Check myk-pi-tools
35
+
36
+ ```bash
37
+ myk-pi-tools --version
38
+ ```
39
+
40
+ If not found, prompt user: "myk-pi-tools is required. Install with: `uv tool install myk-pi-tools`. Install now?"
41
+
42
+ - Yes: Run `uv tool install myk-pi-tools`
43
+ - No: Abort with instructions
44
+
45
+ ### Step 2: Continue with workflow
46
+
47
+ ## Usage
48
+
49
+ - `/pr-review` - Review PR from current branch (auto-detect)
50
+ - `/pr-review 123` - Review PR #123 in current repo
51
+ - `/pr-review https://github.com/owner/repo/pull/123` - Review from URL
52
+
53
+ ## Task Plan
54
+
55
+ Before starting any work, create ALL tasks upfront using `TaskCreate`, then set their dependencies
56
+ using `TaskUpdate` with `addBlockedBy`. The task system enforces execution order — blocked tasks cannot start.
57
+
58
+ ### Task List
59
+
60
+ | Task | Title | blockedBy |
61
+ |------|-------|-----------|
62
+ | 1 | PR Detection | — |
63
+ | 2 | Clone & checkout PR | 1 |
64
+ | 3 | (auto-complete — reviewers read from clone) | 1 |
65
+ | 4 | Check past review comments | 1, 2 |
66
+ | 5 | Review — Code Quality | 2 |
67
+ | 6 | Review — Guidelines | 2 |
68
+ | 7 | Review — Security | 2 |
69
+ | 8 | Review — Docs | 2 |
70
+ | 9 | Review — Spec | 2 |
71
+ | 10 | Merge & deduplicate findings | 4, 5, 6, 7, 8, 9 |
72
+ | 11 | User selection | 10 |
73
+ | 12 | Post comments | 11 |
74
+ | 13 | Store comments | 12 |
75
+ | 14 | Summary | 13 |
76
+
77
+ ### Dependency Graph
78
+
79
+ ```text
80
+ Task 1 (PR Detection)
81
+ ├── Task 2 (Clone & checkout PR) ────┐
82
+ │ Task 3 auto-completes instantly │
83
+ │ Task 2 unblocks: │
84
+ │ ├── Task 5 (Review: Quality) │
85
+ │ ├── Task 6 (Review: Guidelines) │
86
+ │ ├── Task 7 (Review: Security) │
87
+ │ ├── Task 8 (Review: Docs) │
88
+ │ └── Task 9 (Review: Spec) │
89
+ └── Task 4 (Past comments) ──────────┤ (also needs Task 2)
90
+ ▼
91
+ Task 10 (Merge findings)
92
+ │
93
+ Task 11 (User selection)
94
+ │
95
+ Task 12 (Post comments)
96
+ │
97
+ Task 13 (Store comments)
98
+ │
99
+ Task 14 (Summary)
100
+ ```
101
+
102
+ Create all 14 tasks using `TaskCreate` NOW, before starting any work.
103
+ Then IMMEDIATELY set dependencies using `TaskUpdate` with `addBlockedBy` for each task per the table above.
104
+
105
+ `TaskCreate` does NOT accept `addBlockedBy` — dependencies MUST be set via `TaskUpdate` after creation.
106
+
107
+ Example two-step flow:
108
+
109
+ ```text
110
+ # Step 1: Create all tasks
111
+ TaskCreate(subject="PR Detection", ...) → Task 1
112
+ TaskCreate(subject="Fetch PR diff", ...) → Task 2
113
+ TaskCreate(subject="Fetch AGENTS.md", ...) → Task 3
114
+ TaskCreate(subject="Review — Docs", ...) → Task 8
115
+ TaskCreate(subject="Review — Spec", ...) → Task 9
116
+ ...all 14 tasks...
117
+
118
+ # Step 2: Set dependencies
119
+ TaskUpdate(taskId="2", addBlockedBy=["1"])
120
+ TaskUpdate(taskId="3", addBlockedBy=["1"])
121
+ TaskUpdate(taskId="4", addBlockedBy=["1", "2"])
122
+ TaskUpdate(taskId="5", addBlockedBy=["2"])
123
+ TaskUpdate(taskId="6", addBlockedBy=["2"])
124
+ TaskUpdate(taskId="7", addBlockedBy=["2"])
125
+ TaskUpdate(taskId="8", addBlockedBy=["2"])
126
+ TaskUpdate(taskId="9", addBlockedBy=["2"])
127
+ TaskUpdate(taskId="10", addBlockedBy=["4", "5", "6", "7", "8", "9"])
128
+ TaskUpdate(taskId="11", addBlockedBy=["10"])
129
+ TaskUpdate(taskId="12", addBlockedBy=["11"])
130
+ TaskUpdate(taskId="13", addBlockedBy=["12"])
131
+ TaskUpdate(taskId="14", addBlockedBy=["13"])
132
+ ```
133
+
134
+ > 🚨 **HARD RULE: NEVER start a task while its `blockedBy` tasks are incomplete.**
135
+ > The task system enforces this via `addBlockedBy` — but even if you could bypass it, **DON'T**.
136
+ > Posting comments from partial reviewer results is a **CRITICAL violation**.
137
+ > ALL 5 reviewers (Tasks 5, 6, 7, 8, 9) MUST complete before merging findings (Task 10).
138
+
139
+ ## Workflow
140
+
141
+ **PROJECT_TMP_DIR** is the project-scoped temp directory from `getProjectTmpDir(cwd)`.
142
+ All temp files for this workflow go there —
143
+
144
+ ### Phase 0: PR Detection — Task 1
145
+
146
+ If the raw arguments are empty:
147
+
148
+ 1. Detect from current branch and fetch PR metadata:
149
+
150
+ ```bash
151
+ myk-pi-tools pr info $(gh pr view --json number --jq '.number')
152
+ ```
153
+
154
+ This returns JSON with all needed fields: `owner`, `repo`, `pr_number`, `author`,
155
+ `head_sha`, `base_ref`, `title`, `state`, `labels`, `assignees`, `is_fork`, `head_repo`, `body`.
156
+
157
+ 2. Extract and store all fields from the JSON output — these are used by Phase 1c and Phase 5.
158
+
159
+ 3. Fetch the latest commit timestamp from `head_sha` (needed by Phase 1c to compare
160
+ against comment timestamps):
161
+
162
+ ```bash
163
+ gh api /repos/{owner}/{repo}/commits/{head_sha} --jq '.commit.committer.date'
164
+ ```
165
+
166
+ Always use the base repo (`{owner}/{repo}`) — GitHub resolves fork PR commits
167
+ from the base repo via `refs/pull/*/head`, so this works for both fork and non-fork PRs.
168
+
169
+ Store this as `LATEST_COMMIT_DATE` (ISO 8601 timestamp).
170
+
171
+ If the raw arguments contain a PR number or URL:
172
+
173
+ 1. Fetch PR metadata using the CLI:
174
+
175
+ ```bash
176
+ myk-pi-tools pr info <cleaned_arguments>
177
+ ```
178
+
179
+ This returns JSON with all needed fields: `owner`, `repo`, `pr_number`, `author`,
180
+ `head_sha`, `base_ref`, `title`, `state`, `labels`, `assignees`, `is_fork`, `head_repo`, `body`.
181
+
182
+ 2. Extract and store all fields from the JSON output — these are used by Phase 1c and Phase 5.
183
+
184
+ 3. Fetch the latest commit timestamp from `head_sha` (needed by Phase 1c to compare
185
+ against comment timestamps):
186
+
187
+ ```bash
188
+ gh api /repos/{owner}/{repo}/commits/{head_sha} --jq '.commit.committer.date'
189
+ ```
190
+
191
+ Always use the base repo (`{owner}/{repo}`) — GitHub resolves fork PR commits
192
+ from the base repo via `refs/pull/*/head`, so this works for both fork and non-fork PRs.
193
+
194
+ Store this as `LATEST_COMMIT_DATE` (ISO 8601 timestamp).
195
+
196
+ Tasks 2 and 3 are independent — execute them in parallel.
197
+ Task 4 depends on Task 2 (needs the diff data) and will start after Task 2 completes.
198
+
199
+ ### Phase 1a: Clone & Checkout PR — Task 2
200
+
201
+ Clone the target repo and checkout the PR branch. This gives reviewers full repo access
202
+ instead of passing a truncated diff in the prompt.
203
+
204
+ **Delegate to `git-expert`** with this task:
205
+
206
+ > Clone `https://github.com/{owner}/{repo}.git` (depth 50) to `{PROJECT_TMP_DIR}/pr-review-{owner}-{repo}-{pr_number}`.
207
+ > Then run: gh pr checkout {pr_number}
208
+ > Then get the base branch: gh pr view {pr_number} --json baseRefName --jq '.baseRefName'
209
+ > Then fetch the base: git fetch origin {base_branch} --depth 50
210
+ > Report REVIEW_DIR and BASE_BRANCH.
211
+
212
+ Store:
213
+
214
+ - `REVIEW_DIR` — the clone path (used as `cwd` for reviewers)
215
+ - `BASE_BRANCH` — the PR's target branch (used for `git diff`)
216
+
217
+ If cloning or checkout fails, fall back to `myk-pi-tools pr diff` (original behavior).
218
+
219
+ ### Phase 1b: (Removed — reviewers read AGENTS.md from clone)
220
+
221
+ Task 3 is no longer needed — reviewers have full repo access via the clone
222
+ and read AGENTS.md independently per their agent instructions.
223
+
224
+ ### Phase 1c: Check Past Review Comments — Task 4
225
+
226
+ Fetch ALL human review threads (resolved + unresolved) from the PR:
227
+
228
+ Use the `owner`, `repo`, and `pr_number` from Phase 0 to construct the PR URL:
229
+
230
+ ```bash
231
+ myk-pi-tools reviews fetch --output-dir ${PROJECT_TMP_DIR} --user {current_github_user} --include-resolved https://github.com/{owner}/{repo}/pull/{pr_number}
232
+ ```
233
+
234
+ Where `{current_github_user}` is obtained from:
235
+
236
+ ```bash
237
+ gh api user --jq '.login'
238
+ ```
239
+
240
+ Also fetch ALL unresolved review threads from all authors (for dedup in Phase 2):
241
+
242
+ ```bash
243
+ myk-pi-tools reviews fetch --output-dir ${PROJECT_TMP_DIR}/all-unresolved https://github.com/{owner}/{repo}/pull/{pr_number}
244
+ ```
245
+
246
+ This second call omits `--user` and `--include-resolved`, so it returns only currently-unresolved
247
+ threads from every author (humans, Qodo, CodeRabbit, etc.). The output is passed to
248
+ reviewers in Phase 2 so they can avoid raising duplicate findings.
249
+
250
+ Parse the JSON output from the `--user` fetch (`${PROJECT_TMP_DIR}`). This file is used
251
+ for resolved/unresolved categorization below. The all-unresolved fetch (`${PROJECT_TMP_DIR}/all-unresolved`)
252
+ is used separately in Phase 2 for dedup context — do NOT use it for the resolved/unresolved
253
+ categorization above. However, it IS used later in this same phase for `[AUTHOR-QUESTION]`
254
+ detection (see "Detect questions directed at us" section below).
255
+
256
+ For the `human` list, categorize each thread:
257
+
258
+ **Unresolved threads:**
259
+
260
+ - These are still open on GitHub — but the PR author may have fixed the code without resolving the thread.
261
+ - Check the diff from Phase 1a — did the code at `path:line` change?
262
+ - **Code changed:** Review the changed code to verify the fix is correct.
263
+ - Fix looks correct → resolve the thread on GitHub by setting its status to `addressed`
264
+ with reply "Verified fix in code — resolving." in the JSON, then mark as
265
+ "✅ Fixed but not resolved by author — resolved by us". Store verdict to DB as `resolved_fixed`.
266
+ - Fix looks wrong/incomplete → include in findings as "❌ Code changed but fix is incorrect".
267
+ Store verdict to DB as `resolved_bad_fix`.
268
+ - **Code NOT changed:** The finding may be genuinely unaddressed — but only re-raise
269
+ if the PR author has pushed new commits since the comment was posted.
270
+ - Compare the comment's `created_at` timestamp against `LATEST_COMMIT_DATE` from Phase 0.
271
+ - **New commits exist after comment** (`LATEST_COMMIT_DATE` > comment `created_at`):
272
+ The author pushed changes but didn't address this finding.
273
+ Include in the findings presented to the user in Phase 4.
274
+ Mark as "⚠️ UNRESOLVED from previous review"
275
+ - **No new commits after comment** (`LATEST_COMMIT_DATE` ≤ comment `created_at`):
276
+ The comment is already visible on the PR and the author hasn't pushed any changes yet.
277
+ Silently skip — do NOT include in findings or auto-post.
278
+ This avoids replying to our own still-visible unresolved thread with no new information.
279
+
280
+ **Resolved threads:**
281
+
282
+ - Read the full thread including ALL replies from the PR author.
283
+ - Check the diff from Phase 1a — did the code at `path:line` change?
284
+ - **Code changed:** Review the changed code to verify the fix is correct. Don't trust blindly.
285
+ - Fix looks correct → mark as "✅ Resolved — fix verified"
286
+ - Fix looks wrong/incomplete → include in findings as "❌ Resolved but fix is incorrect"
287
+ - **Code NOT changed:** Read the PR author's response/reply.
288
+ - Valid response (by design, wrong assumption, clarification) → mark as "✅ Resolved — response accepted"
289
+ - Invalid/missing response → include in findings as "❌ Resolved without code change or valid response"
290
+
291
+ **Store resolution verdicts to DB (MANDATORY):**
292
+
293
+ After evaluating each resolved thread, persist YOUR verdict to the PR review database.
294
+ For each resolved thread that was previously posted by us (matched in the `--user` fetch),
295
+ call:
296
+
297
+ To store the verdict, write the author's response to a temp file first (to avoid shell quoting issues),
298
+ then run the CLI:
299
+
300
+ 1. Write `{author_response}` text to `${PROJECT_TMP_DIR}/resolution-response.txt` using the `write` tool
301
+ 2. Run: `myk-pi-tools pr update-resolution {owner} {repo} {pr_number} --path {path} --line {line} --status {resolution_status} --response-file ${PROJECT_TMP_DIR}/resolution-response.txt`
302
+
303
+ Where:
304
+
305
+ - `{resolution_status}` is one of:
306
+ - `resolved_fixed` (code changed, fix verified)
307
+ - `resolved_accepted` (response accepted, no code change needed)
308
+ - `resolved_bad_fix` (code changed but fix is incorrect)
309
+ - `resolved_no_fix` (resolved without code change or valid response)
310
+ - `{author_response}` is the PR author's reply text (why they resolved/dismissed)
311
+
312
+ This persists resolution decisions to the DB so future review cycles can query them.
313
+ Resolution decisions are OURS (from this LLM evaluation), not the PR author's click.
314
+
315
+ **All past comment statuses are included in the combined findings in Phase 4 —
316
+ not presented as a separate summary.**
317
+
318
+ **Detect questions directed at us (MANDATORY):**
319
+
320
+ After processing our own threads above, scan for questions/comments from others that need
321
+ our attention. This covers two sources:
322
+
323
+ **Source 1 — Review thread questions:**
324
+
325
+ Scan the all-unresolved JSON from `${PROJECT_TMP_DIR}/all-unresolved/`. For each thread:
326
+
327
+ - Skip threads authored by us (already handled above)
328
+ - Skip threads from bots (Qodo, CodeRabbit, GitHub Actions, dependabot, etc.)
329
+ - Check if ANY comment in the thread **explicitly @mentions** the current user (`@{current_github_user}`)
330
+
331
+ For each matching @mention comment, include it as an `[AUTHOR-QUESTION]` finding **only if**
332
+ there is no subsequent comment authored by `{current_github_user}` after that mention.
333
+ Compare using the `created_at` field on reply objects (ISO timestamp) — a reply from us
334
+ with a `created_at` later than the @mention comment's `created_at` means we already
335
+ responded. Do NOT rely on array position alone — always compare `created_at` timestamps.
336
+
337
+ **Do NOT use loose heuristics** (e.g., "thread is on a file we changed") or thread-level
338
+ "no reply anywhere" checks. Only explicit @mentions with no subsequent reply from us qualify —
339
+ this prevents false positives from unrelated reviewer conversations and correctly handles
340
+ late @mentions in threads where we participated earlier.
341
+
342
+ **Source 2 — General PR issue comments:**
343
+
344
+ Fetch PR issue comments (standalone PR comments, not tied to code lines):
345
+
346
+ ```bash
347
+ gh api /repos/{owner}/{repo}/issues/{pr_number}/comments --paginate
348
+ ```
349
+
350
+ For each comment:
351
+
352
+ - Skip comments authored by us
353
+ - Skip bot comments (Qodo, CodeRabbit, GitHub Actions, dependabot, etc.)
354
+ - Check if the comment **explicitly @mentions** the current user (`@{current_github_user}`)
355
+ - Check we haven't responded — no comment from us with a `created_at` later than
356
+ the @mention comment's `created_at`. Use `created_at` only (not `updated_at`) —
357
+ edits for typos/formatting shift `updated_at` forward and would cause false positives
358
+ by making our earlier response appear to predate the mention.
359
+
360
+ If matched, include it as an `[AUTHOR-QUESTION]` finding.
361
+
362
+ **Only explicit @mentions qualify.** Do NOT match comments just because they contain a
363
+ question mark — this would produce false positives from conversations between other
364
+ collaborators. Store the original `comment_id` and `comment_url` (from the API's
365
+ `html_url` field) for use in Phase 5 reply formatting.
366
+
367
+ **For each `[AUTHOR-QUESTION]`, generate a suggested answer:**
368
+
369
+ Read the relevant code, diff, and surrounding context referenced by the question. Analyze
370
+ what the commenter is asking and draft a concise, technically accurate suggested answer.
371
+ Store the suggested answer alongside the finding for presentation in Phase 4.
372
+
373
+ The suggested answer should:
374
+
375
+ - Reference specific code/lines when applicable
376
+ - Be ready to post as-is (the user can approve it directly)
377
+ - Be concise — answer the question, don't lecture
378
+ - If the answer requires a code change, note that explicitly
379
+
380
+ ### Phase 2: Code Analysis — Tasks 5, 6, 7, 8, 9
381
+
382
+ Spawn ALL 5 review agents as async subagents
383
+ with `taskId` linking each to its task:
384
+
385
+ Use the actual task IDs returned by `TaskCreate` — do NOT hardcode IDs.
386
+
387
+ Before spawning reviewers, read the all-unresolved JSON from `${PROJECT_TMP_DIR}/all-unresolved/`
388
+ (the output of the second `reviews fetch` call — NOT the `--user` fetch used in Phase 1c)
389
+ and format the existing comments as a block of context. Build an `EXISTING_COMMENTS` string
390
+ listing each unresolved thread with its file path, line number, author, and body.
391
+
392
+ > **Note:** Some comment types (e.g., Qodo sticky findings without code refs) may have an empty
393
+ > `path` or `null` line number. Use `"(no file)"` as fallback when path is missing and
394
+ > `"(no line)"` when line is missing or null.
395
+
396
+ Also build a `CODE_SUGGESTIONS` instruction block to include in each reviewer's task:
397
+
398
+ > When a finding has a concrete code fix, include a GitHub suggestion block showing the
399
+ > corrected code. Use the exact syntax so the PR author can apply it with one click:
400
+ >
401
+ > ````text
402
+ > ```suggestion
403
+ > fixed code here
404
+ > ```
405
+ > ````
406
+ >
407
+ > Only include suggestions for specific code replacements — not for architectural concerns,
408
+ > missing tests, new files, or design questions where the fix isn't a simple line replacement.
409
+ > The suggestion must replace the exact lines referenced by the finding.
410
+
411
+ Then include `EXISTING_COMMENTS` and `CODE_SUGGESTIONS` in every reviewer's task prompt:
412
+
413
+ ```text
414
+ subagent(tasks=[
415
+ {agent: "code-reviewer-quality", task: "Review this PR for code quality. Run: git diff origin/<BASE_BRANCH>...HEAD to see changes. Read any files needed for context.\n\n<review-history>\nMANDATORY — before reviewing any code, run:\nmyk-pi-tools pr get-review-history {owner} {repo} {pr_number}\nReview the output. Do NOT re-raise any finding marked as resolved_accepted, resolved_fixed, or skipped. These have been evaluated and decided in prior review cycles. Only flag a previously resolved finding if the code at that location has materially changed since the resolution.\n</review-history>\n\n<existing-unresolved-comments>\nThe following unresolved review comments already exist on this PR from other reviewers. Do NOT raise findings that duplicate these — skip them. If you find the same issue but with additional context or a different angle, note that it references the existing comment.\n\n<EXISTING_COMMENTS>\n</existing-unresolved-comments>\n\n<code-suggestions>\n<CODE_SUGGESTIONS>\n</code-suggestions>", cwd: "<REVIEW_DIR>", name: "Review Quality", taskId: "<task 5 ID>"},
416
+ {agent: "code-reviewer-guidelines", task: "Review this PR for guideline adherence. Run: git diff origin/<BASE_BRANCH>...HEAD to see changes. Read AGENTS.md and check compliance.\n\n<review-history>\nMANDATORY — before reviewing any code, run:\nmyk-pi-tools pr get-review-history {owner} {repo} {pr_number}\nReview the output. Do NOT re-raise any finding marked as resolved_accepted, resolved_fixed, or skipped. These have been evaluated and decided in prior review cycles. Only flag a previously resolved finding if the code at that location has materially changed since the resolution.\n</review-history>\n\n<existing-unresolved-comments>\nThe following unresolved review comments already exist on this PR from other reviewers. Do NOT raise findings that duplicate these — skip them. If you find the same issue but with additional context or a different angle, note that it references the existing comment.\n\n<EXISTING_COMMENTS>\n</existing-unresolved-comments>\n\n<code-suggestions>\n<CODE_SUGGESTIONS>\n</code-suggestions>", cwd: "<REVIEW_DIR>", name: "Review Guidelines", taskId: "<task 6 ID>"},
417
+ {agent: "code-reviewer-security", task: "Review this PR for bugs and security. Run: git diff origin/<BASE_BRANCH>...HEAD to see changes. Trace data flow through changed code.\n\n<review-history>\nMANDATORY — before reviewing any code, run:\nmyk-pi-tools pr get-review-history {owner} {repo} {pr_number}\nReview the output. Do NOT re-raise any finding marked as resolved_accepted, resolved_fixed, or skipped. These have been evaluated and decided in prior review cycles. Only flag a previously resolved finding if the code at that location has materially changed since the resolution.\n</review-history>\n\n<existing-unresolved-comments>\nThe following unresolved review comments already exist on this PR from other reviewers. Do NOT raise findings that duplicate these — skip them. If you find the same issue but with additional context or a different angle, note that it references the existing comment.\n\n<EXISTING_COMMENTS>\n</existing-unresolved-comments>\n\n<code-suggestions>\n<CODE_SUGGESTIONS>\n</code-suggestions>", cwd: "<REVIEW_DIR>", name: "Review Security", taskId: "<task 7 ID>"},
418
+ {agent: "code-reviewer-docs", task: "Review this PR for documentation quality. Run: git diff origin/<BASE_BRANCH>...HEAD to see changes. Check all docs for completeness and accuracy.\n\n<review-history>\nMANDATORY — before reviewing any code, run:\nmyk-pi-tools pr get-review-history {owner} {repo} {pr_number}\nReview the output. Do NOT re-raise any finding marked as resolved_accepted, resolved_fixed, or skipped. These have been evaluated and decided in prior review cycles. Only flag a previously resolved finding if the code at that location has materially changed since the resolution.\n</review-history>\n\n<existing-unresolved-comments>\nThe following unresolved review comments already exist on this PR from other reviewers. Do NOT raise findings that duplicate these — skip them. If you find the same issue but with additional context or a different angle, note that it references the existing comment.\n\n<EXISTING_COMMENTS>\n</existing-unresolved-comments>\n\n<code-suggestions>\n<CODE_SUGGESTIONS>\n</code-suggestions>", cwd: "<REVIEW_DIR>", name: "Review Docs", taskId: "<task 8 ID>"},
419
+ {agent: "code-reviewer-spec", task: "Review this PR for spec compliance. Run: git diff origin/<BASE_BRANCH>...HEAD to see changes. Check PR description claims vs diff, issue deliverables vs diff, and scope creep.\n\n<review-history>\nMANDATORY — before reviewing any code, run:\nmyk-pi-tools pr get-review-history {owner} {repo} {pr_number}\nReview the output. Do NOT re-raise any finding marked as resolved_accepted, resolved_fixed, or skipped. These have been evaluated and decided in prior review cycles. Only flag a previously resolved finding if the code at that location has materially changed since the resolution.\n</review-history>\n\n<existing-unresolved-comments>\nThe following unresolved review comments already exist on this PR from other reviewers. Do NOT raise findings that duplicate these — skip them. If you find the same issue but with additional context or a different angle, note that it references the existing comment.\n\n<EXISTING_COMMENTS>\n</existing-unresolved-comments>\n\n<code-suggestions>\n<CODE_SUGGESTIONS>\n</code-suggestions>", cwd: "<REVIEW_DIR>", name: "Review Spec", taskId: "<task 9 ID>"},
420
+ ])
421
+ ```
422
+
423
+ Where `<EXISTING_COMMENTS>` is replaced with the formatted unresolved comments from
424
+ `${PROJECT_TMP_DIR}/all-unresolved/`. If no unresolved comments exist, replace with
425
+ "No existing unresolved comments found."
426
+
427
+ Each reviewer runs in the cloned repo directory (`REVIEW_DIR`) and has full access to:
428
+
429
+ - All source files via `read` tool
430
+ - The PR diff via `git diff origin/<BASE_BRANCH>...HEAD`
431
+ - Project guidelines (AGENTS.md/CLAUDE.md) — read independently per agent instructions
432
+ - File history, imports, tests — anything in the repo
433
+
434
+ Each agent should analyze for security, bugs, error handling, and performance issues
435
+ and return their findings as prose.
436
+
437
+ **After spawning, verify the response confirms all 5 agents were spawned.**
438
+ If any spawn fails, STOP and report the error — do NOT continue waiting.
439
+
440
+ **After spawning, your turn is DONE.** Do NOT poll, sleep, call TaskOutput,
441
+ or check status. Results arrive automatically as follow-up messages.
442
+ When each reviewer finishes, its task is auto-completed via `taskId`.
443
+ Task 10 (Merge findings) auto-unblocks when all 5 reviewer tasks complete.
444
+
445
+ ### Phase 3: Merge & Deduplicate Findings — Task 10
446
+
447
+ Merge and deduplicate the findings from all 5 reviewers AND the past review comment analysis from Task 4 into a single combined findings list.
448
+
449
+ Reviewers were already instructed in Phase 2 to skip findings that duplicate existing
450
+ unresolved PR comments. However, verify that no duplicates slipped through by comparing
451
+ the merged findings against the all-unresolved list from `${PROJECT_TMP_DIR}/all-unresolved/`.
452
+ Drop any **`[NEW]`** finding (from Phase 2 reviewers) that raises the same issue as an
453
+ existing unresolved comment.
454
+
455
+ > **IMPORTANT:** `[PREV-UNRESOLVED]`, `[PREV-BAD-FIX]`, and `[PREV-NO-FIX]` items from
456
+ > Task 4 are NEVER dropped by dedup. These represent the current user's own prior review
457
+ > comments that naturally appear in the all-unresolved list — removing them would lose
458
+ > tracking of unresolved prior findings. Dedup applies ONLY to `[NEW]` findings.
459
+
460
+ **Previously skipped findings dedup:** Also check the PR review database for findings
461
+ the user previously skipped on this same PR. Run:
462
+
463
+ ```bash
464
+ myk-pi-tools pr get-skipped-comments {owner} {repo} {pr_number}
465
+ ```
466
+
467
+ This returns a JSON array of previously skipped comments with `path`, `line`, `body`,
468
+ `severity`, `skip_reason`, and `head_sha`.
469
+
470
+ For each `[NEW]` finding, compare against the skipped list using path + body similarity
471
+ (same file and similar description = match). Matched findings are auto-skipped with
472
+ `"Auto-skipped (previously dismissed): <skip_reason>"`. The user still sees them in the
473
+ Phase 4 table and can override by selecting them explicitly.
474
+
475
+ ### Phase 4: User Selection — Task 11
476
+
477
+ Present ALL findings to user in one combined list, grouped by severity (CRITICAL, WARNING, SUGGESTION).
478
+ This includes:
479
+
480
+ 1. **Past review findings** from Phase 1c (unresolved, incorrectly resolved, or bad fixes)
481
+ 2. **New code review findings** from Phase 2
482
+
483
+ Each finding shows its source:
484
+
485
+ - `[PREV-UNRESOLVED]` — unresolved from previous review cycle
486
+ - `[PREV-BAD-FIX]` — resolved but fix is incorrect
487
+ - `[PREV-NO-FIX]` — resolved without code change or valid response
488
+ - `[AUTHOR-QUESTION]` — question/comment from someone on the PR directed at us
489
+ - `[NEW]` — new finding from current code analysis
490
+
491
+ **Auto-post previous findings:** `[PREV-UNRESOLVED]`, `[PREV-BAD-FIX]`, and `[PREV-NO-FIX]`
492
+ findings are **automatically included** in the post list — they are the user's own prior
493
+ comments that remain unaddressed and MUST be re-raised. Do NOT ask the user to select these.
494
+ Show them in the list marked as "(auto-post)" so the user knows they'll be re-raised.
495
+
496
+ > **Note:** `[PREV-UNRESOLVED]` findings where no new commits exist after the comment
497
+ > (silently skipped in Phase 1c) do NOT appear here — they were already filtered out.
498
+
499
+ **Author questions require user approval:** `[AUTHOR-QUESTION]` findings are NOT auto-posted.
500
+ They require user review because the AI-generated answer may need editing or the user may
501
+ choose not to respond. Author questions are presented with approve/edit/skip options (see below).
502
+
503
+ **Author question presentation:**
504
+
505
+ For each `[AUTHOR-QUESTION]` finding, display:
506
+
507
+ 1. The original question/comment (who asked, where, full text)
508
+ 2. The AI-generated **suggested answer** from Phase 1c
509
+ 3. An action prompt for the user:
510
+ - **approve** — post the suggested answer as-is
511
+ - **edit** — user provides a revised answer (print prompt as regular text, NOT `ask_user`)
512
+ - **skip** — don't reply to this question
513
+
514
+ Collect user decisions for all author questions before proceeding. Approved/edited answers
515
+ are included in the Phase 5 post step. Skipped questions are excluded from posting.
516
+
517
+ **Numbering:** Display three separate numbered sections:
518
+
519
+ 1. Previous findings (P1, P2, ...) marked "(auto-post)"
520
+ 2. Author questions (Q1, Q2, ...) with suggested answers and action prompts
521
+ 3. New findings (1, 2, ...) for user selection
522
+
523
+ This avoids ambiguity — user selections for new findings always refer to the `[NEW]` numbering.
524
+
525
+ **User selects from `[NEW]` findings only:**
526
+
527
+ - 'all' = Post all new findings (previous findings are always auto-posted regardless)
528
+ - 'none' = Skip posting new findings (previous findings are still auto-posted)
529
+ - Specific numbers = Post only those new findings (numbers refer to the `[NEW]` list)
530
+
531
+ If there are ZERO `[NEW]` findings AND zero `[AUTHOR-QUESTION]` findings, skip user
532
+ selection entirely — auto-post the previous findings and proceed directly to Phase 5
533
+ (the auto-post path still generates the comments JSON and posts them — see Phase 5).
534
+
535
+ If there are ZERO `[NEW]` findings but `[AUTHOR-QUESTION]` findings exist, skip new
536
+ finding selection but still present author questions with suggested answers for
537
+ user approval/edit/skip.
538
+
539
+ 🚨 **Skip reason collection (MANDATORY — NEVER SKIP THIS STEP):**
540
+
541
+ **HARD RULE: If the user skipped ANY finding (said 'no', selected specific numbers
542
+ that exclude some findings, or said 'none'), you MUST ask for skip reasons
543
+ BEFORE proceeding to Phase 5. Do NOT continue the workflow without collecting
544
+ skip reasons. Skipping this step is a HARD VIOLATION.**
545
+
546
+ After the user selects which findings to post, compute the skipped set (total `[NEW]`
547
+ findings minus user-selected findings). If the skipped set is non-empty:
548
+
549
+ 1. Ask the user for skip reasons as a **normal chat message** (do NOT use `ask_user` — skip
550
+ reasons are often multiline and `ask_user` only supports single-line input).
551
+ Print this prompt as regular text:
552
+
553
+ ```text
554
+ You skipped findings 2, 4, 5. Why?
555
+ Give one reason for all, or per-finding (e.g., "2: not relevant, 4 and 5: style only")
556
+ ```
557
+
558
+ **STOP your turn after printing this prompt.** Do NOT continue the workflow.
559
+ The user will respond with their skip reasons in their next message.
560
+ Resume the workflow (step 2 below) only after receiving the user's response.
561
+
562
+ 2. AI refines each reason — make it concise, technical, and useful for future reference:
563
+ - User: "don't care" → "Style-only finding — no functional impact"
564
+ - User: "we do it this way" → "Intentional pattern — project convention"
565
+ - User: "already covered" → "Already validated by existing test coverage"
566
+
567
+ 3. AI classifies each refined reason (no user interaction):
568
+ - **Finding-specific** — references specific code, line, variable, or one-off context.
569
+ Store in DB only (same-PR dedup).
570
+ - **Generalizable** — references a project-wide pattern, convention, or category of
571
+ findings (e.g., "don't flag snake_case", "print() is intentional in CLI modules").
572
+ Store in DB AND append to `.pi/data/review-guidelines.md`.
573
+
574
+ 4. For generalizable reasons, append one line per finding to `.pi/data/review-guidelines.md`
575
+ (create the file if it doesn't exist). Format:
576
+
577
+ ```markdown
578
+ - Do not flag <finding type> — <refined reason>
579
+ ```
580
+
581
+ This file is read by all 5 reviewer agents before reviewing, so the same class of
582
+ finding won't be raised again on future PRs in this repo.
583
+
584
+ ### Phase 5: Post Comments — Task 12
585
+
586
+ **Step 1: Post `[NEW]` and `[PREV-*]` findings as new review comments:**
587
+
588
+ Write JSON to temp file for all `[NEW]` (user-selected) and `[PREV-*]` (auto-posted)
589
+ findings. If only `[PREV-*]` findings exist (zero `[NEW]` findings, selection was skipped),
590
+ still generate the JSON for the auto-posted items:
591
+
592
+ Use the `owner`, `repo`, `pr_number`, and `head_sha` from Phase 0 or Phase 1a metadata:
593
+
594
+ ```bash
595
+ myk-pi-tools pr post-comment {owner}/{repo} {pr_number} {head_sha} ${PROJECT_TMP_DIR}/pr-review-comments.json
596
+ ```
597
+
598
+ **Step 2: Reply to `[AUTHOR-QUESTION]` findings (approved/edited only):**
599
+
600
+ For each approved or edited author question, reply using the appropriate method based on
601
+ the question's source:
602
+
603
+ **Review thread questions** (have a `thread_id`):
604
+
605
+ Write a JSON file with the reply and use `reviews post` which correctly replies in the
606
+ existing thread via GraphQL `addPullRequestReviewThreadReply`:
607
+
608
+ ```bash
609
+ myk-pi-tools reviews post ${PROJECT_TMP_DIR}/author-question-replies.json
610
+ ```
611
+
612
+ The JSON file MUST use the `reviews post` format with the `"human"` category key:
613
+
614
+ ```json
615
+ {
616
+ "metadata": {"owner": "{owner}", "repo": "{repo}", "pr_number": "{pr_number}"},
617
+ "human": [
618
+ {"thread_id": "{thread_id}", "status": "not_addressed", "reply": "{approved_answer}"}
619
+ ]
620
+ }
621
+ ```
622
+
623
+ **IMPORTANT:** Use `status: "not_addressed"` (NOT `"addressed"`). These are threads owned
624
+ by someone else — `"addressed"` would auto-resolve their thread, which is inappropriate.
625
+ `"not_addressed"` posts the reply but leaves the thread open for the original author to resolve.
626
+
627
+ **General PR issue comments** (no `thread_id`, have `comment_id`):
628
+
629
+ Write the reply body to a temp file to avoid shell injection, then post via the GitHub API
630
+ with a quoted reference to the original question:
631
+
632
+ Write the raw markdown reply to a plain text file first, then use `jq` to safely
633
+ encode it as valid JSON (handles quotes, backslashes, newlines):
634
+
635
+ ```bash
636
+ # 1. Build the reply body as raw markdown (not JSON)
637
+ cat > ${PROJECT_TMP_DIR}/author-reply-body.md << 'REPLY_EOF'
638
+ > @{commenter} [asked]({comment_url}):
639
+ > {original_question_first_line}
640
+
641
+ {approved_answer}
642
+ REPLY_EOF
643
+
644
+ # 2. Encode as valid JSON using jq (handles all special characters safely)
645
+ jq -Rs '{body: .}' < ${PROJECT_TMP_DIR}/author-reply-body.md > ${PROJECT_TMP_DIR}/author-reply-body.json
646
+
647
+ # 3. Post via gh api
648
+ gh api /repos/{owner}/{repo}/issues/{pr_number}/comments --input ${PROJECT_TMP_DIR}/author-reply-body.json
649
+ ```
650
+
651
+ NEVER build JSON by string interpolation — always write the reply body as raw text
652
+ and use `jq -Rs '{body: .}'` to produce valid JSON. This prevents both shell injection
653
+ and JSON encoding errors from quotes, backslashes, or newlines in the answer.
654
+
655
+ ### Phase 5b: Store Posted Comments — Task 13
656
+
657
+ After posting comments, store ALL findings (posted AND skipped) in the PR review database
658
+ for future cycle tracking and same-PR dedup of skipped findings.
659
+
660
+ 1. Write a JSON file with ALL findings:
661
+
662
+ ```bash
663
+ cat > ${PROJECT_TMP_DIR}/pr-review-store.json << 'EOF'
664
+ {
665
+ "metadata": {"owner": "{owner}", "repo": "{repo}", "pr_number": {pr_number}, "head_sha": "{head_sha}", "author": "{author}"},
666
+ "comments": [
667
+ {
668
+ "thread_id": null,
669
+ "comment_id": null,
670
+ "path": "file.py",
671
+ "line": 42,
672
+ "body": "Comment body as posted",
673
+ "severity": "WARNING",
674
+ "posted_at": "<ISO timestamp>",
675
+ "status": "posted"
676
+ },
677
+ {
678
+ "thread_id": null,
679
+ "comment_id": null,
680
+ "path": "file.py",
681
+ "line": 99,
682
+ "body": "Finding description that was skipped",
683
+ "severity": "SUGGESTION",
684
+ "posted_at": null,
685
+ "status": "skipped",
686
+ "skip_reason": "Refined skip reason from Phase 4"
687
+ },
688
+ {
689
+ "thread_id": "thread_abc123",
690
+ "comment_id": 456,
691
+ "path": "utils.py",
692
+ "line": 10,
693
+ "body": "Author question: should this use sleep=0?",
694
+ "severity": "QUESTION",
695
+ "posted_at": "<ISO timestamp>",
696
+ "status": "posted",
697
+ "source": "author-question"
698
+ },
699
+ {
700
+ "thread_id": null,
701
+ "comment_id": 789,
702
+ "path": null,
703
+ "line": null,
704
+ "body": "General PR question that was skipped",
705
+ "severity": "QUESTION",
706
+ "posted_at": null,
707
+ "status": "skipped",
708
+ "skip_reason": "User chose not to respond",
709
+ "source": "author-question"
710
+ }
711
+ ]
712
+ }
713
+ EOF
714
+ ```
715
+
716
+ Include `[AUTHOR-QUESTION]` findings with `status: "posted"` (approved/edited and posted)
717
+ or `status: "skipped"` (user chose to skip). Use `"posted"` (not `"answered"`) because
718
+ the `myk-pi-tools pr store-pr-review` CLI only accepts `posted` or `skipped` as valid
719
+ statuses.
720
+
721
+ **Note on `source` field:** The `source: "author-question"` field in the JSON example is
722
+ for LLM context only — the CLI's DB schema does not have a `source` column and will
723
+ ignore it. Future review cycles detect already-answered questions by matching
724
+ `path`/`line`/`body` similarity against stored comments, same as other finding types.
725
+
726
+ Use `{author}` from Phase 0 (`myk-pi-tools pr info` returns `author` field).
727
+
728
+ 1. Store to database:
729
+
730
+ ```bash
731
+ myk-pi-tools pr store-pr-review ${PROJECT_TMP_DIR}/pr-review-store.json
732
+ ```
733
+
734
+ **This step is MANDATORY — never skip it.** The database is used by future `/pr-review`
735
+ runs to track which comments were posted, verify they were addressed, and auto-skip
736
+ previously dismissed findings.
737
+
738
+ ### Phase 6: Summary — Task 14
739
+
740
+ Display final summary with counts and links. Include:
741
+
742
+ - New findings posted / skipped counts
743
+ - Previous findings re-raised count
744
+ - Author questions answered / skipped counts
745
+ - Total comments posted
746
+ - PR link
747
+
748
+ ### Cleanup
749
+
750
+ After the review is complete (all phases done):
751
+
752
+ 1. Delete all tasks: `TaskUpdate(taskId="N", status="deleted")` for every task created in this workflow
753
+ 2. Delegate to `git-expert`: remove the clone directory `REVIEW_DIR`