supipowers 1.5.3 → 2.0.1

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 (340) hide show
  1. package/README.md +14 -8
  2. package/bin/install.mjs +20 -5
  3. package/bin/install.ts +95 -0
  4. package/package.json +8 -4
  5. package/skills/context-mode/SKILL.md +17 -10
  6. package/skills/harness/SKILL.md +94 -0
  7. package/skills/ui-design/SKILL.md +63 -0
  8. package/skills/ui-design/sub-agent-templates/component-builder.md +29 -0
  9. package/skills/ui-design/sub-agent-templates/design-critic.md +46 -0
  10. package/skills/ui-design/sub-agent-templates/pencil/component-builder.md +29 -0
  11. package/skills/ui-design/sub-agent-templates/pencil/design-critic.md +42 -0
  12. package/skills/ui-design/sub-agent-templates/pencil/section-assembler.md +27 -0
  13. package/skills/ui-design/sub-agent-templates/section-assembler.md +27 -0
  14. package/skills/ultraplan-discover/SKILL.md +96 -0
  15. package/skills/ultraplan-intake/SKILL.md +89 -0
  16. package/skills/ultraplan-research/SKILL.md +129 -0
  17. package/skills/ultraplan-review/SKILL.md +86 -0
  18. package/skills/ultraplan-review-scope/SKILL.md +111 -0
  19. package/skills/ultraplan-review-structure/SKILL.md +120 -0
  20. package/skills/ultraplan-review-tdd/SKILL.md +142 -0
  21. package/skills/ultraplan-scout/SKILL.md +110 -0
  22. package/skills/ultraplan-synthesize/SKILL.md +124 -0
  23. package/src/{quality/ai-session.ts → ai/final-message.ts} +27 -0
  24. package/src/ai/schema-text.ts +129 -0
  25. package/src/ai/structured-output.ts +274 -0
  26. package/src/ai/template.ts +27 -0
  27. package/src/bootstrap.ts +63 -28
  28. package/src/commands/agents.ts +131 -42
  29. package/src/commands/ai-review.ts +251 -30
  30. package/src/commands/clear.ts +434 -0
  31. package/src/commands/commit.ts +1 -0
  32. package/src/commands/config.ts +242 -44
  33. package/src/commands/context.ts +55 -28
  34. package/src/commands/doctor.ts +234 -6
  35. package/src/commands/fix-pr.ts +306 -131
  36. package/src/commands/generate.ts +111 -21
  37. package/src/commands/memory.ts +192 -0
  38. package/src/commands/model-picker.ts +28 -21
  39. package/src/commands/model.ts +18 -8
  40. package/src/commands/optimize-context.ts +408 -29
  41. package/src/commands/plan.ts +2 -0
  42. package/src/commands/qa.ts +312 -137
  43. package/src/commands/release.ts +259 -76
  44. package/src/commands/review.ts +293 -59
  45. package/src/commands/status.ts +200 -13
  46. package/src/commands/supi.ts +3 -35
  47. package/src/commands/ui-design.ts +394 -0
  48. package/src/commands/ultraplan.ts +1518 -0
  49. package/src/commands/update.ts +86 -0
  50. package/src/config/defaults.ts +62 -0
  51. package/src/config/loader.ts +448 -60
  52. package/src/config/schema.ts +108 -2
  53. package/src/context/optimizer.ts +25 -33
  54. package/src/context/rule-renderer.ts +223 -0
  55. package/src/context/savings.ts +258 -0
  56. package/src/context/startup-check.ts +380 -0
  57. package/src/context/startup-optimizer.ts +355 -0
  58. package/src/context/tokenignore.ts +146 -0
  59. package/src/context-mode/cache-handle.ts +49 -0
  60. package/src/context-mode/cache-preview.ts +71 -0
  61. package/src/context-mode/cache-store.ts +738 -0
  62. package/src/context-mode/compressor.ts +131 -26
  63. package/src/context-mode/dedup.ts +108 -0
  64. package/src/context-mode/detector.ts +35 -4
  65. package/src/context-mode/event-extractor.ts +14 -12
  66. package/src/context-mode/event-store.ts +91 -36
  67. package/src/context-mode/hooks.ts +798 -56
  68. package/src/context-mode/knowledge/store.ts +255 -11
  69. package/src/context-mode/memory-store.ts +325 -0
  70. package/src/context-mode/metrics-recorder.ts +158 -0
  71. package/src/context-mode/metrics-store.ts +765 -0
  72. package/src/context-mode/model.ts +24 -0
  73. package/src/context-mode/processor-keys.ts +29 -0
  74. package/src/context-mode/processors/build.ts +66 -0
  75. package/src/context-mode/processors/docker.ts +57 -0
  76. package/src/context-mode/processors/git.ts +111 -0
  77. package/src/context-mode/processors/json.ts +112 -0
  78. package/src/context-mode/processors/k8s.ts +67 -0
  79. package/src/context-mode/processors/lint.ts +67 -0
  80. package/src/context-mode/processors/log.ts +86 -0
  81. package/src/context-mode/processors/registry.ts +116 -0
  82. package/src/context-mode/processors/test-runner.ts +102 -0
  83. package/src/context-mode/processors/types.ts +20 -0
  84. package/src/context-mode/repomap.ts +400 -0
  85. package/src/context-mode/routing.ts +97 -24
  86. package/src/context-mode/sandbox/runners.ts +5 -1
  87. package/src/context-mode/snapshot-builder.ts +106 -11
  88. package/src/context-mode/source-hash.ts +173 -0
  89. package/src/context-mode/tool-name.ts +11 -0
  90. package/src/context-mode/tools.ts +654 -22
  91. package/src/context-mode/web/fetcher.ts +31 -12
  92. package/src/debug/logger.ts +2 -1
  93. package/src/deps/registry.ts +1 -1
  94. package/src/discipline/failure-summarizer.ts +170 -0
  95. package/src/discipline/failure-taxonomy.ts +131 -0
  96. package/src/discipline/workflow-invariants.ts +125 -0
  97. package/src/discovery/index.ts +31 -0
  98. package/src/discovery/lsp.ts +87 -0
  99. package/src/discovery/rank.ts +144 -0
  100. package/src/discovery/sources.ts +89 -0
  101. package/src/discovery/workflow.ts +87 -0
  102. package/src/docs/contracts.ts +39 -0
  103. package/src/docs/drift.ts +117 -87
  104. package/src/fix-pr/assessment.ts +200 -0
  105. package/src/fix-pr/contracts.ts +47 -0
  106. package/src/fix-pr/fetch-comments.ts +80 -0
  107. package/src/fix-pr/prompt-builder.ts +58 -40
  108. package/src/fix-pr/scripts/exec.ts +34 -0
  109. package/src/fix-pr/scripts/trigger-review.ts +106 -0
  110. package/src/fix-pr/scripts/wait-and-check.ts +108 -0
  111. package/src/fix-pr/types.ts +4 -0
  112. package/src/git/branch-finish.ts +5 -0
  113. package/src/git/commit-contract.ts +83 -0
  114. package/src/git/commit.ts +121 -184
  115. package/src/git/status.ts +62 -8
  116. package/src/harness/anti_slop/architecture-parser.ts +210 -0
  117. package/src/harness/anti_slop/backend-factory.ts +30 -0
  118. package/src/harness/anti_slop/backend.ts +140 -0
  119. package/src/harness/anti_slop/desloppify-adapter.ts +319 -0
  120. package/src/harness/anti_slop/fallow-adapter.ts +305 -0
  121. package/src/harness/anti_slop/installer.ts +227 -0
  122. package/src/harness/anti_slop/queue.ts +216 -0
  123. package/src/harness/anti_slop/recommend.ts +84 -0
  124. package/src/harness/anti_slop/score.ts +180 -0
  125. package/src/harness/anti_slop/synthetic-edit-test.ts +128 -0
  126. package/src/harness/artifacts/agents-md.ts +88 -0
  127. package/src/harness/artifacts/checks-wiring.ts +57 -0
  128. package/src/harness/artifacts/docs-tree.ts +79 -0
  129. package/src/harness/artifacts/lint-configs.ts +136 -0
  130. package/src/harness/artifacts/review-agents.ts +67 -0
  131. package/src/harness/bare-entry.ts +108 -0
  132. package/src/harness/command.ts +1010 -0
  133. package/src/harness/default-agents/design.md +23 -0
  134. package/src/harness/default-agents/discover.md +18 -0
  135. package/src/harness/default-agents/implement.md +24 -0
  136. package/src/harness/default-agents/plan.md +19 -0
  137. package/src/harness/default-agents/research.md +21 -0
  138. package/src/harness/default-agents/validate.md +22 -0
  139. package/src/harness/gc/reporter.ts +28 -0
  140. package/src/harness/gc/runner.ts +136 -0
  141. package/src/harness/hooks/layer-context-inject.ts +155 -0
  142. package/src/harness/hooks/post-session-sweep.ts +130 -0
  143. package/src/harness/hooks/pre-edit-dupe-probe.ts +224 -0
  144. package/src/harness/hooks/register.ts +118 -0
  145. package/src/harness/model.ts +117 -0
  146. package/src/harness/pipeline.ts +348 -0
  147. package/src/harness/project-paths.ts +235 -0
  148. package/src/harness/stage-runner.ts +107 -0
  149. package/src/harness/stages/design.ts +386 -0
  150. package/src/harness/stages/discover.ts +454 -0
  151. package/src/harness/stages/implement.ts +162 -0
  152. package/src/harness/stages/plan.ts +335 -0
  153. package/src/harness/stages/research.ts +263 -0
  154. package/src/harness/stages/validate.ts +684 -0
  155. package/src/harness/storage.ts +467 -0
  156. package/src/harness/tools.ts +426 -0
  157. package/src/lsp/bridge.ts +56 -95
  158. package/src/lsp/capabilities.ts +108 -0
  159. package/src/lsp/contracts.ts +35 -0
  160. package/src/lsp/detector.ts +8 -12
  161. package/src/markdown-frontmatter.ts +68 -0
  162. package/src/mempalace/bridge.ts +135 -0
  163. package/src/mempalace/config.ts +75 -0
  164. package/src/mempalace/format.ts +163 -0
  165. package/src/mempalace/hooks.ts +370 -0
  166. package/src/mempalace/installer-helper.ts +194 -0
  167. package/src/mempalace/python/mempalace_bridge.py +440 -0
  168. package/src/mempalace/runtime.ts +565 -0
  169. package/src/mempalace/schema.ts +268 -0
  170. package/src/mempalace/session-summary.ts +198 -0
  171. package/src/mempalace/tool.ts +186 -0
  172. package/src/mempalace/uv.ts +256 -0
  173. package/src/migrate/runner.ts +354 -0
  174. package/src/planning/approval-flow.ts +206 -9
  175. package/src/planning/plan-writer-prompt.ts +4 -3
  176. package/src/planning/planning-ask-tool.ts +39 -0
  177. package/src/planning/render-markdown.ts +74 -0
  178. package/src/planning/spec.ts +42 -0
  179. package/src/planning/system-prompt.ts +11 -8
  180. package/src/planning/validate.ts +84 -0
  181. package/src/platform/omp.ts +15 -2
  182. package/src/platform/system-prompt.ts +37 -0
  183. package/src/platform/test-utils.ts +3 -0
  184. package/src/platform/types.ts +6 -1
  185. package/src/qa/config.ts +12 -6
  186. package/src/qa/detect-app-type.ts +13 -6
  187. package/src/qa/matrix.ts +12 -6
  188. package/src/qa/prompt-builder.ts +28 -30
  189. package/src/qa/scripts/dev-server-utils.ts +72 -0
  190. package/src/qa/scripts/run-e2e-tests.ts +226 -0
  191. package/src/qa/scripts/start-dev-server.ts +138 -0
  192. package/src/qa/scripts/stop-dev-server.ts +77 -0
  193. package/src/qa/session.ts +13 -7
  194. package/src/quality/ai-setup.ts +27 -25
  195. package/src/quality/contracts.ts +34 -0
  196. package/src/quality/gates/ai-review.ts +20 -58
  197. package/src/quality/gates/command.ts +249 -46
  198. package/src/quality/review-gates.ts +18 -2
  199. package/src/quality/runner.ts +63 -22
  200. package/src/quality/schemas.ts +37 -2
  201. package/src/quality/setup.ts +96 -16
  202. package/src/release/changelog.ts +1 -1
  203. package/src/release/channels/custom.ts +13 -3
  204. package/src/release/channels/types.ts +5 -0
  205. package/src/release/contracts.ts +90 -0
  206. package/src/release/executor.ts +122 -45
  207. package/src/release/prompt.ts +18 -2
  208. package/src/release/targets.ts +86 -0
  209. package/src/release/version.ts +96 -71
  210. package/src/review/agent-loader.ts +221 -109
  211. package/src/review/fixer.ts +10 -6
  212. package/src/review/multi-agent-runner.ts +114 -13
  213. package/src/review/output.ts +12 -139
  214. package/src/review/runner.ts +12 -6
  215. package/src/review/scope.ts +144 -24
  216. package/src/review/types.ts +1 -20
  217. package/src/review/validator.ts +12 -6
  218. package/src/storage/fix-pr-sessions.ts +21 -14
  219. package/src/storage/plans.ts +14 -5
  220. package/src/storage/qa-sessions.ts +25 -19
  221. package/src/storage/reliability-metrics.ts +180 -0
  222. package/src/storage/reports.ts +8 -7
  223. package/src/storage/review-sessions.ts +55 -20
  224. package/src/tool-catalog/active-tool-controller.ts +164 -0
  225. package/src/tool-catalog/active-tool-planner.ts +212 -0
  226. package/src/tool-catalog/tool-groups.ts +102 -0
  227. package/src/types.ts +1399 -5
  228. package/src/ui-design/backend-adapter.ts +78 -0
  229. package/src/ui-design/backends/local-html.ts +82 -0
  230. package/src/ui-design/backends/pencil-mcp.ts +111 -0
  231. package/src/ui-design/components-scanner.ts +124 -0
  232. package/src/ui-design/config.ts +55 -0
  233. package/src/ui-design/pen-scanner.ts +95 -0
  234. package/src/ui-design/pen-selector.ts +72 -0
  235. package/src/ui-design/prompt-builder.ts +73 -0
  236. package/src/ui-design/scanner.ts +136 -0
  237. package/src/ui-design/session.ts +974 -0
  238. package/src/ui-design/system-prompt.ts +312 -0
  239. package/src/ui-design/tokens-scanner.ts +181 -0
  240. package/src/ui-design/types.ts +96 -0
  241. package/src/ultraplan/agent-catalog.ts +522 -0
  242. package/src/ultraplan/authoring/agent-catalog.ts +310 -0
  243. package/src/ultraplan/authoring/authoring-tools.ts +552 -0
  244. package/src/ultraplan/authoring/command-handlers.ts +339 -0
  245. package/src/ultraplan/authoring/markdown.ts +510 -0
  246. package/src/ultraplan/authoring/model.ts +162 -0
  247. package/src/ultraplan/authoring/pipeline.ts +319 -0
  248. package/src/ultraplan/authoring/stage-runner.ts +141 -0
  249. package/src/ultraplan/authoring/stages/approve.ts +249 -0
  250. package/src/ultraplan/authoring/stages/discover.ts +289 -0
  251. package/src/ultraplan/authoring/stages/intake.ts +203 -0
  252. package/src/ultraplan/authoring/stages/research.ts +399 -0
  253. package/src/ultraplan/authoring/stages/review.ts +333 -0
  254. package/src/ultraplan/authoring/stages/scout.ts +188 -0
  255. package/src/ultraplan/authoring/stages/synthesize.ts +348 -0
  256. package/src/ultraplan/authoring/storage.ts +594 -0
  257. package/src/ultraplan/authoring/synth-gate.ts +165 -0
  258. package/src/ultraplan/authoring-draft.ts +653 -0
  259. package/src/ultraplan/authoring-persist.ts +180 -0
  260. package/src/ultraplan/authoring-tool.ts +608 -0
  261. package/src/ultraplan/authoring-wizard.ts +587 -0
  262. package/src/ultraplan/batch/merge.ts +98 -0
  263. package/src/ultraplan/batch/planner.ts +150 -0
  264. package/src/ultraplan/batch/presenter.ts +97 -0
  265. package/src/ultraplan/batch/storage.ts +420 -0
  266. package/src/ultraplan/batch/supervisor.ts +317 -0
  267. package/src/ultraplan/batch/worker.ts +26 -0
  268. package/src/ultraplan/batch/worktree.ts +110 -0
  269. package/src/ultraplan/contracts.ts +1593 -0
  270. package/src/ultraplan/default-agents/authoring/discoverer.md +12 -0
  271. package/src/ultraplan/default-agents/authoring/intake.md +12 -0
  272. package/src/ultraplan/default-agents/authoring/planner.md +12 -0
  273. package/src/ultraplan/default-agents/authoring/researcher.md +12 -0
  274. package/src/ultraplan/default-agents/authoring/scope-checker.md +12 -0
  275. package/src/ultraplan/default-agents/authoring/scout.md +12 -0
  276. package/src/ultraplan/default-agents/authoring/structure-checker.md +12 -0
  277. package/src/ultraplan/default-agents/authoring/tdd-checker.md +12 -0
  278. package/src/ultraplan/default-agents/backend-domain-reviewer.md +10 -0
  279. package/src/ultraplan/default-agents/backend-executor.md +10 -0
  280. package/src/ultraplan/default-agents/backend-stack-reviewer.md +10 -0
  281. package/src/ultraplan/default-agents/backend-tester.md +10 -0
  282. package/src/ultraplan/default-agents/frontend-domain-reviewer.md +10 -0
  283. package/src/ultraplan/default-agents/frontend-executor.md +10 -0
  284. package/src/ultraplan/default-agents/frontend-stack-reviewer.md +10 -0
  285. package/src/ultraplan/default-agents/frontend-tester.md +10 -0
  286. package/src/ultraplan/default-agents/infrastructure-domain-reviewer.md +10 -0
  287. package/src/ultraplan/default-agents/infrastructure-executor.md +10 -0
  288. package/src/ultraplan/default-agents/infrastructure-stack-reviewer.md +10 -0
  289. package/src/ultraplan/default-agents/infrastructure-tester.md +10 -0
  290. package/src/ultraplan/execution/contract.ts +71 -0
  291. package/src/ultraplan/execution/policy.ts +217 -0
  292. package/src/ultraplan/execution/runtime-tools.ts +107 -0
  293. package/src/ultraplan/execution/session-runner.ts +281 -0
  294. package/src/ultraplan/next-router.ts +85 -0
  295. package/src/ultraplan/presenter.ts +359 -0
  296. package/src/ultraplan/project-paths.ts +342 -0
  297. package/src/ultraplan/runtime/active-execution.ts +72 -0
  298. package/src/ultraplan/runtime/apply-mutation.ts +416 -0
  299. package/src/ultraplan/runtime/blockers.ts +243 -0
  300. package/src/ultraplan/runtime/hook-bridge.ts +486 -0
  301. package/src/ultraplan/runtime/launch-context.ts +207 -0
  302. package/src/ultraplan/runtime/migration.ts +524 -0
  303. package/src/ultraplan/runtime/normalize.ts +281 -0
  304. package/src/ultraplan/runtime/proof.ts +260 -0
  305. package/src/ultraplan/runtime/reducer.ts +416 -0
  306. package/src/ultraplan/runtime/repair.ts +251 -0
  307. package/src/ultraplan/runtime/tracker-storage.ts +368 -0
  308. package/src/ultraplan/session-selection.ts +291 -0
  309. package/src/ultraplan/storage.ts +374 -0
  310. package/src/utils/editor.ts +38 -0
  311. package/src/utils/executable.ts +80 -0
  312. package/src/utils/paths.ts +1 -20
  313. package/src/utils/shell.ts +31 -0
  314. package/src/visual/companion.ts +2 -1
  315. package/src/visual/scripts/frame-template.html +60 -0
  316. package/src/visual/scripts/index.js +59 -13
  317. package/src/visual/scripts/package.json +3 -0
  318. package/src/visual/start-server.ts +2 -1
  319. package/src/workspace/git-scope.ts +64 -0
  320. package/src/workspace/locks.ts +23 -0
  321. package/src/workspace/package-manager.ts +117 -0
  322. package/src/workspace/path-mapping.ts +75 -0
  323. package/src/workspace/project-slug.ts +92 -0
  324. package/src/workspace/repo-root.ts +137 -0
  325. package/src/workspace/selector.ts +115 -0
  326. package/src/workspace/state-paths.ts +118 -0
  327. package/src/workspace/targets.ts +313 -0
  328. package/src/fix-pr/scripts/diff-comments.sh +0 -33
  329. package/src/fix-pr/scripts/fetch-pr-comments.sh +0 -25
  330. package/src/fix-pr/scripts/trigger-review.sh +0 -36
  331. package/src/fix-pr/scripts/wait-and-check.sh +0 -37
  332. package/src/qa/scripts/detect-app-type.sh +0 -68
  333. package/src/qa/scripts/discover-routes.sh +0 -143
  334. package/src/qa/scripts/run-e2e-tests.sh +0 -131
  335. package/src/qa/scripts/start-dev-server.sh +0 -46
  336. package/src/qa/scripts/stop-dev-server.sh +0 -36
  337. package/src/review/prompts/fix-output-schema.md +0 -18
  338. package/src/review/prompts/review-output-schema.md +0 -38
  339. package/src/review/template.ts +0 -15
  340. /package/src/{review → ai}/prompts/invalid-output-retry.md +0 -0
