supipowers 1.5.2 → 2.0.0

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 +149 -45
  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 +19 -9
  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 +129 -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 +264 -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 +298 -127
  211. package/src/review/fixer.ts +10 -6
  212. package/src/review/multi-agent-runner.ts +115 -14
  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 +11 -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 +1401 -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
@@ -10,7 +10,11 @@ import { modelRegistry } from "../config/model-registry-instance.js";
10
10
  import { resolveModelForAction, createModelBridge, applyModelOverride } from "../config/model-resolver.js";
11
11
  import { loadModelConfig } from "../config/model-config.js";
12
12
  import { createWorkflowProgress } from "../platform/progress.js";
13
- import { runQualityGates, type ReviewRunEvent } from "../quality/runner.js";
13
+ import {
14
+ discoverChangedRepoFiles,
15
+ runQualityGates,
16
+ type ReviewRunEvent,
17
+ } from "../quality/runner.js";
14
18
  import {
15
19
  interactivelySaveGateSetup,
16
20
  setupGates,
@@ -23,10 +27,20 @@ import type {
23
27
  QualityGatesConfig,
24
28
  ReviewReport,
25
29
  SupipowersConfig,
30
+ WorkspaceTarget,
26
31
  } from "../types.js";
27
32
  import { CANONICAL_GATE_ORDER, GATE_DISPLAY_NAMES } from "../quality/registry.js";
28
33
  import { REVIEW_GATE_REGISTRY } from "../quality/review-gates.js";
29
34
  import { saveReviewReport } from "../storage/reports.js";
35
+ import { resolvePackageManager } from "../workspace/package-manager.js";
36
+ import { resolveRepoRoot } from "../workspace/repo-root.js";
37
+ import { getChangedWorkspaceTargets } from "../workspace/path-mapping.js";
38
+ import {
39
+ parseTargetArg,
40
+ selectWorkspaceTarget,
41
+ sortWorkspaceTargetOptions,
42
+ } from "../workspace/selector.js";
43
+ import { discoverWorkspaceTargets } from "../workspace/targets.js";
30
44
 
31
45
  modelRegistry.register({
32
46
  id: "checks",
@@ -61,6 +75,8 @@ export interface ChecksCommandDependencies {
61
75
  interactivelySaveGateSetup: typeof interactivelySaveGateSetup;
62
76
  runQualityGates: typeof runQualityGates;
63
77
  saveReviewReport: typeof saveReviewReport;
78
+ resolvePackageManager: typeof resolvePackageManager;
79
+ discoverWorkspaceTargets: typeof discoverWorkspaceTargets;
64
80
  notifyInfo: typeof notifyInfo;
65
81
  }
66
82
 
@@ -77,9 +93,35 @@ const CHECKS_COMMAND_DEPENDENCIES: ChecksCommandDependencies = {
77
93
  interactivelySaveGateSetup,
78
94
  runQualityGates,
79
95
  saveReviewReport,
96
+ resolvePackageManager,
97
+ discoverWorkspaceTargets,
80
98
  notifyInfo,
81
99
  };
82
100
 
101
+ interface ResolvedChecksTargets {
102
+ mode: "single" | "all";
103
+ runTargets: WorkspaceTarget[];
104
+ workspaceTargets: WorkspaceTarget[];
105
+ }
106
+
107
+ interface CompletedChecksRun {
108
+ target: WorkspaceTarget;
109
+ report: ReviewReport;
110
+ reportPath: string;
111
+ failedGates: GateResult[];
112
+ }
113
+
114
+ interface RunChecksForTargetInput {
115
+ platform: Platform;
116
+ ctx: any;
117
+ deps: ChecksCommandDependencies;
118
+ target: WorkspaceTarget;
119
+ workspaceTargets: WorkspaceTarget[];
120
+ filters: GateFilters;
121
+ reviewModel: ReturnType<ChecksCommandDependencies["resolveModelForAction"]>;
122
+ }
123
+
124
+
83
125
  function tokenizeGateList(raw: string): string[] {
84
126
  return raw
85
127
  .split(/[\s,]+/)
@@ -156,7 +198,7 @@ function validateGateSelection(enabledGateIds: GateId[], filters: GateFilters):
156
198
  }
157
199
 
158
200
  function describeScope(scope: ConfigScope): string {
159
- return scope === "global" ? "global" : "project";
201
+ return scope === "global" ? "global" : "repository";
160
202
  }
161
203
 
162
204
  function buildRecoveryDetail(scopes: ConfigScope[]): string {
@@ -168,6 +210,122 @@ function buildRecoveryDetail(scopes: ConfigScope[]): string {
168
210
  ].join("\n");
169
211
  }
170
212
 
213
+ function getTargetConfigOptions(target: WorkspaceTarget) {
214
+ return { repoRoot: target.repoRoot };
215
+ }
216
+
217
+ function formatTargetLocation(target: WorkspaceTarget): string {
218
+ return target.kind === "root" ? "root" : target.relativeDir;
219
+ }
220
+
221
+ function formatTargetLabel(target: WorkspaceTarget): string {
222
+ return target.kind === "root" ? `${target.name} (root)` : `${target.name} (${target.relativeDir})`;
223
+ }
224
+
225
+ function buildChecksTargetOptionLabel(option: { target: WorkspaceTarget; changed: boolean }): string {
226
+ return `${option.target.name} — ${formatTargetLocation(option.target)} — ${option.changed ? "changed" : "unchanged"}`;
227
+ }
228
+
229
+ function buildAllChecksTargetLabel(
230
+ workspaceTargets: WorkspaceTarget[],
231
+ changedTargetIds: Set<string>,
232
+ ): string {
233
+ const workspaceCount = workspaceTargets.filter((target) => target.kind === "workspace").length;
234
+ const base = workspaceCount === 0
235
+ ? "All — root target"
236
+ : `All — root + ${workspaceCount} workspace${workspaceCount === 1 ? "" : "s"}`;
237
+ const changedCount = workspaceTargets.filter((target) => changedTargetIds.has(target.id)).length;
238
+ return changedCount > 0 ? `${base} — ${changedCount} changed` : `${base} — no changed targets`;
239
+ }
240
+
241
+ function getDefaultChecksTarget(workspaceTargets: WorkspaceTarget[]): WorkspaceTarget {
242
+ return workspaceTargets.find((target) => target.kind === "root") ?? workspaceTargets[0]!;
243
+ }
244
+
245
+ function isMonorepoTargets(workspaceTargets: WorkspaceTarget[]): boolean {
246
+ return workspaceTargets.some((target) => target.kind === "workspace");
247
+ }
248
+
249
+ async function resolveChecksTargets(
250
+ platform: Platform,
251
+ ctx: any,
252
+ args: string | undefined,
253
+ deps: ChecksCommandDependencies,
254
+ ): Promise<ResolvedChecksTargets | null> {
255
+ const requestedTarget = parseTargetArg(args);
256
+ const repoRoot = await resolveRepoRoot(platform, ctx.cwd);
257
+ const packageManager = deps.resolvePackageManager(repoRoot);
258
+ const workspaceTargets = deps.discoverWorkspaceTargets(repoRoot, packageManager.id);
259
+
260
+ if (workspaceTargets.length === 0) {
261
+ throw new Error("No workspace targets found for checks.");
262
+ }
263
+
264
+ if (requestedTarget?.toLowerCase() === "all") {
265
+ return { mode: "all", runTargets: workspaceTargets, workspaceTargets };
266
+ }
267
+
268
+ if (requestedTarget) {
269
+ const target = await selectWorkspaceTarget(
270
+ ctx,
271
+ workspaceTargets.map((target) => ({ target, changed: false })),
272
+ requestedTarget,
273
+ {
274
+ title: "Checks target",
275
+ helpText: "Pick one target to run checks for. Use --target all to run the root target and every workspace target.",
276
+ },
277
+ );
278
+ if (!target) {
279
+ throw new Error(`Checks target not found: ${requestedTarget}`);
280
+ }
281
+ return { mode: "single", runTargets: [target], workspaceTargets };
282
+ }
283
+
284
+ if (!isMonorepoTargets(workspaceTargets)) {
285
+ return {
286
+ mode: "single",
287
+ runTargets: [getDefaultChecksTarget(workspaceTargets)],
288
+ workspaceTargets,
289
+ };
290
+ }
291
+
292
+ const changedRepoFiles = await discoverChangedRepoFiles(platform.exec.bind(platform), repoRoot);
293
+ const changedTargetIds = new Set(
294
+ getChangedWorkspaceTargets(workspaceTargets, changedRepoFiles).map((target) => target.id),
295
+ );
296
+ const options = sortWorkspaceTargetOptions(
297
+ workspaceTargets.map((target) => ({
298
+ target,
299
+ changed: changedTargetIds.has(target.id),
300
+ label: buildChecksTargetOptionLabel({
301
+ target,
302
+ changed: changedTargetIds.has(target.id),
303
+ }),
304
+ })),
305
+ );
306
+
307
+ if (!ctx.hasUI) {
308
+ return { mode: "all", runTargets: workspaceTargets, workspaceTargets };
309
+ }
310
+
311
+ const allLabel = buildAllChecksTargetLabel(workspaceTargets, changedTargetIds);
312
+ const labels = [allLabel, ...options.map((option) => option.label ?? buildChecksTargetOptionLabel(option))];
313
+ const choice = await ctx.ui.select("Checks target", labels, {
314
+ initialIndex: 0,
315
+ helpText: "All runs the root target and every workspace target. Choose a single target to narrow the run.",
316
+ });
317
+ if (!choice) {
318
+ return null;
319
+ }
320
+ if (choice === allLabel) {
321
+ return { mode: "all", runTargets: workspaceTargets, workspaceTargets };
322
+ }
323
+
324
+ const selectedIndex = labels.indexOf(choice) - 1;
325
+ const target = selectedIndex >= 0 ? options[selectedIndex]?.target ?? null : null;
326
+ return target ? { mode: "single", runTargets: [target], workspaceTargets } : null;
327
+ }
328
+
171
329
  function gateStepKey(gateId: GateId): string {
172
330
  return `gate-${gateId}`;
173
331
  }
@@ -350,12 +508,15 @@ async function recoverInvalidQualityGateConfig(
350
508
  ctx: any,
351
509
  deps: ChecksCommandDependencies,
352
510
  reviewProgress: ReturnType<typeof createReviewProgress>,
511
+ target: WorkspaceTarget,
353
512
  ): Promise<
354
513
  | { status: "unrecoverable" }
355
514
  | { status: "cancelled" }
356
515
  | { status: "recovered"; config: SupipowersConfig }
357
516
  > {
358
- const recovery = deps.inspectQualityGateRecovery(platform.paths, ctx.cwd);
517
+ const configRoot = target.repoRoot;
518
+ const configOptions = getTargetConfigOptions(target);
519
+ const recovery = deps.inspectQualityGateRecovery(platform.paths, configRoot, configOptions);
359
520
  const recoverableScopes = recovery.scopes
360
521
  .filter((scope) => scope.recoverableInvalidQualityGates)
361
522
  .map((scope) => scope.scope);
@@ -374,7 +535,7 @@ async function recoverInvalidQualityGateConfig(
374
535
  reviewProgress.startRepair(`cleaning ${recoverableScopes.join(" + ")}`);
375
536
 
376
537
  for (const scope of recoverableScopes) {
377
- deps.removeQualityGatesConfig(platform.paths, ctx.cwd, scope);
538
+ deps.removeQualityGatesConfig(platform.paths, configRoot, scope, configOptions);
378
539
  }
379
540
 
380
541
  deps.notifyInfo(
@@ -385,8 +546,8 @@ async function recoverInvalidQualityGateConfig(
385
546
 
386
547
  const setupResult = await deps.setupGates(
387
548
  platform,
388
- ctx.cwd,
389
- deps.inspectConfig(platform.paths, ctx.cwd),
549
+ configRoot,
550
+ deps.inspectConfig(platform.paths, configRoot, configOptions),
390
551
  { mode: "deterministic" },
391
552
  );
392
553
  if (setupResult.status !== "proposed") {
@@ -400,7 +561,7 @@ async function recoverInvalidQualityGateConfig(
400
561
  const saveResult = await deps.interactivelySaveGateSetup(
401
562
  ctx,
402
563
  platform.paths,
403
- ctx.cwd,
564
+ configRoot,
404
565
  setupResult.proposal,
405
566
  );
406
567
  if (saveResult !== "saved") {
@@ -414,7 +575,7 @@ async function recoverInvalidQualityGateConfig(
414
575
  return { status: "cancelled" };
415
576
  }
416
577
 
417
- const config = deps.loadConfig(platform.paths, ctx.cwd);
578
+ const config = deps.loadConfig(platform.paths, configRoot, configOptions);
418
579
  reviewProgress.completeRepair("reconfigured");
419
580
  return {
420
581
  status: "recovered",
@@ -422,6 +583,96 @@ async function recoverInvalidQualityGateConfig(
422
583
  };
423
584
  }
424
585
 
586
+ async function runChecksForTarget(input: RunChecksForTargetInput): Promise<CompletedChecksRun | null> {
587
+ const { platform, ctx, deps, target, workspaceTargets, filters, reviewModel } = input;
588
+ const reviewProgress = createReviewProgress(ctx);
589
+ const configRoot = target.repoRoot;
590
+ const configOptions = getTargetConfigOptions(target);
591
+
592
+ try {
593
+ reviewProgress.startLoadingConfig();
594
+
595
+ let config: SupipowersConfig;
596
+ try {
597
+ config = deps.loadConfig(platform.paths, configRoot, configOptions);
598
+ reviewProgress.completeLoadingConfig();
599
+ } catch (error) {
600
+ const recovered = await recoverInvalidQualityGateConfig(
601
+ platform,
602
+ ctx,
603
+ deps,
604
+ reviewProgress,
605
+ target,
606
+ );
607
+ if (recovered.status === "unrecoverable") {
608
+ throw error;
609
+ }
610
+ if (recovered.status === "cancelled") {
611
+ return null;
612
+ }
613
+ config = recovered.config;
614
+ }
615
+
616
+ const enabledGateIds = getEnabledGateIds(config.quality.gates);
617
+ reviewProgress.configureGateSteps(config.quality.gates, filters);
618
+ validateGateSelection(enabledGateIds, filters);
619
+
620
+ reviewProgress.startScopeDiscovery();
621
+ const report = await deps.runQualityGates({
622
+ platform,
623
+ cwd: target.packageDir,
624
+ target,
625
+ workspaceTargets,
626
+ gates: config.quality.gates,
627
+ filters,
628
+ reviewModel,
629
+ gateRegistry: REVIEW_GATE_REGISTRY,
630
+ onEvent: (event) => reviewProgress.handleRunnerEvent(event),
631
+ });
632
+
633
+ reviewProgress.startSavingReport();
634
+ const reportPath = deps.saveReviewReport(platform.paths, target, report);
635
+ reviewProgress.completeSavingReport(report.overallStatus);
636
+
637
+ return {
638
+ target,
639
+ report,
640
+ reportPath,
641
+ failedGates: getFailedGates(report),
642
+ };
643
+ } catch (error) {
644
+ reviewProgress.failActive((error as Error).message);
645
+ throw error;
646
+ } finally {
647
+ reviewProgress.dispose();
648
+ }
649
+ }
650
+
651
+ function buildBatchChecksTitle(results: CompletedChecksRun[]): string {
652
+ const counts = results.reduce(
653
+ (summary, result) => {
654
+ summary[result.report.overallStatus] += 1;
655
+ return summary;
656
+ },
657
+ { passed: 0, failed: 0, blocked: 0 } satisfies Record<ReviewReport["overallStatus"], number>,
658
+ );
659
+ const parts = [
660
+ counts.passed > 0 ? `${counts.passed} passed` : null,
661
+ counts.failed > 0 ? `${counts.failed} failed` : null,
662
+ counts.blocked > 0 ? `${counts.blocked} blocked` : null,
663
+ ].filter((part): part is string => part !== null);
664
+
665
+ return `Checks complete: ${parts.join(", ")}`;
666
+ }
667
+
668
+ function buildBatchChecksSummary(results: CompletedChecksRun[]): string {
669
+ return results.map((result) => {
670
+ const { passed, failed, blocked, skipped } = result.report.summary;
671
+ return `${formatTargetLabel(result.target)}: ${result.report.overallStatus} — ${passed} passed, ${failed} failed, ${blocked} blocked, ${skipped} skipped — saved: ${result.reportPath}`;
672
+ }).join("\n");
673
+ }
674
+
675
+
425
676
  export function buildReviewSummary(report: ReviewReport, reportPath: string): string {
426
677
  const orderedGates = [...report.gates].sort(
427
678
  (left, right) =>
@@ -548,7 +799,6 @@ function buildFixPrompt(failedGates: GateResult[]): string {
548
799
  ].join("\n"));
549
800
  }
550
801
 
551
- const gateNames = failedGates.map((g) => GATE_DISPLAY_NAMES[g.gate] ?? g.gate);
552
802
  const rerunCmd = `/supi:checks --only ${failedGates.map((g) => g.gate).join(" ")}`;
553
803
 
554
804
  return [
@@ -565,7 +815,6 @@ export async function handleChecks(
565
815
  args: string | undefined,
566
816
  deps: ChecksCommandDependencies = CHECKS_COMMAND_DEPENDENCIES,
567
817
  ): Promise<void> {
568
- const reviewProgress = createReviewProgress(ctx);
569
818
  let modelCleanup: (() => Promise<void>) | undefined;
570
819
 
571
820
  try {
@@ -574,82 +823,67 @@ export async function handleChecks(
574
823
  const resolved = deps.resolveModelForAction("checks", modelRegistry, modelCfg, bridge);
575
824
  modelCleanup = await deps.applyModelOverride(platform, ctx, "checks", resolved);
576
825
 
577
- reviewProgress.startLoadingConfig();
826
+ const filters = parseGateFilters(args);
827
+ const selection = await resolveChecksTargets(platform, ctx, args, deps);
828
+ if (!selection) {
829
+ return;
830
+ }
578
831
 
579
- let config: SupipowersConfig;
580
- try {
581
- config = deps.loadConfig(platform.paths, ctx.cwd);
582
- reviewProgress.completeLoadingConfig();
583
- } catch (error) {
584
- const recovered = await recoverInvalidQualityGateConfig(platform, ctx, deps, reviewProgress);
585
- if (recovered.status === "unrecoverable") {
586
- throw error;
587
- }
588
- if (recovered.status === "cancelled") {
832
+ const results: CompletedChecksRun[] = [];
833
+ for (const target of selection.runTargets) {
834
+ const result = await runChecksForTarget({
835
+ platform,
836
+ ctx,
837
+ deps,
838
+ target,
839
+ workspaceTargets: selection.workspaceTargets,
840
+ filters,
841
+ reviewModel: resolved,
842
+ });
843
+ if (!result) {
589
844
  return;
590
845
  }
591
- config = recovered.config;
846
+ results.push(result);
592
847
  }
593
848
 
594
- const enabledGateIds = getEnabledGateIds(config.quality.gates);
595
- const filters = parseGateFilters(args);
596
- reviewProgress.configureGateSteps(config.quality.gates, filters);
597
- validateGateSelection(enabledGateIds, filters);
598
-
599
- reviewProgress.startScopeDiscovery();
600
- const report = await deps.runQualityGates({
601
- platform,
602
- cwd: ctx.cwd,
603
- gates: config.quality.gates,
604
- filters,
605
- reviewModel: resolved,
606
- gateRegistry: REVIEW_GATE_REGISTRY,
607
- onEvent: (event) => reviewProgress.handleRunnerEvent(event),
608
- });
609
-
610
- reviewProgress.startSavingReport();
611
- const reportPath = deps.saveReviewReport(platform.paths, ctx.cwd, report);
612
- reviewProgress.completeSavingReport(report.overallStatus);
613
-
614
- // Dispose widget before showing any TUI dialogs
615
- reviewProgress.dispose();
849
+ if (selection.mode === "all" && results.length > 1) {
850
+ deps.notifyInfo(ctx, buildBatchChecksTitle(results), buildBatchChecksSummary(results));
851
+ return;
852
+ }
616
853
 
617
- const failedGates = getFailedGates(report);
854
+ const [result] = results;
855
+ if (!result) {
856
+ return;
857
+ }
618
858
 
619
- if (failedGates.length === 0) {
859
+ if (result.failedGates.length === 0) {
620
860
  deps.notifyInfo(
621
861
  ctx,
622
- `Checks complete: ${report.overallStatus}`,
623
- buildReviewSummary(report, reportPath),
862
+ `Checks complete: ${result.report.overallStatus}`,
863
+ buildReviewSummary(result.report, result.reportPath),
624
864
  );
625
865
  return;
626
866
  }
627
867
 
628
- // Show compact failure summary
629
- const failureNames = failedGates.map((g) => GATE_DISPLAY_NAMES[g.gate] ?? g.gate);
868
+ const failureNames = result.failedGates.map((gate) => GATE_DISPLAY_NAMES[gate.gate] ?? gate.gate);
630
869
  deps.notifyInfo(
631
870
  ctx,
632
- `Checks complete: ${report.overallStatus}`,
633
- buildFailureSummary(failedGates),
871
+ `Checks complete: ${result.report.overallStatus}`,
872
+ buildFailureSummary(result.failedGates),
634
873
  );
635
874
 
636
- // Offer to fix
637
875
  const FIX_NOW = `Yes, fix ${failureNames.join(", ")}`;
638
876
  const SAVE_ONLY = "No, just save for later";
639
877
  const choice = await ctx.ui.select(
640
- `${failedGates.length} check${failedGates.length === 1 ? "" : "s"} failed — do you want to fix now?`,
878
+ `${result.failedGates.length} check${result.failedGates.length === 1 ? "" : "s"} failed — do you want to fix now?`,
641
879
  [FIX_NOW, SAVE_ONLY],
642
880
  );
643
881
 
644
882
  if (choice === FIX_NOW) {
645
- platform.sendUserMessage(buildFixPrompt(failedGates));
883
+ platform.sendUserMessage(buildFixPrompt(result.failedGates));
646
884
  }
647
- } catch (error) {
648
- reviewProgress.failActive((error as Error).message);
649
- throw error;
650
885
  } finally {
651
886
  await modelCleanup?.();
652
- reviewProgress.dispose();
653
887
  }
654
888
  }
655
889