supipowers 1.2.6 → 1.5.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 (137) hide show
  1. package/README.md +118 -56
  2. package/bin/install.ts +48 -128
  3. package/package.json +11 -3
  4. package/skills/code-review/SKILL.md +137 -40
  5. package/skills/context-mode/SKILL.md +67 -56
  6. package/skills/creating-supi-agents/SKILL.md +204 -0
  7. package/skills/debugging/SKILL.md +86 -40
  8. package/skills/fix-pr/SKILL.md +96 -65
  9. package/skills/planning/SKILL.md +103 -46
  10. package/skills/qa-strategy/SKILL.md +68 -46
  11. package/skills/receiving-code-review/SKILL.md +60 -53
  12. package/skills/release/SKILL.md +111 -39
  13. package/skills/tdd/SKILL.md +118 -67
  14. package/skills/verification/SKILL.md +71 -37
  15. package/src/bootstrap.ts +27 -5
  16. package/src/commands/agents.ts +249 -0
  17. package/src/commands/ai-review.ts +1113 -0
  18. package/src/commands/config.ts +224 -95
  19. package/src/commands/doctor.ts +19 -13
  20. package/src/commands/fix-pr.ts +8 -11
  21. package/src/commands/generate.ts +200 -0
  22. package/src/commands/model-picker.ts +5 -15
  23. package/src/commands/model.ts +4 -5
  24. package/src/commands/optimize-context.ts +202 -0
  25. package/src/commands/plan.ts +148 -92
  26. package/src/commands/qa.ts +14 -23
  27. package/src/commands/release.ts +504 -275
  28. package/src/commands/review.ts +643 -86
  29. package/src/commands/status.ts +44 -17
  30. package/src/commands/supi.ts +69 -41
  31. package/src/commands/update.ts +57 -2
  32. package/src/config/defaults.ts +6 -39
  33. package/src/config/loader.ts +388 -40
  34. package/src/config/model-resolver.ts +26 -22
  35. package/src/config/schema.ts +113 -48
  36. package/src/context/analyzer.ts +61 -2
  37. package/src/context/optimizer.ts +199 -0
  38. package/src/context-mode/compressor.ts +14 -11
  39. package/src/context-mode/detector.ts +16 -54
  40. package/src/context-mode/event-extractor.ts +45 -16
  41. package/src/context-mode/event-store.ts +225 -16
  42. package/src/context-mode/hooks.ts +195 -22
  43. package/src/context-mode/knowledge/chunker.ts +235 -0
  44. package/src/context-mode/knowledge/store.ts +187 -0
  45. package/src/context-mode/routing.ts +12 -23
  46. package/src/context-mode/sandbox/executor.ts +183 -0
  47. package/src/context-mode/sandbox/runners.ts +40 -0
  48. package/src/context-mode/snapshot-builder.ts +243 -7
  49. package/src/context-mode/tools.ts +440 -0
  50. package/src/context-mode/web/fetcher.ts +117 -0
  51. package/src/context-mode/web/html-to-md.ts +293 -0
  52. package/src/debug/logger.ts +107 -0
  53. package/src/deps/registry.ts +0 -20
  54. package/src/docs/drift.ts +454 -0
  55. package/src/fix-pr/fetch-comments.ts +66 -0
  56. package/src/git/commit-msg.ts +2 -1
  57. package/src/git/commit.ts +123 -141
  58. package/src/git/conventions.ts +2 -2
  59. package/src/git/status.ts +4 -1
  60. package/src/lsp/bridge.ts +138 -12
  61. package/src/planning/approval-flow.ts +125 -19
  62. package/src/planning/plan-writer-prompt.ts +4 -11
  63. package/src/planning/planning-ask-tool.ts +81 -0
  64. package/src/planning/prompt-builder.ts +9 -169
  65. package/src/planning/system-prompt.ts +290 -0
  66. package/src/platform/omp.ts +50 -4
  67. package/src/platform/progress.ts +182 -0
  68. package/src/platform/test-utils.ts +4 -1
  69. package/src/platform/tui-colors.ts +30 -0
  70. package/src/platform/types.ts +1 -0
  71. package/src/qa/detect-app-type.ts +102 -0
  72. package/src/qa/discover-routes.ts +353 -0
  73. package/src/quality/ai-session.ts +96 -0
  74. package/src/quality/ai-setup.ts +86 -0
  75. package/src/quality/gates/ai-review.ts +129 -0
  76. package/src/quality/gates/build.ts +8 -0
  77. package/src/quality/gates/command.ts +150 -0
  78. package/src/quality/gates/format.ts +28 -0
  79. package/src/quality/gates/lint.ts +22 -0
  80. package/src/quality/gates/lsp-diagnostics.ts +84 -0
  81. package/src/quality/gates/test-suite.ts +8 -0
  82. package/src/quality/gates/typecheck.ts +22 -0
  83. package/src/quality/registry.ts +25 -0
  84. package/src/quality/review-gates.ts +33 -0
  85. package/src/quality/runner.ts +268 -0
  86. package/src/quality/schemas.ts +48 -0
  87. package/src/quality/setup.ts +227 -0
  88. package/src/release/changelog.ts +7 -3
  89. package/src/release/channels/custom.ts +43 -0
  90. package/src/release/channels/gitea.ts +35 -0
  91. package/src/release/channels/github.ts +35 -0
  92. package/src/release/channels/gitlab.ts +35 -0
  93. package/src/release/channels/registry.ts +52 -0
  94. package/src/release/channels/types.ts +27 -0
  95. package/src/release/detector.ts +10 -63
  96. package/src/release/executor.ts +61 -51
  97. package/src/release/prompt.ts +38 -38
  98. package/src/release/version.ts +129 -10
  99. package/src/review/agent-loader.ts +331 -0
  100. package/src/review/consolidator.ts +180 -0
  101. package/src/review/default-agents/correctness.md +72 -0
  102. package/src/review/default-agents/maintainability.md +64 -0
  103. package/src/review/default-agents/security.md +67 -0
  104. package/src/review/fixer.ts +219 -0
  105. package/src/review/multi-agent-runner.ts +135 -0
  106. package/src/review/output.ts +147 -0
  107. package/src/review/prompts/agent-review-wrapper.md +36 -0
  108. package/src/review/prompts/fix-findings.md +32 -0
  109. package/src/review/prompts/fix-output-schema.md +18 -0
  110. package/src/review/prompts/invalid-output-retry.md +22 -0
  111. package/src/review/prompts/output-instructions.md +14 -0
  112. package/src/review/prompts/review-output-schema.md +38 -0
  113. package/src/review/prompts/single-review.md +53 -0
  114. package/src/review/prompts/validation-review.md +30 -0
  115. package/src/review/runner.ts +128 -0
  116. package/src/review/scope.ts +353 -0
  117. package/src/review/template.ts +15 -0
  118. package/src/review/types.ts +296 -0
  119. package/src/review/validator.ts +160 -0
  120. package/src/storage/plans.ts +5 -3
  121. package/src/storage/reports.ts +50 -7
  122. package/src/storage/review-sessions.ts +117 -0
  123. package/src/text.ts +19 -0
  124. package/src/types.ts +336 -26
  125. package/src/utils/paths.ts +39 -0
  126. package/src/visual/companion.ts +5 -3
  127. package/src/visual/start-server.ts +101 -0
  128. package/src/visual/stop-server.ts +39 -0
  129. package/bin/ctx-mode-wrapper.mjs +0 -66
  130. package/src/config/profiles.ts +0 -64
  131. package/src/context-mode/installer.ts +0 -38
  132. package/src/quality/ai-review-gate.ts +0 -43
  133. package/src/quality/gate-runner.ts +0 -67
  134. package/src/quality/lsp-gate.ts +0 -24
  135. package/src/quality/test-gate.ts +0 -39
  136. package/src/visual/scripts/start-server.sh +0 -98
  137. package/src/visual/scripts/stop-server.sh +0 -21
