@wrongstack/cli 0.66.13 → 0.73.1

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/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ import { color, writeErr, renderProgress, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, DefaultTaskStore, TaskTracker, renderTaskGraph, DefaultSecretScrubber, atomicWrite, DefaultPathResolver, TOKENS, mergeCustomModelDefs, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, resolveSessionLoggingConfig, createSessionEventBridge, HookRegistry, HookRunner, SlashCommandRegistry, BrainDecisionQueue, ObservableBrainArbiter, HumanEscalatingBrainArbiter, DefaultBrainArbiter, createDelegateTool, FLEET_ROSTER, createMcpControlTool, SpecVersioning, DefaultLogger, DefaultModelsRegistry, isStdinTTY, writeOut, runProviderWithRetry, ReplayLogStore, ReplayProviderRunner, ProviderRegistry, InMemoryMetricsSink, wireMetricsToEvents, DefaultHealthRegistry, startMetricsServer, RecoveryLock, DefaultAttachmentStore, QueueStore, Context, loadTodosCheckpoint, attachTodosCheckpoint, loadDirectorState, loadPlan, createDefaultPipelines, resolveContextWindowPolicy, resolveAuditLevel, AutoCompactionMiddleware, estimateRequestTokensCalibrated, Agent, loadPlugins, FleetManager, makeDirectorSessionFactory, Director, makeFleetEmitTool, makeFleetStatusTool, resolveModelMatrix, DEFAULT_SUBAGENT_BASELINE, AutoApprovePermissionPolicy, PhaseStore, AutoPhasePlanner, PhaseGraphBuilder, WorktreeManager, PhaseOrchestrator, makeLLMClassifier, ParallelEternalEngine, EternalAutonomyEngine, allServers as allServers$1, bootConfig as bootConfig$1, setRawMode, DefaultSessionReader, resolveWstackPaths, ToolAuditLog, DefaultSessionRewinder, DefaultSessionStore, DefaultPluginAPI, ProviderError, makeAgentSubagentRunner, NULL_FLEET_BUS, buildChildEnv, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, AGENTS_BY_PHASE, dispatchAgent, formatTodosList, SessionRecovery, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, pendingBtwCount, setBtwNote, MATRIX_PHASE_KEYS, AGENT_CATALOG, matrixKeyKind, onResize, ERROR_CODES, decryptConfigSecrets as decryptConfigSecrets$1, encryptConfigSecrets as encryptConfigSecrets$1, InputBuilder, FsError } from '@wrongstack/core';
2
3
  import * as path8 from 'path';
3
4
  import { join } from 'path';
4
- import * as fsp3 from 'fs/promises';
5
- import { color, writeErr, DefaultTaskStore, TaskTracker, renderProgress, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, renderTaskGraph, SpecVersioning, DefaultSecretScrubber, atomicWrite, DefaultPathResolver, TOKENS, mergeCustomModelDefs, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, resolveSessionLoggingConfig, createSessionEventBridge, HookRegistry, HookRunner, SlashCommandRegistry, BrainDecisionQueue, ObservableBrainArbiter, HumanEscalatingBrainArbiter, DefaultBrainArbiter, createDelegateTool, FLEET_ROSTER, createMcpControlTool, DefaultLogger, DefaultModelsRegistry, isStdinTTY, writeOut, runProviderWithRetry, ReplayLogStore, ReplayProviderRunner, ProviderRegistry, InMemoryMetricsSink, wireMetricsToEvents, DefaultHealthRegistry, startMetricsServer, RecoveryLock, DefaultAttachmentStore, QueueStore, Context, loadTodosCheckpoint, attachTodosCheckpoint, loadDirectorState, loadPlan, createDefaultPipelines, resolveContextWindowPolicy, resolveAuditLevel, AutoCompactionMiddleware, estimateRequestTokensCalibrated, Agent, loadPlugins, FleetManager, makeDirectorSessionFactory, Director, makeFleetEmitTool, makeFleetStatusTool, resolveModelMatrix, AutoApprovePermissionPolicy, PhaseStore, AutoPhasePlanner, PhaseGraphBuilder, WorktreeManager, PhaseOrchestrator, makeLLMClassifier, ParallelEternalEngine, EternalAutonomyEngine, allServers as allServers$1, bootConfig as bootConfig$1, setRawMode, DefaultSessionReader, resolveWstackPaths, ToolAuditLog, DefaultSessionRewinder, DefaultSessionStore, DefaultPluginAPI, ProviderError, makeAgentSubagentRunner, NULL_FLEET_BUS, buildChildEnv, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, AGENTS_BY_PHASE, dispatchAgent, formatTodosList, SessionRecovery, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, pendingBtwCount, setBtwNote, MATRIX_PHASE_KEYS, AGENT_CATALOG, matrixKeyKind, onResize, ERROR_CODES, decryptConfigSecrets as decryptConfigSecrets$1, encryptConfigSecrets as encryptConfigSecrets$1, InputBuilder, FsError } from '@wrongstack/core';
5
+ import * as fsp4 from 'fs/promises';
6
6
  import { createRequire } from 'module';
7
7
  import * as os2 from 'os';
8
8
  import os2__default from 'os';
@@ -14,7 +14,7 @@ import { WebSocketServer, WebSocket } from 'ws';
14
14
  import { MCPRegistry, MCPServer, serveHttp, serveStdio } from '@wrongstack/mcp';
15
15
  import { capabilitiesFor, buildProviderFactoriesFromRegistry, makeProviderFromConfig } from '@wrongstack/providers';
16
16
  import { createDefaultContainer, routeImagesForModel, readClipboardImage } from '@wrongstack/runtime';
17
- import { builtinToolsPack, rememberTool, forgetTool } from '@wrongstack/tools';
17
+ import { builtinToolsPack, rememberTool, forgetTool, runStartupIndex, isIndexableFile, enqueueReindex, cancelPendingReindexes } from '@wrongstack/tools';
18
18
  import { fileURLToPath } from 'url';
19
19
  import * as readline from 'readline';
20
20
  import * as fs12 from 'fs';
@@ -31,12 +31,6 @@ var __defProp = Object.defineProperty;
31
31
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
32
32
  var __getOwnPropNames = Object.getOwnPropertyNames;
33
33
  var __hasOwnProp = Object.prototype.hasOwnProperty;
34
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
35
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
36
- }) : x)(function(x) {
37
- if (typeof require !== "undefined") return require.apply(this, arguments);
38
- throw Error('Dynamic require of "' + x + '" is not supported');
39
- });
40
34
  var __esm = (fn, res) => function __init() {
41
35
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
42
36
  };
@@ -53,32 +47,8 @@ var __copyProps = (to, from, except, desc) => {
53
47
  return to;
54
48
  };