@@ -1,3 +1,4 @@
1
+ import path from "node:path";
1
2
  import { matchesKey, truncateToWidth, wrapTextWithAnsi, type Component, type Focusable } from "@oh-my-pi/pi-tui";
2
3
  import type { Platform } from "../platform/types.js";
3
4
  import { createWorkflowProgress } from "../platform/progress.js";
@@ -19,6 +20,16 @@ import {
19
20
  writeReviewArtifact,
20
21
  } from "../storage/review-sessions.js";
21
22
  import { accent, bright, muted } from "../platform/tui-colors.js";
23
+ import { resolvePackageManager } from "../workspace/package-manager.js";
24
+ import { resolveRepoRoot } from "../workspace/repo-root.js";
25
+ import {
26
+ buildWorkspaceTargetOptionLabel,
27
+ parseTargetArg,
28
+ selectWorkspaceTarget,
29
+ type WorkspaceTargetOption,
30
+ } from "../workspace/selector.js";
31
+ import { getProjectStatePath, getProjectTargetStatePath } from "../workspace/state-paths.js";
32
+ import { discoverWorkspaceTargets } from "../workspace/targets.js";
22
33
  import type {
23
34
  ConfiguredReviewAgent,
24
35
  ReviewFinding,
@@ -27,6 +38,7 @@ import type {
27
38
  ReviewPostConsolidationAction,
28
39
  ReviewScope,
29
40
  ReviewSession,
41
+ WorkspaceTarget,
30
42
  } from "../types.js";
31
43
 
32
44
  modelRegistry.register({
@@ -80,6 +92,123 @@ interface ReviewResultsSummary {
80
92
  helpText: string;
81
93
  }
82
94
 
95
+ interface ParsedAiReviewArgs {
96
+ requestedTarget: string | null;
97
+ }
98
+
99
+ interface ReviewTargetChoice {
100
+ repoRoot: string;
101
+ target: WorkspaceTarget | null;
102
+ targets: WorkspaceTarget[];
103
+ }
104
+
105
+ function parseAiReviewArgs(args?: string): ParsedAiReviewArgs {
106
+ return {
107
+ requestedTarget: parseTargetArg(args),
108
+ };
109
+ }
110
+
111
+ function buildReviewTargetSummary(target: WorkspaceTarget): string {
112
+ return `${target.name} (${target.relativeDir})`;
113
+ }
114
+
115
+ function buildReviewTargetOption(target: WorkspaceTarget): WorkspaceTargetOption {
116
+ return {
117
+ target,
118
+ changed: false,
119
+ label: target.kind === "root"
120
+ ? `${buildWorkspaceTargetOptionLabel({ target, changed: false })} — root only`
121
+ : buildWorkspaceTargetOptionLabel({ target, changed: false }),
122
+ };
123
+ }
124
+
125
+ function buildAllReviewTargetLabel(targets: WorkspaceTarget[]): string {
126
+ const workspaceCount = targets.filter((target) => target.kind === "workspace").length;
127
+ return workspaceCount === 0
128
+ ? "All — root target"
129
+ : `All — root + ${workspaceCount} workspace${workspaceCount === 1 ? "" : "s"}`;
130
+ }
131
+
132
+ function isMonorepoTargets(targets: WorkspaceTarget[]): boolean {
133
+ return targets.some((target) => target.kind === "workspace");
134
+ }
135
+
136
+ async function selectReviewTarget(
137
+ platform: Platform,
138
+ ctx: any,
139
+ requestedTarget: string | null,
140
+ ): Promise<ReviewTargetChoice | null> {
141
+ const repoRoot = await resolveRepoRoot(platform, ctx.cwd);
142
+ const packageManager = resolvePackageManager(repoRoot);
143
+ const discoveredTargets = discoverWorkspaceTargets(repoRoot, packageManager.id);
144
+ const targets = discoveredTargets.length > 0
145
+ ? discoveredTargets
146
+ : [{
147
+ id: "root",
148
+ name: path.basename(repoRoot) || "root",
149
+ kind: "root",
150
+ repoRoot,
151
+ packageDir: repoRoot,
152
+ manifestPath: path.join(repoRoot, "package.json"),
153
+ relativeDir: ".",
154
+ version: "0.0.0",
155
+ private: true,
156
+ packageManager: packageManager.id,
157
+ } satisfies WorkspaceTarget];
158
+ const options = targets.map(buildReviewTargetOption);
159
+
160
+ if (requestedTarget?.toLowerCase() === "all") {
161
+ return { repoRoot, target: null, targets };
162
+ }
163
+
164
+ if (requestedTarget) {
165
+ const selectedTarget = await selectWorkspaceTarget(
166
+ ctx,
167
+ options,
168
+ requestedTarget,
169
+ {
170
+ title: "Review target",
171
+ helpText: "Pick one package to narrow the review, or use --target all to review the root target and every workspace.",
172
+ },
173
+ );
174
+ if (!selectedTarget) {
175
+ throw new Error(`Review target not found: ${requestedTarget}`);
176
+ }
177
+ return { repoRoot, target: selectedTarget, targets };
178
+ }
179
+
180
+ if (!isMonorepoTargets(targets)) {
181
+ const selectedTarget = await selectWorkspaceTarget(
182
+ ctx,
183
+ options,
184
+ null,
185
+ {
186
+ title: "Review target",
187
+ helpText: "Pick the target to review.",
188
+ },
189
+ );
190
+ return selectedTarget ? { repoRoot, target: selectedTarget, targets } : null;
191
+ }
192
+
193
+ const allLabel = buildAllReviewTargetLabel(targets);
194
+ const labels = [allLabel, ...options.map((option) => option.label ?? buildWorkspaceTargetOptionLabel(option))];
195
+ const choice = await ctx.ui.select("Review target", labels, {
196
+ initialIndex: 0,
197
+ helpText: "All reviews the root target and every workspace. Choose a single target to narrow the review.",
198
+ });
199
+ if (!choice) {
200
+ return null;
201
+ }
202
+ if (choice === allLabel) {
203
+ return { repoRoot, target: null, targets };
204
+ }
205
+
206
+ const selectedIndex = labels.indexOf(choice) - 1;
207
+ const selectedTarget = selectedIndex >= 0 ? options[selectedIndex]?.target ?? null : null;
208
+ return selectedTarget ? { repoRoot, target: selectedTarget, targets } : null;
209
+ }
210
+
211
+
83
212
  function formatFindingLocation(finding: ReviewFinding): string {
84
213
  if (!finding.file) {
85
214
  return "unknown location";
@@ -384,8 +513,9 @@ function buildDiscussionPrompt(
384
513
  ctx: any,
385
514
  session: ReviewSession,
386
515
  summary: ReviewResultsSummary,
516
+ selectedTarget: WorkspaceTarget | null,
387
517
  ): string {
388
- const sessionDir = buildSavedSessionPath(platform, ctx, session);
518
+ const sessionDir = buildSavedSessionPath(platform, ctx, session, selectedTarget);
389
519
  const artifactLines = [
390
520
  `- session: ${sessionDir}/session.json`,
391
521
  `- scope: ${sessionDir}/${session.artifacts.scope}`,
@@ -435,8 +565,15 @@ function buildPostConsolidationDetail(action: ReviewPostConsolidationAction): st
435
565
  }
436
566
  }
437
567
 
438
- function buildSavedSessionPath(platform: Platform, ctx: any, session: ReviewSession): string {
439
- return platform.paths.project(ctx.cwd, "reviews", session.id);
568
+ function buildSavedSessionPath(
569
+ platform: Platform,
570
+ ctx: any,
571
+ session: ReviewSession,
572
+ selectedTarget: WorkspaceTarget | null,
573
+ ): string {
574
+ return selectedTarget
575
+ ? getProjectTargetStatePath(platform.paths, selectedTarget, "reviews", session.id)
576
+ : getProjectStatePath(platform.paths, ctx.cwd, "reviews", session.id);
440
577
  }
441
578
 
442
579
  function buildActionLabel(action: ReviewPostConsolidationAction | null): string {
@@ -714,9 +851,14 @@ async function selectMaxIterations(ctx: any, defaultValue = 3): Promise<number |
714
851
  return parsed;
715
852
  }
716
853
 
717
- function buildCompletionDetail(session: ReviewSession, output: ReviewOutput): string {
854
+ function buildCompletionDetail(
855
+ session: ReviewSession,
856
+ output: ReviewOutput,
857
+ selectedTarget: WorkspaceTarget | null,
858
+ ): string {
718
859
  return [
719
860
  `session: ${session.id}`,
861
+ ...(selectedTarget ? [`target: ${buildReviewTargetSummary(selectedTarget)}`] : []),
720
862
  `status: ${output.status}`,
721
863
  `findings: ${output.findings.length}`,
722
864
  `iterations: ${session.currentIteration}`,
@@ -730,6 +872,7 @@ function writeFindingsReport(
730
872
  ctx: any,
731
873
  session: ReviewSession,
732
874
  output: ReviewOutput,
875
+ selectedTarget: WorkspaceTarget | null,
733
876
  options: { preFixSnapshot?: boolean } = {},
734
877
  ): string {
735
878
  const artifactPath = deps.writeReviewArtifact(
@@ -738,6 +881,7 @@ function writeFindingsReport(
738
881
  session.id,
739
882
  FINDINGS_REPORT_FILE,
740
883
  buildReviewFindingsMarkdown(output, session, options),
884
+ selectedTarget,
741
885
  );
742
886
  session.artifacts.findingsReport = FINDINGS_REPORT_FILE;
743
887
  return artifactPath;
@@ -750,13 +894,14 @@ function persistIteration(
750
894
  session: ReviewSession,
751
895
  iteration: number,
752
896
  output: ReviewOutput,
897
+ selectedTarget: WorkspaceTarget | null,
753
898
  extra: Record<string, unknown> = {},
754
899
  ): void {
755
900
  const relativePath = `${ITERATIONS_DIR}/${iteration}.json`;
756
901
  deps.writeReviewArtifact(platform.paths, ctx.cwd, session.id, relativePath, {
757
902
  output,
758
903
  ...extra,
759
- });
904
+ }, selectedTarget);
760
905
  session.iterations.push({
761
906
  iteration,
762
907
  findings: output.findings.length,
@@ -814,6 +959,7 @@ async function runReviewPass(
814
959
  scope,
815
960
  agents,
816
961
  createAgentSession: platform.createAgentSession.bind(platform),
962
+ activeTools: platform.getActiveTools(),
817
963
  model: resolvedModel.model,
818
964
  thinkingLevel: resolvedModel.thinkingLevel,
819
965
  onAgentStart: (agent) => progress.startAgent(agent),
@@ -829,13 +975,22 @@ async function runAiReviewSession(
829
975
  platform: Platform,
830
976
  ctx: any,
831
977
  deps: AiReviewCommandDependencies = AI_REVIEW_COMMAND_DEPENDENCIES,
978
+ args?: string,
832
979
  ): Promise<void> {
833
980
  if (!ctx.hasUI) {
834
981
  ctx.ui.notify("/supi:review requires interactive mode.", "warning");
835
982
  return;
836
983
  }
837
984
 
838
- const scope = await deps.selectReviewScope(platform, ctx);
985
+ const { requestedTarget } = parseAiReviewArgs(args);
986
+ const selectedReviewTarget = await selectReviewTarget(platform, ctx, requestedTarget);
987
+ if (!selectedReviewTarget) {
988
+ return;
989
+ }
990
+ const reviewTarget = selectedReviewTarget;
991
+ const scopeSelection = reviewTarget.target ? { target: reviewTarget.target, targets: reviewTarget.targets } : null;
992
+
993
+ const scope = await deps.selectReviewScope(platform, ctx, scopeSelection);
839
994
  if (!scope) {
840
995
  return;
841
996
  }
@@ -846,7 +1001,10 @@ async function runAiReviewSession(
846
1001
  }
847
1002
 
848
1003
  const loadedAgents = level === "multi-agent"
849
- ? await deps.loadReviewAgents(platform.paths, ctx.cwd)
1004
+ ? await deps.loadReviewAgents(platform.paths, ctx.cwd, {
1005
+ repoRoot: reviewTarget.repoRoot,
1006
+ workspaceRelativeDir: reviewTarget.target?.kind === "workspace" ? reviewTarget.target.relativeDir : null,
1007
+ })
850
1008
  : null;
851
1009
  const agents = loadedAgents?.agents ?? [];
852
1010
  if (level === "multi-agent" && agents.length === 0) {
@@ -863,8 +1021,8 @@ async function runAiReviewSession(
863
1021
  scope,
864
1022
  agents,
865
1023
  );
866
- deps.createReviewSession(platform.paths, ctx.cwd, session);
867
- deps.writeReviewArtifact(platform.paths, ctx.cwd, session.id, session.artifacts.scope, scope);
1024
+ deps.createReviewSession(platform.paths, ctx.cwd, session, reviewTarget.target);
1025
+ deps.writeReviewArtifact(platform.paths, ctx.cwd, session.id, session.artifacts.scope, scope, reviewTarget.target);
868
1026
 
869
1027
  const progress = createAiReviewProgress(ctx, level, agents);
870
1028
  progress.completeScope(scope);
@@ -872,14 +1030,20 @@ async function runAiReviewSession(
872
1030
  function saveSession(status: ReviewSession["status"]): void {
873
1031
  progress.startSave();
874
1032
  session.status = status;
875
- deps.updateReviewSession(platform.paths, ctx.cwd, session);
1033
+ deps.updateReviewSession(platform.paths, ctx.cwd, session, reviewTarget.target);
876
1034
  progress.completeSave(status);
877
1035
  }
878
1036
 
879
-
880
1037
  try {
881
1038
  const initialRun = await runReviewPass(platform, ctx, deps, scope, level, agents, progress, resolvedModel);
882
- deps.writeReviewArtifact(platform.paths, ctx.cwd, session.id, RAW_FINDINGS_FILE, initialRun.rawOutput);
1039
+ deps.writeReviewArtifact(
1040
+ platform.paths,
1041
+ ctx.cwd,
1042
+ session.id,
1043
+ RAW_FINDINGS_FILE,
1044
+ initialRun.rawOutput,
1045
+ reviewTarget.target,
1046
+ );
883
1047
  session.artifacts.rawFindings = RAW_FINDINGS_FILE;
884
1048
  for (const agentResult of initialRun.agentResults) {
885
1049
  deps.writeReviewArtifact(
@@ -888,6 +1052,7 @@ async function runAiReviewSession(
888
1052
  session.id,
889
1053
  `${AGENTS_DIR}/${agentResult.agent.name}.json`,
890
1054
  agentResult,
1055
+ reviewTarget.target,
891
1056
  );
892
1057
  }
893
1058
 
@@ -906,7 +1071,14 @@ async function runAiReviewSession(
906
1071
  });
907
1072
  const validatedOutput = preserveBlockedReviewStatus(validation.output, currentOutput.status);
908
1073
  currentOutput = prepareReviewOutputForFollowUp(validatedOutput, currentOutput.status);
909
- deps.writeReviewArtifact(platform.paths, ctx.cwd, session.id, VALIDATED_FINDINGS_FILE, validatedOutput);
1074
+ deps.writeReviewArtifact(
1075
+ platform.paths,
1076
+ ctx.cwd,
1077
+ session.id,
1078
+ VALIDATED_FINDINGS_FILE,
1079
+ validatedOutput,
1080
+ reviewTarget.target,
1081
+ );
910
1082
  session.artifacts.validatedFindings = VALIDATED_FINDINGS_FILE;
911
1083
  progress.completeValidate(validatedOutput);
912
1084
  } else {
@@ -921,7 +1093,14 @@ async function runAiReviewSession(
921
1093
  deps.consolidateReviewOutputs([currentOutput]),
922
1094
  currentOutput.status,
923
1095
  );
924
- deps.writeReviewArtifact(platform.paths, ctx.cwd, session.id, CONSOLIDATED_FINDINGS_FILE, currentOutput);
1096
+ deps.writeReviewArtifact(
1097
+ platform.paths,
1098
+ ctx.cwd,
1099
+ session.id,
1100
+ CONSOLIDATED_FINDINGS_FILE,
1101
+ currentOutput,
1102
+ reviewTarget.target,
1103
+ );
925
1104
  session.artifacts.consolidatedFindings = CONSOLIDATED_FINDINGS_FILE;
926
1105
  progress.completeConsolidate(currentOutput);
927
1106
  } else {
@@ -929,13 +1108,28 @@ async function runAiReviewSession(
929
1108
  progress.skipConsolidate(level === "multi-agent" ? "no findings" : "single-agent");
930
1109
  }
931
1110
 
932
- persistIteration(deps, platform, ctx, session, 1, currentOutput);
933
- let findingsReportPath = writeFindingsReport(deps, platform, ctx, session, currentOutput);
1111
+ persistIteration(deps, platform, ctx, session, 1, currentOutput, reviewTarget.target);
1112
+ let findingsReportPath = writeFindingsReport(
1113
+ deps,
1114
+ platform,
1115
+ ctx,
1116
+ session,
1117
+ currentOutput,
1118
+ reviewTarget.target,
1119
+ );
934
1120
  let findingsReportIsPreFixSnapshot = false;
935
1121
 
936
1122
  async function cancelSession(): Promise<void> {
937
1123
  if (findingsReportIsPreFixSnapshot) {
938
- findingsReportPath = writeFindingsReport(deps, platform, ctx, session, currentOutput, { preFixSnapshot: true });
1124
+ findingsReportPath = writeFindingsReport(
1125
+ deps,
1126
+ platform,
1127
+ ctx,
1128
+ session,
1129
+ currentOutput,
1130
+ reviewTarget.target,
1131
+ { preFixSnapshot: true },
1132
+ );
939
1133
  }
940
1134
  saveSession("cancelled");
941
1135
  }
@@ -963,7 +1157,7 @@ async function runAiReviewSession(
963
1157
  deps.notifyInfo(
964
1158
  ctx,
965
1159
  "AI review documented without fixes",
966
- `session: ${session.id} | findings: ${currentOutput.findings.length} | report: ${findingsReportPath}`,
1160
+ `${buildCompletionDetail(session, currentOutput, reviewTarget.target)} | report: ${findingsReportPath}`,
967
1161
  );
968
1162
  return;
969
1163
  }
@@ -975,9 +1169,11 @@ async function runAiReviewSession(
975
1169
  deps.notifyInfo(
976
1170
  ctx,
977
1171
  "AI review saved for discussion",
978
- `session: ${session.id} | findings: ${currentOutput.findings.length} | report: ${findingsReportPath}`,
1172
+ `${buildCompletionDetail(session, currentOutput, reviewTarget.target)} | report: ${findingsReportPath}`,
1173
+ );
1174
+ platform.sendUserMessage(
1175
+ buildDiscussionPrompt(platform, ctx, session, reviewResultsSummary, reviewTarget.target),
979
1176
  );
980
- platform.sendUserMessage(buildDiscussionPrompt(platform, ctx, session, reviewResultsSummary));
981
1177
  return;
982
1178
  }
983
1179
 
@@ -1038,8 +1234,24 @@ async function runAiReviewSession(
1038
1234
  }
1039
1235
 
1040
1236
  const delta = compareReviewOutputs(previousOutput, rerunOutput);
1041
- persistIteration(deps, platform, ctx, session, iteration, rerunOutput, { delta });
1042
- findingsReportPath = writeFindingsReport(deps, platform, ctx, session, rerunOutput);
1237
+ persistIteration(
1238
+ deps,
1239
+ platform,
1240
+ ctx,
1241
+ session,
1242
+ iteration,
1243
+ rerunOutput,
1244
+ reviewTarget.target,
1245
+ { delta },
1246
+ );
1247
+ findingsReportPath = writeFindingsReport(
1248
+ deps,
1249
+ platform,
1250
+ ctx,
1251
+ session,
1252
+ rerunOutput,
1253
+ reviewTarget.target,
1254
+ );
1043
1255
  findingsReportIsPreFixSnapshot = false;
1044
1256
  progress.completeRerun(iteration, session.maxIterations);
1045
1257
 
@@ -1070,18 +1282,26 @@ async function runAiReviewSession(
1070
1282
  }
1071
1283
 
1072
1284
  if (findingsReportIsPreFixSnapshot) {
1073
- findingsReportPath = writeFindingsReport(deps, platform, ctx, session, currentOutput, { preFixSnapshot: true });
1285
+ findingsReportPath = writeFindingsReport(
1286
+ deps,
1287
+ platform,
1288
+ ctx,
1289
+ session,
1290
+ currentOutput,
1291
+ reviewTarget.target,
1292
+ { preFixSnapshot: true },
1293
+ );
1074
1294
  }
1075
1295
 
1076
1296
  saveSession(currentOutput.status === "blocked" ? "blocked" : "completed");
1077
1297
  deps.notifyInfo(
1078
1298
  ctx,
1079
1299
  `AI review complete: ${findingsReportIsPreFixSnapshot ? "post-fix verification pending" : currentOutput.status}`,
1080
- `${buildCompletionDetail(session, currentOutput)} | report: ${findingsReportIsPreFixSnapshot ? `${findingsReportPath} (pre-fix snapshot)` : findingsReportPath}`,
1300
+ `${buildCompletionDetail(session, currentOutput, reviewTarget.target)} | report: ${findingsReportIsPreFixSnapshot ? `${findingsReportPath} (pre-fix snapshot)` : findingsReportPath}`,
1081
1301
  );
1082
1302
  } catch (error) {
1083
1303
  session.status = "blocked";
1084
- deps.updateReviewSession(platform.paths, ctx.cwd, session);
1304
+ deps.updateReviewSession(platform.paths, ctx.cwd, session, reviewTarget.target);
1085
1305
  progress.failActive((error as Error).message);
1086
1306
  throw error;
1087
1307
  } finally {
@@ -1089,8 +1309,8 @@ async function runAiReviewSession(
1089
1309
  }
1090
1310
  }
1091
1311
 
1092
- export function handleAiReview(platform: Platform, ctx: any): void {
1093
- void runAiReviewSession(platform, ctx, AI_REVIEW_COMMAND_DEPENDENCIES).catch((error) => {
1312
+ export function handleAiReview(platform: Platform, ctx: any, args?: string): void {
1313
+ void runAiReviewSession(platform, ctx, AI_REVIEW_COMMAND_DEPENDENCIES, args).catch((error) => {
1094
1314
  ctx.ui.notify(`AI review failed: ${(error as Error).message}`, "error");
1095
1315
  });
1096
1316
  }
@@ -1099,15 +1319,16 @@ export async function runAiReviewSessionForTest(
1099
1319
  platform: Platform,
1100
1320
  ctx: any,
1101
1321
  deps: AiReviewCommandDependencies,
1322
+ args?: string,
1102
1323
  ): Promise<void> {
1103
- await runAiReviewSession(platform, ctx, deps);
1324
+ await runAiReviewSession(platform, ctx, deps, args);
1104
1325
  }
1105
1326
 
1106
1327
  export function registerAiReviewCommand(platform: Platform): void {
1107
1328
  platform.registerCommand("supi:review", {
1108
1329
  description: "Run the AI code review pipeline",
1109
- async handler(_args: string | undefined, ctx: any) {
1110
- handleAiReview(platform, ctx);
1330
+ async handler(args: string | undefined, ctx: any) {
1331
+ handleAiReview(platform, ctx, args);
1111
1332
  },
1112
1333
  });
1113
1334
  }