@@ -1,5 +1,7 @@
1
1
  import type { Platform } from "../platform/types.js";
2
+ import type { DebugLogger } from "../debug/logger.js";
2
3
  import type { ResolvedModel } from "../types.js";
4
+ import type { PlanningSystemPromptOptions } from "./system-prompt.js";
3
5
  import { applyModelOverride } from "../config/model-resolver.js";
4
6
  import { listPlans, readPlanFile } from "../storage/plans.js";
5
7
 
@@ -18,6 +20,12 @@ let planCwd: string = "";
18
20
  let capturedNewSession: ((options?: any) => Promise<{ cancelled: boolean }>) | null = null;
19
21
  /** Resolved model for plan action — re-applied on execution handoff. */
20
22
  let capturedResolvedModel: ResolvedModel | null = null;
23
+ /** Guards against concurrent approval prompts from rapid agent_end events. */
24
+ let approvalPending = false;
25
+ /** Planning-system-prompt options captured from the command context at plan start. */
26
+ let planningPromptOptions: PlanningSystemPromptOptions | null = null;
27
+ /** Active debug logger for the current planning session. */
28
+ let planningDebugLogger: DebugLogger | null = null;
21
29
 
22
30
  /** Mark planning as started (called by plan command after sending steer). */
23
31
  export function startPlanTracking(
@@ -25,12 +33,25 @@ export function startPlanTracking(
25
33
  paths: any,
26
34
  newSession?: (options?: any) => Promise<{ cancelled: boolean }>,
27
35
  resolvedModel?: ResolvedModel,
28
- ): void {
36
+ promptOptions?: PlanningSystemPromptOptions,
37
+ debugLogger?: DebugLogger,
38
+ ): void {
29
39
  planningActive = true;
30
40
  planCwd = cwd;
31
41
  plansBefore = listPlans(paths, cwd);
32
42
  capturedNewSession = newSession ?? null;
33
43
  capturedResolvedModel = resolvedModel ?? null;
44
+ planningPromptOptions = promptOptions ?? null;
45
+ planningDebugLogger = debugLogger ?? null;
46
+ approvalPending = false;
47
+
48
+ planningDebugLogger?.log("planning_tracking_started", {
49
+ cwd,
50
+ existingPlanCount: plansBefore.length,
51
+ hasNewSession: Boolean(newSession),
52
+ hasResolvedModel: Boolean(resolvedModel),
53
+ promptOptions: promptOptions ?? null,
54
+ });
34
55
  }
35
56
 
36
57
  /** Cancel plan tracking (e.g., session change). */
@@ -40,6 +61,9 @@ export function cancelPlanTracking(): void {
40
61
  planCwd = "";
41
62
  capturedNewSession = null;
42
63
  capturedResolvedModel = null;
64
+ planningPromptOptions = null;
65
+ planningDebugLogger = null;
66
+ approvalPending = false;
43
67
  }
44
68
 
45
69
  /** Whether a planning session is currently active. */
@@ -47,6 +71,14 @@ export function isPlanningActive(): boolean {
47
71
  return planningActive;
48
72
  }
49
73
 
74
+ export function getPlanningPromptOptions(): PlanningSystemPromptOptions | null {
75
+ return planningPromptOptions;
76
+ }
77
+
78
+ export function getPlanningDebugLogger(): DebugLogger | null {
79
+ return planningDebugLogger;
80
+ }
81
+
50
82
  /**
51
83
  * Build the execution handoff prompt from an approved plan.
52
84
  *
@@ -93,23 +125,40 @@ async function executeApproveFlow(
93
125
  ctx: any,
94
126
  planContent: string,
95
127
  planPath: string,
96
- ): Promise<void> {
128
+ newSession: ((options?: any) => Promise<{ cancelled: boolean }>) | null,
129
+ resolvedModel: ResolvedModel | null,
130
+ debugLogger: DebugLogger | null,
131
+ ): Promise<void> {
97
132
  const prompt = buildExecutionPrompt(planContent, planPath);
133
+ debugLogger?.log("execution_handoff_started", {
134
+ planPath,
135
+ promptLength: prompt.length,
136
+ usesNewSession: Boolean(newSession),
137
+ });
98
138
 
99
139
  // Re-apply the plan model override for the execution turn.
100
140
  // The planning turn's restore hook already fired (model reverted to default).
101
141
  // We must switch again so the execution LLM turn uses the configured model.
102
- if (capturedResolvedModel) {
103
- await applyModelOverride(platform, ctx, "plan", capturedResolvedModel);
142
+ if (resolvedModel) {
143
+ await applyModelOverride(platform, ctx, "plan", resolvedModel);
144
+ debugLogger?.log("execution_handoff_model_override_applied", {
145
+ configuredAction: "plan",
146
+ });
104
147
  }
105
148
 
106
- if (capturedNewSession) {
107
- const result = await capturedNewSession();
149
+ if (newSession) {
150
+ const result = await newSession();
108
151
  if (result?.cancelled) {
152
+ debugLogger?.log("execution_handoff_new_session_cancelled", {
153
+ planPath,
154
+ });
109
155
  ctx.ui.notify("Session start cancelled. Plan saved; run /supi:plan again to execute.");
110
156
  return;
111
157
  }
112
158
  platform.sendUserMessage(prompt);
159
+ debugLogger?.log("execution_handoff_user_message_sent", {
160
+ planPath,
161
+ });
113
162
  } else {
114
163
  // Fallback: headless/SDK mode — steer in the current session.
115
164
  platform.sendMessage(
@@ -120,6 +169,9 @@ async function executeApproveFlow(
120
169
  },
121
170
  { deliverAs: "steer", triggerTurn: true },
122
171
  );
172
+ debugLogger?.log("execution_handoff_same_session_steer_sent", {
173
+ planPath,
174
+ });
123
175
  ctx.ui.notify("Plan approved — starting execution");
124
176
  }
125
177
  }
@@ -135,7 +187,7 @@ async function executeApproveFlow(
135
187
  */
136
188
  export function registerPlanApprovalHook(platform: Platform): void {
137
189
  platform.on("agent_end", async (_event: any, ctx: any) => {
138
- if (!planningActive || !ctx?.hasUI) return;
190
+ if (!planningActive || !ctx?.hasUI || approvalPending) return;
139
191
 
140
192
  // Detect newly written plan files
141
193
  const plansNow = listPlans(platform.paths, planCwd);
@@ -151,20 +203,47 @@ export function registerPlanApprovalHook(platform: Platform): void {
151
203
  // Pick the most recent new plan
152
204
  const planName = newPlans[newPlans.length - 1];
153
205
  const planContent = readPlanFile(platform.paths, planCwd, planName);
154
- if (!planContent) return;
206
+ const debugLogger = planningDebugLogger;
207
+ if (!planContent) {
208
+ debugLogger?.log("approval_flow_plan_content_missing", {
209
+ planName,
210
+ });
211
+ return;
212
+ }
155
213
 
156
214
  const planPath = `${platform.paths.dotDirDisplay}/supipowers/plans/${planName}`;
157
-
158
- const choice = await ctx.ui.select("Plan complete — what next?", [
215
+ const approvalOptions = [
159
216
  "Approve and execute",
160
217
  "Refine plan",
161
218
  "Stay in plan mode",
162
- ]);
219
+ ];
220
+
221
+ approvalPending = true;
222
+ debugLogger?.log("approval_flow_presented", {
223
+ planName,
224
+ planPath,
225
+ options: approvalOptions,
226
+ });
227
+ const choice = await ctx.ui.select("Plan complete — what next?", approvalOptions);
228
+ approvalPending = false;
229
+ debugLogger?.log("approval_flow_choice", {
230
+ choice: choice ?? null,
231
+ planPath,
232
+ });
163
233
 
164
234
  if (choice === "Approve and execute") {
165
- planningActive = false;
166
- plansBefore = [];
167
- await executeApproveFlow(platform, ctx, planContent, planPath);
235
+ const executionNewSession = capturedNewSession;
236
+ const executionModel = capturedResolvedModel;
237
+ cancelPlanTracking();
238
+ await executeApproveFlow(
239
+ platform,
240
+ ctx,
241
+ planContent,
242
+ planPath,
243
+ executionNewSession,
244
+ executionModel,
245
+ debugLogger,
246
+ );
168
247
  } else if (choice === "Refine plan") {
169
248
  // Keep planning active, let user type refinement.
170
249
  // Empty input is treated as misclick → fall through to approve.
@@ -172,16 +251,43 @@ export function registerPlanApprovalHook(platform: Platform): void {
172
251
  const refinement = await ctx.ui.input("What should be refined?");
173
252
  if (!refinement || !refinement.trim()) {
174
253
  // Misclick: treat empty input as approval
175
- planningActive = false;
176
- plansBefore = [];
177
- await executeApproveFlow(platform, ctx, planContent, planPath);
254
+ debugLogger?.log("approval_flow_empty_refinement_treated_as_approve", {
255
+ planPath,
256
+ });
257
+ const executionNewSession = capturedNewSession;
258
+ const executionModel = capturedResolvedModel;
259
+ cancelPlanTracking();
260
+ await executeApproveFlow(
261
+ platform,
262
+ ctx,
263
+ planContent,
264
+ planPath,
265
+ executionNewSession,
266
+ executionModel,
267
+ debugLogger,
268
+ );
178
269
  } else {
270
+ debugLogger?.log("approval_flow_refine_requested", {
271
+ planPath,
272
+ refinementLength: refinement.length,
273
+ });
179
274
  ctx.ui.setEditorText?.(refinement);
180
275
  }
181
- } else {
182
- // Stay in plan mode user keeps control, tracking cancelled
276
+ } else if (choice === "Stay in plan mode") {
277
+ // Explicit user choicecancel tracking, return control
278
+ debugLogger?.log("planning_tracking_cancelled", {
279
+ reason: "stay_in_plan_mode",
280
+ planPath,
281
+ });
183
282
  cancelPlanTracking();
184
283
  ctx.ui.notify("Planning complete. Plan saved but not executing.");
284
+ } else {
285
+ // Select was cancelled (returned undefined/null) — likely because a new
286
+ // agent turn started (e.g., background job completion). Don't cancel
287
+ // tracking; the next agent_end will re-prompt.
288
+ debugLogger?.log("approval_flow_choice_cancelled", {
289
+ planPath,
290
+ });
185
291
  }
186
292
  });
187
293
  }
@@ -25,7 +25,8 @@ export function buildPlanWriterPrompt(options: PlanWriterOptions): string {
25
25
  "",
26
26
  "Write the plan assuming the implementing engineer has zero context for this codebase.",
27
27
  "Document everything they need: which files to touch, complete code, testing, exact commands.",
28
- "Give them the whole plan as bite-sized tasks. DRY. YAGNI. TDD. Frequent commits.",
28
+ "Give them the whole plan as bite-sized tasks. DRY. YAGNI. TDD.",
29
+ "Keep the plan local-only: do NOT include git add, git commit, git push, or other VCS steps in the plan.",
29
30
  "",
30
31
 
31
32
  // ── Scope Check ──────────────────────────────────────────────
@@ -73,7 +74,6 @@ export function buildPlanWriterPrompt(options: PlanWriterOptions): string {
73
74
  "- Run it to verify it fails — one step",
74
75
  "- Write minimal implementation — one step",
75
76
  "- Run tests to verify it passes — one step",
76
- "- Commit — one step",
77
77
  "",
78
78
 
79
79
  // ── Task Structure ───────────────────────────────────────────
@@ -113,13 +113,6 @@ export function buildPlanWriterPrompt(options: PlanWriterOptions): string {
113
113
  "",
114
114
  "Run: `bun test tests/path/test.ts`",
115
115
  "Expected: PASS",
116
- "",
117
- "- [ ] **Step 5: Commit**",
118
- "",
119
- "```bash",
120
- "git add tests/path/test.ts src/path/file.ts",
121
- 'git commit -m "feat: add specific feature"',
122
- "```",
123
116
  "````",
124
117
  "",
125
118
 
@@ -129,9 +122,9 @@ export function buildPlanWriterPrompt(options: PlanWriterOptions): string {
129
122
  "- Exact file paths always",
130
123
  "- Complete code in plan (not 'add validation' — show the actual code)",
131
124
  "- Exact commands with expected output",
132
- "- DRY, YAGNI, TDD, frequent commits",
125
+ "- DRY, YAGNI, TDD",
126
+ "- No git commit, push, or other VCS steps in the plan",
133
127
  "",
134
-
135
128
  // ── Plan Review Loop ─────────────────────────────────────────
136
129
  "## Step 4: plan review loop",
137
130
  "",
@@ -0,0 +1,81 @@
1
+ import type { Platform } from "../platform/types.js";
2
+
3
+ /**
4
+ * Register a `planning_ask` tool — identical to the built-in `ask` tool
5
+ * but with **no timeout**. OMP's built-in ask tool applies the user's
6
+ * `ask.timeout` setting (default 30s) and only disables it for OMP's
7
+ * native plan mode. Since `/supi:plan` is not native plan mode, planning
8
+ * questions would auto-dismiss. This tool bypasses that limitation.
9
+ *
10
+ * The tool is always registered (lightweight) but the planning system
11
+ * prompt directs the model to use it only during planning sessions.
12
+ */
13
+ export function registerPlanningAskTool(platform: Platform): void {
14
+ if (!platform.registerTool) return;
15
+
16
+ platform.registerTool({
17
+ name: "planning_ask",
18
+ label: "Planning Question",
19
+ description:
20
+ "Ask the user questions during planning sessions. Use this instead of the ask tool when in /supi:plan planning mode. No timeout — the user can take as long as needed.",
21
+ promptSnippet:
22
+ "planning_ask — ask user questions during planning (no timeout, unlimited thinking time)",
23
+ parameters: {
24
+ type: "object",
25
+ properties: {
26
+ question: {
27
+ type: "string",
28
+ description: "Question text to present to the user",
29
+ },
30
+ options: {
31
+ type: "array",
32
+ items: {
33
+ type: "object",
34
+ properties: {
35
+ label: { type: "string", description: "Option label" },
36
+ },
37
+ required: ["label"],
38
+ },
39
+ description: "Available options for the user to choose from",
40
+ },
41
+ recommended: {
42
+ type: "number",
43
+ description: "Index of recommended option (0-indexed)",
44
+ },
45
+ },
46
+ required: ["question", "options"],
47
+ },
48
+ async execute(
49
+ _toolCallId: string,
50
+ params: { question: string; options: { label: string }[]; recommended?: number },
51
+ _signal: AbortSignal,
52
+ _onUpdate: unknown,
53
+ ctx: any,
54
+ ) {
55
+ const labels = params.options.map((o) => o.label);
56
+ if (labels.length === 0) {
57
+ return {
58
+ content: [{ type: "text", text: "Error: options must not be empty" }],
59
+ details: {},
60
+ };
61
+ }
62
+
63
+ const choice = await ctx.ui.select(params.question, labels, {
64
+ initialIndex: params.recommended,
65
+ // No timeout — planning decisions need unlimited time
66
+ });
67
+
68
+ const selected = choice ?? labels[params.recommended ?? 0] ?? labels[0];
69
+
70
+ return {
71
+ content: [
72
+ {
73
+ type: "text",
74
+ text: JSON.stringify({ question: params.question, selected }),
75
+ },
76
+ ],
77
+ details: { question: params.question, selected },
78
+ };
79
+ },
80
+ });
81
+ }
@@ -1,181 +1,21 @@
1
- import { buildSpecReviewerPrompt } from "./spec-reviewer.js";
2
- import { buildPlanWriterPrompt } from "./plan-writer-prompt.js";
3
-
4
1
  export interface PlanningPromptOptions {
5
2
  topic?: string;
6
- skillContent?: string;
7
- dotDirDisplay: string;
8
3
  }
9
4
 
10
5
  /**
11
- * Build the comprehensive planning prompt that encodes the full brainstorming flow.
12
- * This is the steering prompt sent to the agent when `/supi:plan` runs.
13
- *
14
- * Follows supipowers' brainstorming skill flow:
15
- * 1. Explore project context
16
- * 2. Ask clarifying questions (one at a time)
17
- * 3. Propose 2-3 approaches with trade-offs
18
- * 4. Present design section by section
19
- * 5. Write design doc to .omp/supipowers/specs/
20
- * 6. Spec review loop (dispatch reviewer sub-agent)
21
- * 7. User review gate
22
- * 8. Handoff to implementation plan
6
+ * Build the kickoff steer prompt for collaborative planning.
7
+ * The planning workflow itself lives in the planning-mode system prompt.
23
8
  */
24
9
  export function buildPlanningPrompt(options: PlanningPromptOptions): string {
25
- const { topic, skillContent, dotDirDisplay } = options;
26
-
27
- const sections: string[] = [
28
- "You are starting a collaborative planning session with the user.",
29
- "Follow this process step by step. Do NOT skip phases or combine them.",
30
- "",
31
-
32
- // ── Phase 1: Context ─────────────────────────────────────────
33
- "## Phase 1: Explore project context",
34
- "",
35
- "Before asking questions, understand the current project context:",
36
- "- Check files, docs, recent commits",
37
- "- Understand existing architecture and patterns",
38
- "- Assess scope: if the request describes multiple independent subsystems, flag it immediately and help decompose into sub-projects before proceeding",
39
- "",
40
-
41
- // ── Topic ────────────────────────────────────────────────────
42
- topic
43
- ? `The user wants to plan: ${topic}`
44
- : "Ask the user what they want to build or accomplish.",
45
- "",
46
-
47
- // ── Phase 2: Clarify ─────────────────────────────────────────
48
- "## Phase 2: Ask Clarifying Questions",
49
- "",
50
- "- Ask one question at a time — never overwhelm with multiple questions",
51
- "- Prefer **multiple choice** questions when possible, but open-ended is fine too",
52
- "- Focus on: purpose, constraints, success criteria",
53
- "- If a topic needs more exploration, break it into multiple questions",
54
- "- Continue until you have enough clarity to propose approaches",
55
- "",
56
-
57
- // ── Phase 3: Approaches ──────────────────────────────────────
58
- "## Phase 3: Propose 2-3 Approaches",
59
- "",
60
- "- Present 2-3 different approaches with trade-offs",
61
- "- Lead with your recommended option and explain why",
62
- "- Present options conversationally with your recommendation and reasoning",
63
- "- Wait for the user to choose before proceeding",
64
- "",
65
-
66
- // ── Phase 4: Design ──────────────────────────────────────────
67
- "## Phase 4: Present Design",
68
- "",
69
- "Once aligned on approach, present the design:",
70
- "- Scale each section to its complexity: a few sentences if straightforward, up to 200-300 words if nuanced",
71
- "- Cover: architecture, components, data flow, error handling, testing",
72
- "- Ask after each section whether it looks right so far",
73
- "- Design for isolation and clarity: smaller units with clear boundaries",
74
- "- Apply YAGNI ruthlessly — remove unnecessary features",
75
- "- Be ready to go back and clarify if something doesn't make sense",
76
- "",
77
-
78
- // ── Phase 5: Write Spec ──────────────────────────────────────
79
- "## Phase 5: Write Design Doc",
80
- "",
81
- "Once the user approves the design:",
82
- "- Write the validated design doc to `.omp/supipowers/specs/YYYY-MM-DD-<topic>-design.md`",
83
- "- Use clear, concise writing",
84
- "- Commit the design document to git",
85
- "",
86
-
87
- // ── Phase 6: Spec Review Loop ────────────────────────────────
88
- "## Phase 6: Spec Review Loop",
89
- "",
90
- "After writing the design doc, dispatch a spec-document-reviewer sub-agent to verify it:",
91
- "",
92
- "1. Dispatch the reviewer with this prompt:",
93
- "",
94
- "```",
95
- buildSpecReviewerPrompt("<path-to-spec-file>"),
96
- "```",
97
- "",
98
- "(Replace `<path-to-spec-file>` with the actual spec path.)",
99
- "",
100
- "2. If **Issues Found**: fix the issues, re-dispatch the reviewer",
101
- "3. Repeat until **Approved** (max 5 iterations, then surface to human for guidance)",
102
- "",
103
-
104
- // ── Phase 7: User Gate ───────────────────────────────────────
105
- "## Phase 7: User Review Gate",
106
- "",
107
- "After the spec review loop passes, ask the user to review the spec before proceeding:",
108
- "",
109
- '> "Spec written and committed to `<path>`. Please review it and let me know if you want to make any changes before we start writing out the implementation plan."',
110
- "",
111
- "Wait for the user's response. If they request changes, make them and re-run the spec review loop. Only proceed once the user approves.",
112
- "",
113
-
114
- // ── Phase 8: Handoff ─────────────────────────────────────────
115
- "## Phase 8: Transition to Implementation Plan",
116
- "",
117
- "Once the user approves the spec, write a comprehensive implementation plan.",
118
- "Follow these plan writing instructions:",
119
- "",
120
- buildPlanWriterPrompt({ specPath: "<path-to-approved-spec>", dotDirDisplay }),
121
- "",
122
- "(Replace `<path-to-approved-spec>` with the actual spec file path from Phase 5.)",
123
- "",
124
-
125
- // ── Principles ───────────────────────────────────────────────
126
- "## Key Principles",
127
- "",
128
- "- **One question at a time** — Don't overwhelm with multiple questions",
129
- "- **Multiple choice preferred** — Easier to answer than open-ended when possible",
130
- "- **YAGNI ruthlessly** — Remove unnecessary features from all designs",
131
- "- **Explore alternatives** — Always propose 2-3 approaches before settling",
132
- "- **Incremental validation** — Present design, get approval before moving on",
133
- "- **Decompose large scope** — If the request covers multiple independent subsystems, decompose into sub-projects first",
134
- "- **Design for isolation** — Smaller units with clear boundaries and well-defined interfaces",
135
- "",
136
- ];
137
-
138
- if (skillContent) {
139
- sections.push("## Additional Planning Guidelines", "", skillContent, "");
140
- }
141
-
142
- return sections.join("\n");
10
+ return options.topic
11
+ ? "Begin planning. Follow the planning phases in order."
12
+ : "Ask the user what they want to build or accomplish."
143
13
  }
144
14
 
145
15
  /**
146
- * Build the quick plan prompt that skips brainstorming.
147
- * Used when `/supi:plan --quick <description>` is invoked.
16
+ * Build the quick-plan kickoff steer prompt.
17
+ * The detailed quick-planning rules live in the planning-mode system prompt.
148
18
  */
149
- export function buildQuickPlanPrompt(
150
- description: string,
151
- skillContent?: string,
152
- ): string {
153
- const sections: string[] = [
154
- "Generate a concise implementation plan for the following task.",
155
- "Skip brainstorming — go straight to task breakdown.",
156
- "",
157
- `Task: ${description}`,
158
- "",
159
- "Format the plan as markdown with YAML frontmatter:",
160
- "",
161
- "```yaml",
162
- "---",
163
- "name: <feature-name>",
164
- "created: YYYY-MM-DD",
165
- "tags: [tag1, tag2]",
166
- "---",
167
- "```",
168
- "",
169
- "Each task should have: name, **files**, **criteria**, and **complexity** (small/medium/large).",
170
- "",
171
- "After generating the plan, save it and tell the user:",
172
- '> "Plan saved to `<path>`. Review it and approve when ready."',
173
- "Then stop and wait. The user will see an approval prompt.",
174
- ];
175
-
176
- if (skillContent) {
177
- sections.push("", "Follow these planning guidelines:", skillContent);
178
- }
179
-
180
- return sections.join("\n");
19
+ export function buildQuickPlanPrompt(description: string): string {
20
+ return `Generate a concise implementation plan for: ${description}. Skip brainstorming — go straight to task breakdown.`;
181
21
  }