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
@@ -5,16 +5,19 @@ import {
5
5
  generateVisualSessionId,
6
6
  createSessionDir,
7
7
  getScriptsDir,
8
- parseServerInfo,
9
8
  } from "../visual/companion.js";
9
+ import { startVisualServer } from "../visual/start-server.js";
10
10
  import { buildVisualInstructions } from "../visual/prompt-instructions.js";
11
11
  import { buildPlanningPrompt, buildQuickPlanPrompt } from "../planning/prompt-builder.js";
12
+ import type { PlanningSystemPromptOptions } from "../planning/system-prompt.js";
13
+ import { createDebugLogger } from "../debug/logger.js";
12
14
  import * as fs from "node:fs";
13
15
  import * as path from "node:path";
14
16
  import { modelRegistry } from "../config/model-registry-instance.js";
15
17
  import { resolveModelForAction, createModelBridge, applyModelOverride } from "../config/model-resolver.js";
16
18
  import { loadModelConfig } from "../config/model-config.js";
17
- import { startPlanTracking } from "../planning/approval-flow.js";
19
+ import { cancelPlanTracking, startPlanTracking } from "../planning/approval-flow.js";
20
+ import { stopVisualServer } from "../visual/stop-server.js";
18
21
 
19
22
  modelRegistry.register({
20
23
  id: "plan",
@@ -38,121 +41,174 @@ export function registerPlanCommand(platform: Platform): void {
38
41
  platform.registerCommand("supi:plan", {
39
42
  description: "Start collaborative planning for a feature or task",
40
43
  async handler(args: string | undefined, ctx: any) {
41
- // Resolve and apply model override early — before any logic that might fail
42
- const modelCfg = loadModelConfig(platform.paths, ctx.cwd);
43
- const bridge = createModelBridge(platform);
44
- const resolved = resolveModelForAction("plan", modelRegistry, modelCfg, bridge);
45
- await applyModelOverride(platform, ctx, "plan", resolved);
46
-
47
- const skillPath = findSkillPath("planning");
48
- let skillContent = "";
49
- if (skillPath) {
50
- try {
51
- skillContent = fs.readFileSync(skillPath, "utf-8");
52
- } catch {
53
- // Skill file not found proceed without it
44
+ const debugLogger = createDebugLogger(platform.paths, ctx, "plan");
45
+ let trackingStarted = false;
46
+ debugLogger.log("plan_command_invoked", {
47
+ args: args ?? null,
48
+ cwd: ctx.cwd ?? null,
49
+ hasUI: ctx.hasUI ?? false,
50
+ });
51
+
52
+ try {
53
+ // Resolve and apply model override early — before any logic that might fail
54
+ const modelCfg = loadModelConfig(platform.paths, ctx.cwd);
55
+ const bridge = createModelBridge(platform);
56
+ const resolved = resolveModelForAction("plan", modelRegistry, modelCfg, bridge);
57
+ await applyModelOverride(platform, ctx, "plan", resolved);
58
+ debugLogger.log("plan_model_override_applied", {
59
+ configuredAction: "plan",
60
+ });
61
+
62
+ const skillPath = findSkillPath("planning");
63
+ let skillContent = "";
64
+ if (skillPath) {
65
+ try {
66
+ skillContent = fs.readFileSync(skillPath, "utf-8");
67
+ } catch {
68
+ // Skill file not found — proceed without it
69
+ }
54
70
  }
55
- }
71
+ debugLogger.log("planning_skill_loaded", {
72
+ found: Boolean(skillPath),
73
+ skillPath: skillPath ?? null,
74
+ skillBytes: skillContent.length,
75
+ });
56
76
 
57
- const isQuick = args?.startsWith("--quick") ?? false;
58
- const quickDesc = isQuick ? args!.replace("--quick", "").trim() : "";
59
-
60
- // ── Visual companion consent ──────────────────────────────────
61
- let visualUrl: string | null = null;
62
- let visualSessionDir: string | null = null;
63
-
64
- if (ctx.hasUI && !isQuick) {
65
- const modeChoice = await ctx.ui.select(
66
- "Planning mode",
67
- [
68
- "Terminal only",
69
- "Terminal + Visual companion (opens browser)",
70
- ],
71
- { helpText: "Visual companion shows mockups and diagrams in a browser · Esc to cancel" },
72
- );
73
- if (!modeChoice) return;
74
-
75
- if (modeChoice.startsWith("Terminal + Visual")) {
76
- const sessionId = generateVisualSessionId();
77
- visualSessionDir = createSessionDir(platform.paths, ctx.cwd, sessionId);
78
- const scriptsDir = getScriptsDir();
79
-
80
- // Install server dependencies if needed
81
- const nodeModules = path.join(scriptsDir, "node_modules");
82
- if (!fs.existsSync(nodeModules)) {
83
- notifyInfo(ctx, "Installing visual companion dependencies...");
84
- const installResult = await platform.exec("npm", ["install", "--production"], { cwd: scriptsDir });
85
- if (installResult.code !== 0) {
86
- notifyError(ctx, "Failed to install visual companion dependencies", installResult.stderr);
87
- visualSessionDir = null;
88
- }
77
+ const isQuick = args?.startsWith("--quick") ?? false;
78
+ const quickDesc = isQuick ? args!.replace("--quick", "").trim() : "";
79
+ const quickMode = isQuick && quickDesc.length > 0;
80
+ const planningTopic = quickMode ? quickDesc : args || undefined;
81
+
82
+ // ── Visual companion consent ──────────────────────────────────
83
+ let visualUrl: string | null = null;
84
+ let visualSessionDir: string | null = null;
85
+
86
+ if (ctx.hasUI && !quickMode) {
87
+ const modeChoice = await ctx.ui.select(
88
+ "Planning mode",
89
+ [
90
+ "Terminal only",
91
+ "Terminal + Visual companion (opens browser)",
92
+ ],
93
+ { helpText: "Visual companion shows mockups and diagrams in a browser · Esc to cancel" },
94
+ );
95
+ if (!modeChoice) {
96
+ debugLogger.log("visual_companion_selection_cancelled");
97
+ return;
89
98
  }
90
99
 
91
- if (visualSessionDir) {
92
- // Stop any previous visual companion
93
- if (activeSessionDir) {
94
- const stopScript = path.join(scriptsDir, "stop-server.sh");
95
- await platform.exec("bash", [stopScript, activeSessionDir], { cwd: scriptsDir });
100
+ debugLogger.log("visual_companion_mode_selected", {
101
+ choice: modeChoice,
102
+ });
103
+
104
+ if (modeChoice.startsWith("Terminal + Visual")) {
105
+ const sessionId = generateVisualSessionId();
106
+ visualSessionDir = createSessionDir(platform.paths, ctx.cwd, sessionId);
107
+ const scriptsDir = getScriptsDir();
108
+
109
+ // Install server dependencies if needed
110
+ const nodeModules = path.join(scriptsDir, "node_modules");
111
+ if (!fs.existsSync(nodeModules)) {
112
+ notifyInfo(ctx, "Installing visual companion dependencies...");
113
+ const installResult = await platform.exec("npm", ["install", "--production"], { cwd: scriptsDir });
114
+ if (installResult.code !== 0) {
115
+ notifyError(ctx, "Failed to install visual companion dependencies", installResult.stderr);
116
+ debugLogger.log("visual_companion_dependency_install_failed", {
117
+ code: installResult.code,
118
+ stderr: installResult.stderr,
119
+ });
120
+ visualSessionDir = null;
121
+ }
96
122
  }
97
123
 
98
- // Start the server (pass session dir via env command since ExecOptions has no env)
99
- const startScript = path.join(scriptsDir, "start-server.sh");
100
- const startResult = await platform.exec("env", [
101
- `SUPI_VISUAL_DIR=${visualSessionDir}`,
102
- "bash",
103
- startScript,
104
- ], { cwd: scriptsDir });
124
+ if (visualSessionDir) {
125
+ // Stop any previous visual companion
126
+ if (activeSessionDir) {
127
+ stopVisualServer(activeSessionDir);
128
+ }
129
+
130
+ // Start the server in a detached cross-platform process
131
+ const serverInfo = await startVisualServer({ sessionDir: visualSessionDir });
105
132
 
106
- if (startResult.code === 0) {
107
- const serverInfo = parseServerInfo(startResult.stdout);
108
133
  if (serverInfo) {
109
134
  visualUrl = serverInfo.url;
110
135
  activeSessionDir = visualSessionDir;
111
136
  notifyInfo(ctx, "Visual companion ready", visualUrl);
137
+ debugLogger.log("visual_companion_ready", {
138
+ url: visualUrl,
139
+ sessionDir: visualSessionDir,
140
+ });
112
141
  } else {
113
- notifyError(ctx, "Visual companion started but no connection info received");
142
+ notifyError(ctx, "Visual companion failed to start");
143
+ debugLogger.log("visual_companion_start_failed", {
144
+ sessionDir: visualSessionDir,
145
+ });
114
146
  visualSessionDir = null;
115
147
  }
116
- } else {
117
- const errorMsg = startResult.stderr || startResult.stdout;
118
- notifyError(ctx, "Failed to start visual companion", errorMsg);
119
- visualSessionDir = null;
120
148
  }
121
149
  }
150
+ } else {
151
+ debugLogger.log("visual_companion_skipped", {
152
+ reason: !ctx.hasUI ? "no_ui" : "quick_mode",
153
+ });
122
154
  }
123
- }
124
155
 
125
- // ── Build prompt ──────────────────────────────────────────────
126
- let prompt: string;
127
- if (isQuick && quickDesc) {
128
- prompt = buildQuickPlanPrompt(quickDesc, skillContent || undefined);
129
- } else {
130
- prompt = buildPlanningPrompt({
131
- topic: args || undefined,
156
+ // ── Build prompt ──────────────────────────────────────────────
157
+ const planningPromptOptions: PlanningSystemPromptOptions = {
158
+ topic: planningTopic,
132
159
  skillContent: skillContent || undefined,
133
160
  dotDirDisplay: platform.paths.dotDirDisplay,
134
- });
135
- }
161
+ isQuick: quickMode,
162
+ };
136
163
 
137
- // Append visual companion instructions if active
138
- if (visualUrl && visualSessionDir) {
139
- prompt += "\n\n" + buildVisualInstructions(visualUrl, visualSessionDir);
140
- }
164
+ let prompt = quickMode
165
+ ? buildQuickPlanPrompt(quickDesc)
166
+ : buildPlanningPrompt({ topic: planningTopic });
141
167
 
168
+ // Append visual companion instructions if active
169
+ if (visualUrl && visualSessionDir) {
170
+ prompt += "\n\n" + buildVisualInstructions(visualUrl, visualSessionDir);
171
+ }
142
172
 
143
- platform.sendMessage(
144
- {
145
- customType: "supi-plan-start",
146
- content: [{ type: "text", text: prompt }],
147
- display: "none",
148
- },
149
- { deliverAs: "steer", triggerTurn: true }
150
- );
173
+ debugLogger.log("planning_kickoff_prompt_built", {
174
+ quickMode,
175
+ topic: planningTopic ?? null,
176
+ promptLength: prompt.length,
177
+ prompt,
178
+ });
151
179
 
152
- // Track planning state for the approval flow (agent_end hook)
153
- startPlanTracking(ctx.cwd, platform.paths, ctx.newSession?.bind(ctx), resolved);
180
+ // Track planning state before sending the steer message so the triggered
181
+ // planning turn sees planning mode as active during before_agent_start.
182
+ startPlanTracking(
183
+ ctx.cwd,
184
+ platform.paths,
185
+ ctx.newSession?.bind(ctx),
186
+ resolved,
187
+ planningPromptOptions,
188
+ debugLogger,
189
+ );
190
+ trackingStarted = true;
154
191
 
155
- notifyInfo(ctx, "Planning started", args ? `Topic: ${args}` : "Describe what you want to build");
192
+ platform.sendUserMessage(prompt);
193
+ debugLogger.log("planning_kickoff_steer_sent", {
194
+ deliverAs: "sendUserMessage",
195
+ triggerTurn: true,
196
+ });
197
+
198
+ notifyInfo(ctx, "Planning started", planningTopic ? `Topic: ${planningTopic}` : "Describe what you want to build");
199
+ } catch (error) {
200
+ debugLogger.log("plan_command_failed", {
201
+ message: error instanceof Error ? error.message : String(error),
202
+ stack: error instanceof Error ? error.stack ?? null : null,
203
+ });
204
+ if (trackingStarted) {
205
+ debugLogger.log("planning_tracking_cancelled", {
206
+ reason: "plan_command_failed_before_turn",
207
+ });
208
+ cancelPlanTracking();
209
+ }
210
+ throw error;
211
+ }
156
212
  },
157
213
  });
158
214
  }
@@ -1,6 +1,7 @@
1
1
  import type { Platform } from "../platform/types.js";
2
2
  import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
+ import { moduleDir, toBashPath } from "../utils/paths.js";
4
5
  import { notifyInfo } from "../notifications/renderer.js";
5
6
  import { loadE2eQaConfig, saveE2eQaConfig, DEFAULT_E2E_QA_CONFIG } from "../qa/config.js";
6
7
  import { loadE2eMatrix } from "../qa/matrix.js";
@@ -11,6 +12,8 @@ import type { E2eQaConfig, AppType, E2eRegression } from "../qa/types.js";
11
12
  import { modelRegistry } from "../config/model-registry-instance.js";
12
13
  import { resolveModelForAction, createModelBridge, applyModelOverride } from "../config/model-resolver.js";
13
14
  import { loadModelConfig } from "../config/model-config.js";
15
+ import { detectAppType } from "../qa/detect-app-type.js";
16
+ import { discoverRoutes } from "../qa/discover-routes.js";
14
17
 
15
18
  modelRegistry.register({
16
19
  id: "qa",
@@ -20,13 +23,13 @@ modelRegistry.register({
20
23
  });
21
24
 
22
25
  function getScriptsDir(): string {
23
- return path.join(path.dirname(new URL(import.meta.url).pathname), "..", "qa", "scripts");
26
+ return toBashPath(path.join(moduleDir(import.meta.url), "..", "qa", "scripts"));
24
27
  }
25
28
 
26
29
  function findSkillPath(skillName: string): string | null {
27
30
  const candidates = [
28
31
  path.join(process.cwd(), "skills", skillName, "SKILL.md"),
29
- path.join(path.dirname(new URL(import.meta.url).pathname), "..", "..", "skills", skillName, "SKILL.md"),
32
+ path.join(moduleDir(import.meta.url), "..", "..", "skills", skillName, "SKILL.md"),
30
33
  ];
31
34
  for (const p of candidates) {
32
35
  if (fs.existsSync(p)) return p;
@@ -127,17 +130,10 @@ export function registerQaCommand(platform: Platform): void {
127
130
  let detectedPort: number | null = null;
128
131
 
129
132
  try {
130
- const detectResult = await platform.exec("bash", [
131
- path.join(scriptsDir, "detect-app-type.sh"),
132
- ctx.cwd,
133
- ], { cwd: ctx.cwd });
134
-
135
- if (detectResult.code === 0) {
136
- const detected = JSON.parse(detectResult.stdout.trim());
137
- detectedType = detected.type;
138
- detectedDevCommand = detected.devCommand;
139
- detectedPort = detected.port;
140
- }
133
+ const detected = detectAppType(ctx.cwd);
134
+ detectedType = detected.type;
135
+ detectedDevCommand = detected.devCommand;
136
+ detectedPort = detected.port;
141
137
  } catch { /* proceed without detection */ }
142
138
 
143
139
  // ── Step 2: Load or create config ────────────────────────────────
@@ -189,14 +185,9 @@ export function registerQaCommand(platform: Platform): void {
189
185
  // ── Step 4: Route discovery ──────────────────────────────────────
190
186
  let discoveredRoutes = "";
191
187
  try {
192
- const routeResult = await platform.exec("bash", [
193
- path.join(scriptsDir, "discover-routes.sh"),
194
- ctx.cwd,
195
- config.app.type,
196
- ], { cwd: ctx.cwd });
197
-
198
- if (routeResult.code === 0 && routeResult.stdout.trim()) {
199
- discoveredRoutes = routeResult.stdout.trim();
188
+ const routes = discoverRoutes(ctx.cwd, config.app.type);
189
+ if (routes.length > 0) {
190
+ discoveredRoutes = routes.map((r) => JSON.stringify(r)).join("\n");
200
191
  }
201
192
  } catch { /* agent will discover routes manually */ }
202
193
 
@@ -210,7 +201,7 @@ export function registerQaCommand(platform: Platform): void {
210
201
 
211
202
  // ── Step 6: Create session ───────────────────────────────────────
212
203
  const ledger = createNewE2eSession(platform.paths, ctx.cwd, config);
213
- const sessionDir = getSessionDir(platform.paths, ctx.cwd, ledger.id);
204
+ const sessionDir = toBashPath(getSessionDir(platform.paths, ctx.cwd, ledger.id));
214
205
 
215
206
  // ── Step 7: Load skill ───────────────────────────────────────────
216
207
  let skillContent = "";
@@ -225,7 +216,7 @@ export function registerQaCommand(platform: Platform): void {
225
216
  const routeCount = discoveredRoutes.split("\n").filter(Boolean).length;
226
217
 
227
218
  const prompt = buildE2eOrchestratorPrompt({
228
- cwd: ctx.cwd,
219
+ cwd: toBashPath(ctx.cwd),
229
220
  appType: config.app,
230
221
  sessionDir,
231
222
  scriptsDir,