55
49
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
56
-
57
- // src/slash-commands/sdd.ts
58
- var sdd_exports = {};
59
- __export(sdd_exports, {
60
- advanceToNextTask: () => advanceToNextTask,
61
- autoDetectTaskCompletion: () => autoDetectTaskCompletion,
62
- buildSddCommand: () => buildSddCommand,
63
- getActiveBuilder: () => getActiveBuilder,
64
- getActiveSDDContext: () => getActiveSDDContext,
65
- getActiveSDDPhase: () => getActiveSDDPhase,
66
- getCurrentExecutingContext: () => getCurrentExecutingContext,
67
- getCurrentTask: () => getCurrentTask,
68
- getTaskGraphId: () => getTaskGraphId,
69
- getTaskListText: () => getTaskListText,
70
- getTaskProgress: () => getTaskProgress,
71
- getTaskTracker: () => getTaskTracker,
72
- markTaskCompleted: () => markTaskCompleted,
73
- renderTaskListWithProgress: () => renderTaskListWithProgress,
74
- trySaveImplementationPlan: () => trySaveImplementationPlan,
75
- trySaveSpecFromAIOutput: () => trySaveSpecFromAIOutput,
76
- trySaveTasksFromAIOutput: () => trySaveTasksFromAIOutput
77
- });
78
50
  function getSessionState(ctx) {
79
- if (!ctx) {
80
- return sddState;
81
- }
51
+ if (!ctx) return sddState;
82
52
  let state = ctx.meta[SDD_META_KEY];
83
53
  if (!state) {
84
54
  state = new SDDState();
@@ -86,19 +56,103 @@ function getSessionState(ctx) {
86
56
  }
87
57
  return state;
88
58
  }
89
- function getActiveSDDContext() {
90
- return sddState.getContext();
91
- }
92
- function getActiveSDDPhase() {
93
- return sddState.getPhase();
59
+ var SDD_META_KEY, SDDState, sddState;
60
+ var init_state = __esm({
61
+ "src/slash-commands/sdd/state.ts"() {
62
+ SDD_META_KEY = "sdd.state";
63
+ SDDState = class {
64
+ builder = null;
65
+ taskStore = null;
66
+ taskTracker = null;
67
+ taskGraphId = null;
68
+ sessionStartTime = Date.now();
69
+ phaseStartTime = Date.now();
70
+ versioning = null;
71
+ getBuilder() {
72
+ return this.builder;
73
+ }
74
+ setBuilder(b) {
75
+ this.builder = b;
76
+ }
77
+ getTaskStore() {
78
+ return this.taskStore;
79
+ }
80
+ setTaskStore(s) {
81
+ this.taskStore = s;
82
+ }
83
+ getTaskTracker() {
84
+ return this.taskTracker;
85
+ }
86
+ setTaskTracker(t) {
87
+ this.taskTracker = t;
88
+ }
89
+ getTaskGraphId() {
90
+ return this.taskGraphId;
91
+ }
92
+ setTaskGraphId(id) {
93
+ this.taskGraphId = id;
94
+ }
95
+ getSessionStartTime() {
96
+ return this.sessionStartTime;
97
+ }
98
+ setSessionStartTime(t) {
99
+ this.sessionStartTime = t;
100
+ }
101
+ setPhaseStartTime(t) {
102
+ this.phaseStartTime = t;
103
+ }
104
+ getPhaseStartTime() {
105
+ return this.phaseStartTime;
106
+ }
107
+ getSessionElapsed() {
108
+ return Date.now() - this.sessionStartTime;
109
+ }
110
+ getPhaseElapsed() {
111
+ return Date.now() - this.phaseStartTime;
112
+ }
113
+ getVersioning() {
114
+ if (this.versioning === null) this.versioning = new SpecVersioning();
115
+ return this.versioning;
116
+ }
117
+ clearTaskState() {
118
+ this.taskStore = null;
119
+ this.taskTracker = null;
120
+ this.taskGraphId = null;
121
+ }
122
+ getContext() {
123
+ if (!this.builder) return null;
124
+ const session = this.builder.getSession();
125
+ if (session.phase === "done") return null;
126
+ return this.builder.getAIPrompt();
127
+ }
128
+ getPhase() {
129
+ return this.builder?.getPhase() ?? null;
130
+ }
131
+ };
132
+ sddState = new SDDState();
133
+ }
134
+ });
135
+ function formatElapsed(ms) {
136
+ if (ms < 1e3) return `${ms}ms`;
137
+ const s = Math.floor(ms / 1e3);
138
+ if (s < 60) return `${s}s`;
139
+ const m = Math.floor(s / 60);
140
+ const remS = s % 60;
141
+ if (m < 60) return remS > 0 ? `${m}m ${remS}s` : `${m}m`;
142
+ const h = Math.floor(m / 60);
143
+ const remM = m % 60;
144
+ return `${h}h ${remM}m`;
94
145
  }
95
- async function trySaveSpecFromAIOutput(aiOutput) {
96
- const builder = sddState.getBuilder();
97
- if (!builder) return false;
98
- const spec = builder.tryParseSpecFromOutput(aiOutput);
99
- if (!spec) return false;
100
- builder.setSpec(spec);
101
- return true;
146
+ function addTaskToTracker(tracker, task) {
147
+ tracker.addNode({
148
+ title: String(task.title),
149
+ description: String(task.description ?? ""),
150
+ type: ["feature", "bugfix", "refactor", "docs", "test", "chore"].includes(String(task.type)) ? String(task.type) : "feature",
151
+ priority: ["critical", "high", "medium", "low"].includes(String(task.priority)) ? String(task.priority) : "medium",
152
+ status: "pending",
153
+ estimateHours: Number(task.estimateHours) || 2,
154
+ tags: Array.isArray(task.tags) ? task.tags.map(String) : []
155
+ });
102
156
  }
103
157
  async function trySaveTasksFromAIOutput(aiOutput) {
104
158
  const builder = sddState.getBuilder();
@@ -118,45 +172,13 @@ async function trySaveTasksFromAIOutput(aiOutput) {
118
172
  if (validTasks.length === 0) return false;
119
173
  const existingTracker = sddState.getTaskTracker();
120
174
  if (existingTracker) {
121
- for (const task of validTasks) {
122
- const title = String(task.title);
123
- const description = String(task.description ?? "");
124
- const type = ["feature", "bugfix", "refactor", "docs", "test", "chore"].includes(String(task.type)) ? String(task.type) : "feature";
125
- const priority = ["critical", "high", "medium", "low"].includes(String(task.priority)) ? String(task.priority) : "medium";
126
- const estimateHours = Number(task.estimateHours) || 2;
127
- const tags = Array.isArray(task.tags) ? task.tags.map(String) : [];
128
- existingTracker.addNode({
129
- title,
130
- description,
131
- type,
132
- priority,
133
- status: "pending",
134
- estimateHours,
135
- tags
136
- });
137
- }
175
+ for (const task of validTasks) addTaskToTracker(existingTracker, task);
138
176
  return true;
139
177
  }
140
178
  const store = new DefaultTaskStore();
141
179
  const tracker = new TaskTracker({ store });
142
180
  const graph = await tracker.createGraph(session.spec.id, session.spec.title);
143
- for (const task of validTasks) {
144
- const title = String(task.title);
145
- const description = String(task.description ?? "");
146
- const type = ["feature", "bugfix", "refactor", "docs", "test", "chore"].includes(String(task.type)) ? String(task.type) : "feature";
147
- const priority = ["critical", "high", "medium", "low"].includes(String(task.priority)) ? String(task.priority) : "medium";
148
- const estimateHours = Number(task.estimateHours) || 2;
149
- const tags = Array.isArray(task.tags) ? task.tags.map(String) : [];
150
- tracker.addNode({
151
- title,
152
- description,
153
- type,
154
- priority,
155
- status: "pending",
156
- estimateHours,
157
- tags
158
- });
159
- }
181
+ for (const task of validTasks) addTaskToTracker(tracker, task);
160
182
  sddState.setTaskStore(store);
161
183
  sddState.setTaskTracker(tracker);
162
184
  sddState.setTaskGraphId(graph.id);
@@ -174,15 +196,7 @@ function getCurrentTask() {
174
196
  const nodes = tracker.getAllNodes({ status: ["in_progress"] });
175
197
  if (nodes.length === 0) return null;
176
198
  const n = nodes[0];
177
- return {
178
- id: n.id,
179
- title: n.title,
180
- description: n.description,
181
- priority: n.priority,
182
- estimateHours: n.estimateHours ?? 0,
183
- tags: n.tags ?? [],
184
- startedAt: n.startedAt
185
- };
199
+ return { id: n.id, title: n.title, description: n.description, priority: n.priority, estimateHours: n.estimateHours ?? 0, tags: n.tags ?? [], startedAt: n.startedAt };
186
200
  }
187
201
  function advanceToNextTask() {
188
202
  const tracker = sddState.getTaskTracker();
@@ -196,27 +210,15 @@ function advanceToNextTask() {
196
210
  }
197
211
  return false;
198
212
  }
199
- function formatElapsed(ms) {
200
- if (ms < 1e3) return `${ms}ms`;
201
- const s = Math.floor(ms / 1e3);
202
- if (s < 60) return `${s}s`;
203
- const m = Math.floor(s / 60);
204
- const remS = s % 60;
205
- if (m < 60) return remS > 0 ? `${m}m ${remS}s` : `${m}m`;
206
- const h = Math.floor(m / 60);
207
- const remM = m % 60;
208
- return `${h}h ${remM}m`;
209
- }
210
213
  function getTaskListText() {
211
214
  const tracker = sddState.getTaskTracker();
212
215
  if (!tracker) return null;
213
216
  const nodes = tracker.getAllNodes();
214
217
  if (nodes.length === 0) return null;
215
- const lines = nodes.map((n, i) => {
218
+ return nodes.map((n, i) => {
216
219
  const status = n.status === "completed" ? "\u2705" : n.status === "in_progress" ? "\u{1F504}" : "\u23F3";
217
220
  return `${i + 1}. ${status} [${n.priority}] ${n.title}`;
218
- });
219
- return lines.join("\n");
221
+ }).join("\n");
220
222
  }
221
223
  function renderTaskListWithProgress() {
222
224
  const tracker = sddState.getTaskTracker();
@@ -225,20 +227,8 @@ function renderTaskListWithProgress() {
225
227
  if (nodes.length === 0) return null;
226
228
  const progress = tracker.getProgress();
227
229
  const phase = sddState.getPhase();
228
- const phaseLabel = {
229
- questioning: "\u2753 Questioning",
230
- spec_review: "\u{1F4CB} Spec Review",
231
- implementation: "\u{1F3D7}\uFE0F Implementation",
232
- task_review: "\u{1F4DD} Task Review",
233
- executing: "\u26A1 Executing",
234
- done: "\u2705 Done"
235
- };
236
- const lines = [
237
- `**${phaseLabel[phase ?? ""] ?? phase} \u2014 Task Status**`,
238
- "",
239
- renderProgress(progress),
240
- ""
241
- ];
230
+ const phaseLabel = { questioning: "\u2753 Questioning", spec_review: "\u{1F4CB} Spec Review", implementation: "\u{1F3D7}\uFE0F Implementation", task_review: "\u{1F4DD} Task Review", executing: "\u26A1 Executing", done: "\u2705 Done" };
231
+ const lines = [`**${phaseLabel[phase ?? ""] ?? phase} \u2014 Task Status**`, "", renderProgress(progress), ""];
242
232
  const sorted = [...nodes].sort((a, b) => {
243
233
  const order = { in_progress: 0, pending: 1, review: 2, blocked: 3, failed: 4, completed: 5 };
244
234
  return (order[a.status] ?? 6) - (order[b.status] ?? 6);
@@ -248,9 +238,7 @@ function renderTaskListWithProgress() {
248
238
  const status = n.status === "completed" ? "\u2705" : n.status === "in_progress" ? "\u{1F504}" : n.status === "failed" ? "\u274C" : n.status === "blocked" ? "\u{1F6AB}" : n.status === "review" ? "\u{1F441}" : "\u23F3";
249
239
  const title = n.title.length > 50 ? n.title.slice(0, 49) + "\u2026" : n.title;
250
240
  let elapsed = "";
251
- if (n.status === "in_progress" && n.startedAt) {
252
- elapsed = ` \xB7 ${formatElapsed(Date.now() - n.startedAt)}`;
253
- }
241
+ if (n.status === "in_progress" && n.startedAt) elapsed = ` \xB7 ${formatElapsed(Date.now() - n.startedAt)}`;
254
242
  lines.push(`${i + 1}. ${status} ${title}${elapsed}`);
255
243
  }
256
244
  return lines.join("\n");
@@ -274,13 +262,114 @@ function markTaskCompleted(taskTitle) {
274
262
  const tracker = sddState.getTaskTracker();
275
263
  if (!tracker) return false;
276
264
  const nodes = tracker.getAllNodes({ status: ["pending", "in_progress"] });
277
- const match = nodes.find(
278
- (n) => n.title.toLowerCase().includes(taskTitle.toLowerCase()) || taskTitle.toLowerCase().includes(n.title.toLowerCase())
279
- );
265
+ const match = nodes.find((n) => n.title.toLowerCase().includes(taskTitle.toLowerCase()) || taskTitle.toLowerCase().includes(n.title.toLowerCase()));
280
266
  if (!match) return false;
281
267
  tracker.updateNodeStatus(match.id, "completed");
282
268
  return true;
283
269
  }
270
+ function getTaskGraphId() {
271
+ return sddState.getTaskGraphId();
272
+ }
273
+ function getTaskTrackerExport() {
274
+ return sddState.getTaskTracker();
275
+ }
276
+ var init_task_manager = __esm({
277
+ "src/slash-commands/sdd/task-manager.ts"() {
278
+ init_state();
279
+ }
280
+ });
281
+ function getActiveBuilder() {
282
+ return sddState.getBuilder();
283
+ }
284
+ function getActiveSDDContext() {
285
+ return sddState.getContext();
286
+ }
287
+ function getActiveSDDPhase() {
288
+ return sddState.getPhase();
289
+ }
290
+ async function findSpec(store, idOrTitle) {
291
+ if (!idOrTitle) return null;
292
+ const byId = await store.load(idOrTitle);
293
+ if (byId) return byId;
294
+ const all = await store.list();
295
+ const match = all.find(
296
+ (e) => e.id.startsWith(idOrTitle) || e.title.toLowerCase().includes(idOrTitle.toLowerCase())
297
+ );
298
+ if (match) return store.load(match.id);
299
+ return null;
300
+ }
301
+ async function gatherProjectContext2(projectRoot) {
302
+ const parts = [];
303
+ try {
304
+ const pkgPath = path8.join(projectRoot, "package.json");
305
+ const pkgRaw = await fsp4.readFile(pkgPath, "utf8");
306
+ const pkg = JSON.parse(pkgRaw);
307
+ parts.push(`Project: ${String(pkg.name ?? "unknown")}`);
308
+ parts.push(`Description: ${String(pkg.description ?? "none")}`);
309
+ if (pkg.dependencies) {
310
+ const deps = Object.keys(pkg.dependencies);
311
+ parts.push(`Dependencies: ${deps.slice(0, 20).join(", ")}${deps.length > 20 ? "..." : ""}`);
312
+ }
313
+ if (pkg.devDependencies) {
314
+ const devDeps = Object.keys(pkg.devDependencies);
315
+ parts.push(`Dev Dependencies: ${devDeps.slice(0, 15).join(", ")}${devDeps.length > 15 ? "..." : ""}`);
316
+ }
317
+ } catch {
318
+ }
319
+ try {
320
+ const tsconfigPath = path8.join(projectRoot, "tsconfig.json");
321
+ await fsp4.access(tsconfigPath);
322
+ parts.push("Language: TypeScript");
323
+ } catch {
324
+ }
325
+ try {
326
+ const srcDir = path8.join(projectRoot, "src");
327
+ const entries = await fsp4.readdir(srcDir, { withFileTypes: true });
328
+ const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
329
+ if (dirs.length > 0) parts.push(`Source structure: src/${dirs.join(", src/")}`);
330
+ } catch {
331
+ }
332
+ return parts.join("\n");
333
+ }
334
+ var init_project_context = __esm({
335
+ "src/slash-commands/sdd/project-context.ts"() {
336
+ init_state();
337
+ }
338
+ });
339
+
340
+ // src/slash-commands/sdd/spec-detection.ts
341
+ function isExplanatoryText(text) {
342
+ const lower = text.toLowerCase();
343
+ return lower.startsWith("i'") || lower.startsWith("i will") || lower.startsWith("let me") || lower.startsWith("here's my") || lower.startsWith("here is my") || lower.startsWith("i'm going to") || lower.startsWith("first, let me") || lower.startsWith("sure") || lower.startsWith("of course") || lower.startsWith("okay") || lower.startsWith("ok,") || lower.startsWith("sounds good") || lower.startsWith("no problem") || text.split("\n").length < 3 && !text.includes(".");
344
+ }
345
+ async function trySaveSpecFromAIOutput(aiOutput) {
346
+ const builder = sddState.getBuilder();
347
+ if (!builder) return false;
348
+ const spec = builder.tryParseSpecFromOutput(aiOutput);
349
+ if (!spec) return false;
350
+ builder.setSpec(spec);
351
+ return true;
352
+ }
353
+ function trySaveImplementationPlan(aiOutput) {
354
+ const builder = sddState.getBuilder();
355
+ if (!builder) return false;
356
+ const session = builder.getSession();
357
+ if (session.phase !== "implementation") return false;
358
+ const current = session.implementation ?? "";
359
+ const jsonMatch = aiOutput.match(/```json\s*\[/);
360
+ if (jsonMatch?.index && jsonMatch.index > 0) {
361
+ const plan = aiOutput.substring(0, jsonMatch.index).trim();
362
+ if (plan.length > 50 && plan !== current && !isExplanatoryText(plan)) {
363
+ builder.setImplementation(plan);
364
+ return true;
365
+ }
366
+ }
367
+ if (aiOutput.length > 100 && !aiOutput.includes("```json") && aiOutput !== current && !isExplanatoryText(aiOutput)) {
368
+ builder.setImplementation(aiOutput.trim());
369
+ return true;
370
+ }
371
+ return false;
372
+ }
284
373
  function autoDetectTaskCompletion(aiOutput) {
285
374
  const tracker = sddState.getTaskTracker();
286
375
  if (!tracker) return 0;
@@ -301,9 +390,7 @@ function autoDetectTaskCompletion(aiOutput) {
301
390
  completed++;
302
391
  }
303
392
  } else {
304
- const match = pending.find(
305
- (n) => n.title.toLowerCase().includes(target.toLowerCase()) || target.toLowerCase().includes(n.title.toLowerCase())
306
- );
393
+ const match = pending.find((n) => n.title.toLowerCase().includes(target.toLowerCase()) || target.toLowerCase().includes(n.title.toLowerCase()));
307
394
  if (match && match.status !== "completed") {
308
395
  tracker.updateNodeStatus(match.id, "completed");
309
396
  completed++;
@@ -314,9 +401,7 @@ function autoDetectTaskCompletion(aiOutput) {
314
401
  const checkmarkMatch = trimmed.match(/^✅\s*(?:Task:\s*)?(.+)/i);
315
402
  if (checkmarkMatch?.[1]) {
316
403
  const title = checkmarkMatch[1].trim();
317
- const match = pending.find(
318
- (n) => n.title.toLowerCase().includes(title.toLowerCase()) || title.toLowerCase().includes(n.title.toLowerCase())
319
- );
404
+ const match = pending.find((n) => n.title.toLowerCase().includes(title.toLowerCase()) || title.toLowerCase().includes(n.title.toLowerCase()));
320
405
  if (match && match.status !== "completed") {
321
406
  tracker.updateNodeStatus(match.id, "completed");
322
407
  completed++;
@@ -338,9 +423,7 @@ function autoDetectTaskCompletion(aiOutput) {
338
423
  const completedMatch = trimmed.match(/^(?:Completed|Done|Finished)\s*[:]\s*(.+)/i);
339
424
  if (completedMatch?.[1]) {
340
425
  const title = completedMatch[1].trim();
341
- const match = pending.find(
342
- (n) => n.title.toLowerCase().includes(title.toLowerCase()) || title.toLowerCase().includes(n.title.toLowerCase())
343
- );
426
+ const match = pending.find((n) => n.title.toLowerCase().includes(title.toLowerCase()) || title.toLowerCase().includes(n.title.toLowerCase()));
344
427
  if (match && match.status !== "completed") {
345
428
  tracker.updateNodeStatus(match.id, "completed");
346
429
  completed++;
@@ -349,33 +432,132 @@ function autoDetectTaskCompletion(aiOutput) {
349
432
  }
350
433
  return completed;
351
434
  }
352
- function trySaveImplementationPlan(aiOutput) {
353
- const builder = sddState.getBuilder();
354
- if (!builder) return false;
355
- const session = builder.getSession();
356
- if (session.phase !== "implementation") return false;
357
- const current = session.implementation ?? "";
358
- const jsonMatch = aiOutput.match(/```json\s*\[/);
359
- if (jsonMatch?.index && jsonMatch.index > 0) {
360
- const plan = aiOutput.substring(0, jsonMatch.index).trim();
361
- if (plan.length > 50 && plan !== current && !isExplanatoryText(plan)) {
362
- builder.setImplementation(plan);
363
- return true;
364
- }
365
- }
366
- if (aiOutput.length > 100 && !aiOutput.includes("```json") && aiOutput !== current && !isExplanatoryText(aiOutput)) {
367
- builder.setImplementation(aiOutput.trim());
368
- return true;
435
+ var init_spec_detection = __esm({
436
+ "src/slash-commands/sdd/spec-detection.ts"() {
437
+ init_state();
438
+ }
439
+ });
440
+
441
+ // src/slash-commands/sdd/rendering.ts
442
+ function sddHelp() {
443
+ return [
444
+ "",
445
+ "\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557",
446
+ "\u2551 \u{1F680} SDD \u2014 AI-Driven Spec Builder \u2551",
447
+ "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D",
448
+ "",
449
+ " \u250C\u2500 \u{1F195} Start \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
450
+ " \u2502 /sdd new [title] Start a new spec session \u2502",
451
+ " \u2502 /sdd new --force Start fresh (skip resume check) \u2502",
452
+ " \u2502 /sdd resume Resume a saved session \u2502",
453
+ " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
454
+ "",
455
+ " \u250C\u2500 \u{1F504} Flow \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
456
+ " \u2502 /sdd approve Approve current phase \u2502",
457
+ " \u2502 /sdd spec Show current session's spec \u2502",
458
+ " \u2502 /sdd plan Show implementation plan \u2502",
459
+ " \u2502 /sdd execute Execute generated tasks \u2502",
460
+ " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
461
+ "",
462
+ " \u250C\u2500 \u23F8 Goal Lifecycle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
463
+ " \u2502 /sdd goal Show current goal + journal \u2502",
464
+ " \u2502 /sdd goal set <text> Set autonomous mission \u2502",
465
+ " \u2502 /sdd goal pause Pause at end of current iteration \u2502",
466
+ " \u2502 /sdd goal resume Resume a paused goal \u2502",
467
+ " \u2502 /sdd goal journal [N] Show recent journal entries \u2502",
468
+ " \u2502 /sdd goal clear Clear goal + stop eternal mode \u2502",
469
+ " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
470
+ "",
471
+ " \u250C\u2500 \u{1F4E1} Eternal Stage \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
472
+ " \u2502 decide \u2192 execute \u2192 reflect \u2192 sleep | paused | stopped \u2502",
473
+ " \u2502 Stage shown in real-time during /sdd goal mode \u2502",
474
+ " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
475
+ "",
476
+ " \u250C\u2500 \u{1F527} Task Lifecycle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
477
+ " \u2502 /sdd tasks Show task list + progress bar \u2502",
478
+ " \u2502 /sdd next Show next executable task \u2502",
479
+ " \u2502 /sdd done <N> Complete a task \u2502",
480
+ " \u2502 /sdd skip <N> Skip a task (back to pending) \u2502",
481
+ " \u2502 /sdd fail <N> Mark task as failed \u2502",
482
+ " \u2502 /sdd review <N> Send task to review \u2502",
483
+ " \u2502 /sdd edit <N> <txt> Edit task title or description \u2502",
484
+ " \u2502 /sdd undo Undo last completion \u2502",
485
+ " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
486
+ "",
487
+ " \u250C\u2500 \u{1F4CA} Session Info \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
488
+ " \u2502 /sdd status Full session status + tasks preview \u2502",
489
+ " \u2502 /sdd cancel Cancel session \u2502",
490
+ " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
491
+ "",
492
+ " \u250C\u2500 \u{1F4C1} Spec History \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
493
+ " \u2502 /sdd list List saved specs \u2502",
494
+ " \u2502 /sdd show <id> Show spec details \u2502",
495
+ " \u2502 /sdd templates List available templates \u2502",
496
+ " \u2502 /sdd from <tmpl> Create from template \u2502",
497
+ " \u2502 /sdd version <id> Show version history \u2502",
498
+ " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
499
+ "",
500
+ " \u250C\u2500 \u{1F4A1} Quick Start \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
501
+ " \u2502 \u2502",
502
+ " \u2502 1. /sdd new Auth System \u2502",
503
+ " \u2502 \u2192 AI starts asking questions \u2502",
504
+ " \u2502 \u2502",
505
+ " \u2502 2. Just type your answers naturally \u2502",
506
+ " \u2502 \u2192 AI continues the interview \u2502",
507
+ " \u2502 \u2502",
508
+ " \u2502 3. AI generates spec (auto-detected) \u2502",
509
+ " \u2502 \u2192 /sdd approve \u2502",
510
+ " \u2502 \u2502",
511
+ " \u2502 3. AI generates implementation + tasks \u2502",
512
+ " \u2502 \u2192 /sdd approve \u2502",
513
+ " \u2502 \u2502",
514
+ " \u2502 4. AI executes tasks one by one \u2502",
515
+ " \u2502 \u2192 /sdd tasks (view progress) \u2502",
516
+ " \u2502 \u2192 /sdd done 1 (mark task complete) \u2502",
517
+ " \u2502 \u2502",
518
+ " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
519
+ "",
520
+ " Tip: tasks are shown with progress bar after each AI turn.",
521
+ ""
522
+ ].join("\n");
523
+ }
524
+ var init_rendering = __esm({
525
+ "src/slash-commands/sdd/rendering.ts"() {
369
526
  }
370
- return false;
371
- }
372
- function isExplanatoryText(text) {
373
- const lower = text.toLowerCase();
374
- return lower.startsWith("i'") || lower.startsWith("i will") || lower.startsWith("let me") || lower.startsWith("here's my") || lower.startsWith("here is my") || lower.startsWith("i'm going to") || lower.startsWith("first, let me") || lower.startsWith("sure") || lower.startsWith("of course") || lower.startsWith("okay") || lower.startsWith("ok,") || lower.startsWith("sounds good") || lower.startsWith("no problem") || // Skip if mostly code-like with minimal prose
375
- text.split("\n").length < 3 && !text.includes(".");
376
- }
377
- function getActiveBuilder() {
378
- return sddState.getBuilder();
527
+ });
528
+
529
+ // src/slash-commands/sdd.ts
530
+ var sdd_exports = {};
531
+ __export(sdd_exports, {
532
+ SDDState: () => SDDState,
533
+ advanceToNextTask: () => advanceToNextTask,
534
+ autoDetectTaskCompletion: () => autoDetectTaskCompletion,
535
+ buildSddCommand: () => buildSddCommand,
536
+ findSpec: () => findSpec,
537
+ formatElapsed: () => formatElapsed,
538
+ gatherProjectContext: () => gatherProjectContext2,
539
+ getActiveBuilder: () => getActiveBuilder,
540
+ getActiveSDDContext: () => getActiveSDDContext,
541
+ getActiveSDDPhase: () => getActiveSDDPhase,
542
+ getCurrentExecutingContext: () => getCurrentExecutingContext,
543
+ getCurrentTask: () => getCurrentTask,
544
+ getSessionState: () => getSessionState,
545
+ getTaskGraphId: () => getTaskGraphId,
546
+ getTaskListText: () => getTaskListText,
547
+ getTaskProgress: () => getTaskProgress,
548
+ getTaskTracker: () => getTaskTracker,
549
+ getTaskTrackerExport: () => getTaskTrackerExport,
550
+ isExplanatoryText: () => isExplanatoryText,
551
+ markTaskCompleted: () => markTaskCompleted,
552
+ renderProgress: () => renderProgress,
553
+ renderTaskListWithProgress: () => renderTaskListWithProgress,
554
+ sddState: () => sddState,
555
+ trySaveImplementationPlan: () => trySaveImplementationPlan,
556
+ trySaveSpecFromAIOutput: () => trySaveSpecFromAIOutput,
557
+ trySaveTasksFromAIOutput: () => trySaveTasksFromAIOutput
558
+ });
559
+ function getTaskTracker() {
560
+ return getTaskTrackerExport();
379
561
  }
380
562
  function buildSddCommand(opts) {
381
563
  const sessionState = getSessionState(opts.context);
@@ -401,7 +583,7 @@ function buildSddCommand(opts) {
401
583
  if (!sessionState.getBuilder() && !forceFlag) {
402
584
  const sessionPath = opts.paths.projectSddSession;
403
585
  try {
404
- await fsp3.access(sessionPath);
586
+ await fsp4.access(sessionPath);
405
587
  const projectContext2 = await gatherProjectContext2(opts.context?.projectRoot ?? process.cwd());
406
588
  const tempBuilder = new AISpecBuilder({
407
589
  store: specStore,
@@ -1052,16 +1234,16 @@ Start executing the tasks one by one.`
1052
1234
  const sessionPath = opts.paths.projectSddSession;
1053
1235
  let deletedFromDisk = false;
1054
1236
  try {
1055
- await fsp3.unlink(sessionPath);
1237
+ await fsp4.unlink(sessionPath);
1056
1238
  deletedFromDisk = true;
1057
1239
  } catch {
1058
1240
  }
1059
1241
  try {
1060
- await fsp3.rm(opts.paths.projectSpecs, { recursive: true, force: true });
1242
+ await fsp4.rm(opts.paths.projectSpecs, { recursive: true, force: true });
1061
1243
  } catch {
1062
1244
  }
1063
1245
  try {
1064
- await fsp3.rm(opts.paths.projectTaskGraphs, { recursive: true, force: true });
1246
+ await fsp4.rm(opts.paths.projectTaskGraphs, { recursive: true, force: true });
1065
1247
  } catch {
1066
1248
  }
1067
1249
  const cancelBuilder = sddState.getBuilder();
@@ -1294,233 +1476,34 @@ ${lines.join("\n")}`
1294
1476
  lines.push(` \u2022 ${node.title}`);
1295
1477
  }
1296
1478
  }
1297
- }
1298
- lines.push(`\u2570${"\u2500".repeat(55)}\u256F`);
1299
- return { message: lines.join("\n") };
1300
- } catch {
1301
- return { message: "Could not analyze critical path." };
1302
- }
1303
- }
1304
- default:
1305
- return {
1306
- message: `Unknown command "${verb}".
1307
-
1308
- ${sddHelp()}`
1309
- };
1310
- }
1311
- }
1312
- };
1313
- }
1314
- function sddHelp() {
1315
- return [
1316
- "",
1317
- "\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557",
1318
- "\u2551 \u{1F680} SDD \u2014 AI-Driven Spec Builder \u2551",
1319
- "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D",
1320
- "",
1321
- " \u250C\u2500 \u{1F195} Start \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
1322
- " \u2502 /sdd new [title] Start a new spec session \u2502",
1323
- " \u2502 /sdd new --force Start fresh (skip resume check) \u2502",
1324
- " \u2502 /sdd resume Resume a saved session \u2502",
1325
- " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
1326
- "",
1327
- " \u250C\u2500 \u{1F504} Flow \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
1328
- " \u2502 /sdd approve Approve current phase \u2502",
1329
- " \u2502 /sdd spec Show current session's spec \u2502",
1330
- " \u2502 /sdd plan Show implementation plan \u2502",
1331
- " \u2502 /sdd execute Execute generated tasks \u2502",
1332
- " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
1333
- "",
1334
- " \u250C\u2500 \u23F8 Goal Lifecycle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
1335
- " \u2502 /sdd goal Show current goal + journal \u2502",
1336
- " \u2502 /sdd goal set <text> Set autonomous mission \u2502",
1337
- " \u2502 /sdd goal pause Pause at end of current iteration \u2502",
1338
- " \u2502 /sdd goal resume Resume a paused goal \u2502",
1339
- " \u2502 /sdd goal journal [N] Show recent journal entries \u2502",
1340
- " \u2502 /sdd goal clear Clear goal + stop eternal mode \u2502",
1341
- " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
1342
- "",
1343
- " \u250C\u2500 \u{1F4E1} Eternal Stage \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
1344
- " \u2502 decide \u2192 execute \u2192 reflect \u2192 sleep | paused | stopped \u2502",
1345
- " \u2502 Stage shown in real-time during /sdd goal mode \u2502",
1346
- " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
1347
- "",
1348
- " \u250C\u2500 \u{1F527} Task Lifecycle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
1349
- " \u2502 /sdd tasks Show task list + progress bar \u2502",
1350
- " \u2502 /sdd next Show next executable task \u2502",
1351
- " \u2502 /sdd done <N> Complete a task \u2502",
1352
- " \u2502 /sdd skip <N> Skip a task (back to pending) \u2502",
1353
- " \u2502 /sdd fail <N> Mark task as failed \u2502",
1354
- " \u2502 /sdd review <N> Send task to review \u2502",
1355
- " \u2502 /sdd edit <N> <txt> Edit task title or description \u2502",
1356
- " \u2502 /sdd undo Undo last completion \u2502",
1357
- " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
1358
- "",
1359
- " \u250C\u2500 \u{1F4CA} Session Info \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
1360
- " \u2502 /sdd status Full session status + tasks preview \u2502",
1361
- " \u2502 /sdd cancel Cancel session \u2502",
1362
- " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
1363
- "",
1364
- " \u250C\u2500 \u{1F4C1} Spec History \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
1365
- " \u2502 /sdd list List saved specs \u2502",
1366
- " \u2502 /sdd show <id> Show spec details \u2502",
1367
- " \u2502 /sdd templates List available templates \u2502",
1368
- " \u2502 /sdd from <tmpl> Create from template \u2502",
1369
- " \u2502 /sdd version <id> Show version history \u2502",
1370
- " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
1371
- "",
1372
- " \u250C\u2500 \u{1F4A1} Quick Start \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
1373
- " \u2502 \u2502",
1374
- " \u2502 1. /sdd new Auth System \u2502",
1375
- " \u2502 \u2192 AI starts asking questions \u2502",
1376
- " \u2502 \u2502",
1377
- " \u2502 2. Just type your answers naturally \u2502",
1378
- " \u2502 \u2192 AI continues the interview \u2502",
1379
- " \u2502 \u2502",
1380
- " \u2502 3. AI generates spec (auto-detected) \u2502",
1381
- " \u2502 \u2192 /sdd approve \u2502",
1382
- " \u2502 \u2502",
1383
- " \u2502 3. AI generates implementation + tasks \u2502",
1384
- " \u2502 \u2192 /sdd approve \u2502",
1385
- " \u2502 \u2502",
1386
- " \u2502 4. AI executes tasks one by one \u2502",
1387
- " \u2502 \u2192 /sdd tasks (view progress) \u2502",
1388
- " \u2502 \u2192 /sdd done 1 (mark task complete) \u2502",
1389
- " \u2502 \u2502",
1390
- " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518",
1391
- "",
1392
- " Tip: tasks are shown with progress bar after each AI turn.",
1393
- ""
1394
- ].join("\n");
1395
- }
1396
- async function gatherProjectContext2(projectRoot) {
1397
- const parts = [];
1398
- try {
1399
- const pkgPath = path8.join(projectRoot, "package.json");
1400
- const pkgRaw = await fsp3.readFile(pkgPath, "utf8");
1401
- const pkg = JSON.parse(pkgRaw);
1402
- parts.push(`Project: ${String(pkg.name ?? "unknown")}`);
1403
- parts.push(`Description: ${String(pkg.description ?? "none")}`);
1404
- if (pkg.dependencies) {
1405
- const deps = Object.keys(pkg.dependencies);
1406
- parts.push(`Dependencies: ${deps.slice(0, 20).join(", ")}${deps.length > 20 ? "..." : ""}`);
1407
- }
1408
- if (pkg.devDependencies) {
1409
- const devDeps = Object.keys(pkg.devDependencies);
1410
- parts.push(`Dev Dependencies: ${devDeps.slice(0, 15).join(", ")}${devDeps.length > 15 ? "..." : ""}`);
1411
- }
1412
- } catch {
1413
- }
1414
- try {
1415
- const tsconfigPath = path8.join(projectRoot, "tsconfig.json");
1416
- await fsp3.access(tsconfigPath);
1417
- parts.push("Language: TypeScript");
1418
- } catch {
1419
- }
1420
- try {
1421
- const srcDir = path8.join(projectRoot, "src");
1422
- const entries = await fsp3.readdir(srcDir, { withFileTypes: true });
1423
- const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
1424
- if (dirs.length > 0) {
1425
- parts.push(`Source structure: src/${dirs.join(", src/")}`);
1426
- }
1427
- } catch {
1428
- }
1429
- return parts.join("\n");
1430
- }
1431
- async function findSpec(store, idOrTitle) {
1432
- if (!idOrTitle) return null;
1433
- const byId = await store.load(idOrTitle);
1434
- if (byId) return byId;
1435
- const all = await store.list();
1436
- const match = all.find(
1437
- (e) => e.id.startsWith(idOrTitle) || e.title.toLowerCase().includes(idOrTitle.toLowerCase())
1438
- );
1439
- if (match) return store.load(match.id);
1440
- return null;
1441
- }
1442
- function getTaskGraphId() {
1443
- return sddState.getTaskGraphId();
1444
- }
1445
- function getTaskTracker() {
1446
- return sddState.getTaskTracker();
1447
- }
1448
- var SDD_META_KEY, SDDState, sddState;
1449
- var init_sdd = __esm({
1450
- "src/slash-commands/sdd.ts"() {
1451
- SDD_META_KEY = "sdd.state";
1452
- SDDState = class {
1453
- builder = null;
1454
- taskStore = null;
1455
- taskTracker = null;
1456
- taskGraphId = null;
1457
- sessionStartTime = Date.now();
1458
- phaseStartTime = Date.now();
1459
- versioning = null;
1460
- getBuilder() {
1461
- return this.builder;
1462
- }
1463
- setBuilder(b) {
1464
- this.builder = b;
1465
- }
1466
- getTaskStore() {
1467
- return this.taskStore;
1468
- }
1469
- setTaskStore(s) {
1470
- this.taskStore = s;
1471
- }
1472
- getTaskTracker() {
1473
- return this.taskTracker;
1474
- }
1475
- setTaskTracker(t) {
1476
- this.taskTracker = t;
1477
- }
1478
- getTaskGraphId() {
1479
- return this.taskGraphId;
1480
- }
1481
- setTaskGraphId(id) {
1482
- this.taskGraphId = id;
1483
- }
1484
- getSessionStartTime() {
1485
- return this.sessionStartTime;
1486
- }
1487
- setSessionStartTime(t) {
1488
- this.sessionStartTime = t;
1489
- }
1490
- setPhaseStartTime(t) {
1491
- this.phaseStartTime = t;
1492
- }
1493
- getPhaseStartTime() {
1494
- return this.phaseStartTime;
1495
- }
1496
- getSessionElapsed() {
1497
- return Date.now() - this.sessionStartTime;
1498
- }
1499
- getPhaseElapsed() {
1500
- return Date.now() - this.phaseStartTime;
1501
- }
1502
- getVersioning() {
1503
- if (this.versioning === null) {
1504
- this.versioning = new SpecVersioning();
1479
+ }
1480
+ lines.push(`\u2570${"\u2500".repeat(55)}\u256F`);
1481
+ return { message: lines.join("\n") };
1482
+ } catch {
1483
+ return { message: "Could not analyze critical path." };
1484
+ }
1505
1485
  }
1506
- return this.versioning;
1507
- }
1508
- clearTaskState() {
1509
- this.taskStore = null;
1510
- this.taskTracker = null;
1511
- this.taskGraphId = null;
1512
- }
1513
- getContext() {
1514
- if (!this.builder) return null;
1515
- const session = this.builder.getSession();
1516
- if (session.phase === "done") return null;
1517
- return this.builder.getAIPrompt();
1518
- }
1519
- getPhase() {
1520
- return this.builder?.getPhase() ?? null;
1486
+ default:
1487
+ return {
1488
+ message: `Unknown command "${verb}".
1489
+
1490
+ ${sddHelp()}`
1491
+ };
1521
1492
  }
1522
- };
1523
- sddState = new SDDState();
1493
+ }
1494
+ };
1495
+ }
1496
+ var init_sdd = __esm({
1497
+ "src/slash-commands/sdd.ts"() {
1498
+ init_state();
1499
+ init_task_manager();
1500
+ init_project_context();
1501
+ init_state();
1502
+ init_spec_detection();
1503
+ init_task_manager();
1504
+ init_project_context();
1505
+ init_task_manager();
1506
+ init_rendering();
1524
1507
  }
1525
1508
  });
1526
1509
  function normalizeKeys(cfg) {
@@ -1601,7 +1584,7 @@ function isNewer(a, b) {
1601
1584
  }
1602
1585
  async function readCache(homeFn = defaultHomeDir2) {
1603
1586
  try {
1604
- const raw = await fsp3.readFile(cachePath(homeFn), "utf8");
1587
+ const raw = await fsp4.readFile(cachePath(homeFn), "utf8");
1605
1588
  const entry = JSON.parse(raw);
1606
1589
  if (Date.now() - entry.timestamp > CACHE_TTL_MS) return null;
1607
1590
  return entry;
@@ -1612,8 +1595,8 @@ async function readCache(homeFn = defaultHomeDir2) {
1612
1595
  async function writeCache(entry, homeFn = defaultHomeDir2) {
1613
1596
  try {
1614
1597
  const dir = path8.dirname(cachePath(homeFn));
1615
- await fsp3.mkdir(dir, { recursive: true });
1616
- await fsp3.writeFile(cachePath(homeFn), JSON.stringify(entry, null, 2), "utf8");
1598
+ await fsp4.mkdir(dir, { recursive: true });
1599
+ await fsp4.writeFile(cachePath(homeFn), JSON.stringify(entry, null, 2), "utf8");
1617
1600
  } catch {
1618
1601
  }
1619
1602
  }
@@ -1947,7 +1930,7 @@ async function runWebUI(opts) {
1947
1930
  );
1948
1931
  }
1949
1932
  }
1950
- return new Promise((resolve4) => {
1933
+ return new Promise((resolve5) => {
1951
1934
  wss.on("listening", () => {
1952
1935
  console.log(`[WebUI] WebSocket server running on ws://${host}:${port}`);
1953
1936
  setupEvents();
@@ -2029,8 +2012,8 @@ async function runWebUI(opts) {
2029
2012
  console.log("[WebUI] Client disconnected");
2030
2013
  clients.delete(ws);
2031
2014
  if (clients.size === 0 && pendingConfirms.size > 0) {
2032
- for (const [id, resolve5] of pendingConfirms) {
2033
- resolve5("no");
2015
+ for (const [id, resolve6] of pendingConfirms) {
2016
+ resolve6("no");
2034
2017
  pendingConfirms.delete(id);
2035
2018
  }
2036
2019
  }
@@ -2060,7 +2043,7 @@ async function runWebUI(opts) {
2060
2043
  httpServer?.close();
2061
2044
  wss.close(() => {
2062
2045
  console.log("[WebUI] Server stopped");
2063
- resolve4();
2046
+ resolve5();
2064
2047
  });
2065
2048
  }
2066
2049
  process.on("SIGINT", shutdown);
@@ -2087,10 +2070,10 @@ async function runWebUI(opts) {
2087
2070
  break;
2088
2071
  case "tool.confirm_result": {
2089
2072
  const { id, decision } = msg.payload;
2090
- const resolve4 = pendingConfirms.get(id);
2091
- if (resolve4) {
2073
+ const resolve5 = pendingConfirms.get(id);
2074
+ if (resolve5) {
2092
2075
  pendingConfirms.delete(id);
2093
- resolve4(decision);
2076
+ resolve5(decision);
2094
2077
  }
2095
2078
  break;
2096
2079
  }
@@ -2375,7 +2358,7 @@ async function runWebUI(opts) {
2375
2358
  if (!opts.globalConfigPath) return {};
2376
2359
  let raw;
2377
2360
  try {
2378
- raw = await fsp3.readFile(opts.globalConfigPath, "utf8");
2361
+ raw = await fsp4.readFile(opts.globalConfigPath, "utf8");
2379
2362
  } catch {
2380
2363
  return {};
2381
2364
  }
@@ -2395,7 +2378,7 @@ async function runWebUI(opts) {
2395
2378
  let raw;
2396
2379
  let fileExists = true;
2397
2380
  try {
2398
- raw = await fsp3.readFile(opts.globalConfigPath, "utf8");
2381
+ raw = await fsp4.readFile(opts.globalConfigPath, "utf8");
2399
2382
  } catch (err) {
2400
2383
  if (err.code !== "ENOENT") {
2401
2384
  throw new Error(
@@ -2433,6 +2416,25 @@ var init_webui_server = __esm({
2433
2416
  init_provider_config_utils();
2434
2417
  }
2435
2418
  });
2419
+ var req = createRequire(import.meta.url);
2420
+ function readOwnVersion() {
2421
+ const candidates = ["../package.json", "../../package.json"];
2422
+ for (const rel of candidates) {
2423
+ try {
2424
+ const pkg = req(rel);
2425
+ if (typeof pkg.version === "string" && pkg.version.length > 0) return pkg.version;
2426
+ } catch {
2427
+ }
2428
+ }
2429
+ return "dev";
2430
+ }
2431
+ var CLI_VERSION = readOwnVersion();
2432
+ var API_VERSION = "0.0.0";
2433
+ try {
2434
+ const corePkg = req("@wrongstack/core/package.json");
2435
+ if (corePkg.wrongstackApiVersion) API_VERSION = corePkg.wrongstackApiVersion;
2436
+ } catch {
2437
+ }
2436
2438
 
2437
2439
  // src/slash-commands/commit-llm.ts
2438
2440
  async function generateCommitMessageWithLLM(diff, opts) {
@@ -2564,7 +2566,6 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
2564
2566
  "recover",
2565
2567
  "no-alt-screen",
2566
2568
  "alt-screen",
2567
- "mouse",
2568
2569
  "output-json",
2569
2570
  "prompt",
2570
2571
  "metrics",
@@ -2686,7 +2687,7 @@ function parseSpawnFlags(input) {
2686
2687
  }
2687
2688
  async function pathExists(file) {
2688
2689
  try {
2689
- await fsp3.access(file);
2690
+ await fsp4.access(file);
2690
2691
  return true;
2691
2692
  } catch {
2692
2693
  return false;
@@ -2721,7 +2722,7 @@ function parseMakeTargets(makefile) {
2721
2722
  async function detectProjectFacts(root) {
2722
2723
  const facts = { hints: [] };
2723
2724
  try {
2724
- const pkg = JSON.parse(await fsp3.readFile(path8.join(root, "package.json"), "utf8"));
2725
+ const pkg = JSON.parse(await fsp4.readFile(path8.join(root, "package.json"), "utf8"));
2725
2726
  const scripts = pkg.scripts ?? {};
2726
2727
  const pm = await detectPackageManager(root, pkg.packageManager);
2727
2728
  if (hasUsableScript(scripts, "build")) facts.build = `${pm} run build`;
@@ -2759,7 +2760,7 @@ async function detectProjectFacts(root) {
2759
2760
  } catch {
2760
2761
  }
2761
2762
  try {
2762
- const makefile = await fsp3.readFile(path8.join(root, "Makefile"), "utf8");
2763
+ const makefile = await fsp4.readFile(path8.join(root, "Makefile"), "utf8");
2763
2764
  const targets = parseMakeTargets(makefile);
2764
2765
  facts.build ??= targets.has("build") ? "make build" : "make";
2765
2766
  if (targets.has("test")) facts.test ??= "make test";
@@ -3131,7 +3132,7 @@ function formatPhaseList(graph) {
3131
3132
  }
3132
3133
  async function gatherProjectContext(projectRoot) {
3133
3134
  try {
3134
- const raw = await fsp3.readFile(path8.join(projectRoot, "package.json"), "utf8");
3135
+ const raw = await fsp4.readFile(path8.join(projectRoot, "package.json"), "utf8");
3135
3136
  const pkg = JSON.parse(raw);
3136
3137
  const parts = [
3137
3138
  `Project: ${String(pkg.name ?? "unknown")}`,
@@ -3319,6 +3320,37 @@ function buildClearCommand(opts) {
3319
3320
  }
3320
3321
  };
3321
3322
  }
3323
+ function buildCodebaseReindexCommand(opts) {
3324
+ return {
3325
+ name: "codebase-reindex",
3326
+ aliases: ["reindex"],
3327
+ description: "Rebuild the codebase symbol index used by codebase-search.",
3328
+ argsHint: "[force]",
3329
+ help: [
3330
+ "Usage:",
3331
+ " /codebase-reindex Incremental reindex (only changed files).",
3332
+ " /codebase-reindex force Clear the index and rebuild from scratch.",
3333
+ "",
3334
+ "The index powers codebase-search. It is normally kept fresh automatically",
3335
+ "(at session start and as files change); use this when you want to force a",
3336
+ "refresh \u2014 e.g. after a large branch switch, merge, or external edit."
3337
+ ].join("\n"),
3338
+ async run(args, _ctx) {
3339
+ const force = /\b(force|--force|-f)\b/.test(args.trim());
3340
+ opts.renderer.write(color.dim(`${force ? "Rebuilding" : "Reindexing"} codebase index\u2026
3341
+ `));
3342
+ try {
3343
+ const r = await runStartupIndex({ projectRoot: opts.projectRoot, force });
3344
+ const summary = `${color.green("\u2713")} codebase index ${force ? "rebuilt" : "updated"} ` + color.dim(`\u2014 ${r.symbolsIndexed} symbols \xB7 ${r.filesIndexed} files \xB7 ${r.durationMs}ms`) + (r.errors.length ? `
3345
+ ${color.yellow(` ${r.errors.length} file(s) had errors`)}` : "");
3346
+ return { message: summary };
3347
+ } catch (err) {
3348
+ const msg = `${color.red("Codebase reindex failed:")} ${err instanceof Error ? err.message : String(err)}`;
3349
+ return { message: msg };
3350
+ }
3351
+ }
3352
+ };
3353
+ }
3322
3354
  function buildCollabCommand(opts) {
3323
3355
  return {
3324
3356
  name: "collab",
@@ -3726,7 +3758,7 @@ async function persistContextConfig(opts, patch) {
3726
3758
  if (!opts.configStore || !opts.paths) return "Cannot persist context settings: config store not available.";
3727
3759
  let raw = "{}";
3728
3760
  try {
3729
- raw = await fsp3.readFile(opts.paths.globalConfig, "utf8");
3761
+ raw = await fsp4.readFile(opts.paths.globalConfig, "utf8");
3730
3762
  } catch (err) {
3731
3763
  if (err.code !== "ENOENT") {
3732
3764
  return `Could not read ${opts.paths.globalConfig}: ${err.message}`;
@@ -4644,6 +4676,7 @@ function buildFleetCommand(opts) {
4644
4676
  " /fleet terminate <subagentId> Stop a specific subagent by id",
4645
4677
  " /fleet kill Stop all running subagents",
4646
4678
  " /fleet usage Token and cost breakdown across the fleet",
4679
+ " /fleet concurrency [n] Show or set the concurrent-subagent ceiling",
4647
4680
  " /fleet journal Show recent journal entries from /goal journal",
4648
4681
  "",
4649
4682
  "In the TUI, press Ctrl+F to open the graphical fleet monitor.",
@@ -4886,6 +4919,16 @@ function buildFleetCommand(opts) {
4886
4919
  opts.renderer.write(msg2);
4887
4920
  return { message: msg2 };
4888
4921
  }
4922
+ if (cmd === "concurrency" || cmd === "slots" || cmd === "parallel") {
4923
+ if (opts.onFleet) {
4924
+ const n = subargs[0];
4925
+ const msg3 = await opts.onFleet("concurrency", n || void 0);
4926
+ return { message: msg3 };
4927
+ }
4928
+ const msg2 = `${color.amber("\u26A0 /fleet concurrency is not wired in this session.")}`;
4929
+ opts.renderer.writeWarning(msg2);
4930
+ return { message: msg2 };
4931
+ }
4889
4932
  if (cmd === "help" || cmd === "?") {
4890
4933
  const msg2 = [
4891
4934
  `${color.bold("Fleet Commands")}`,
@@ -4897,12 +4940,13 @@ function buildFleetCommand(opts) {
4897
4940
  ` ${color.dim("/fleet terminate <subagentId>")} Stop a specific subagent by id`,
4898
4941
  ` ${color.dim("/fleet kill")} Stop all running subagents`,
4899
4942
  ` ${color.dim("/fleet usage")} Token and cost breakdown across the fleet`,
4943
+ ` ${color.dim("/fleet concurrency [n]")} Show or set the concurrent-subagent ceiling`,
4900
4944
  ` ${color.dim("/fleet journal")} Show recent journal entries from /goal journal`
4901
4945
  ].join("\n");
4902
4946
  opts.renderer.write(msg2);
4903
4947
  return { message: msg2 };
4904
4948
  }
4905
- const valid = ["status", "list", "dispatch", "usage", "spawn", "terminate", "kill", "retry", "journal"];
4949
+ const valid = ["status", "list", "dispatch", "usage", "spawn", "terminate", "kill", "retry", "concurrency", "journal"];
4906
4950
  const msg = `Unknown subcommand "${cmd}". Valid subcommands: ${valid.join(", ")}. Run /fleet with no args to see status, or /fleet help for usage.`;
4907
4951
  opts.renderer.writeWarning(msg);
4908
4952
  return { message: msg };
@@ -5144,8 +5188,8 @@ function buildInitCommand(opts) {
5144
5188
  const file = path8.join(dir, "AGENTS.md");
5145
5189
  const detected = await detectProjectFacts(ctx.projectRoot);
5146
5190
  const body = renderAgentsTemplate(detected);
5147
- await fsp3.mkdir(dir, { recursive: true });
5148
- await fsp3.writeFile(file, body, "utf8");
5191
+ await fsp4.mkdir(dir, { recursive: true });
5192
+ await fsp4.writeFile(file, body, "utf8");
5149
5193
  if (detected.hints.length > 0) {
5150
5194
  const msg2 = `Wrote ${file}
5151
5195
  Pre-filled: ${detected.hints.join(", ")}. Edit the file with project context and instructions the system prompt should carry.`;
@@ -5356,9 +5400,9 @@ function stateBadge(state) {
5356
5400
  return color.dim(state);
5357
5401
  }
5358
5402
  }
5359
- async function readConfig(path25) {
5403
+ async function readConfig(path26) {
5360
5404
  try {
5361
- return JSON.parse(await fsp3.readFile(path25, "utf8"));
5405
+ return JSON.parse(await fsp4.readFile(path26, "utf8"));
5362
5406
  } catch {
5363
5407
  return {};
5364
5408
  }
@@ -5366,11 +5410,11 @@ async function readConfig(path25) {
5366
5410
  function isMcpServerRecord(value) {
5367
5411
  return !!value && typeof value === "object" && !Array.isArray(value);
5368
5412
  }
5369
- async function writeConfig(path25, cfg) {
5413
+ async function writeConfig(path26, cfg) {
5370
5414
  const raw = JSON.stringify(cfg, null, 2);
5371
- const tmp = path25 + ".tmp";
5372
- await fsp3.writeFile(tmp, raw, "utf8");
5373
- await fsp3.rename(tmp, path25);
5415
+ const tmp = path26 + ".tmp";
5416
+ await fsp4.writeFile(tmp, raw, "utf8");
5417
+ await fsp4.rename(tmp, path26);
5374
5418
  }
5375
5419
 
5376
5420
  // src/slash-commands/mcp.ts
@@ -5562,7 +5606,7 @@ async function patchGlobalConfig(globalConfigPath, mutate) {
5562
5606
  let raw = "{}";
5563
5607
  let fileExists = true;
5564
5608
  try {
5565
- raw = await fsp3.readFile(globalConfigPath, "utf8");
5609
+ raw = await fsp4.readFile(globalConfigPath, "utf8");
5566
5610
  } catch (err) {
5567
5611
  if (err.code !== "ENOENT") throw err;
5568
5612
  fileExists = false;
@@ -6067,7 +6111,7 @@ async function patchGlobalConfig2(globalConfigPath, mutate) {
6067
6111
  let raw = "{}";
6068
6112
  let fileExists = true;
6069
6113
  try {
6070
- raw = await fsp3.readFile(globalConfigPath, "utf8");
6114
+ raw = await fsp4.readFile(globalConfigPath, "utf8");
6071
6115
  } catch (err) {
6072
6116
  if (err.code !== "ENOENT") throw err;
6073
6117
  fileExists = false;
@@ -6246,7 +6290,7 @@ async function persistAutonomySetting(deps, mutator) {
6246
6290
  let raw;
6247
6291
  let fileExists = true;
6248
6292
  try {
6249
- raw = await fsp3.readFile(deps.globalConfigPath, "utf8");
6293
+ raw = await fsp4.readFile(deps.globalConfigPath, "utf8");
6250
6294
  } catch (err) {
6251
6295
  if (err.code !== "ENOENT") {
6252
6296
  throw new Error(`Could not read ${deps.globalConfigPath}: ${err.message}`);
@@ -6473,7 +6517,7 @@ function resolveConfigPath() {
6473
6517
  async function loadStatuslineConfig() {
6474
6518
  const p = resolveConfigPath();
6475
6519
  try {
6476
- const raw = await fsp3.readFile(p, "utf8");
6520
+ const raw = await fsp4.readFile(p, "utf8");
6477
6521
  return { ...DEFAULTS, ...JSON.parse(raw) };
6478
6522
  } catch {
6479
6523
  return { ...DEFAULTS };
@@ -6482,7 +6526,7 @@ async function loadStatuslineConfig() {
6482
6526
  async function saveStatuslineConfig(cfg) {
6483
6527
  const p = resolveConfigPath();
6484
6528
  try {
6485
- await fsp3.mkdir(path8.dirname(p), { recursive: true });
6529
+ await fsp4.mkdir(path8.dirname(p), { recursive: true });
6486
6530
  await atomicWrite(p, JSON.stringify(cfg, null, 2));
6487
6531
  } catch (err) {
6488
6532
  throw new FsError({
@@ -6736,6 +6780,7 @@ function buildBuiltinSlashCommands(opts) {
6736
6780
  buildClearCommand(opts),
6737
6781
  buildCompactCommand(opts),
6738
6782
  buildContextCommand(opts),
6783
+ buildCodebaseReindexCommand(opts),
6739
6784
  buildToolsCommand(opts),
6740
6785
  buildPluginCommand(opts),
6741
6786
  buildMcpSlashCommand(opts),
@@ -6791,13 +6836,13 @@ var MANIFESTS = [
6791
6836
  ];
6792
6837
  async function detectProjectKind(projectRoot) {
6793
6838
  try {
6794
- await fsp3.access(path8.join(projectRoot, ".wrongstack", "AGENTS.md"));
6839
+ await fsp4.access(path8.join(projectRoot, ".wrongstack", "AGENTS.md"));
6795
6840
  return "initialized";
6796
6841
  } catch {
6797
6842
  }
6798
6843
  for (const m of MANIFESTS) {
6799
6844
  try {
6800
- await fsp3.access(path8.join(projectRoot, m));
6845
+ await fsp4.access(path8.join(projectRoot, m));
6801
6846
  return "project";
6802
6847
  } catch {
6803
6848
  }
@@ -6809,8 +6854,8 @@ async function scaffoldAgentsMd(projectRoot) {
6809
6854
  const file = path8.join(dir, "AGENTS.md");
6810
6855
  const facts = await detectProjectFacts(projectRoot);
6811
6856
  const body = renderAgentsTemplate(facts);
6812
- await fsp3.mkdir(dir, { recursive: true });
6813
- await fsp3.writeFile(file, body, "utf8");
6857
+ await fsp4.mkdir(dir, { recursive: true });
6858
+ await fsp4.writeFile(file, body, "utf8");
6814
6859
  return file;
6815
6860
  }
6816
6861
  async function runProjectCheck(opts) {
@@ -6853,7 +6898,7 @@ async function runProjectCheck(opts) {
6853
6898
  const gitDir = path8.join(projectRoot, ".git");
6854
6899
  let hasGit = false;
6855
6900
  try {
6856
- await fsp3.access(gitDir);
6901
+ await fsp4.access(gitDir);
6857
6902
  hasGit = true;
6858
6903
  } catch {
6859
6904
  }
@@ -6873,10 +6918,10 @@ async function runProjectCheck(opts) {
6873
6918
  if (answer2 === "y" || answer2 === "yes") {
6874
6919
  try {
6875
6920
  const { spawn: spawn3 } = await import('child_process');
6876
- await new Promise((resolve4, reject) => {
6921
+ await new Promise((resolve5, reject) => {
6877
6922
  const child = spawn3("git", ["init"], { cwd: projectRoot });
6878
6923
  child.on("error", reject);
6879
- child.on("close", (code) => code === 0 ? resolve4() : reject(new Error(`git init failed with ${code}`)));
6924
+ child.on("close", (code) => code === 0 ? resolve5() : reject(new Error(`git init failed with ${code}`)));
6880
6925
  });
6881
6926
  renderer.write(` ${color.green("\u2713")} Git repository initialized
6882
6927
  `);
@@ -6907,7 +6952,43 @@ var LaunchAbortedError = class extends Error {
6907
6952
  }
6908
6953
  };
6909
6954
  async function runLaunchPrompts(opts) {
6910
- const { renderer, reader, modePinned, yoloPinned, directorPinned, autonomyPinned } = opts;
6955
+ const { renderer, reader, modePinned, yoloPinned, directorPinned, autonomyPinned, lastChoices } = opts;
6956
+ if (modePinned !== void 0 && yoloPinned !== void 0 && directorPinned !== void 0 && autonomyPinned !== void 0) {
6957
+ return { mode: modePinned, yolo: yoloPinned, director: directorPinned, autonomy: autonomyPinned };
6958
+ }
6959
+ if (lastChoices) {
6960
+ const effective = {
6961
+ mode: modePinned ?? lastChoices.mode,
6962
+ yolo: yoloPinned ?? lastChoices.yolo,
6963
+ director: directorPinned ?? lastChoices.director,
6964
+ autonomy: autonomyPinned ?? lastChoices.autonomy
6965
+ };
6966
+ const onOff = (v) => v ? color.green("on") : color.dim("off");
6967
+ const modeLabel = effective.mode.toUpperCase();
6968
+ renderer.write(
6969
+ `
6970
+ ${color.dim("Last settings:")} ${color.bold(modeLabel)} \xB7 YOLO ${onOff(effective.yolo)} \xB7 Director ${onOff(effective.director)} \xB7 Autonomy ${effective.autonomy === "auto" ? color.green("auto") : color.dim("off")}
6971
+ `
6972
+ );
6973
+ const answer = (await reader.readLine(
6974
+ ` ${color.amber("?")} Continue with these? ${color.dim("[Y/n/q]")} `
6975
+ )).trim().toLowerCase();
6976
+ if (answer === "q") {
6977
+ renderer.write(color.dim(" Goodbye!\n"));
6978
+ throw new LaunchAbortedError();
6979
+ }
6980
+ if (answer !== "n" && answer !== "no") {
6981
+ const badges2 = buildBadges(effective);
6982
+ const badgeStr2 = badges2.length > 0 ? ` (${badges2.join(" \xB7 ")})` : "";
6983
+ renderer.write(
6984
+ `
6985
+ ${color.green("\u25B6")} Launching in ${color.bold(modeLabel)} mode${badgeStr2}
6986
+
6987
+ `
6988
+ );
6989
+ return effective;
6990
+ }
6991
+ }
6911
6992
  let mode;
6912
6993
  if (modePinned) {
6913
6994
  mode = modePinned;
@@ -6961,10 +7042,7 @@ async function runLaunchPrompts(opts) {
6961
7042
  }
6962
7043
  autonomy = answer !== "n" && answer !== "no" ? "auto" : "off";
6963
7044
  }
6964
- const badges = [];
6965
- if (yolo) badges.push(color.yellow("YOLO"));
6966
- if (director) badges.push(color.cyan("DIRECTOR"));
6967
- if (autonomy !== "off") badges.push(color.magenta(`AUTONOMY:${autonomy.toUpperCase()}`));
7045
+ const badges = buildBadges({ yolo, director, autonomy });
6968
7046
  const badgeStr = badges.length > 0 ? ` (${badges.join(" \xB7 ")})` : "";
6969
7047
  renderer.write(
6970
7048
  `
@@ -6974,6 +7052,28 @@ async function runLaunchPrompts(opts) {
6974
7052
  );
6975
7053
  return { mode, yolo, director, autonomy };
6976
7054
  }
7055
+ function buildBadges(chosen) {
7056
+ const badges = [];
7057
+ if (chosen.yolo) badges.push(color.yellow("YOLO"));
7058
+ if (chosen.director) badges.push(color.cyan("DIRECTOR"));
7059
+ if (chosen.autonomy !== "off") badges.push(color.magenta(`AUTONOMY:${chosen.autonomy.toUpperCase()}`));
7060
+ return badges;
7061
+ }
7062
+ async function persistLaunchChoices(configPath2, choices) {
7063
+ let existing = {};
7064
+ try {
7065
+ const raw = await fsp4.readFile(configPath2, "utf8");
7066
+ existing = JSON.parse(raw);
7067
+ } catch {
7068
+ }
7069
+ existing.yolo = choices.yolo;
7070
+ existing.launch = {
7071
+ mode: choices.mode,
7072
+ director: choices.director,
7073
+ autonomy: choices.autonomy
7074
+ };
7075
+ await atomicWrite(configPath2, JSON.stringify(existing, null, 2), { mode: 384 });
7076
+ }
6977
7077
  async function bootConfig(flags) {
6978
7078
  const opts = { flags, appLabel: "wstack" };
6979
7079
  const { cwd, projectRoot, userHome, wpaths, pathResolver, config, vault } = await bootConfig$1(opts);
@@ -6993,7 +7093,7 @@ var ReadlineInputReader = class {
6993
7093
  }
6994
7094
  async loadHistory() {
6995
7095
  try {
6996
- const raw = await fsp3.readFile(this.historyFile, "utf8");
7096
+ const raw = await fsp4.readFile(this.historyFile, "utf8");
6997
7097
  this.history = raw.split("\n").filter(Boolean).slice(-1e3);
6998
7098
  } catch {
6999
7099
  this.history = [];
@@ -7001,8 +7101,8 @@ var ReadlineInputReader = class {
7001
7101
  }
7002
7102
  async saveHistory() {
7003
7103
  try {
7004
- await fsp3.mkdir(path8.dirname(this.historyFile), { recursive: true });
7005
- await fsp3.writeFile(this.historyFile, this.history.slice(-1e3).join("\n"));
7104
+ await fsp4.mkdir(path8.dirname(this.historyFile), { recursive: true });
7105
+ await fsp4.writeFile(this.historyFile, this.history.slice(-1e3).join("\n"));
7006
7106
  } catch {
7007
7107
  }
7008
7108
  }
@@ -7020,28 +7120,34 @@ var ReadlineInputReader = class {
7020
7120
  async readLine(prompt) {
7021
7121
  if (this.history.length === 0) await this.loadHistory();
7022
7122
  while (this.pending) {
7023
- await new Promise((resolve4) => setTimeout(resolve4, 50));
7123
+ await new Promise((resolve5) => setTimeout(resolve5, 50));
7024
7124
  }
7025
7125
  this.pending = true;
7026
7126
  try {
7027
- const rl = this.ensure();
7028
- if (rl.closed || rl._flushed) {
7029
- rl.close();
7127
+ if (this.rl) {
7128
+ const old = this.rl;
7030
7129
  this.rl = void 0;
7130
+ await new Promise((resolve5) => {
7131
+ if (old.closed) {
7132
+ resolve5();
7133
+ } else {
7134
+ old.once("close", resolve5);
7135
+ old.close();
7136
+ }
7137
+ });
7031
7138
  }
7032
7139
  const fresh = this.ensure();
7033
- return new Promise((resolve4) => {
7140
+ return new Promise((resolve5) => {
7034
7141
  fresh.question(prompt ?? "> ", (line) => {
7035
7142
  if (line.trim()) {
7036
7143
  this.history.push(line);
7037
7144
  void this.saveHistory();
7038
7145
  }
7039
- resolve4(line);
7146
+ resolve5(line);
7040
7147
  });
7041
- fresh.once("close", () => resolve4(""));
7148
+ fresh.once("close", () => resolve5(""));
7042
7149
  }).then((result) => {
7043
7150
  this.rl?.close();
7044
- this.rl = void 0;
7045
7151
  return result;
7046
7152
  });
7047
7153
  } finally {
@@ -7050,7 +7156,7 @@ var ReadlineInputReader = class {
7050
7156
  }
7051
7157
  async readKey(prompt, options) {
7052
7158
  writeOut(prompt);
7053
- return new Promise((resolve4) => {
7159
+ return new Promise((resolve5) => {
7054
7160
  const stdin = process.stdin;
7055
7161
  const wasRaw = stdin.isRaw;
7056
7162
  const wasPaused = stdin.isPaused();
@@ -7061,7 +7167,7 @@ var ReadlineInputReader = class {
7061
7167
  if (key === "") {
7062
7168
  cleanup();
7063
7169
  writeOut("\n");
7064
- resolve4("");
7170
+ resolve5("");
7065
7171
  return;
7066
7172
  }
7067
7173
  const opt = options.find(
@@ -7071,12 +7177,12 @@ var ReadlineInputReader = class {
7071
7177
  cleanup();
7072
7178
  writeOut(`${opt.key}
7073
7179
  `);
7074
- resolve4(opt.value);
7180
+ resolve5(opt.value);
7075
7181
  }
7076
7182
  };
7077
7183
  const onClose = () => {
7078
7184
  cleanup();
7079
- resolve4("");
7185
+ resolve5("");
7080
7186
  };
7081
7187
  const cleanup = () => {
7082
7188
  stdin.off("data", onData);
@@ -7104,7 +7210,7 @@ var ReadlineInputReader = class {
7104
7210
  this.rl?.close();
7105
7211
  this.rl = void 0;
7106
7212
  writeOut(prompt);
7107
- return new Promise((resolve4) => {
7213
+ return new Promise((resolve5) => {
7108
7214
  let buf = "";
7109
7215
  const wasRaw = stdin.isRaw;
7110
7216
  setRawMode(stdin, true);
@@ -7122,7 +7228,7 @@ var ReadlineInputReader = class {
7122
7228
  cleanup();
7123
7229
  writeOut(` ${dim(`[${buf.length} chars]`)}
7124
7230
  `);
7125
- resolve4(buf);
7231
+ resolve5(buf);
7126
7232
  return;
7127
7233
  }
7128
7234
  if (ch === "") {
@@ -7222,7 +7328,7 @@ async function buildPickableProviders(modelsRegistry, config) {
7222
7328
  var defaultUidFn = () => os2__default.userInfo().uid;
7223
7329
  async function getFileUid(filePath) {
7224
7330
  try {
7225
- const stat4 = await fsp3.stat(filePath);
7331
+ const stat4 = await fsp4.stat(filePath);
7226
7332
  return stat4.uid;
7227
7333
  } catch {
7228
7334
  return void 0;
@@ -7262,7 +7368,7 @@ async function safeDelete(filePath) {
7262
7368
  const filename = path8.basename(filePath);
7263
7369
  try {
7264
7370
  assertSafeToDelete(filename, dir);
7265
- await fsp3.unlink(filePath);
7371
+ await fsp4.unlink(filePath);
7266
7372
  } catch (err) {
7267
7373
  if (err instanceof Error && err.message.startsWith("Refusing")) {
7268
7374
  writeErr(`[config-history] SAFETY: ${err.message}
@@ -7320,7 +7426,7 @@ function entryId(ts) {
7320
7426
  }
7321
7427
  async function ensureHistoryDir(homeFn = defaultHomeDir) {
7322
7428
  try {
7323
- await fsp3.mkdir(historyDir(homeFn), { recursive: true });
7429
+ await fsp4.mkdir(historyDir(homeFn), { recursive: true });
7324
7430
  } catch (err) {
7325
7431
  throw new FsError({
7326
7432
  message: err instanceof Error ? err.message : String(err),
@@ -7332,7 +7438,7 @@ async function ensureHistoryDir(homeFn = defaultHomeDir) {
7332
7438
  }
7333
7439
  async function readIndex(homeFn = defaultHomeDir) {
7334
7440
  try {
7335
- const raw = await fsp3.readFile(historyIndexPath(homeFn), "utf8");
7441
+ const raw = await fsp4.readFile(historyIndexPath(homeFn), "utf8");
7336
7442
  return JSON.parse(raw);
7337
7443
  } catch {
7338
7444
  return { version: 1, entries: [] };
@@ -7357,7 +7463,7 @@ async function backupCurrent(homeFn = defaultHomeDir) {
7357
7463
  const ts = Date.now();
7358
7464
  let content;
7359
7465
  try {
7360
- content = await fsp3.readFile(cfg, "utf8");
7466
+ content = await fsp4.readFile(cfg, "utf8");
7361
7467
  } catch {
7362
7468
  }
7363
7469
  if (content !== void 0) {
@@ -7375,7 +7481,7 @@ async function backupCurrent(homeFn = defaultHomeDir) {
7375
7481
  }
7376
7482
  try {
7377
7483
  const dir = path8.join(homeFn(), ".wrongstack");
7378
- const files = await fsp3.readdir(dir);
7484
+ const files = await fsp4.readdir(dir);
7379
7485
  const baks = files.filter((f) => f.startsWith("config.json.") && f.endsWith(".bak")).sort().reverse();
7380
7486
  for (const f of baks.slice(10)) {
7381
7487
  await safeDelete(path8.join(dir, f));
@@ -7395,7 +7501,7 @@ async function appendHistory(oldCfg, newCfg, description, homeFn = defaultHomeDi
7395
7501
  diffSummary: diffSummary(oldCfg, newCfg)
7396
7502
  };
7397
7503
  try {
7398
- await fsp3.writeFile(
7504
+ await fsp4.writeFile(
7399
7505
  path8.join(historyDir(homeFn), `${id}.json`),
7400
7506
  JSON.stringify(entry, null, 2),
7401
7507
  "utf8"
@@ -7419,7 +7525,7 @@ async function listHistory(homeFn = defaultHomeDir) {
7419
7525
  }
7420
7526
  async function getHistoryEntry(id, homeFn = defaultHomeDir) {
7421
7527
  try {
7422
- const raw = await fsp3.readFile(path8.join(historyDir(homeFn), `${id}.json`), "utf8");
7528
+ const raw = await fsp4.readFile(path8.join(historyDir(homeFn), `${id}.json`), "utf8");
7423
7529
  return JSON.parse(raw);
7424
7530
  } catch {
7425
7531
  return null;
@@ -7434,7 +7540,7 @@ async function restoreFromHistory(id, homeFn = defaultHomeDir) {
7434
7540
  await backupCurrent(homeFn);
7435
7541
  let oldCfg = {};
7436
7542
  try {
7437
- const raw = await fsp3.readFile(configPath(homeFn), "utf8");
7543
+ const raw = await fsp4.readFile(configPath(homeFn), "utf8");
7438
7544
  oldCfg = JSON.parse(raw);
7439
7545
  } catch {
7440
7546
  }
@@ -7456,13 +7562,13 @@ async function restoreLast(homeFn = defaultHomeDir) {
7456
7562
  const cfg = configPath(homeFn);
7457
7563
  let oldCfg = {};
7458
7564
  try {
7459
- const raw = await fsp3.readFile(cfg, "utf8");
7565
+ const raw = await fsp4.readFile(cfg, "utf8");
7460
7566
  oldCfg = JSON.parse(raw);
7461
7567
  } catch {
7462
7568
  }
7463
7569
  let lastCfg = {};
7464
7570
  try {
7465
- const raw = await fsp3.readFile(last, "utf8");
7571
+ const raw = await fsp4.readFile(last, "utf8");
7466
7572
  lastCfg = JSON.parse(raw);
7467
7573
  } catch {
7468
7574
  return { ok: false, error: "No prior backup found" };
@@ -7482,21 +7588,25 @@ async function restoreLast(homeFn = defaultHomeDir) {
7482
7588
 
7483
7589
  // src/picker.ts
7484
7590
  var theme = { primary: color.amber };
7485
- async function saveToGlobalConfig(configPath2, provider, model, homeFn = () => process.env.HOME ?? __require("os").homedir()) {
7591
+ async function saveToGlobalConfig(configPath2, provider, model, homeFn = () => process.env.HOME ?? os2__default.homedir()) {
7486
7592
  try {
7487
- const { atomicWrite: atomicWrite13 } = await import('@wrongstack/core');
7488
- const fs25 = await import('fs/promises');
7593
+ const { atomicWrite: atomicWrite14 } = await import('@wrongstack/core');
7594
+ const fs26 = await import('fs/promises');
7489
7595
  let existing = {};
7490
7596
  try {
7491
- const raw = await fs25.readFile(configPath2, "utf8");
7597
+ const raw = await fs26.readFile(configPath2, "utf8");
7492
7598
  existing = JSON.parse(raw);
7493
7599
  } catch {
7494
7600
  }
7495
7601
  const oldCfg = { ...existing };
7496
7602
  existing.provider = provider;
7497
7603
  existing.model = model;
7498
- await backupCurrent(homeFn);
7499
- await atomicWrite13(configPath2, JSON.stringify(existing, null, 2), { mode: 384 });
7604
+ try {
7605
+ await backupCurrent(homeFn);
7606
+ } catch (err) {
7607
+ console.warn("[picker] backupCurrent failed:", err);
7608
+ }
7609
+ await atomicWrite14(configPath2, JSON.stringify(existing, null, 2), { mode: 384 });
7500
7610
  try {
7501
7611
  await appendHistory(
7502
7612
  oldCfg,
@@ -7507,7 +7617,8 @@ async function saveToGlobalConfig(configPath2, provider, model, homeFn = () => p
7507
7617
  } catch {
7508
7618
  }
7509
7619
  return true;
7510
- } catch {
7620
+ } catch (err) {
7621
+ console.warn("[picker] saveToGlobalConfig failed:", err instanceof Error ? err.message : String(err));
7511
7622
  return false;
7512
7623
  }
7513
7624
  }
@@ -8159,14 +8270,14 @@ function summarize(value, name) {
8159
8270
  if (typeof v === "object" && v !== null) {
8160
8271
  const o = v;
8161
8272
  if (name === "edit") {
8162
- const path25 = typeof o["path"] === "string" ? o["path"] : "";
8273
+ const path26 = typeof o["path"] === "string" ? o["path"] : "";
8163
8274
  const reps = typeof o["replacements"] === "number" ? o["replacements"] : 0;
8164
- return `${path25} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
8275
+ return `${path26} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
8165
8276
  }
8166
8277
  if (name === "write") {
8167
- const path25 = typeof o["path"] === "string" ? o["path"] : "";
8278
+ const path26 = typeof o["path"] === "string" ? o["path"] : "";
8168
8279
  const bytes = typeof o["bytes"] === "number" ? o["bytes"] : void 0;
8169
- return bytes !== void 0 ? `${path25} ${bytes}B` : path25;
8280
+ return bytes !== void 0 ? `${path26} ${bytes}B` : path26;
8170
8281
  }
8171
8282
  if (typeof o["count"] === "number") {
8172
8283
  return `${o["count"]} match${o["count"] === 1 ? "" : "es"}`;
@@ -8926,7 +9037,7 @@ async function readKeyInput(deps, intent) {
8926
9037
  async function loadProviders(deps) {
8927
9038
  let raw;
8928
9039
  try {
8929
- raw = await fsp3.readFile(deps.globalConfigPath, "utf8");
9040
+ raw = await fsp4.readFile(deps.globalConfigPath, "utf8");
8930
9041
  } catch (err) {
8931
9042
  if (err.code !== "ENOENT") {
8932
9043
  deps.renderer.writeWarning(
@@ -8951,7 +9062,7 @@ async function mutateProviders(deps, mutator) {
8951
9062
  let raw;
8952
9063
  let fileExists = true;
8953
9064
  try {
8954
- raw = await fsp3.readFile(deps.globalConfigPath, "utf8");
9065
+ raw = await fsp4.readFile(deps.globalConfigPath, "utf8");
8955
9066
  } catch (err) {
8956
9067
  if (err.code !== "ENOENT") {
8957
9068
  throw new Error(
@@ -9026,7 +9137,7 @@ var updateCmd = async (args, deps) => {
9026
9137
  deps.renderer.write(`Updating wrongstack from v${info.current} to v${info.latest}...
9027
9138
  `);
9028
9139
  try {
9029
- const result = await new Promise((resolve4, reject) => {
9140
+ const result = await new Promise((resolve5, reject) => {
9030
9141
  const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
9031
9142
  const child = spawn(npmCommand, ["install", "-g", "wrongstack@latest"], {
9032
9143
  cwd,
@@ -9037,7 +9148,7 @@ var updateCmd = async (args, deps) => {
9037
9148
  _stderr += d;
9038
9149
  });
9039
9150
  child.on("error", reject);
9040
- child.on("close", (code) => resolve4({ code: code ?? 0 }));
9151
+ child.on("close", (code) => resolve5({ code: code ?? 0 }));
9041
9152
  });
9042
9153
  if (result.code === 0) {
9043
9154
  deps.renderer.write(`
@@ -9063,27 +9174,6 @@ Update failed: ${msg}
9063
9174
  return 1;
9064
9175
  }
9065
9176
  };
9066
- var req = createRequire(import.meta.url);
9067
- function readOwnVersion() {
9068
- const candidates = ["../package.json", "../../package.json"];
9069
- for (const rel of candidates) {
9070
- try {
9071
- const pkg = req(rel);
9072
- if (typeof pkg.version === "string" && pkg.version.length > 0) return pkg.version;
9073
- } catch {
9074
- }
9075
- }
9076
- return "dev";
9077
- }
9078
- var CLI_VERSION = readOwnVersion();
9079
- var API_VERSION = "0.0.0";
9080
- try {
9081
- const corePkg = req("@wrongstack/core/package.json");
9082
- if (corePkg.wrongstackApiVersion) API_VERSION = corePkg.wrongstackApiVersion;
9083
- } catch {
9084
- }
9085
-
9086
- // src/subcommands/handlers/diag-doctor.ts
9087
9177
  var diagCmd = async (_args, deps) => {
9088
9178
  const cfg = deps.config;
9089
9179
  const age = await deps.modelsRegistry.ageSeconds();
@@ -9166,7 +9256,7 @@ var doctorCmd = async (_args, deps) => {
9166
9256
  });
9167
9257
  }
9168
9258
  try {
9169
- await fsp3.access(deps.paths.secretsKey);
9259
+ await fsp4.access(deps.paths.secretsKey);
9170
9260
  checks.push({ name: "secret vault", status: "ok", detail: deps.paths.secretsKey });
9171
9261
  } catch {
9172
9262
  checks.push({
@@ -9176,10 +9266,10 @@ var doctorCmd = async (_args, deps) => {
9176
9266
  });
9177
9267
  }
9178
9268
  try {
9179
- await fsp3.mkdir(deps.paths.projectSessions, { recursive: true });
9269
+ await fsp4.mkdir(deps.paths.projectSessions, { recursive: true });
9180
9270
  const probe = path8.join(deps.paths.projectSessions, `.probe-${Date.now()}`);
9181
- await fsp3.writeFile(probe, "");
9182
- await fsp3.unlink(probe);
9271
+ await fsp4.writeFile(probe, "");
9272
+ await fsp4.unlink(probe);
9183
9273
  checks.push({ name: "sessions writable", status: "ok", detail: deps.paths.projectSessions });
9184
9274
  } catch (err) {
9185
9275
  checks.push({
@@ -9280,8 +9370,8 @@ var exportCmd = async (args, deps) => {
9280
9370
  return 1;
9281
9371
  }
9282
9372
  if (output) {
9283
- await fsp3.mkdir(path8.dirname(path8.resolve(deps.cwd, output)), { recursive: true });
9284
- await fsp3.writeFile(path8.resolve(deps.cwd, output), rendered, "utf8");
9373
+ await fsp4.mkdir(path8.dirname(path8.resolve(deps.cwd, output)), { recursive: true });
9374
+ await fsp4.writeFile(path8.resolve(deps.cwd, output), rendered, "utf8");
9285
9375
  deps.renderer.write(`Wrote ${rendered.length} bytes to ${output}
9286
9376
  `);
9287
9377
  } else {
@@ -9348,13 +9438,13 @@ var initCmd = async (_args, deps) => {
9348
9438
  } else {
9349
9439
  deps.renderer.writeInfo(`Found API key in env (${provider.envVars.join(" / ")}).`);
9350
9440
  }
9351
- await fsp3.mkdir(deps.paths.globalRoot, { recursive: true });
9441
+ await fsp4.mkdir(deps.paths.globalRoot, { recursive: true });
9352
9442
  const config = { version: 1, provider: providerId, model: modelId };
9353
9443
  if (apiKey) config.apiKey = apiKey;
9354
9444
  const vault = new DefaultSecretVault({ keyFile: deps.paths.secretsKey });
9355
9445
  const encrypted = encryptConfigSecrets(config, vault);
9356
9446
  await atomicWrite(deps.paths.globalConfig, JSON.stringify(encrypted, null, 2), { mode: 384 });
9357
- await fsp3.mkdir(path8.join(deps.projectRoot, ".wrongstack"), { recursive: true });
9447
+ await fsp4.mkdir(path8.join(deps.projectRoot, ".wrongstack"), { recursive: true });
9358
9448
  const agentsFile = path8.join(deps.projectRoot, ".wrongstack", "AGENTS.md");
9359
9449
  const projectFacts = await detectProjectFacts(deps.projectRoot);
9360
9450
  await atomicWrite(agentsFile, renderAgentsTemplate(projectFacts));
@@ -9494,8 +9584,8 @@ async function serveMcpStdio(deps) {
9494
9584
  log(
9495
9585
  `wrongstack MCP server ready at ${handle2.url} \u2014 exposing ${allowed.length} tool(s) (${mode})${token ? " [token auth]" : ""}.`
9496
9586
  );
9497
- await new Promise((resolve4) => {
9498
- const stop = () => resolve4();
9587
+ await new Promise((resolve5) => {
9588
+ const stop = () => resolve5();
9499
9589
  process.once("SIGINT", stop);
9500
9590
  process.once("SIGTERM", stop);
9501
9591
  });
@@ -9580,7 +9670,7 @@ async function addMcpServer(args, deps) {
9580
9670
  serverCfg.enabled = enable;
9581
9671
  let existing = {};
9582
9672
  try {
9583
- existing = JSON.parse(await fsp3.readFile(deps.paths.globalConfig, "utf8"));
9673
+ existing = JSON.parse(await fsp4.readFile(deps.paths.globalConfig, "utf8"));
9584
9674
  } catch {
9585
9675
  }
9586
9676
  const mcpServers = existing.mcpServers ?? {};
@@ -9600,7 +9690,7 @@ async function addMcpServer(args, deps) {
9600
9690
  async function removeMcpServer(name, deps) {
9601
9691
  let existing = {};
9602
9692
  try {
9603
- existing = JSON.parse(await fsp3.readFile(deps.paths.globalConfig, "utf8"));
9693
+ existing = JSON.parse(await fsp4.readFile(deps.paths.globalConfig, "utf8"));
9604
9694
  } catch {
9605
9695
  deps.renderer.writeError("No config file found.\n");
9606
9696
  return 1;
@@ -9721,7 +9811,7 @@ function renderConfiguredPlugins(config) {
9721
9811
  }
9722
9812
  async function readConfig2(file) {
9723
9813
  try {
9724
- return JSON.parse(await fsp3.readFile(file, "utf8"));
9814
+ return JSON.parse(await fsp4.readFile(file, "utf8"));
9725
9815
  } catch {
9726
9816
  return {};
9727
9817
  }
@@ -9814,7 +9904,7 @@ var usageCmd = async (_args, deps) => {
9814
9904
  var projectsCmd = async (_args, deps) => {
9815
9905
  const projectsRoot = path8.join(deps.paths.globalRoot, "projects");
9816
9906
  try {
9817
- const entries = await fsp3.readdir(projectsRoot);
9907
+ const entries = await fsp4.readdir(projectsRoot);
9818
9908
  if (entries.length === 0) {
9819
9909
  deps.renderer.write("No projects tracked.\n");
9820
9910
  return 0;
@@ -9822,7 +9912,7 @@ var projectsCmd = async (_args, deps) => {
9822
9912
  for (const hash of entries) {
9823
9913
  try {
9824
9914
  const meta = JSON.parse(
9825
- await fsp3.readFile(path8.join(projectsRoot, hash, "meta.json"), "utf8")
9915
+ await fsp4.readFile(path8.join(projectsRoot, hash, "meta.json"), "utf8")
9826
9916
  );
9827
9917
  deps.renderer.write(
9828
9918
  ` ${color.dim(hash)} ${color.dim(meta.lastSeen ?? "")} ${meta.root ?? "?"}
@@ -10032,7 +10122,7 @@ async function mutateModelsConfig(deps, mutator) {
10032
10122
  let fileExists = true;
10033
10123
  let raw;
10034
10124
  try {
10035
- raw = await fsp3.readFile(configPath2, "utf8");
10125
+ raw = await fsp4.readFile(configPath2, "utf8");
10036
10126
  } catch (err) {
10037
10127
  if (err.code !== "ENOENT") throw err;
10038
10128
  fileExists = false;
@@ -10193,7 +10283,7 @@ var sessionsFleetCmd = async (args, deps) => {
10193
10283
  async function listFleetRuns(deps) {
10194
10284
  let entries = [];
10195
10285
  try {
10196
- entries = await fsp3.readdir(deps.paths.projectSessions);
10286
+ entries = await fsp4.readdir(deps.paths.projectSessions);
10197
10287
  } catch {
10198
10288
  deps.renderer.writeError(`Cannot read projectSessions: ${deps.paths.projectSessions}
10199
10289
  `);
@@ -10204,7 +10294,7 @@ async function listFleetRuns(deps) {
10204
10294
  const runDir = path8.join(deps.paths.projectSessions, id);
10205
10295
  let stat4;
10206
10296
  try {
10207
- stat4 = await fsp3.stat(runDir);
10297
+ stat4 = await fsp4.stat(runDir);
10208
10298
  } catch {
10209
10299
  continue;
10210
10300
  }
@@ -10214,18 +10304,18 @@ async function listFleetRuns(deps) {
10214
10304
  let subagentCount = 0;
10215
10305
  let subagentsDir;
10216
10306
  try {
10217
- await fsp3.access(path8.join(runDir, "fleet.json"));
10307
+ await fsp4.access(path8.join(runDir, "fleet.json"));
10218
10308
  manifest = true;
10219
10309
  } catch {
10220
10310
  }
10221
10311
  try {
10222
- await fsp3.access(path8.join(runDir, "checkpoint.json"));
10312
+ await fsp4.access(path8.join(runDir, "checkpoint.json"));
10223
10313
  checkpoint = true;
10224
10314
  } catch {
10225
10315
  }
10226
10316
  try {
10227
10317
  subagentsDir = path8.join(runDir, "subagents");
10228
- const files = await fsp3.readdir(subagentsDir);
10318
+ const files = await fsp4.readdir(subagentsDir);
10229
10319
  subagentCount = files.filter((f) => f.endsWith(".jsonl")).length;
10230
10320
  } catch {
10231
10321
  }
@@ -10256,7 +10346,7 @@ async function showFleetRun(runId, deps) {
10256
10346
  const runDir = path8.join(deps.paths.projectSessions, runId);
10257
10347
  let stat4;
10258
10348
  try {
10259
- stat4 = await fsp3.stat(runDir);
10349
+ stat4 = await fsp4.stat(runDir);
10260
10350
  } catch {
10261
10351
  deps.renderer.writeError(`Fleet run not found: ${runId}
10262
10352
  `);
@@ -10273,7 +10363,7 @@ Fleet Run: ${runId}
10273
10363
  const manifestPath = path8.join(runDir, "fleet.json");
10274
10364
  let manifestData = null;
10275
10365
  try {
10276
- manifestData = await fsp3.readFile(manifestPath, "utf8");
10366
+ manifestData = await fsp4.readFile(manifestPath, "utf8");
10277
10367
  const manifest = JSON.parse(manifestData);
10278
10368
  const subagents = manifest.subagents ?? [];
10279
10369
  const tasks = manifest.tasks ?? [];
@@ -10289,12 +10379,12 @@ Fleet Run: ${runId}
10289
10379
  const checkpointPath = path8.join(runDir, "checkpoint.json");
10290
10380
  let checkpointData = null;
10291
10381
  try {
10292
- checkpointData = await fsp3.readFile(checkpointPath, "utf8");
10382
+ checkpointData = await fsp4.readFile(checkpointPath, "utf8");
10293
10383
  const snap = JSON.parse(checkpointData);
10294
10384
  const lockPath = `${checkpointPath}.lock`;
10295
10385
  let lockStatus = color.dim("\u25CB no lock");
10296
10386
  try {
10297
- const lockRaw = await fsp3.readFile(lockPath, "utf8");
10387
+ const lockRaw = await fsp4.readFile(lockPath, "utf8");
10298
10388
  const lock = JSON.parse(lockRaw);
10299
10389
  lockStatus = `${color.yellow("\u25B8")} lock held by pid ${lock.pid} on ${lock.hostname} (started ${lock.startedAt})`;
10300
10390
  } catch {
@@ -10336,7 +10426,7 @@ Fleet Run: ${runId}
10336
10426
  const subagentsDir = path8.join(runDir, "subagents");
10337
10427
  let subagentFiles = [];
10338
10428
  try {
10339
- subagentFiles = await fsp3.readdir(subagentsDir);
10429
+ subagentFiles = await fsp4.readdir(subagentsDir);
10340
10430
  subagentFiles = subagentFiles.filter((f) => f.endsWith(".jsonl"));
10341
10431
  } catch {
10342
10432
  }
@@ -10348,7 +10438,7 @@ Fleet Run: ${runId}
10348
10438
  const filePath = path8.join(subagentsDir, f);
10349
10439
  let size;
10350
10440
  try {
10351
- const s = await fsp3.stat(filePath);
10441
+ const s = await fsp4.stat(filePath);
10352
10442
  size = s.size;
10353
10443
  } catch {
10354
10444
  size = 0;
@@ -10364,7 +10454,7 @@ Fleet Run: ${runId}
10364
10454
  }
10365
10455
  const sharedDir = path8.join(runDir, "shared");
10366
10456
  try {
10367
- const files = await fsp3.readdir(sharedDir);
10457
+ const files = await fsp4.readdir(sharedDir);
10368
10458
  deps.renderer.write(`
10369
10459
  Shared scratchpad: ${files.length} file(s)
10370
10460
  `);
@@ -10764,10 +10854,10 @@ var auditCmd = async (args, deps) => {
10764
10854
  return verify.ok ? 0 : 1;
10765
10855
  };
10766
10856
  async function listAudits(log, dir, deps) {
10767
- const fs25 = await import('fs/promises');
10857
+ const fs26 = await import('fs/promises');
10768
10858
  let entries;
10769
10859
  try {
10770
- entries = await fs25.readdir(dir);
10860
+ entries = await fs26.readdir(dir);
10771
10861
  } catch {
10772
10862
  deps.renderer.write(
10773
10863
  color.dim(`No sessions dir found at ${dir}. Run a session first.`) + "\n"
@@ -10918,22 +11008,22 @@ function fmtDuration(ms) {
10918
11008
  const remMin = m - h * 60;
10919
11009
  return `${h}h${remMin}m`;
10920
11010
  }
10921
- function fmtTaskResultLine(r, color46) {
11011
+ function fmtTaskResultLine(r, color49) {
10922
11012
  const stats = `${r.iterations}it ${r.toolCalls}tc ${fmtDuration(r.durationMs)}`;
10923
11013
  const errMsg = typeof r.error === "string" ? r.error : r.error?.message;
10924
11014
  const errKind = typeof r.error === "object" ? r.error?.kind : void 0;
10925
11015
  const errTail = errMsg ? ` \u2014 ${errMsg.replace(/\s+/g, " ").slice(0, 80)}${errMsg.length > 80 ? "\u2026" : ""}` : "";
10926
- const errKindChip = errKind ? color46.dim(` [${errKind}]`) : "";
10927
- const errSnip = errMsg || errKind ? `${errKindChip}${color46.dim(errTail)}` : "";
11016
+ const errKindChip = errKind ? color49.dim(` [${errKind}]`) : "";
11017
+ const errSnip = errMsg || errKind ? `${errKindChip}${color49.dim(errTail)}` : "";
10928
11018
  switch (r.status) {
10929
11019
  case "success":
10930
- return { mark: color46.green("\u2713"), stats, tail: "" };
11020
+ return { mark: color49.green("\u2713"), stats, tail: "" };
10931
11021
  case "timeout":
10932
- return { mark: color46.yellow("\u23F1"), stats: `${color46.yellow("timeout")} ${stats}`, tail: errSnip };
11022
+ return { mark: color49.yellow("\u23F1"), stats: `${color49.yellow("timeout")} ${stats}`, tail: errSnip };
10933
11023
  case "stopped":
10934
- return { mark: color46.dim("\u2298"), stats: `${color46.dim("stopped")} ${stats}`, tail: errSnip };
11024
+ return { mark: color49.dim("\u2298"), stats: `${color49.dim("stopped")} ${stats}`, tail: errSnip };
10935
11025
  case "failed":
10936
- return { mark: color46.red("\u2717"), stats: `${color46.red("failed")} ${stats}`, tail: errSnip };
11026
+ return { mark: color49.red("\u2717"), stats: `${color49.red("failed")} ${stats}`, tail: errSnip };
10937
11027
  }
10938
11028
  }
10939
11029
 
@@ -11057,20 +11147,51 @@ async function boot(argv) {
11057
11147
  const modelFlag = typeof flags["model"] === "string" ? flags["model"] : void 0;
11058
11148
  if (!(!!providerFlag && !!modelFlag)) {
11059
11149
  if (isStdinTTY()) {
11060
- const picked = await runPicker({
11061
- modelsRegistry,
11062
- renderer,
11063
- reader,
11064
- config,
11065
- defaultProvider: providerFlag ?? config.provider,
11066
- defaultModel: modelFlag ?? config.model
11067
- });
11068
- if (!picked) {
11150
+ let picked;
11151
+ let skipPicker = false;
11152
+ const savedProvider = config.provider;
11153
+ const savedModel = config.model;
11154
+ if (savedProvider && savedModel) {
11155
+ renderer.write(
11156
+ `
11157
+ ${color.dim("Last settings:")} ${color.bold(savedProvider)} / ${color.bold(savedModel)}
11158
+ `
11159
+ );
11160
+ const answer = (await reader.readLine(
11161
+ ` ${color.amber("?")} Continue with these? ${color.dim("[Y/n/q]")} `
11162
+ )).trim().toLowerCase();
11163
+ if (answer === "q") {
11164
+ renderer.write(color.dim(" Goodbye!\n"));
11165
+ await reader.close();
11166
+ return 0;
11167
+ }
11168
+ if (answer !== "n" && answer !== "no") {
11169
+ skipPicker = true;
11170
+ renderer.write(
11171
+ `
11172
+ ${color.green("\u25B6")} ${color.bold(savedProvider)} / ${color.bold(savedModel)}
11173
+
11174
+ `
11175
+ );
11176
+ }
11177
+ }
11178
+ if (!skipPicker) {
11179
+ picked = await runPicker({
11180
+ modelsRegistry,
11181
+ renderer,
11182
+ reader,
11183
+ config,
11184
+ defaultProvider: providerFlag ?? config.provider,
11185
+ defaultModel: modelFlag ?? config.model
11186
+ });
11187
+ }
11188
+ if (!picked && !skipPicker) {
11069
11189
  if (!config.provider || !config.model) {
11070
11190
  await reader.close();
11071
11191
  return 2;
11072
11192
  }
11073
- } else {
11193
+ }
11194
+ if (picked) {
11074
11195
  const prevProvider = config.provider;
11075
11196
  const prevModel = config.model;
11076
11197
  config = patchConfig(config, { provider: picked.provider, model: picked.model });
@@ -11080,8 +11201,15 @@ async function boot(argv) {
11080
11201
  picked.provider,
11081
11202
  picked.model
11082
11203
  );
11083
- if (saved) renderer.writeInfo(`Saved ${picked.provider}/${picked.model} as default.
11204
+ if (saved) {
11205
+ renderer.writeInfo(`Saved ${picked.provider}/${picked.model} as default.
11084
11206
  `);
11207
+ } else {
11208
+ renderer.writeWarning(
11209
+ `Could not save ${picked.provider}/${picked.model} to config. Check permissions or disk space.
11210
+ `
11211
+ );
11212
+ }
11085
11213
  }
11086
11214
  }
11087
11215
  } else if (!config.provider || !config.model) {
@@ -11114,6 +11242,12 @@ async function boot(argv) {
11114
11242
  } else if (flags["autonomy"] === true) {
11115
11243
  autonomyPinned = "auto";
11116
11244
  }
11245
+ const lastChoices = config.launch ? {
11246
+ mode: config.launch.mode ?? "tui",
11247
+ yolo: config.yolo ?? true,
11248
+ director: config.launch.director ?? true,
11249
+ autonomy: config.launch.autonomy ?? "auto"
11250
+ } : void 0;
11117
11251
  let choices;
11118
11252
  try {
11119
11253
  choices = await runLaunchPrompts({
@@ -11122,7 +11256,8 @@ async function boot(argv) {
11122
11256
  modePinned,
11123
11257
  yoloPinned,
11124
11258
  directorPinned,
11125
- autonomyPinned
11259
+ autonomyPinned,
11260
+ lastChoices
11126
11261
  });
11127
11262
  } catch (err) {
11128
11263
  if (err instanceof LaunchAbortedError) {
@@ -11141,6 +11276,10 @@ async function boot(argv) {
11141
11276
  if (choices.yolo !== config.yolo) config = patchConfig(config, { yolo: choices.yolo });
11142
11277
  if (choices.director) flags["director"] = true;
11143
11278
  flags["autonomy"] = choices.autonomy;
11279
+ try {
11280
+ await persistLaunchChoices(wpaths.globalConfig, choices);
11281
+ } catch {
11282
+ }
11144
11283
  printLaunchHints(renderer, flags, {
11145
11284
  cursorFile: path8.join(wpaths.cacheDir, "hint-cursor")
11146
11285
  });
@@ -11534,7 +11673,7 @@ async function runRepl(opts) {
11534
11673
  `[eternal] ${err instanceof Error ? err.message : String(err)}`
11535
11674
  );
11536
11675
  }
11537
- await new Promise((resolve4) => setTimeout(resolve4, 250));
11676
+ await new Promise((resolve5) => setTimeout(resolve5, 250));
11538
11677
  continue;
11539
11678
  }
11540
11679
  } else if (opts.getAutonomy?.() === "eternal-parallel") {
@@ -11580,7 +11719,7 @@ async function runRepl(opts) {
11580
11719
  `[parallel] ${err instanceof Error ? err.message : String(err)}`
11581
11720
  );
11582
11721
  }
11583
- await new Promise((resolve4) => setTimeout(resolve4, 250));
11722
+ await new Promise((resolve5) => setTimeout(resolve5, 250));
11584
11723
  continue;
11585
11724
  }
11586
11725
  }
@@ -12059,10 +12198,10 @@ var EMPTY = "\u2591";
12059
12198
  function renderContextChip(used, max) {
12060
12199
  const ratio = Math.max(0, Math.min(1, used / max));
12061
12200
  const pct2 = Math.round(ratio * 100);
12062
- const bar = renderProgress2(ratio, 6);
12201
+ const bar = renderProgress3(ratio, 6);
12063
12202
  return `${bar} ${pct2}% (${fmtTok(used)}/${fmtTok(max)})`;
12064
12203
  }
12065
- function renderProgress2(ratio, width) {
12204
+ function renderProgress3(ratio, width) {
12066
12205
  const clamped = Math.max(0, Math.min(1, ratio));
12067
12206
  const filled = clamped === 0 ? 0 : Math.max(1, Math.round(clamped * width));
12068
12207
  const capped = Math.min(width, filled);
@@ -12348,15 +12487,10 @@ async function execute(deps) {
12348
12487
  },
12349
12488
  effectiveMaxContext,
12350
12489
  // Default OFF so the terminal's native scrollback works for chat
12351
- // history out of the box (mouse wheel / Shift+PgUp). Users who hit
12352
- // resize/overlay-leak artifacts can opt back into alt-screen with
12353
- // `--alt-screen`. `--no-alt-screen` still wins when both are passed.
12490
+ // history out of the box. Users who hit resize/overlay-leak
12491
+ // artifacts can opt back into alt-screen with `--alt-screen`.
12492
+ // `--no-alt-screen` still wins when both are passed.
12354
12493
  altScreen: flags["alt-screen"] === true && flags["no-alt-screen"] !== true,
12355
- // Mouse mode is DISABLED. It was unreliable on Windows consoles
12356
- // (freezes / constant repaint in the managed viewport) and is not
12357
- // wanted, so `--mouse` is intentionally ignored and never engages —
12358
- // the TUI stays keyboard-only. Do not re-wire `flags.mouse` here.
12359
- mouse: false,
12360
12494
  director,
12361
12495
  fleetRoster,
12362
12496
  onAfterExit: () => {
@@ -12502,6 +12636,22 @@ async function execute(deps) {
12502
12636
  }
12503
12637
  return code;
12504
12638
  }
12639
+ function buildRoutingRunner(config, host) {
12640
+ const standardRunner = makeAgentSubagentRunner({
12641
+ factory: host.makeSubagentFactory(config),
12642
+ fleetBus: host.getDirector()?.fleet ?? NULL_FLEET_BUS
12643
+ });
12644
+ return async (task, ctx) => {
12645
+ const subCfg = ctx.config;
12646
+ if (subCfg.provider === "acp") {
12647
+ const cacheKey = subCfg.role ?? subCfg.name ?? subCfg.id;
12648
+ return host.buildACPRunner(cacheKey).then((r) => r(task, ctx));
12649
+ }
12650
+ return standardRunner(task, ctx);
12651
+ };
12652
+ }
12653
+
12654
+ // src/fleet/host.ts
12505
12655
  var MultiAgentHost = class {
12506
12656
  constructor(deps, opts = {}) {
12507
12657
  this.deps = deps;
@@ -12703,8 +12853,10 @@ var MultiAgentHost = class {
12703
12853
  // meaningless to a single delegated subtask.
12704
12854
  subagent: true
12705
12855
  });
12706
- if (subCfg.systemPromptOverride) {
12707
- baseSystem.push({ type: "text", text: subCfg.systemPromptOverride });
12856
+ baseSystem.unshift({ type: "text", text: DEFAULT_SUBAGENT_BASELINE });
12857
+ const rolePrompt = subCfg.systemPromptOverride ?? (subCfg.role ? FLEET_ROSTER[subCfg.role]?.prompt : void 0);
12858
+ if (rolePrompt) {
12859
+ baseSystem.push({ type: "text", text: rolePrompt });
12708
12860
  }
12709
12861
  let subSession;
12710
12862
  if (this.sessionFactory) {
@@ -13133,20 +13285,6 @@ var MultiAgentHost = class {
13133
13285
  }
13134
13286
  }
13135
13287
  };
13136
- function buildRoutingRunner(config, host) {
13137
- const standardRunner = makeAgentSubagentRunner({
13138
- factory: host.makeSubagentFactory(config),
13139
- fleetBus: host.getDirector()?.fleet ?? NULL_FLEET_BUS
13140
- });
13141
- return async (task, ctx) => {
13142
- const subCfg = ctx.config;
13143
- if (subCfg.provider === "acp") {
13144
- const cacheKey = subCfg.role ?? subCfg.name ?? subCfg.id;
13145
- return host.buildACPRunner(cacheKey).then((r) => r(task, ctx));
13146
- }
13147
- return standardRunner(task, ctx);
13148
- };
13149
- }
13150
13288
  function makePromptDelegate(reader) {
13151
13289
  return async (tool, input, suggestedPattern) => {
13152
13290
  writeOut("\x07");
@@ -13248,11 +13386,11 @@ var SessionStats = class {
13248
13386
  if (e.name === "bash") this.bashCommands++;
13249
13387
  else if (e.name === "fetch") this.fetches++;
13250
13388
  if (!e.ok) return;
13251
- const path25 = typeof input?.path === "string" ? input.path : void 0;
13252
- if (e.name === "read" && path25) this.readPaths.add(path25);
13253
- else if (e.name === "edit" && path25) this.editedPaths.add(path25);
13254
- else if (e.name === "write" && path25) {
13255
- this.writtenPaths.add(path25);
13389
+ const path26 = typeof input?.path === "string" ? input.path : void 0;
13390
+ if (e.name === "read" && path26) this.readPaths.add(path26);
13391
+ else if (e.name === "edit" && path26) this.editedPaths.add(path26);
13392
+ else if (e.name === "write" && path26) {
13393
+ this.writtenPaths.add(path26);
13256
13394
  const content = typeof input?.content === "string" ? input.content : "";
13257
13395
  this.bytesWritten += Buffer.byteLength(content, "utf8");
13258
13396
  }
@@ -13358,7 +13496,7 @@ function samplePaths(set) {
13358
13496
  }
13359
13497
  var WORKTREE_PHASE_CONCURRENCY = 4;
13360
13498
  function gitText(args, cwd) {
13361
- return new Promise((resolve4) => {
13499
+ return new Promise((resolve5) => {
13362
13500
  let out = "";
13363
13501
  const child = spawn("git", args, {
13364
13502
  cwd,
@@ -13371,8 +13509,8 @@ function gitText(args, cwd) {
13371
13509
  child.stderr?.on("data", (c) => {
13372
13510
  out += c.toString();
13373
13511
  });
13374
- child.on("error", () => resolve4({ code: 1, out }));
13375
- child.on("close", (code) => resolve4({ code: code ?? 1, out: out.trim() }));
13512
+ child.on("error", () => resolve5({ code: 1, out }));
13513
+ child.on("close", (code) => resolve5({ code: code ?? 1, out: out.trim() }));
13376
13514
  });
13377
13515
  }
13378
13516
  async function isGitRepo(cwd) {
@@ -13380,7 +13518,7 @@ async function isGitRepo(cwd) {
13380
13518
  return code === 0 && out.trim() === "true";
13381
13519
  }
13382
13520
  function runCmd(cmd, args, cwd, shell = false) {
13383
- return new Promise((resolve4) => {
13521
+ return new Promise((resolve5) => {
13384
13522
  let out = "";
13385
13523
  const child = spawn(cmd, args, {
13386
13524
  cwd,
@@ -13394,8 +13532,8 @@ function runCmd(cmd, args, cwd, shell = false) {
13394
13532
  child.stderr?.on("data", (c) => {
13395
13533
  out += c.toString();
13396
13534
  });
13397
- child.on("error", (e) => resolve4({ code: 1, out: `${out}${String(e)}` }));
13398
- child.on("close", (code) => resolve4({ code: code ?? 1, out: out.trim() }));
13535
+ child.on("error", (e) => resolve5({ code: 1, out: `${out}${String(e)}` }));
13536
+ child.on("close", (code) => resolve5({ code: code ?? 1, out: out.trim() }));
13399
13537
  });
13400
13538
  }
13401
13539
  function detectPackageManager2(root) {
@@ -13779,10 +13917,10 @@ function renderContextChip2(ctx) {
13779
13917
  const ratio = Math.max(0, Math.min(1, ctx.used / ctx.max));
13780
13918
  const pct2 = Math.round(ratio * 100);
13781
13919
  const chipColor = ratio >= 0.85 ? color.red : ratio >= 0.65 ? color.yellow : color.cyan;
13782
- const bar = renderProgress3(ratio, 8);
13920
+ const bar = renderProgress4(ratio, 8);
13783
13921
  return color.dim("ctx ") + chipColor(bar) + chipColor(` ${pct2}%`) + color.dim(` (${fmtTok(ctx.used)}/${fmtTok(ctx.max)})`);
13784
13922
  }
13785
- function renderProgress3(ratio, width) {
13923
+ function renderProgress4(ratio, width) {
13786
13924
  const clamped = Math.max(0, Math.min(1, ratio));
13787
13925
  const filled = clamped === 0 ? 0 : Math.max(1, Math.round(clamped * width));
13788
13926
  const capped = Math.min(width, filled);
@@ -14042,7 +14180,7 @@ function setupMetrics(params) {
14042
14180
  name: "session-store",
14043
14181
  check: async () => {
14044
14182
  try {
14045
- await fsp3.access(wpaths.projectSessions);
14183
+ await fsp4.access(wpaths.projectSessions);
14046
14184
  return { status: "healthy" };
14047
14185
  } catch (e) {
14048
14186
  return { status: "unhealthy", detail: e instanceof Error ? e.message : "access denied" };
@@ -14089,6 +14227,91 @@ function setupMetrics(params) {
14089
14227
  }
14090
14228
  return { metricsSink, healthRegistry, metricsServerHandle };
14091
14229
  }
14230
+ var FILE_EDIT_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "multi-edit", "notebook-edit"]);
14231
+ var IGNORE_DIRS = /* @__PURE__ */ new Set([
14232
+ "node_modules",
14233
+ ".git",
14234
+ "dist",
14235
+ "build",
14236
+ ".next",
14237
+ "coverage",
14238
+ ".turbo",
14239
+ "__snapshots__",
14240
+ ".nyc_output"
14241
+ ]);
14242
+ function isIgnored(rel) {
14243
+ return rel.split(/[/\\]/).some((seg) => IGNORE_DIRS.has(seg));
14244
+ }
14245
+ async function setupCodebaseIndexing(deps) {
14246
+ const { config, pipelines, projectRoot, logger } = deps;
14247
+ const idx = config.indexing;
14248
+ if (!idx) return () => {
14249
+ };
14250
+ const debounceMs = idx.debounceMs ?? 400;
14251
+ const onError = (err) => logger.debug(`codebase auto-index failed: ${err instanceof Error ? err.message : String(err)}`);
14252
+ if (idx.onSessionStart) {
14253
+ void runStartupIndex({ projectRoot }).then((r) => {
14254
+ const summary = `${color.green("\u2713")} codebase index ready ${color.dim(`\u2014 ${r.symbolsIndexed} symbols \xB7 ${r.filesIndexed} files \xB7 ${r.durationMs}ms`)}`;
14255
+ process.stderr.write(`
14256
+ ${summary}
14257
+ `);
14258
+ }).catch((err) => {
14259
+ logger.warn(
14260
+ `codebase index (startup) failed: ${err instanceof Error ? err.message : String(err)}`
14261
+ );
14262
+ });
14263
+ }
14264
+ if (idx.onEdit) {
14265
+ pipelines.toolCall.use({
14266
+ name: "CodebaseAutoIndex",
14267
+ // Non-core owner → the pipeline error boundary swallows failures instead
14268
+ // of failing the turn (see wiring/pipeline.ts).
14269
+ owner: "codebase-index",
14270
+ handler: async (payload, next) => {
14271
+ try {
14272
+ const tool = payload.tool;
14273
+ if (tool?.mutating && FILE_EDIT_TOOLS.has(tool.name)) {
14274
+ const fp = payload.toolUse.input?.file_path;
14275
+ if (typeof fp === "string" && fp.length > 0) {
14276
+ const abs = path8.resolve(payload.ctx.cwd, fp);
14277
+ if (isIndexableFile(abs)) {
14278
+ enqueueReindex({ projectRoot, files: [abs], debounceMs, onError });
14279
+ }
14280
+ }
14281
+ }
14282
+ } catch {
14283
+ }
14284
+ return next(payload);
14285
+ }
14286
+ });
14287
+ }
14288
+ let watcher;
14289
+ if (idx.watchExternal) {
14290
+ try {
14291
+ watcher = fs12.watch(projectRoot, { recursive: true }, (_event, filename) => {
14292
+ if (!filename) return;
14293
+ const rel = filename.toString();
14294
+ if (isIgnored(rel)) return;
14295
+ const abs = path8.resolve(projectRoot, rel);
14296
+ if (!isIndexableFile(abs)) return;
14297
+ enqueueReindex({ projectRoot, files: [abs], debounceMs, onError });
14298
+ });
14299
+ watcher.on("error", (err) => logger.debug(`codebase index watcher error: ${err}`));
14300
+ watcher.unref?.();
14301
+ } catch (err) {
14302
+ logger.debug(
14303
+ `codebase index watcher unavailable: ${err instanceof Error ? err.message : String(err)}`
14304
+ );
14305
+ }
14306
+ }
14307
+ return () => {
14308
+ try {
14309
+ watcher?.close();
14310
+ } catch {
14311
+ }
14312
+ cancelPendingReindexes();
14313
+ };
14314
+ }
14092
14315
  function createApi(ownerName, base) {
14093
14316
  return new DefaultPluginAPI({ ownerName, ...base });
14094
14317
  }
@@ -14425,21 +14648,6 @@ async function promptRecovery(reader, renderer, abandoned, autoRecover) {
14425
14648
  );
14426
14649
  return answer;
14427
14650
  }
14428
- var isMain = import.meta.url === `file://${process.argv[1]?.replace(/\\/g, "/")}` || process.argv[1]?.endsWith("/cli/dist/index.js") || process.argv[1]?.endsWith("\\cli\\dist\\index.js");
14429
- function runAsMain(mainFn) {
14430
- if (!isMain) return;
14431
- mainFn(process.argv.slice(2)).then(
14432
- (c) => {
14433
- process.exitCode = c;
14434
- setTimeout(() => process.exit(c), 500).unref();
14435
- },
14436
- (err) => {
14437
- writeErr((err instanceof Error ? err.stack : String(err)) + "\n");
14438
- process.exitCode = 1;
14439
- setTimeout(() => process.exit(1), 500).unref();
14440
- }
14441
- );
14442
- }
14443
14651
  async function launchEternalFromFlag(deps) {
14444
14652
  const { eternalFlag } = deps;
14445
14653
  if (eternalFlag.length === 0) return false;
@@ -14475,7 +14683,7 @@ async function launchEternalFromFlag(deps) {
14475
14683
  return true;
14476
14684
  }
14477
14685
 
14478
- // src/index.ts
14686
+ // src/cli-main.ts
14479
14687
  async function main(argv) {
14480
14688
  const ctx = await boot(argv);
14481
14689
  if (typeof ctx === "number") return ctx;
@@ -14912,7 +15120,8 @@ async function main(argv) {
14912
15120
  const directorMode = flags["director"] === true || typeof flags["resume"] === "string";
14913
15121
  const maxConcurrentFromFlag = typeof flags["max-concurrent"] === "string" ? Number.parseInt(flags["max-concurrent"], 10) : void 0;
14914
15122
  const maxConcurrentFromEnv = typeof process.env["WRONGSTACK_MAX_CONCURRENT"] === "string" ? Number.parseInt(process.env["WRONGSTACK_MAX_CONCURRENT"], 10) : void 0;
14915
- const maxConcurrent = Number.isFinite(maxConcurrentFromFlag) && maxConcurrentFromFlag > 0 ? maxConcurrentFromFlag : Number.isFinite(maxConcurrentFromEnv) && maxConcurrentFromEnv > 0 ? maxConcurrentFromEnv : void 0;
15123
+ const maxConcurrentFromConfig = typeof config.maxConcurrent === "number" && config.maxConcurrent > 0 ? config.maxConcurrent : void 0;
15124
+ const maxConcurrent = Number.isFinite(maxConcurrentFromFlag) && maxConcurrentFromFlag > 0 ? maxConcurrentFromFlag : Number.isFinite(maxConcurrentFromEnv) && maxConcurrentFromEnv > 0 ? maxConcurrentFromEnv : Number.isFinite(maxConcurrentFromConfig) && maxConcurrentFromConfig > 0 ? maxConcurrentFromConfig : void 0;
14916
15125
  let director = null;
14917
15126
  let autonomyMode = (() => {
14918
15127
  const v = flags["autonomy"];
@@ -15242,6 +15451,7 @@ async function main(argv) {
15242
15451
  }
15243
15452
  try {
15244
15453
  multiAgentHost.setMaxConcurrent(n);
15454
+ events.emit("concurrency.changed", { n });
15245
15455
  } catch (err) {
15246
15456
  return err instanceof Error ? err.message : String(err);
15247
15457
  }
@@ -15296,7 +15506,7 @@ async function main(argv) {
15296
15506
  const subagentsRoot = path8.join(fleetRootForPromotion, "subagents");
15297
15507
  let runDirs;
15298
15508
  try {
15299
- runDirs = await fsp3.readdir(subagentsRoot);
15509
+ runDirs = await fsp4.readdir(subagentsRoot);
15300
15510
  } catch {
15301
15511
  return "No fleet transcripts on disk \u2014 no subagents have been spawned for this session.";
15302
15512
  }
@@ -15305,7 +15515,7 @@ async function main(argv) {
15305
15515
  const runDir = path8.join(subagentsRoot, runId);
15306
15516
  let files;
15307
15517
  try {
15308
- files = await fsp3.readdir(runDir);
15518
+ files = await fsp4.readdir(runDir);
15309
15519
  } catch {
15310
15520
  continue;
15311
15521
  }
@@ -15313,7 +15523,7 @@ async function main(argv) {
15313
15523
  if (!f.endsWith(".jsonl")) continue;
15314
15524
  const full = path8.join(runDir, f);
15315
15525
  try {
15316
- const stat4 = await fsp3.stat(full);
15526
+ const stat4 = await fsp4.stat(full);
15317
15527
  found.push({
15318
15528
  runId,
15319
15529
  subagentId: f.replace(/\.jsonl$/, ""),
@@ -15354,7 +15564,7 @@ async function main(argv) {
15354
15564
  ].join("\n");
15355
15565
  }
15356
15566
  const t = matches[0];
15357
- const raw = await fsp3.readFile(t.file, "utf8");
15567
+ const raw = await fsp4.readFile(t.file, "utf8");
15358
15568
  if (mode === "raw") return raw;
15359
15569
  const lines = raw.split("\n").filter((l) => l.trim());
15360
15570
  const counts = {};
@@ -15610,7 +15820,7 @@ Restart WrongStack to load or unload plugin code in this session.`;
15610
15820
  const { spawn: spawn3 } = await import('child_process');
15611
15821
  const cwd2 = projectRoot;
15612
15822
  const statusResult = await new Promise(
15613
- (resolve4, reject) => {
15823
+ (resolve5, reject) => {
15614
15824
  const child = spawn3("git", ["status", "--porcelain"], {
15615
15825
  cwd: cwd2,
15616
15826
  stdio: ["ignore", "pipe", "pipe"]
@@ -15620,7 +15830,7 @@ Restart WrongStack to load or unload plugin code in this session.`;
15620
15830
  stdout += d;
15621
15831
  });
15622
15832
  child.on("error", reject);
15623
- child.on("close", (code) => resolve4({ stdout, code: code ?? 0 }));
15833
+ child.on("close", (code) => resolve5({ stdout, code: code ?? 0 }));
15624
15834
  }
15625
15835
  );
15626
15836
  if (statusResult.stdout.trim().length > 0) {
@@ -15746,6 +15956,13 @@ Restart WrongStack to load or unload plugin code in this session.`;
15746
15956
  if (eternalFlag.length > 0) {
15747
15957
  autonomyMode = "eternal";
15748
15958
  }
15959
+ const disposeIndexing = await setupCodebaseIndexing({
15960
+ config,
15961
+ pipelines,
15962
+ projectRoot,
15963
+ logger
15964
+ });
15965
+ process.once("exit", disposeIndexing);
15749
15966
  const savedProviderCfg = config.providers?.[config.provider];
15750
15967
  return execute({
15751
15968
  agent,
@@ -15805,6 +16022,23 @@ Restart WrongStack to load or unload plugin code in this session.`;
15805
16022
  skillLoader: config.features.skills ? skillLoader : void 0
15806
16023
  });
15807
16024
  }
16025
+ var isMain = import.meta.url === `file://${process.argv[1]?.replace(/\\/g, "/")}` || process.argv[1]?.endsWith("/cli/dist/index.js") || process.argv[1]?.endsWith("\\cli\\dist\\index.js");
16026
+ function runAsMain(mainFn) {
16027
+ if (!isMain) return;
16028
+ mainFn(process.argv.slice(2)).then(
16029
+ (c) => {
16030
+ process.exitCode = c;
16031
+ setTimeout(() => process.exit(c), 500).unref();
16032
+ },
16033
+ (err) => {
16034
+ writeErr((err instanceof Error ? err.stack : String(err)) + "\n");
16035
+ process.exitCode = 1;
16036
+ setTimeout(() => process.exit(1), 500).unref();
16037
+ }
16038
+ );
16039
+ }
16040
+
16041
+ // src/index.ts
15808
16042
  runAsMain(main);
15809
16043
 
15810
16044
  export { CLI_VERSION, main };