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
@@ -1,5 +1,5 @@
1
1
  import type { Platform } from "../platform/types.js";
2
- import type { DriftCheckResult } from "../types.js";
2
+ import type { DriftCheckResult, WorkspaceTarget } from "../types.js";
3
3
  import { notifyInfo, notifyError, notifyWarning } from "../notifications/renderer.js";
4
4
  import {
5
5
  loadState,
@@ -7,7 +7,19 @@ import {
7
7
  discoverDocFiles,
8
8
  getHeadCommit,
9
9
  checkDocDrift,
10
+ type DocDriftScope,
10
11
  } from "../docs/drift.js";
12
+ import {
13
+ buildWorkspaceTargetOptionLabel,
14
+ parseTargetArg,
15
+ selectWorkspaceTarget,
16
+ stripCliArg,
17
+ tokenizeCliArgs,
18
+ type WorkspaceTargetOption,
19
+ } from "../workspace/selector.js";
20
+ import { detectPackageManager } from "../workspace/package-manager.js";
21
+ import { resolveRepoRoot } from "../workspace/repo-root.js";
22
+ import { discoverWorkspaceTargets } from "../workspace/targets.js";
11
23
 
12
24
  // ── Multi-select UI ───────────────────────────────────────────
13
25
 
@@ -47,44 +59,109 @@ async function selectDocFiles(
47
59
  return [...selected];
48
60
  }
49
61
 
62
+
63
+ function parseGenerateSubcommand(args?: string): string {
64
+ return tokenizeCliArgs(stripCliArg(args, "--target"))[0] ?? "docs";
65
+ }
66
+
67
+ function formatGenerateTarget(target: WorkspaceTarget): string {
68
+ return target.kind === "root"
69
+ ? `${target.name} (root · ${target.relativeDir})`
70
+ : `${target.name} (${target.relativeDir})`;
71
+ }
72
+
73
+ function buildGenerateTargetOptionLabel(option: WorkspaceTargetOption<WorkspaceTarget>): string {
74
+ return option.target.kind === "root"
75
+ ? buildWorkspaceTargetOptionLabel(option, ["root docs"])
76
+ : buildWorkspaceTargetOptionLabel(option, ["package docs"]);
77
+ }
78
+
79
+ async function resolveGenerateScope(
80
+ platform: Platform,
81
+ ctx: any,
82
+ args?: string,
83
+ ): Promise<DocDriftScope | null> {
84
+ const requestedTarget = parseTargetArg(args);
85
+ const repoRoot = await resolveRepoRoot(platform, ctx.cwd);
86
+ const packageManager = detectPackageManager(repoRoot);
87
+ const targets = discoverWorkspaceTargets(repoRoot, packageManager);
88
+ if (targets.length === 0) {
89
+ notifyError(ctx, "No documentation targets found", "Create a package.json with name and version before running /supi:generate.");
90
+ return null;
91
+ }
92
+
93
+ const selectedTarget = await selectWorkspaceTarget(
94
+ ctx,
95
+ targets.map((target) => ({
96
+ target,
97
+ changed: false,
98
+ label: buildGenerateTargetOptionLabel({ target, changed: false }),
99
+ })),
100
+ requestedTarget,
101
+ {
102
+ title: "Documentation target",
103
+ helpText: "Pick the package whose documentation should be checked. Root selects only repository-level docs.",
104
+ },
105
+ );
106
+
107
+ if (requestedTarget && !selectedTarget) {
108
+ notifyError(ctx, "Documentation target not found", requestedTarget);
109
+ return null;
110
+ }
111
+
112
+ if (!selectedTarget) {
113
+ return null;
114
+ }
115
+
116
+ return { target: selectedTarget, allTargets: targets };
117
+ }
118
+
50
119
  // ── Subcommand: docs ──────────────────────────────────────────
51
120
 
52
- async function handleDocs(platform: Platform, ctx: any): Promise<void> {
121
+ async function handleDocs(platform: Platform, ctx: any, args?: string): Promise<void> {
53
122
  if (!ctx.hasUI) {
54
123
  notifyWarning(ctx, "Doc drift check requires interactive mode");
55
124
  return;
56
125
  }
57
126
 
127
+ const scope = await resolveGenerateScope(platform, ctx, args);
128
+ if (!scope) {
129
+ return;
130
+ }
131
+
58
132
  const cwd = ctx.cwd;
59
133
  const { paths } = platform;
60
- const state = loadState(paths, cwd);
134
+ const targetSummary = formatGenerateTarget(scope.target);
135
+ const state = loadState(paths, cwd, scope);
61
136
 
62
137
  // First run: discover and select files, then steer main thread for full audit
63
138
  if (state.trackedFiles.length === 0) {
64
- const discovered = await discoverDocFiles(platform, cwd);
139
+ const discovered = await discoverDocFiles(platform, cwd, scope);
65
140
  if (discovered.length === 0) {
66
- notifyWarning(ctx, "No documentation files found in this repository");
141
+ notifyWarning(ctx, "No documentation files found for selected target", `Target: ${targetSummary}`);
67
142
  return;
68
143
  }
69
144
 
70
145
  const selected = await selectDocFiles(ctx, discovered);
71
146
  if (selected.length === 0) {
72
- notifyInfo(ctx, "No files selected \u2014 doc tracking not set up");
147
+ notifyInfo(ctx, "No files selected doc tracking not set up", `Target: ${targetSummary}`);
73
148
  return;
74
149
  }
75
150
 
76
- // Persist tracked files but leave lastCommit null \u2014 updated after fix starts
151
+ // Persist tracked files but leave lastCommit null updated after fix starts
77
152
  saveState(paths, cwd, {
78
153
  trackedFiles: selected,
79
154
  lastCommit: null,
80
155
  lastRunAt: new Date().toISOString(),
81
- });
156
+ }, scope.target);
82
157
 
83
158
  // Steer the main thread to audit and fix docs directly
84
159
  const docList = selected.map((f) => `- \`${f}\``).join("\n");
85
160
  const prompt = [
86
161
  `Check these documentation files for accuracy against the current codebase:`,
87
162
  ``,
163
+ `Target: ${targetSummary}`,
164
+ ``,
88
165
  docList,
89
166
  ``,
90
167
  `<critical>`,
@@ -96,15 +173,16 @@ async function handleDocs(platform: Platform, ctx: any): Promise<void> {
96
173
  `2. **Missing documentation**: new commands, features, config options that exist in code but not in docs`,
97
174
  `3. **Structural gaps**: important sections that should exist based on the codebase but don't`,
98
175
  ``,
99
- `For each issue found, fix it directly in the documentation file. Do NOT output JSON or a report \u2014 just fix the files.`,
176
+ `For each issue found, fix it directly in the documentation file. Do NOT output JSON or a report just fix the files.`,
100
177
  `If documentation is accurate, say so and make no changes.`,
101
178
  ``,
102
179
  `Rules:`,
103
180
  `- Only fix factual inaccuracies and add missing sections for undocumented features`,
104
181
  `- Do NOT rewrite prose, improve wording, or restructure existing content`,
105
182
  `- Preserve each document's existing formatting, tone, and conventions`,
183
+ `- Limit the review to the selected target`,
106
184
  ].join("\n");
107
- notifyInfo(ctx, "Starting full documentation audit", `${selected.length} file(s) selected`);
185
+ notifyInfo(ctx, "Starting full documentation audit", `${selected.length} file(s) selected · Target: ${targetSummary}`);
108
186
 
109
187
  platform.sendMessage(
110
188
  {
@@ -118,21 +196,30 @@ async function handleDocs(platform: Platform, ctx: any): Promise<void> {
118
196
  }
119
197
 
120
198
  // Subsequent run: headless sub-agent drift check
121
- const result = await checkDocDrift(platform, cwd);
199
+ const result = await checkDocDrift(platform, cwd, scope);
200
+
201
+ if (result?.errors && result.errors.length > 0) {
202
+ notifyError(
203
+ ctx,
204
+ "Doc drift check failed",
205
+ `${result.errors.length} sub-agent(s) could not produce valid output. Target: ${targetSummary}\n\n- ${result.errors.join("\n- ")}`,
206
+ );
207
+ return;
208
+ }
122
209
 
123
210
  if (!result || !result.drifted) {
124
- notifyInfo(ctx, "Docs are up to date", result?.summary ?? "No changes since last check");
211
+ notifyInfo(ctx, "Docs are up to date", `${result?.summary ?? "No changes since last check"} · Target: ${targetSummary}`);
125
212
  return;
126
213
  }
127
214
 
128
215
  // Build lightweight steer summary from findings
129
- const steer = buildSteerSummary(result);
130
- notifyInfo(ctx, "Documentation drift detected", `${result.findings.length} finding(s)`);
216
+ const steer = buildSteerSummary(result, targetSummary);
217
+ notifyInfo(ctx, "Documentation drift detected", `${result.findings.length} finding(s) · Target: ${targetSummary}`);
131
218
 
132
- // Update state only now \u2014 user has seen findings and we\u2019re about to fix.
219
+ // Update state only now user has seen findings and we’re about to fix.
133
220
  const head = await getHeadCommit(platform, cwd);
134
- const currentState = loadState(paths, cwd);
135
- saveState(paths, cwd, { ...currentState, lastCommit: head, lastRunAt: new Date().toISOString() });
221
+ const currentState = loadState(paths, cwd, scope);
222
+ saveState(paths, cwd, { ...currentState, lastCommit: head, lastRunAt: new Date().toISOString() }, scope.target);
136
223
 
137
224
  platform.sendMessage(
138
225
  {
@@ -144,8 +231,11 @@ async function handleDocs(platform: Platform, ctx: any): Promise<void> {
144
231
  );
145
232
  }
146
233
 
147
- function buildSteerSummary(result: DriftCheckResult): string {
148
- const lines: string[] = ["Documentation drift detected. Please fix the following issues:", ""];
234
+ function buildSteerSummary(result: DriftCheckResult, targetSummary: string): string {
235
+ const lines: string[] = [
236
+ `Documentation drift detected for target ${targetSummary}. Please fix the following issues:`,
237
+ "",
238
+ ];
149
239
 
150
240
  const byFile = new Map<string, typeof result.findings>();
151
241
  for (const f of result.findings) {
@@ -182,11 +272,11 @@ export function registerGenerateCommand(platform: Platform): void {
182
272
  return matches.length > 0 ? matches : null;
183
273
  },
184
274
  async handler(args: string | undefined, ctx: any) {
185
- const subcommand = args?.trim().split(/\s+/)[0] ?? "docs";
275
+ const subcommand = parseGenerateSubcommand(args);
186
276
 
187
277
  switch (subcommand) {
188
278
  case "docs":
189
- await handleDocs(platform, ctx);
279
+ await handleDocs(platform, ctx, args);
190
280
  break;
191
281
  default:
192
282
  notifyError(
@@ -0,0 +1,192 @@
1
+ import type { Platform, PlatformContext } from "../platform/types.js";
2
+ import { loadConfig } from "../config/loader.js";
3
+ import {
4
+ checkMempalaceProjectInitialized,
5
+ runMempalaceSetup,
6
+ snapshotMempalaceInstall,
7
+ steerMempalaceInitialization,
8
+ } from "../mempalace/installer-helper.js";
9
+
10
+ const SUBCOMMANDS = [
11
+ { name: "status", description: "Show palace path, managed venv, and install status" },
12
+ { name: "setup", description: "Install or repair the managed Python environment and MemPalace package" },
13
+ ] as const;
14
+
15
+ const HELP = [
16
+ "/supi:memory — native MemPalace integration",
17
+ "",
18
+ "Subcommands:",
19
+ ...SUBCOMMANDS.map((subcommand) => ` ${subcommand.name.padEnd(8)} ${subcommand.description}`),
20
+ "",
21
+ "Memory APIs are exposed to the agent via the `mempalace` tool.",
22
+ ].join("\n");
23
+
24
+ function statusReport(platform: Platform, cwd: string): string {
25
+ const config = loadConfig(platform.paths, cwd);
26
+ const snap = snapshotMempalaceInstall(platform.paths, cwd, config);
27
+ const lines = [
28
+ "/supi:memory status",
29
+ "",
30
+ `enabled: ${snap.enabled}`,
31
+ `palace path: ${config.mempalace.palacePath}`,
32
+ `default wing strategy: ${config.mempalace.defaultWingStrategy}`,
33
+ `managed venv: ${snap.venvPath}`,
34
+ `managed python: ${snap.venvPython} (${snap.venvInstalled ? "present" : "missing"})`,
35
+ `managed uv: ${snap.uvPath} (${snap.uvInstalled ? "present" : "missing"})`,
36
+ `bridge script: ${snap.bridgeOk ? snap.bridgePath : `${snap.bridgePath} (missing)`}`,
37
+ `package version: ${snap.packageVersion}`,
38
+ "",
39
+ snap.ready
40
+ ? "Run `/supi:memory setup` again to upgrade or repair the managed environment."
41
+ : "Run `/supi:memory setup` to install the managed environment.",
42
+ ];
43
+ return lines.join("\n");
44
+ }
45
+
46
+ async function runSetup(platform: Platform, ctx: PlatformContext): Promise<void> {
47
+ const config = loadConfig(platform.paths, ctx.cwd);
48
+ if (!config.mempalace.enabled) {
49
+ ctx.ui.notify("MemPalace integration is disabled in config (mempalace.enabled=false). Enable it before running setup.", "warning");
50
+ return;
51
+ }
52
+
53
+ const snap = snapshotMempalaceInstall(platform.paths, ctx.cwd, config);
54
+ if (!snap.bridgeOk) {
55
+ ctx.ui.notify(`MemPalace bridge missing at ${snap.bridgePath}. Reinstall supipowers and retry.`, "error");
56
+ return;
57
+ }
58
+
59
+ ctx.ui.notify(
60
+ [
61
+ "/supi:memory setup",
62
+ "",
63
+ `palace path: ${config.mempalace.palacePath}`,
64
+ `managed venv: ${config.mempalace.managedVenvPath}`,
65
+ `package: mempalace==${snap.packageVersion} (PyPI)`,
66
+ "",
67
+ "This may take a minute on first install while ChromaDB and native deps are built.",
68
+ ].join("\n"),
69
+ "info",
70
+ );
71
+
72
+ const exec = async (command: string, args: string[], options?: { input?: string; timeoutMs?: number }) => {
73
+ const result = await platform.exec(command, args, {
74
+ cwd: ctx.cwd,
75
+ ...(options?.timeoutMs ? { timeout: options.timeoutMs } : {}),
76
+ });
77
+ return { code: result.code, stdout: result.stdout, stderr: result.stderr };
78
+ };
79
+
80
+ const result = await runMempalaceSetup({
81
+ paths: platform.paths,
82
+ cwd: ctx.cwd,
83
+ config,
84
+ runner: exec,
85
+ onProgress: (message) => ctx.ui.notify(`MemPalace setup: ${message}`, "info"),
86
+ });
87
+
88
+ if (!result.ok) {
89
+ const stderr = result.stderrTail ? `\n\n${result.stderrTail}` : "";
90
+ ctx.ui.notify(
91
+ `MemPalace setup failed (${result.error.code}): ${result.error.message}\n${result.error.remediation ?? ""}${stderr}`.trim(),
92
+ "error",
93
+ );
94
+ return;
95
+ }
96
+
97
+ ctx.ui.notify(
98
+ [
99
+ "MemPalace setup complete.",
100
+ `uv: ${result.details.uvPath} (${result.details.uvVersion})`,
101
+ `python: ${result.details.managedPython} (managed by uv)`,
102
+ `venv: ${result.details.venvPath}`,
103
+ `package: mempalace==${result.details.packageVersion}`,
104
+ ].join("\n"),
105
+ "info",
106
+ );
107
+
108
+ // Check if the current project's wing is already initialized; if not, steer
109
+ // the model to run init + mine through the mempalace tool.
110
+ const initState = await checkMempalaceProjectInitialized({
111
+ paths: platform.paths,
112
+ cwd: ctx.cwd,
113
+ config,
114
+ });
115
+
116
+ if (initState.initialized) {
117
+ ctx.ui.notify(
118
+ `MemPalace project wing \`${initState.wing}\` is already initialized.`,
119
+ "info",
120
+ );
121
+ return;
122
+ }
123
+
124
+ const steered = steerMempalaceInitialization(platform, {
125
+ wing: initState.wing,
126
+ cwd: ctx.cwd,
127
+ });
128
+ if (steered) {
129
+ ctx.ui.notify(
130
+ `Steering the agent to initialize project wing \`${initState.wing}\` (running mempalace init + mine).`,
131
+ "info",
132
+ );
133
+ } else {
134
+ ctx.ui.notify(
135
+ `Project wing \`${initState.wing}\` not initialized. Ask the agent to run mempalace(action="init", dir=".", yes=true).`,
136
+ "warning",
137
+ );
138
+ }
139
+ }
140
+
141
+ export function handleMemory(platform: Platform, ctx: PlatformContext, args?: string): void {
142
+ if (!ctx.hasUI) return;
143
+
144
+ const sub = (args ?? "").trim().split(/\s+/)[0] ?? "";
145
+
146
+ if (sub === "" || sub === "help" || sub === "--help" || sub === "-h") {
147
+ ctx.ui.notify(HELP, "info");
148
+ return;
149
+ }
150
+
151
+ if (sub === "status") {
152
+ try {
153
+ ctx.ui.notify(statusReport(platform, ctx.cwd), "info");
154
+ } catch (err) {
155
+ ctx.ui.notify(`MemPalace status failed: ${(err as Error).message}`, "error");
156
+ }
157
+ return;
158
+ }
159
+
160
+ if (sub === "setup") {
161
+ void (async () => {
162
+ try {
163
+ await runSetup(platform, ctx);
164
+ } catch (err) {
165
+ ctx.ui.notify(`MemPalace setup crashed: ${(err as Error).message}`, "error");
166
+ }
167
+ })();
168
+ return;
169
+ }
170
+
171
+ ctx.ui.notify(`Unknown /supi:memory subcommand: ${sub}\n\n${HELP}`, "warning");
172
+ }
173
+
174
+ export function registerMemoryCommand(platform: Platform): void {
175
+ platform.registerCommand("supi:memory", {
176
+ description: "Manage native MemPalace integration (status, setup)",
177
+ getArgumentCompletions(prefix: string) {
178
+ const lower = prefix.trim().toLowerCase();
179
+ const matches = SUBCOMMANDS
180
+ .filter((subcommand) => subcommand.name.startsWith(lower))
181
+ .map((subcommand) => ({
182
+ value: `${subcommand.name} `,
183
+ label: subcommand.name,
184
+ description: subcommand.description,
185
+ }));
186
+ return matches.length > 0 ? matches : null;
187
+ },
188
+ async handler(args: string | undefined, ctx: any) {
189
+ handleMemory(platform, ctx, args);
190
+ },
191
+ });
192
+ }
@@ -33,10 +33,9 @@ import {
33
33
  const ALL_TAB = "ALL";
34
34
  const MAX_VISIBLE = 12;
35
35
 
36
- /** Set of available (authenticated) providers and model IDs, from ctx.modelRegistry */
36
+ /** Available (authenticated) models sourced directly from ctx.modelRegistry.getAvailable() */
37
37
  export interface AvailableModelSet {
38
- providers: Set<string>;
39
- modelIds: Set<string>;
38
+ models: Array<{ provider: string; id: string }>;
40
39
  }
41
40
 
42
41
  interface ModelItem {
@@ -48,45 +47,53 @@ interface ModelItem {
48
47
 
49
48
 
50
49
  /**
51
- * Build the flat model list from bundled providers.
52
- * @param available if provided, marks models whose provider has auth
50
+ * Build the flat model list.
51
+ * When registry models are provided, uses them as source of truth (all authenticated).
52
+ * Falls back to the bundled static list when no registry data is available.
53
53
  */
54
54
  function loadAllModels(available?: AvailableModelSet): { items: ModelItem[]; configuredProviders: Set<string> } {
55
- const providers = getBundledProviders();
56
55
  const items: ModelItem[] = [];
57
56
  const configuredProviders = new Set<string>();
58
57
 
59
- for (const provider of providers) {
60
- const name = String(provider);
61
- const configured = available ? available.providers.has(name) : true;
62
- if (configured) configuredProviders.add(name);
63
-
64
- const models = getBundledModels(provider as GeneratedProvider);
65
- for (const m of models) {
58
+ if (available && available.models.length > 0) {
59
+ // Registry-sourced: all returned models are authenticated — use them directly
60
+ for (const m of available.models) {
61
+ configuredProviders.add(m.provider);
66
62
  items.push({
67
- provider: name,
63
+ provider: m.provider,
68
64
  id: m.id,
69
- displayLabel: `${name}/${m.id}`,
70
- configured,
65
+ displayLabel: `${m.provider}/${m.id}`,
66
+ configured: true,
71
67
  });
72
68
  }
69
+ } else {
70
+ // Fallback: bundled static list (no registry data available)
71
+ for (const provider of getBundledProviders()) {
72
+ const name = String(provider);
73
+ const models = getBundledModels(provider as GeneratedProvider);
74
+ for (const m of models) {
75
+ items.push({
76
+ provider: name,
77
+ id: m.id,
78
+ displayLabel: `${name}/${m.id}`,
79
+ configured: true,
80
+ });
81
+ }
82
+ }
73
83
  }
74
84
 
75
- // Sort like OMP's native /model: provider → version desc → -latest first → date desc → alpha
85
+ // Sort: provider asc → version desc → -latest first → date desc → alpha
76
86
  const dateRe = /-(\d{8})$/;
77
87
  const latestRe = /-latest$/;
78
88
 
79
89
  items.sort((a, b) => {
80
- // Group by provider
81
90
  const provCmp = a.provider.localeCompare(b.provider);
82
91
  if (provCmp !== 0) return provCmp;
83
92
 
84
- // Version number descending (higher = newer model)
85
93
  const aVer = extractVersionNumber(a.id);
86
94
  const bVer = extractVersionNumber(b.id);
87
95
  if (aVer !== bVer) return bVer - aVer;
88
96
 
89
- // Recency: models with -latest or YYYYMMDD suffix come first
90
97
  const aIsLatest = latestRe.test(a.id);
91
98
  const bIsLatest = latestRe.test(b.id);
92
99
  const aDate = a.id.match(dateRe)?.[1] ?? "";
@@ -96,7 +103,7 @@ function loadAllModels(available?: AvailableModelSet): { items: ModelItem[]; con
96
103
 
97
104
  if (aHasRecency !== bHasRecency) return aHasRecency ? -1 : 1;
98
105
  if (aIsLatest !== bIsLatest) return aIsLatest ? -1 : 1;
99
- if (aDate && bDate) return bDate.localeCompare(aDate); // newest first
106
+ if (aDate && bDate) return bDate.localeCompare(aDate);
100
107
 
101
108
  return a.id.localeCompare(b.id);
102
109
  });
@@ -11,7 +11,7 @@ import type { ModelAction, ModelAssignment, ThinkingLevel } from "../types.js";
11
11
  import { getBundledProviders, getBundledModels, type GeneratedProvider } from "@oh-my-pi/pi-ai";
12
12
  import { createModelPicker, type AvailableModelSet } from "./model-picker.js";
13
13
 
14
- const THINKING_LEVELS: Array<{ label: string; value: ThinkingLevel | null }> = [
14
+ export const THINKING_LEVELS: Array<{ label: string; value: ThinkingLevel | null }> = [
15
15
  { label: "Inherit (model default)", value: null },
16
16
  { label: "Off", value: "off" },
17
17
  { label: "Minimal", value: "minimal" },
@@ -194,12 +194,11 @@ export async function selectModelFromList(
194
194
  const models = ctx.modelRegistry?.getAvailable?.() ?? [];
195
195
  if (models.length > 0) {
196
196
  available = {
197
- providers: new Set(models.map((m: any) => String(m.provider))),
198
- modelIds: new Set(models.map((m: any) => `${m.provider}/${m.id}`)),
197
+ models: models.map((m: any) => ({ provider: String(m.provider), id: m.id })),
199
198
  };
200
199
  }
201
200
  } catch {
202
- // Fall through — picker will show all models unfiltered
201
+ // Fall through — picker will show bundled list unfiltered
203
202
  }
204
203
  return ctx.ui.custom((tui: any, theme: any, kb: any, done: any) =>
205
204
  createModelPicker(tui, theme, kb, done, available),
@@ -207,12 +206,23 @@ export async function selectModelFromList(
207
206
  }
208
207
 
209
208
  // Fallback: flat select list for non-OMP platforms
210
- const providers = getBundledProviders();
209
+ // Prefer live registry models; fall back to bundled list when unavailable
211
210
  const allModels: string[] = [];
212
- for (const provider of providers.sort()) {
213
- const models = getBundledModels(provider as GeneratedProvider);
214
- for (const m of models) {
215
- allModels.push(`${provider}/${m.id}`);
211
+ try {
212
+ const registryModels = ctx.modelRegistry?.getAvailable?.() ?? [];
213
+ for (const m of registryModels) {
214
+ allModels.push(`${m.provider}/${m.id}`);
215
+ }
216
+ } catch {
217
+ // ignore
218
+ }
219
+ if (allModels.length === 0) {
220
+ const providers = getBundledProviders();
221
+ for (const provider of providers.sort()) {
222
+ const models = getBundledModels(provider as GeneratedProvider);
223
+ for (const m of models) {
224
+ allModels.push(`${provider}/${m.id}`);
225
+ }
216
226
  }
217
227
  }
218
228
  allModels.sort();