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.
- package/README.md +118 -56
- package/bin/install.ts +48 -128
- package/package.json +11 -3
- package/skills/code-review/SKILL.md +137 -40
- package/skills/context-mode/SKILL.md +67 -56
- package/skills/creating-supi-agents/SKILL.md +204 -0
- package/skills/debugging/SKILL.md +86 -40
- package/skills/fix-pr/SKILL.md +96 -65
- package/skills/planning/SKILL.md +103 -46
- package/skills/qa-strategy/SKILL.md +68 -46
- package/skills/receiving-code-review/SKILL.md +60 -53
- package/skills/release/SKILL.md +111 -39
- package/skills/tdd/SKILL.md +118 -67
- package/skills/verification/SKILL.md +71 -37
- package/src/bootstrap.ts +27 -5
- package/src/commands/agents.ts +249 -0
- package/src/commands/ai-review.ts +1113 -0
- package/src/commands/config.ts +224 -95
- package/src/commands/doctor.ts +19 -13
- package/src/commands/fix-pr.ts +8 -11
- package/src/commands/generate.ts +200 -0
- package/src/commands/model-picker.ts +5 -15
- package/src/commands/model.ts +4 -5
- package/src/commands/optimize-context.ts +202 -0
- package/src/commands/plan.ts +148 -92
- package/src/commands/qa.ts +14 -23
- package/src/commands/release.ts +504 -275
- package/src/commands/review.ts +643 -86
- package/src/commands/status.ts +44 -17
- package/src/commands/supi.ts +69 -41
- package/src/commands/update.ts +57 -2
- package/src/config/defaults.ts +6 -39
- package/src/config/loader.ts +388 -40
- package/src/config/model-resolver.ts +26 -22
- package/src/config/schema.ts +113 -48
- package/src/context/analyzer.ts +61 -2
- package/src/context/optimizer.ts +199 -0
- package/src/context-mode/compressor.ts +14 -11
- package/src/context-mode/detector.ts +16 -54
- package/src/context-mode/event-extractor.ts +45 -16
- package/src/context-mode/event-store.ts +225 -16
- package/src/context-mode/hooks.ts +195 -22
- package/src/context-mode/knowledge/chunker.ts +235 -0
- package/src/context-mode/knowledge/store.ts +187 -0
- package/src/context-mode/routing.ts +12 -23
- package/src/context-mode/sandbox/executor.ts +183 -0
- package/src/context-mode/sandbox/runners.ts +40 -0
- package/src/context-mode/snapshot-builder.ts +243 -7
- package/src/context-mode/tools.ts +440 -0
- package/src/context-mode/web/fetcher.ts +117 -0
- package/src/context-mode/web/html-to-md.ts +293 -0
- package/src/debug/logger.ts +107 -0
- package/src/deps/registry.ts +0 -20
- package/src/docs/drift.ts +454 -0
- package/src/fix-pr/fetch-comments.ts +66 -0
- package/src/git/commit-msg.ts +2 -1
- package/src/git/commit.ts +123 -141
- package/src/git/conventions.ts +2 -2
- package/src/git/status.ts +4 -1
- package/src/lsp/bridge.ts +138 -12
- package/src/planning/approval-flow.ts +125 -19
- package/src/planning/plan-writer-prompt.ts +4 -11
- package/src/planning/planning-ask-tool.ts +81 -0
- package/src/planning/prompt-builder.ts +9 -169
- package/src/planning/system-prompt.ts +290 -0
- package/src/platform/omp.ts +50 -4
- package/src/platform/progress.ts +182 -0
- package/src/platform/test-utils.ts +4 -1
- package/src/platform/tui-colors.ts +30 -0
- package/src/platform/types.ts +1 -0
- package/src/qa/detect-app-type.ts +102 -0
- package/src/qa/discover-routes.ts +353 -0
- package/src/quality/ai-session.ts +96 -0
- package/src/quality/ai-setup.ts +86 -0
- package/src/quality/gates/ai-review.ts +129 -0
- package/src/quality/gates/build.ts +8 -0
- package/src/quality/gates/command.ts +150 -0
- package/src/quality/gates/format.ts +28 -0
- package/src/quality/gates/lint.ts +22 -0
- package/src/quality/gates/lsp-diagnostics.ts +84 -0
- package/src/quality/gates/test-suite.ts +8 -0
- package/src/quality/gates/typecheck.ts +22 -0
- package/src/quality/registry.ts +25 -0
- package/src/quality/review-gates.ts +33 -0
- package/src/quality/runner.ts +268 -0
- package/src/quality/schemas.ts +48 -0
- package/src/quality/setup.ts +227 -0
- package/src/release/changelog.ts +7 -3
- package/src/release/channels/custom.ts +43 -0
- package/src/release/channels/gitea.ts +35 -0
- package/src/release/channels/github.ts +35 -0
- package/src/release/channels/gitlab.ts +35 -0
- package/src/release/channels/registry.ts +52 -0
- package/src/release/channels/types.ts +27 -0
- package/src/release/detector.ts +10 -63
- package/src/release/executor.ts +61 -51
- package/src/release/prompt.ts +38 -38
- package/src/release/version.ts +129 -10
- package/src/review/agent-loader.ts +331 -0
- package/src/review/consolidator.ts +180 -0
- package/src/review/default-agents/correctness.md +72 -0
- package/src/review/default-agents/maintainability.md +64 -0
- package/src/review/default-agents/security.md +67 -0
- package/src/review/fixer.ts +219 -0
- package/src/review/multi-agent-runner.ts +135 -0
- package/src/review/output.ts +147 -0
- package/src/review/prompts/agent-review-wrapper.md +36 -0
- package/src/review/prompts/fix-findings.md +32 -0
- package/src/review/prompts/fix-output-schema.md +18 -0
- package/src/review/prompts/invalid-output-retry.md +22 -0
- package/src/review/prompts/output-instructions.md +14 -0
- package/src/review/prompts/review-output-schema.md +38 -0
- package/src/review/prompts/single-review.md +53 -0
- package/src/review/prompts/validation-review.md +30 -0
- package/src/review/runner.ts +128 -0
- package/src/review/scope.ts +353 -0
- package/src/review/template.ts +15 -0
- package/src/review/types.ts +296 -0
- package/src/review/validator.ts +160 -0
- package/src/storage/plans.ts +5 -3
- package/src/storage/reports.ts +50 -7
- package/src/storage/review-sessions.ts +117 -0
- package/src/text.ts +19 -0
- package/src/types.ts +336 -26
- package/src/utils/paths.ts +39 -0
- package/src/visual/companion.ts +5 -3
- package/src/visual/start-server.ts +101 -0
- package/src/visual/stop-server.ts +39 -0
- package/bin/ctx-mode-wrapper.mjs +0 -66
- package/src/config/profiles.ts +0 -64
- package/src/context-mode/installer.ts +0 -38
- package/src/quality/ai-review-gate.ts +0 -43
- package/src/quality/gate-runner.ts +0 -67
- package/src/quality/lsp-gate.ts +0 -24
- package/src/quality/test-gate.ts +0 -39
- package/src/visual/scripts/start-server.sh +0 -98
- package/src/visual/scripts/stop-server.sh +0 -21
package/src/commands/plan.ts
CHANGED
|
@@ -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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
|
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
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
153
|
-
|
|
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
|
-
|
|
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
|
}
|
package/src/commands/qa.ts
CHANGED
|
@@ -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(
|
|
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(
|
|
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
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
|
193
|
-
|
|
194
|
-
|
|
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,
|