@wrongstack/cli 0.5.5 → 0.5.6

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,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import * as path20 from 'path';
2
+ import * as path21 from 'path';
3
3
  import { join } from 'path';
4
- import * as fs3 from 'fs/promises';
4
+ import * as fsp2 from 'fs/promises';
5
5
  import { readdir, readFile } from 'fs/promises';
6
- import { color, allServers, DefaultPathResolver, TOKENS, DefaultSystemPromptBuilder, ToolRegistry, createContextManagerTool, EventBus, InMemoryMetricsSink, wireMetricsToEvents, DefaultHealthRegistry, startMetricsServer, SlashCommandRegistry, loadPlugins, createDelegateTool, FLEET_ROSTER, DefaultLogger, DefaultModelsRegistry, ProviderRegistry, RecoveryLock, DefaultAttachmentStore, QueueStore, Context, loadTodosCheckpoint, attachTodosCheckpoint, loadDirectorState, loadPlan, createDefaultPipelines, AutoCompactionMiddleware, estimateRequestTokens, Agent, makeDirectorSessionFactory, Director, DefaultMultiAgentCoordinator, makeAgentSubagentRunner, resolveWstackPaths, DefaultSecretVault, migratePlaintextSecrets, DefaultConfigLoader, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, atomicWrite, AutoApprovePermissionPolicy, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, formatTodosList, emptyPlan, clearPlan, savePlan, removePlanItem, formatPlan, setPlanItemStatus, addPlanItem, SpecStore, TaskGraphStore, SpecVersioning, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, DefaultTaskStore, TaskTracker, InputBuilder, projectHash, defaultOrchestrator, decryptConfigSecrets, encryptConfigSecrets as encryptConfigSecrets$1, DefaultPluginAPI } from '@wrongstack/core';
6
+ import { color, allServers, DefaultPathResolver, TOKENS, DefaultSystemPromptBuilder, ToolRegistry, createContextManagerTool, EventBus, InMemoryMetricsSink, wireMetricsToEvents, DefaultHealthRegistry, startMetricsServer, SlashCommandRegistry, loadPlugins, createDelegateTool, FLEET_ROSTER, DefaultLogger, DefaultModelsRegistry, ProviderRegistry, RecoveryLock, DefaultAttachmentStore, QueueStore, Context, loadTodosCheckpoint, attachTodosCheckpoint, loadDirectorState, loadPlan, createDefaultPipelines, AutoCompactionMiddleware, estimateRequestTokens, Agent, makeDirectorSessionFactory, Director, DefaultMultiAgentCoordinator, makeAgentSubagentRunner, resolveWstackPaths, DefaultSecretVault, migratePlaintextSecrets, DefaultConfigLoader, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, atomicWrite, AutoApprovePermissionPolicy, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, formatTodosList, emptyPlan, clearPlan, savePlan, formatPlanTemplates, getPlanTemplate, addPlanItem, formatPlan, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, SpecStore, TaskGraphStore, SpecVersioning, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, DefaultTaskStore, TaskTracker, InputBuilder, projectHash, defaultOrchestrator, decryptConfigSecrets, encryptConfigSecrets as encryptConfigSecrets$1, DefaultPluginAPI } from '@wrongstack/core';
7
7
  import { createRequire } from 'module';
8
8
  import * as os6 from 'os';
9
9
  import os6__default from 'os';
@@ -261,8 +261,8 @@ function buildSddCommand(opts) {
261
261
  async run(args) {
262
262
  const ctx = opts.context;
263
263
  const projectRoot = ctx?.projectRoot ?? process.cwd();
264
- const specsDir = path20.join(projectRoot, ".wrongstack", "specs");
265
- const graphsDir = path20.join(projectRoot, ".wrongstack", "task-graphs");
264
+ const specsDir = path21.join(projectRoot, ".wrongstack", "specs");
265
+ const graphsDir = path21.join(projectRoot, ".wrongstack", "task-graphs");
266
266
  const specStore = new SpecStore({ baseDir: specsDir });
267
267
  new TaskGraphStore({ baseDir: graphsDir });
268
268
  const versioning = new SpecVersioning();
@@ -278,9 +278,9 @@ function buildSddCommand(opts) {
278
278
  const forceFlag = rest.includes("--force") || rest.includes("-f");
279
279
  const title = rest.filter((a) => !a.startsWith("-")).join(" ").trim() || "Untitled Feature";
280
280
  if (!sddState.getBuilder() && !forceFlag) {
281
- const sessionPath = path20.join(projectRoot, ".wrongstack", "sdd-session.json");
281
+ const sessionPath = path21.join(projectRoot, ".wrongstack", "sdd-session.json");
282
282
  try {
283
- await fs3.access(sessionPath);
283
+ await fsp2.access(sessionPath);
284
284
  const projectContext2 = await gatherProjectContext(projectRoot);
285
285
  const tempBuilder = new AISpecBuilder({
286
286
  store: specStore,
@@ -313,7 +313,7 @@ function buildSddCommand(opts) {
313
313
  projectContext,
314
314
  minQuestions: 2,
315
315
  maxQuestions: 10,
316
- sessionPath: path20.join(projectRoot, ".wrongstack", "sdd-session.json")
316
+ sessionPath: path21.join(projectRoot, ".wrongstack", "sdd-session.json")
317
317
  }));
318
318
  const builder = sddState.getBuilder();
319
319
  builder.startSession(title);
@@ -581,10 +581,10 @@ Start executing the tasks one by one.`
581
581
  };
582
582
  }
583
583
  case "cancel": {
584
- const sessionPath = path20.join(projectRoot, ".wrongstack", "sdd-session.json");
584
+ const sessionPath = path21.join(projectRoot, ".wrongstack", "sdd-session.json");
585
585
  let deletedFromDisk = false;
586
586
  try {
587
- await fs3.unlink(sessionPath);
587
+ await fsp2.unlink(sessionPath);
588
588
  deletedFromDisk = true;
589
589
  } catch {
590
590
  }
@@ -605,7 +605,7 @@ Start executing the tasks one by one.`
605
605
  if (sddState.getBuilder()) {
606
606
  return { message: "An SDD session is already active. Use /sdd cancel first." };
607
607
  }
608
- const sessionPath = path20.join(projectRoot, ".wrongstack", "sdd-session.json");
608
+ const sessionPath = path21.join(projectRoot, ".wrongstack", "sdd-session.json");
609
609
  const projectContext = await gatherProjectContext(projectRoot);
610
610
  sddState.setBuilder(new AISpecBuilder({
611
611
  store: specStore,
@@ -831,8 +831,8 @@ function sddHelp() {
831
831
  async function gatherProjectContext(projectRoot) {
832
832
  const parts = [];
833
833
  try {
834
- const pkgPath = path20.join(projectRoot, "package.json");
835
- const pkgRaw = await fs3.readFile(pkgPath, "utf8");
834
+ const pkgPath = path21.join(projectRoot, "package.json");
835
+ const pkgRaw = await fsp2.readFile(pkgPath, "utf8");
836
836
  const pkg = JSON.parse(pkgRaw);
837
837
  parts.push(`Project: ${String(pkg.name ?? "unknown")}`);
838
838
  parts.push(`Description: ${String(pkg.description ?? "none")}`);
@@ -847,14 +847,14 @@ async function gatherProjectContext(projectRoot) {
847
847
  } catch {
848
848
  }
849
849
  try {
850
- const tsconfigPath = path20.join(projectRoot, "tsconfig.json");
851
- await fs3.access(tsconfigPath);
850
+ const tsconfigPath = path21.join(projectRoot, "tsconfig.json");
851
+ await fsp2.access(tsconfigPath);
852
852
  parts.push("Language: TypeScript");
853
853
  } catch {
854
854
  }
855
855
  try {
856
- const srcDir = path20.join(projectRoot, "src");
857
- const entries = await fs3.readdir(srcDir, { withFileTypes: true });
856
+ const srcDir = path21.join(projectRoot, "src");
857
+ const entries = await fsp2.readdir(srcDir, { withFileTypes: true });
858
858
  const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
859
859
  if (dirs.length > 0) {
860
860
  parts.push(`Source structure: src/${dirs.join(", src/")}`);
@@ -976,7 +976,7 @@ __export(update_check_exports, {
976
976
  getUpdateNotification: () => getUpdateNotification
977
977
  });
978
978
  function cachePath(homeFn = defaultHomeDir2) {
979
- return path20.join(homeFn(), ".wrongstack", "update-cache.json");
979
+ return path21.join(homeFn(), ".wrongstack", "update-cache.json");
980
980
  }
981
981
  function currentVersion() {
982
982
  const req2 = createRequire(import.meta.url);
@@ -1003,7 +1003,7 @@ function isNewer(a, b) {
1003
1003
  }
1004
1004
  async function readCache(homeFn = defaultHomeDir2) {
1005
1005
  try {
1006
- const raw = await fs3.readFile(cachePath(homeFn), "utf8");
1006
+ const raw = await fsp2.readFile(cachePath(homeFn), "utf8");
1007
1007
  const entry = JSON.parse(raw);
1008
1008
  if (Date.now() - entry.timestamp > CACHE_TTL_MS) return null;
1009
1009
  return entry;
@@ -1013,9 +1013,9 @@ async function readCache(homeFn = defaultHomeDir2) {
1013
1013
  }
1014
1014
  async function writeCache(entry, homeFn = defaultHomeDir2) {
1015
1015
  try {
1016
- const dir = path20.dirname(cachePath(homeFn));
1017
- await fs3.mkdir(dir, { recursive: true });
1018
- await fs3.writeFile(cachePath(homeFn), JSON.stringify(entry, null, 2), "utf8");
1016
+ const dir = path21.dirname(cachePath(homeFn));
1017
+ await fsp2.mkdir(dir, { recursive: true });
1018
+ await fsp2.writeFile(cachePath(homeFn), JSON.stringify(entry, null, 2), "utf8");
1019
1019
  } catch {
1020
1020
  }
1021
1021
  }
@@ -1573,7 +1573,7 @@ async function runWebUI(opts) {
1573
1573
  if (!opts.globalConfigPath) return {};
1574
1574
  let raw;
1575
1575
  try {
1576
- raw = await fs3.readFile(opts.globalConfigPath, "utf8");
1576
+ raw = await fsp2.readFile(opts.globalConfigPath, "utf8");
1577
1577
  } catch {
1578
1578
  return {};
1579
1579
  }
@@ -1584,7 +1584,7 @@ async function runWebUI(opts) {
1584
1584
  return {};
1585
1585
  }
1586
1586
  if (!parsed.providers) return {};
1587
- const keyFile = path20.join(path20.dirname(opts.globalConfigPath), ".key");
1587
+ const keyFile = path21.join(path21.dirname(opts.globalConfigPath), ".key");
1588
1588
  const vault = new DefaultSecretVault$1({ keyFile });
1589
1589
  return decryptConfigSecrets$1(parsed.providers, vault);
1590
1590
  }
@@ -1592,7 +1592,7 @@ async function runWebUI(opts) {
1592
1592
  if (!opts.globalConfigPath) return;
1593
1593
  let raw;
1594
1594
  try {
1595
- raw = await fs3.readFile(opts.globalConfigPath, "utf8");
1595
+ raw = await fsp2.readFile(opts.globalConfigPath, "utf8");
1596
1596
  } catch {
1597
1597
  raw = "{}";
1598
1598
  }
@@ -1603,7 +1603,7 @@ async function runWebUI(opts) {
1603
1603
  parsed = {};
1604
1604
  }
1605
1605
  parsed.providers = providers;
1606
- const keyFile = path20.join(path20.dirname(opts.globalConfigPath), ".key");
1606
+ const keyFile = path21.join(path21.dirname(opts.globalConfigPath), ".key");
1607
1607
  const vault = new DefaultSecretVault$1({ keyFile });
1608
1608
  const encrypted = encryptConfigSecrets(parsed, vault);
1609
1609
  await atomicWrite(opts.globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
@@ -1681,7 +1681,8 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
1681
1681
  "prompt",
1682
1682
  "metrics",
1683
1683
  "webui",
1684
- "no-check"
1684
+ "no-check",
1685
+ "director"
1685
1686
  ]);
1686
1687
  function parseArgs(argv) {
1687
1688
  const flags = {};
@@ -1787,7 +1788,7 @@ function parseSpawnFlags(input) {
1787
1788
  return { description: rest.trim(), opts };
1788
1789
  }
1789
1790
  async function bootConfig(flags) {
1790
- const cwd = typeof flags["cwd"] === "string" ? path20.resolve(flags["cwd"]) : process.cwd();
1791
+ const cwd = typeof flags["cwd"] === "string" ? path21.resolve(flags["cwd"]) : process.cwd();
1791
1792
  const pathResolver = new DefaultPathResolver(cwd);
1792
1793
  const projectRoot = pathResolver.projectRoot;
1793
1794
  const userHome = os6.homedir();
@@ -1838,13 +1839,13 @@ function flagsToConfigPatch(flags) {
1838
1839
  }
1839
1840
  async function ensureProjectMeta(paths, projectRoot) {
1840
1841
  try {
1841
- await fs3.mkdir(paths.projectDir, { recursive: true });
1842
+ await fsp2.mkdir(paths.projectDir, { recursive: true });
1842
1843
  const meta = {
1843
1844
  hash: paths.projectHash,
1844
1845
  root: projectRoot,
1845
1846
  lastSeen: (/* @__PURE__ */ new Date()).toISOString()
1846
1847
  };
1847
- await fs3.writeFile(paths.projectMeta, JSON.stringify(meta, null, 2));
1848
+ await fsp2.writeFile(paths.projectMeta, JSON.stringify(meta, null, 2));
1848
1849
  } catch {
1849
1850
  }
1850
1851
  }
@@ -1854,11 +1855,11 @@ var ReadlineInputReader = class {
1854
1855
  history = [];
1855
1856
  pending = false;
1856
1857
  constructor(opts = {}) {
1857
- this.historyFile = opts.historyFile ?? path20.join(os6.homedir(), ".wrongstack", "history");
1858
+ this.historyFile = opts.historyFile ?? path21.join(os6.homedir(), ".wrongstack", "history");
1858
1859
  }
1859
1860
  async loadHistory() {
1860
1861
  try {
1861
- const raw = await fs3.readFile(this.historyFile, "utf8");
1862
+ const raw = await fsp2.readFile(this.historyFile, "utf8");
1862
1863
  this.history = raw.split("\n").filter(Boolean).slice(-1e3);
1863
1864
  } catch {
1864
1865
  this.history = [];
@@ -1866,8 +1867,8 @@ var ReadlineInputReader = class {
1866
1867
  }
1867
1868
  async saveHistory() {
1868
1869
  try {
1869
- await fs3.mkdir(path20.dirname(this.historyFile), { recursive: true });
1870
- await fs3.writeFile(this.historyFile, this.history.slice(-1e3).join("\n"));
1870
+ await fsp2.mkdir(path21.dirname(this.historyFile), { recursive: true });
1871
+ await fsp2.writeFile(this.historyFile, this.history.slice(-1e3).join("\n"));
1871
1872
  } catch {
1872
1873
  }
1873
1874
  }
@@ -2093,23 +2094,23 @@ function assertSafeToDelete(filename, parentDir) {
2093
2094
  if (PROTECTED_BASENAMES.has(filename)) {
2094
2095
  throw new Error(`Refusing to delete protected file: ${filename}`);
2095
2096
  }
2096
- if (filename !== path20.basename(filename)) {
2097
+ if (filename !== path21.basename(filename)) {
2097
2098
  throw new Error(`Refusing to delete path with traversal: ${filename}`);
2098
2099
  }
2099
2100
  if (!filename.startsWith("config.json.") || !filename.endsWith(".bak")) {
2100
2101
  throw new Error(`Refusing to delete unknown file: ${filename}`);
2101
2102
  }
2102
- const resolvedParent = path20.resolve(parentDir);
2103
+ const resolvedParent = path21.resolve(parentDir);
2103
2104
  if (!resolvedParent.endsWith(".wrongstack")) {
2104
2105
  throw new Error(`Unexpected parent directory for bak prune: ${resolvedParent}`);
2105
2106
  }
2106
2107
  }
2107
2108
  async function safeDelete(filePath) {
2108
- const dir = path20.dirname(filePath);
2109
- const filename = path20.basename(filePath);
2109
+ const dir = path21.dirname(filePath);
2110
+ const filename = path21.basename(filePath);
2110
2111
  try {
2111
2112
  assertSafeToDelete(filename, dir);
2112
- await fs3.unlink(filePath);
2113
+ await fsp2.unlink(filePath);
2113
2114
  } catch (err) {
2114
2115
  if (err instanceof Error && err.message.startsWith("Refusing")) {
2115
2116
  process.stderr.write(`[config-history] SAFETY: ${err.message}
@@ -2151,26 +2152,26 @@ function diffSummary(oldCfg, newCfg) {
2151
2152
  }
2152
2153
  var defaultHomeDir = () => os6__default.homedir();
2153
2154
  function historyDir(homeFn = defaultHomeDir) {
2154
- return path20.join(homeFn(), ".wrongstack", "config.history", "entries");
2155
+ return path21.join(homeFn(), ".wrongstack", "config.history", "entries");
2155
2156
  }
2156
2157
  function historyIndexPath(homeFn = defaultHomeDir) {
2157
- return path20.join(homeFn(), ".wrongstack", "config.history", "index.json");
2158
+ return path21.join(homeFn(), ".wrongstack", "config.history", "index.json");
2158
2159
  }
2159
2160
  function configPath(homeFn = defaultHomeDir) {
2160
- return path20.join(homeFn(), ".wrongstack", "config.json");
2161
+ return path21.join(homeFn(), ".wrongstack", "config.json");
2161
2162
  }
2162
2163
  function backupLastPath(homeFn = defaultHomeDir) {
2163
- return path20.join(homeFn(), ".wrongstack", "config.json.last");
2164
+ return path21.join(homeFn(), ".wrongstack", "config.json.last");
2164
2165
  }
2165
2166
  function entryId(ts) {
2166
2167
  return ts.replace(/[:.]/g, "-").slice(0, 19);
2167
2168
  }
2168
2169
  async function ensureHistoryDir(homeFn = defaultHomeDir) {
2169
- await fs3.mkdir(historyDir(homeFn), { recursive: true });
2170
+ await fsp2.mkdir(historyDir(homeFn), { recursive: true });
2170
2171
  }
2171
2172
  async function readIndex(homeFn = defaultHomeDir) {
2172
2173
  try {
2173
- const raw = await fs3.readFile(historyIndexPath(homeFn), "utf8");
2174
+ const raw = await fsp2.readFile(historyIndexPath(homeFn), "utf8");
2174
2175
  return JSON.parse(raw);
2175
2176
  } catch {
2176
2177
  return { version: 1, entries: [] };
@@ -2178,7 +2179,7 @@ async function readIndex(homeFn = defaultHomeDir) {
2178
2179
  }
2179
2180
  async function writeIndex(idx, homeFn = defaultHomeDir) {
2180
2181
  await ensureHistoryDir(homeFn);
2181
- await fs3.writeFile(historyIndexPath(homeFn), JSON.stringify(idx, null, 2), "utf8");
2182
+ await fsp2.writeFile(historyIndexPath(homeFn), JSON.stringify(idx, null, 2), "utf8");
2182
2183
  }
2183
2184
  async function backupCurrent(homeFn = defaultHomeDir) {
2184
2185
  const cfg = configPath(homeFn);
@@ -2186,7 +2187,7 @@ async function backupCurrent(homeFn = defaultHomeDir) {
2186
2187
  const ts = Date.now();
2187
2188
  let content;
2188
2189
  try {
2189
- content = await fs3.readFile(cfg, "utf8");
2190
+ content = await fsp2.readFile(cfg, "utf8");
2190
2191
  } catch {
2191
2192
  }
2192
2193
  if (content !== void 0) {
@@ -2197,17 +2198,17 @@ async function backupCurrent(homeFn = defaultHomeDir) {
2197
2198
  }
2198
2199
  if (content !== void 0) {
2199
2200
  try {
2200
- const bakPath = path20.join(homeFn(), ".wrongstack", `config.json.${ts}.bak`);
2201
+ const bakPath = path21.join(homeFn(), ".wrongstack", `config.json.${ts}.bak`);
2201
2202
  await atomicWrite(bakPath, content);
2202
2203
  } catch {
2203
2204
  }
2204
2205
  }
2205
2206
  try {
2206
- const dir = path20.join(homeFn(), ".wrongstack");
2207
- const files = await fs3.readdir(dir);
2207
+ const dir = path21.join(homeFn(), ".wrongstack");
2208
+ const files = await fsp2.readdir(dir);
2208
2209
  const baks = files.filter((f) => f.startsWith("config.json.") && f.endsWith(".bak")).sort().reverse();
2209
2210
  for (const f of baks.slice(10)) {
2210
- await safeDelete(path20.join(dir, f));
2211
+ await safeDelete(path21.join(dir, f));
2211
2212
  }
2212
2213
  } catch {
2213
2214
  }
@@ -2223,8 +2224,8 @@ async function appendHistory(oldCfg, newCfg, description, homeFn = defaultHomeDi
2223
2224
  snapshotMasked: maskConfigSecrets(newCfg),
2224
2225
  diffSummary: diffSummary(oldCfg, newCfg)
2225
2226
  };
2226
- await fs3.writeFile(
2227
- path20.join(historyDir(homeFn), `${id}.json`),
2227
+ await fsp2.writeFile(
2228
+ path21.join(historyDir(homeFn), `${id}.json`),
2228
2229
  JSON.stringify(entry, null, 2),
2229
2230
  "utf8"
2230
2231
  );
@@ -2239,7 +2240,7 @@ async function listHistory(homeFn = defaultHomeDir) {
2239
2240
  }
2240
2241
  async function getHistoryEntry(id, homeFn = defaultHomeDir) {
2241
2242
  try {
2242
- const raw = await fs3.readFile(path20.join(historyDir(homeFn), `${id}.json`), "utf8");
2243
+ const raw = await fsp2.readFile(path21.join(historyDir(homeFn), `${id}.json`), "utf8");
2243
2244
  return JSON.parse(raw);
2244
2245
  } catch {
2245
2246
  return null;
@@ -2251,7 +2252,7 @@ async function restoreFromHistory(id, homeFn = defaultHomeDir) {
2251
2252
  await backupCurrent(homeFn);
2252
2253
  let oldCfg = {};
2253
2254
  try {
2254
- const raw = await fs3.readFile(configPath(homeFn), "utf8");
2255
+ const raw = await fsp2.readFile(configPath(homeFn), "utf8");
2255
2256
  oldCfg = JSON.parse(raw);
2256
2257
  } catch {
2257
2258
  }
@@ -2273,13 +2274,13 @@ async function restoreLast(homeFn = defaultHomeDir) {
2273
2274
  const cfg = configPath(homeFn);
2274
2275
  let oldCfg = {};
2275
2276
  try {
2276
- const raw = await fs3.readFile(cfg, "utf8");
2277
+ const raw = await fsp2.readFile(cfg, "utf8");
2277
2278
  oldCfg = JSON.parse(raw);
2278
2279
  } catch {
2279
2280
  }
2280
2281
  let lastCfg = {};
2281
2282
  try {
2282
- const raw = await fs3.readFile(last, "utf8");
2283
+ const raw = await fsp2.readFile(last, "utf8");
2283
2284
  lastCfg = JSON.parse(raw);
2284
2285
  } catch {
2285
2286
  return { ok: false, error: "No prior backup found" };
@@ -2557,7 +2558,7 @@ async function resolveModelSelection(answer, models, provider, _registry, render
2557
2558
  }
2558
2559
  async function pathExists(file) {
2559
2560
  try {
2560
- await fs3.access(file);
2561
+ await fsp2.access(file);
2561
2562
  return true;
2562
2563
  } catch {
2563
2564
  return false;
@@ -2568,10 +2569,10 @@ async function detectPackageManager(root, declared) {
2568
2569
  const name = declared.split("@")[0];
2569
2570
  if (name) return name;
2570
2571
  }
2571
- if (await pathExists(path20.join(root, "pnpm-lock.yaml"))) return "pnpm";
2572
- if (await pathExists(path20.join(root, "bun.lockb"))) return "bun";
2573
- if (await pathExists(path20.join(root, "bun.lock"))) return "bun";
2574
- if (await pathExists(path20.join(root, "yarn.lock"))) return "yarn";
2572
+ if (await pathExists(path21.join(root, "pnpm-lock.yaml"))) return "pnpm";
2573
+ if (await pathExists(path21.join(root, "bun.lockb"))) return "bun";
2574
+ if (await pathExists(path21.join(root, "bun.lock"))) return "bun";
2575
+ if (await pathExists(path21.join(root, "yarn.lock"))) return "yarn";
2575
2576
  return "npm";
2576
2577
  }
2577
2578
  function hasUsableScript(scripts, name) {
@@ -2592,7 +2593,7 @@ function parseMakeTargets(makefile) {
2592
2593
  async function detectProjectFacts(root) {
2593
2594
  const facts = { hints: [] };
2594
2595
  try {
2595
- const pkg = JSON.parse(await fs3.readFile(path20.join(root, "package.json"), "utf8"));
2596
+ const pkg = JSON.parse(await fsp2.readFile(path21.join(root, "package.json"), "utf8"));
2596
2597
  const scripts = pkg.scripts ?? {};
2597
2598
  const pm = await detectPackageManager(root, pkg.packageManager);
2598
2599
  if (hasUsableScript(scripts, "build")) facts.build = `${pm} run build`;
@@ -2606,14 +2607,14 @@ async function detectProjectFacts(root) {
2606
2607
  } catch {
2607
2608
  }
2608
2609
  try {
2609
- if (!await pathExists(path20.join(root, "pyproject.toml"))) throw new Error("not python");
2610
+ if (!await pathExists(path21.join(root, "pyproject.toml"))) throw new Error("not python");
2610
2611
  facts.test ??= "pytest";
2611
2612
  facts.lint ??= "ruff check .";
2612
2613
  facts.hints.push("pyproject.toml");
2613
2614
  } catch {
2614
2615
  }
2615
2616
  try {
2616
- if (!await pathExists(path20.join(root, "go.mod"))) throw new Error("not go");
2617
+ if (!await pathExists(path21.join(root, "go.mod"))) throw new Error("not go");
2617
2618
  facts.build ??= "go build ./...";
2618
2619
  facts.test ??= "go test ./...";
2619
2620
  facts.run ??= "go run .";
@@ -2621,7 +2622,7 @@ async function detectProjectFacts(root) {
2621
2622
  } catch {
2622
2623
  }
2623
2624
  try {
2624
- if (!await pathExists(path20.join(root, "Cargo.toml"))) throw new Error("not rust");
2625
+ if (!await pathExists(path21.join(root, "Cargo.toml"))) throw new Error("not rust");
2625
2626
  facts.build ??= "cargo build";
2626
2627
  facts.test ??= "cargo test";
2627
2628
  facts.lint ??= "cargo clippy";
@@ -2630,7 +2631,7 @@ async function detectProjectFacts(root) {
2630
2631
  } catch {
2631
2632
  }
2632
2633
  try {
2633
- const makefile = await fs3.readFile(path20.join(root, "Makefile"), "utf8");
2634
+ const makefile = await fsp2.readFile(path21.join(root, "Makefile"), "utf8");
2634
2635
  const targets = parseMakeTargets(makefile);
2635
2636
  facts.build ??= targets.has("build") ? "make build" : "make";
2636
2637
  if (targets.has("test")) facts.test ??= "make test";
@@ -3266,10 +3267,10 @@ function buildInitCommand(opts) {
3266
3267
  description: "Create .wrongstack/AGENTS.md project context for the system prompt.",
3267
3268
  async run(args, ctx) {
3268
3269
  const force = args.trim() === "--force";
3269
- const dir = path20.join(ctx.projectRoot, ".wrongstack");
3270
- const file = path20.join(dir, "AGENTS.md");
3270
+ const dir = path21.join(ctx.projectRoot, ".wrongstack");
3271
+ const file = path21.join(dir, "AGENTS.md");
3271
3272
  try {
3272
- await fs3.access(file);
3273
+ await fsp2.access(file);
3273
3274
  if (!force) {
3274
3275
  const msg2 = `AGENTS.md already exists at ${file}. Use "/init --force" to overwrite.`;
3275
3276
  opts.renderer.writeWarning(msg2);
@@ -3279,8 +3280,8 @@ function buildInitCommand(opts) {
3279
3280
  }
3280
3281
  const detected = await detectProjectFacts(ctx.projectRoot);
3281
3282
  const body = renderAgentsTemplate(detected);
3282
- await fs3.mkdir(dir, { recursive: true });
3283
- await fs3.writeFile(file, body, "utf8");
3283
+ await fsp2.mkdir(dir, { recursive: true });
3284
+ await fsp2.writeFile(file, body, "utf8");
3284
3285
  if (detected.hints.length > 0) {
3285
3286
  const msg2 = `Wrote ${file}
3286
3287
  Pre-filled: ${detected.hints.join(", ")}. Edit the file with project context and instructions the system prompt should carry.`;
@@ -3378,7 +3379,7 @@ function buildMetricsCommand(opts) {
3378
3379
  function buildPlanCommand(opts) {
3379
3380
  return {
3380
3381
  name: "plan",
3381
- description: "Strategic plan board: /plan [show|add <title>|done <id|#>|remove <id|#>|clear]",
3382
+ description: "Strategic plan board: /plan [show|add <title>|start <id|#>|done <id|#>|remove <id|#>|promote <id|#> [subtask ...]|derive <id|#>|template [list|use <name>]|clear]",
3382
3383
  async run(args) {
3383
3384
  const planPath = opts.planPath;
3384
3385
  if (!planPath) return { message: "Plan storage is not configured for this session." };
@@ -3422,6 +3423,58 @@ ${formatPlan(updated)}` };
3422
3423
  await savePlan(planPath, updated);
3423
3424
  return { message: formatPlan(updated) };
3424
3425
  }
3426
+ case "promote": {
3427
+ if (!restJoined) return { message: "Usage: /plan promote <id|index> [subtask ...]" };
3428
+ const [target, ...subtasks] = restJoined.split(/\s+/);
3429
+ if (!target) return { message: "Usage: /plan promote <id|index> [subtask ...]" };
3430
+ const derived = deriveTodosFromPlanItem(plan, target, subtasks.length > 0 ? subtasks : void 0);
3431
+ if (!derived) return { message: `No plan item matched "${target}".` };
3432
+ await savePlan(planPath, derived.plan);
3433
+ if (ctx) {
3434
+ ctx.state.replaceTodos(derived.todos);
3435
+ }
3436
+ return {
3437
+ message: `Promoted to ${derived.todos.length} todo(s):
3438
+ ${formatTodosList(derived.todos)}
3439
+
3440
+ ${formatPlan(derived.plan)}`
3441
+ };
3442
+ }
3443
+ case "derive": {
3444
+ if (!restJoined) return { message: "Usage: /plan derive <id|index>" };
3445
+ const derived = deriveTodosFromPlanItem(plan, restJoined);
3446
+ if (!derived) return { message: `No plan item matched "${restJoined}".` };
3447
+ await savePlan(planPath, derived.plan);
3448
+ if (ctx) {
3449
+ ctx.state.replaceTodos(derived.todos);
3450
+ }
3451
+ return {
3452
+ message: `Derived ${derived.todos.length} todo(s):
3453
+ ${formatTodosList(derived.todos)}
3454
+
3455
+ ${formatPlan(derived.plan)}`
3456
+ };
3457
+ }
3458
+ case "template": {
3459
+ const subVerb = rest[0] ?? "";
3460
+ const subRest = rest.slice(1).join(" ").trim();
3461
+ if (subVerb === "" || subVerb === "list") {
3462
+ return { message: formatPlanTemplates() };
3463
+ }
3464
+ if (subVerb === "use") {
3465
+ if (!subRest) return { message: "Usage: /plan template use <template-name>" };
3466
+ const template = getPlanTemplate(subRest);
3467
+ if (!template) return { message: `Unknown template "${subRest}". Use /plan template list to see available templates.` };
3468
+ let updated = plan;
3469
+ for (const item of template.items) {
3470
+ ({ plan: updated } = addPlanItem(updated, item.title, item.details));
3471
+ }
3472
+ await savePlan(planPath, updated);
3473
+ return { message: `Applied template "${template.name}" (${template.items.length} items):
3474
+ ${formatPlan(updated)}` };
3475
+ }
3476
+ return { message: `Unknown template subcommand "${subVerb}". Try: list | use <name>` };
3477
+ }
3425
3478
  case "clear": {
3426
3479
  const updated = clearPlan(plan);
3427
3480
  await savePlan(planPath, updated);
@@ -3429,7 +3482,7 @@ ${formatPlan(updated)}` };
3429
3482
  }
3430
3483
  default:
3431
3484
  return {
3432
- message: `Unknown subcommand "${verb}". Try: show | add <title> | start <id|#> | done <id|#> | remove <id|#> | clear`
3485
+ message: `Unknown subcommand "${verb}". Try: show | add <title> | start <id|#> | done <id|#> | remove <id|#> | promote <id|#> | derive <id|#> | template [list|use <name>] | clear`
3433
3486
  };
3434
3487
  }
3435
3488
  }
@@ -4107,11 +4160,11 @@ function getHelpMessage() {
4107
4160
  Run \`/security scan\` to start.`;
4108
4161
  }
4109
4162
  function makeInstaller(opts, projectRoot, global) {
4110
- const globalRoot = path20.join(os6.homedir(), ".wrongstack");
4163
+ const globalRoot = path21.join(os6.homedir(), ".wrongstack");
4111
4164
  return new SkillInstaller({
4112
- manifestPath: path20.join(globalRoot, "installed-skills.json"),
4113
- projectSkillsDir: path20.join(projectRoot, ".wrongstack", "skills"),
4114
- globalSkillsDir: path20.join(globalRoot, "skills"),
4165
+ manifestPath: path21.join(globalRoot, "installed-skills.json"),
4166
+ projectSkillsDir: path21.join(projectRoot, ".wrongstack", "skills"),
4167
+ globalSkillsDir: path21.join(globalRoot, "skills"),
4115
4168
  projectHash: projectHash(projectRoot),
4116
4169
  skillLoader: opts.skillLoader
4117
4170
  });
@@ -4323,13 +4376,13 @@ var MANIFESTS = [
4323
4376
  ];
4324
4377
  async function detectProjectKind(projectRoot) {
4325
4378
  try {
4326
- await fs3.access(path20.join(projectRoot, ".wrongstack", "AGENTS.md"));
4379
+ await fsp2.access(path21.join(projectRoot, ".wrongstack", "AGENTS.md"));
4327
4380
  return "initialized";
4328
4381
  } catch {
4329
4382
  }
4330
4383
  for (const m of MANIFESTS) {
4331
4384
  try {
4332
- await fs3.access(path20.join(projectRoot, m));
4385
+ await fsp2.access(path21.join(projectRoot, m));
4333
4386
  return "project";
4334
4387
  } catch {
4335
4388
  }
@@ -4337,12 +4390,12 @@ async function detectProjectKind(projectRoot) {
4337
4390
  return "empty";
4338
4391
  }
4339
4392
  async function scaffoldAgentsMd(projectRoot) {
4340
- const dir = path20.join(projectRoot, ".wrongstack");
4341
- const file = path20.join(dir, "AGENTS.md");
4393
+ const dir = path21.join(projectRoot, ".wrongstack");
4394
+ const file = path21.join(dir, "AGENTS.md");
4342
4395
  const facts = await detectProjectFacts(projectRoot);
4343
4396
  const body = renderAgentsTemplate(facts);
4344
- await fs3.mkdir(dir, { recursive: true });
4345
- await fs3.writeFile(file, body, "utf8");
4397
+ await fsp2.mkdir(dir, { recursive: true });
4398
+ await fsp2.writeFile(file, body, "utf8");
4346
4399
  return file;
4347
4400
  }
4348
4401
  async function runProjectCheck(opts) {
@@ -4351,7 +4404,7 @@ async function runProjectCheck(opts) {
4351
4404
  if (kind === "initialized") {
4352
4405
  renderer.write(
4353
4406
  `
4354
- ${color.green("\u2713")} Project initialized ${color.dim(`(${path20.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
4407
+ ${color.green("\u2713")} Project initialized ${color.dim(`(${path21.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
4355
4408
  `
4356
4409
  );
4357
4410
  return true;
@@ -4378,10 +4431,10 @@ async function runProjectCheck(opts) {
4378
4431
  }
4379
4432
  return true;
4380
4433
  }
4381
- const gitDir = path20.join(projectRoot, ".git");
4434
+ const gitDir = path21.join(projectRoot, ".git");
4382
4435
  let hasGit = false;
4383
4436
  try {
4384
- await fs3.access(gitDir);
4437
+ await fsp2.access(gitDir);
4385
4438
  hasGit = true;
4386
4439
  } catch {
4387
4440
  }
@@ -4679,14 +4732,14 @@ function summarize(value, name) {
4679
4732
  if (typeof v === "object" && v !== null) {
4680
4733
  const o = v;
4681
4734
  if (name === "edit") {
4682
- const path21 = typeof o["path"] === "string" ? o["path"] : "";
4735
+ const path22 = typeof o["path"] === "string" ? o["path"] : "";
4683
4736
  const reps = typeof o["replacements"] === "number" ? o["replacements"] : 0;
4684
- return `${path21} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
4737
+ return `${path22} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
4685
4738
  }
4686
4739
  if (name === "write") {
4687
- const path21 = typeof o["path"] === "string" ? o["path"] : "";
4740
+ const path22 = typeof o["path"] === "string" ? o["path"] : "";
4688
4741
  const bytes = typeof o["bytes"] === "number" ? o["bytes"] : void 0;
4689
- return bytes !== void 0 ? `${path21} ${bytes}B` : path21;
4742
+ return bytes !== void 0 ? `${path22} ${bytes}B` : path22;
4690
4743
  }
4691
4744
  if (typeof o["count"] === "number") {
4692
4745
  return `${o["count"]} match${o["count"] === 1 ? "" : "es"}`;
@@ -5282,7 +5335,7 @@ async function readKeyInput(deps, intent) {
5282
5335
  async function loadProviders(deps) {
5283
5336
  let raw;
5284
5337
  try {
5285
- raw = await fs3.readFile(deps.globalConfigPath, "utf8");
5338
+ raw = await fsp2.readFile(deps.globalConfigPath, "utf8");
5286
5339
  } catch {
5287
5340
  return {};
5288
5341
  }
@@ -5298,7 +5351,7 @@ async function loadProviders(deps) {
5298
5351
  async function mutateProviders(deps, mutator) {
5299
5352
  let raw;
5300
5353
  try {
5301
- raw = await fs3.readFile(deps.globalConfigPath, "utf8");
5354
+ raw = await fsp2.readFile(deps.globalConfigPath, "utf8");
5302
5355
  } catch {
5303
5356
  raw = "{}";
5304
5357
  }
@@ -5498,7 +5551,7 @@ var doctorCmd = async (_args, deps) => {
5498
5551
  });
5499
5552
  }
5500
5553
  try {
5501
- await fs3.access(deps.paths.secretsKey);
5554
+ await fsp2.access(deps.paths.secretsKey);
5502
5555
  checks.push({ name: "secret vault", status: "ok", detail: deps.paths.secretsKey });
5503
5556
  } catch {
5504
5557
  checks.push({
@@ -5508,10 +5561,10 @@ var doctorCmd = async (_args, deps) => {
5508
5561
  });
5509
5562
  }
5510
5563
  try {
5511
- await fs3.mkdir(deps.paths.projectSessions, { recursive: true });
5512
- const probe = path20.join(deps.paths.projectSessions, `.probe-${Date.now()}`);
5513
- await fs3.writeFile(probe, "");
5514
- await fs3.unlink(probe);
5564
+ await fsp2.mkdir(deps.paths.projectSessions, { recursive: true });
5565
+ const probe = path21.join(deps.paths.projectSessions, `.probe-${Date.now()}`);
5566
+ await fsp2.writeFile(probe, "");
5567
+ await fsp2.unlink(probe);
5515
5568
  checks.push({ name: "sessions writable", status: "ok", detail: deps.paths.projectSessions });
5516
5569
  } catch (err) {
5517
5570
  checks.push({
@@ -5612,8 +5665,8 @@ var exportCmd = async (args, deps) => {
5612
5665
  return 1;
5613
5666
  }
5614
5667
  if (output) {
5615
- await fs3.mkdir(path20.dirname(path20.resolve(deps.cwd, output)), { recursive: true });
5616
- await fs3.writeFile(path20.resolve(deps.cwd, output), rendered, "utf8");
5668
+ await fsp2.mkdir(path21.dirname(path21.resolve(deps.cwd, output)), { recursive: true });
5669
+ await fsp2.writeFile(path21.resolve(deps.cwd, output), rendered, "utf8");
5617
5670
  deps.renderer.write(`Wrote ${rendered.length} bytes to ${output}
5618
5671
  `);
5619
5672
  } else {
@@ -5670,17 +5723,17 @@ var initCmd = async (_args, deps) => {
5670
5723
  } else {
5671
5724
  deps.renderer.writeInfo(`Found API key in env (${provider.envVars.join(" / ")}).`);
5672
5725
  }
5673
- await fs3.mkdir(deps.paths.globalRoot, { recursive: true });
5726
+ await fsp2.mkdir(deps.paths.globalRoot, { recursive: true });
5674
5727
  const config = { version: 1, provider: providerId, model: modelId };
5675
5728
  if (apiKey) config.apiKey = apiKey;
5676
- const keyFile = path20.join(path20.dirname(deps.paths.globalConfig), ".key");
5729
+ const keyFile = path21.join(path21.dirname(deps.paths.globalConfig), ".key");
5677
5730
  const vault = new DefaultSecretVault$1({ keyFile });
5678
5731
  const encrypted = encryptConfigSecrets(config, vault);
5679
5732
  await atomicWrite(deps.paths.globalConfig, JSON.stringify(encrypted, null, 2));
5680
- await fs3.mkdir(path20.join(deps.projectRoot, ".wrongstack"), { recursive: true });
5681
- const agentsFile = path20.join(deps.projectRoot, ".wrongstack", "AGENTS.md");
5733
+ await fsp2.mkdir(path21.join(deps.projectRoot, ".wrongstack"), { recursive: true });
5734
+ const agentsFile = path21.join(deps.projectRoot, ".wrongstack", "AGENTS.md");
5682
5735
  try {
5683
- await fs3.access(agentsFile);
5736
+ await fsp2.access(agentsFile);
5684
5737
  } catch {
5685
5738
  const detected2 = await detectProjectFacts(deps.projectRoot);
5686
5739
  await atomicWrite(agentsFile, renderAgentsTemplate(detected2));
@@ -5756,7 +5809,7 @@ async function addMcpServer(args, deps) {
5756
5809
  serverCfg.enabled = enable;
5757
5810
  let existing = {};
5758
5811
  try {
5759
- existing = JSON.parse(await fs3.readFile(deps.paths.globalConfig, "utf8"));
5812
+ existing = JSON.parse(await fsp2.readFile(deps.paths.globalConfig, "utf8"));
5760
5813
  } catch {
5761
5814
  }
5762
5815
  const mcpServers = existing.mcpServers ?? {};
@@ -5776,7 +5829,7 @@ async function addMcpServer(args, deps) {
5776
5829
  async function removeMcpServer(name, deps) {
5777
5830
  let existing = {};
5778
5831
  try {
5779
- existing = JSON.parse(await fs3.readFile(deps.paths.globalConfig, "utf8"));
5832
+ existing = JSON.parse(await fsp2.readFile(deps.paths.globalConfig, "utf8"));
5780
5833
  } catch {
5781
5834
  deps.renderer.writeError("No config file found.\n");
5782
5835
  return 1;
@@ -5897,7 +5950,7 @@ function renderConfiguredPlugins(config) {
5897
5950
  }
5898
5951
  async function readConfig(file) {
5899
5952
  try {
5900
- return JSON.parse(await fs3.readFile(file, "utf8"));
5953
+ return JSON.parse(await fsp2.readFile(file, "utf8"));
5901
5954
  } catch {
5902
5955
  return {};
5903
5956
  }
@@ -5988,9 +6041,9 @@ var usageCmd = async (_args, deps) => {
5988
6041
  return 0;
5989
6042
  };
5990
6043
  var projectsCmd = async (_args, deps) => {
5991
- const projectsRoot = path20.join(deps.paths.globalRoot, "projects");
6044
+ const projectsRoot = path21.join(deps.paths.globalRoot, "projects");
5992
6045
  try {
5993
- const entries = await fs3.readdir(projectsRoot);
6046
+ const entries = await fsp2.readdir(projectsRoot);
5994
6047
  if (entries.length === 0) {
5995
6048
  deps.renderer.write("No projects tracked.\n");
5996
6049
  return 0;
@@ -5998,7 +6051,7 @@ var projectsCmd = async (_args, deps) => {
5998
6051
  for (const hash of entries) {
5999
6052
  try {
6000
6053
  const meta = JSON.parse(
6001
- await fs3.readFile(path20.join(projectsRoot, hash, "meta.json"), "utf8")
6054
+ await fsp2.readFile(path21.join(projectsRoot, hash, "meta.json"), "utf8")
6002
6055
  );
6003
6056
  deps.renderer.write(
6004
6057
  ` ${color.dim(hash)} ${color.dim(meta.lastSeen ?? "")} ${meta.root ?? "?"}
@@ -6141,9 +6194,210 @@ function redactKeys(obj) {
6141
6194
  }
6142
6195
  return out;
6143
6196
  }
6197
+ var sessionsFleetCmd = async (args, deps) => {
6198
+ const runId = args.find((a) => !a.startsWith("-"));
6199
+ if (runId) {
6200
+ return showFleetRun(runId, deps);
6201
+ }
6202
+ return listFleetRuns(deps);
6203
+ };
6204
+ async function listFleetRuns(deps) {
6205
+ let entries = [];
6206
+ try {
6207
+ entries = await fsp2.readdir(deps.paths.projectSessions);
6208
+ } catch {
6209
+ deps.renderer.writeError(`Cannot read projectSessions: ${deps.paths.projectSessions}
6210
+ `);
6211
+ return 1;
6212
+ }
6213
+ const runs = [];
6214
+ for (const id of entries) {
6215
+ const runDir = path21.join(deps.paths.projectSessions, id);
6216
+ let stat3;
6217
+ try {
6218
+ stat3 = await fsp2.stat(runDir);
6219
+ } catch {
6220
+ continue;
6221
+ }
6222
+ if (!stat3.isDirectory()) continue;
6223
+ let manifest = false;
6224
+ let checkpoint = false;
6225
+ let subagentCount = 0;
6226
+ let subagentsDir;
6227
+ try {
6228
+ await fsp2.access(path21.join(runDir, "fleet.json"));
6229
+ manifest = true;
6230
+ } catch {
6231
+ }
6232
+ try {
6233
+ await fsp2.access(path21.join(runDir, "checkpoint.json"));
6234
+ checkpoint = true;
6235
+ } catch {
6236
+ }
6237
+ try {
6238
+ subagentsDir = path21.join(runDir, "subagents");
6239
+ const files = await fsp2.readdir(subagentsDir);
6240
+ subagentCount = files.filter((f) => f.endsWith(".jsonl")).length;
6241
+ } catch {
6242
+ }
6243
+ runs.push({ id, manifest, checkpoint, subagents: subagentCount });
6244
+ }
6245
+ if (runs.length === 0) {
6246
+ deps.renderer.write("No fleet runs found.\n");
6247
+ return 0;
6248
+ }
6249
+ deps.renderer.write(color.bold("\nFleet Runs\n") + "\n");
6250
+ for (const r of runs.sort((a, b) => b.id.localeCompare(a.id))) {
6251
+ const checkpointFlag = r.checkpoint ? color.green("\u2713") : color.dim("\u25CB");
6252
+ const manifestFlag = r.manifest ? color.green("\u2713") : color.dim("\u25CB");
6253
+ const subagentInfo = r.subagents > 0 ? color.dim(` ${r.subagents} subagent jsonl`) : "";
6254
+ deps.renderer.write(
6255
+ ` ${color.bold(r.id)} ${checkpointFlag} checkpoint ${manifestFlag} manifest${subagentInfo}
6256
+ `
6257
+ );
6258
+ }
6259
+ deps.renderer.write(
6260
+ `
6261
+ ${color.dim("Run `wrongstack sessions fleet <runId>` for details.")}
6262
+ `
6263
+ );
6264
+ return 0;
6265
+ }
6266
+ async function showFleetRun(runId, deps) {
6267
+ const runDir = path21.join(deps.paths.projectSessions, runId);
6268
+ let stat3;
6269
+ try {
6270
+ stat3 = await fsp2.stat(runDir);
6271
+ } catch {
6272
+ deps.renderer.writeError(`Fleet run not found: ${runId}
6273
+ `);
6274
+ return 1;
6275
+ }
6276
+ if (!stat3.isDirectory()) {
6277
+ deps.renderer.writeError(`Not a directory: ${runId}
6278
+ `);
6279
+ return 1;
6280
+ }
6281
+ deps.renderer.write(color.bold(`
6282
+ Fleet Run: ${runId}
6283
+ `) + "\n");
6284
+ const manifestPath = path21.join(runDir, "fleet.json");
6285
+ let manifestData = null;
6286
+ try {
6287
+ manifestData = await fsp2.readFile(manifestPath, "utf8");
6288
+ const manifest = JSON.parse(manifestData);
6289
+ const subagents = manifest.subagents ?? [];
6290
+ const tasks = manifest.tasks ?? [];
6291
+ const completed = tasks.filter((t) => t.status === "completed" || t.status === "failed" || t.status === "timeout" || t.status === "stopped");
6292
+ deps.renderer.write(
6293
+ ` ${color.green("\u2713")} fleet.json \u2014 ${subagents.length} subagent(s), ${completed.length}/${tasks.length} tasks done
6294
+ `
6295
+ );
6296
+ } catch {
6297
+ deps.renderer.write(` ${color.dim("\u25CB")} fleet.json \u2014 not found
6298
+ `);
6299
+ }
6300
+ const checkpointPath = path21.join(runDir, "checkpoint.json");
6301
+ let checkpointData = null;
6302
+ try {
6303
+ checkpointData = await fsp2.readFile(checkpointPath, "utf8");
6304
+ const snap = JSON.parse(checkpointData);
6305
+ const lockPath = `${checkpointPath}.lock`;
6306
+ let lockStatus = color.dim("\u25CB no lock");
6307
+ try {
6308
+ const lockRaw = await fsp2.readFile(lockPath, "utf8");
6309
+ const lock = JSON.parse(lockRaw);
6310
+ lockStatus = `${color.yellow("\u25B8")} lock held by pid ${lock.pid} on ${lock.hostname} (started ${lock.startedAt})`;
6311
+ } catch {
6312
+ lockStatus = color.green("\u2713 no lock (safe to resume)");
6313
+ }
6314
+ deps.renderer.write(
6315
+ ` ${color.green("\u2713")} checkpoint.json \u2014 updated ${snap.updatedAt}, ${snap.spawnCount} spawns, ${snap.tasks?.length ?? 0} tasks tracked
6316
+ ${lockStatus}
6317
+ `
6318
+ );
6319
+ } catch {
6320
+ deps.renderer.write(` ${color.dim("\u25CB")} checkpoint.json \u2014 not found
6321
+ `);
6322
+ }
6323
+ if (checkpointData) {
6324
+ try {
6325
+ const snap = JSON.parse(checkpointData);
6326
+ if (snap.subagents?.length) {
6327
+ deps.renderer.write("\n Subagents:\n");
6328
+ for (const s of snap.subagents) {
6329
+ deps.renderer.write(
6330
+ ` ${color.cyan(s.id)} ${s.name ? `${s.name} ` : ""}${s.provider ? `(${s.provider}/${s.model})` : ""} spawned ${s.spawnedAt}
6331
+ `
6332
+ );
6333
+ }
6334
+ }
6335
+ if (snap.tasks?.length) {
6336
+ deps.renderer.write("\n Tasks:\n");
6337
+ for (const t of snap.tasks) {
6338
+ deps.renderer.write(
6339
+ ` ${color.dim(t.taskId)} ${t.status} ${t.description ? t.description.slice(0, 50) : "(no description)"}
6340
+ `
6341
+ );
6342
+ }
6343
+ }
6344
+ } catch {
6345
+ }
6346
+ }
6347
+ const subagentsDir = path21.join(runDir, "subagents");
6348
+ let subagentFiles = [];
6349
+ try {
6350
+ subagentFiles = await fsp2.readdir(subagentsDir);
6351
+ subagentFiles = subagentFiles.filter((f) => f.endsWith(".jsonl"));
6352
+ } catch {
6353
+ }
6354
+ if (subagentFiles.length > 0) {
6355
+ deps.renderer.write(`
6356
+ Subagent transcripts (${subagentFiles.length}):
6357
+ `);
6358
+ for (const f of subagentFiles.sort()) {
6359
+ const filePath = path21.join(subagentsDir, f);
6360
+ let size;
6361
+ try {
6362
+ const s = await fsp2.stat(filePath);
6363
+ size = s.size;
6364
+ } catch {
6365
+ size = 0;
6366
+ }
6367
+ const sizeStr = size > 1024 * 1024 ? `${(size / 1024 / 1024).toFixed(1)}MB` : `${(size / 1024).toFixed(0)}KB`;
6368
+ deps.renderer.write(` ${color.dim(f)} ${color.dim(sizeStr)}
6369
+ `);
6370
+ }
6371
+ } else {
6372
+ deps.renderer.write(`
6373
+ ${color.dim("\u25CB")} No subagent transcripts
6374
+ `);
6375
+ }
6376
+ const sharedDir = path21.join(runDir, "shared");
6377
+ try {
6378
+ const files = await fsp2.readdir(sharedDir);
6379
+ deps.renderer.write(`
6380
+ Shared scratchpad: ${files.length} file(s)
6381
+ `);
6382
+ } catch {
6383
+ deps.renderer.write(`
6384
+ ${color.dim("\u25CB")} No shared scratchpad
6385
+ `);
6386
+ }
6387
+ deps.renderer.write(
6388
+ `
6389
+ ${color.dim("Resume: wrongstack --resume " + runId)}
6390
+ `
6391
+ );
6392
+ return 0;
6393
+ }
6144
6394
 
6145
6395
  // src/subcommands/handlers/sessions-config.ts
6146
- var sessionsCmd = async (_args, deps) => {
6396
+ var sessionsCmd = async (args, deps) => {
6397
+ const sub = args[0];
6398
+ if (sub === "fleet") {
6399
+ return sessionsFleetCmd(args.slice(1), deps);
6400
+ }
6147
6401
  if (!deps.sessionStore) {
6148
6402
  deps.renderer.writeError("No session store available.");
6149
6403
  return 1;
@@ -6275,7 +6529,7 @@ function parseRewindFlags(args) {
6275
6529
  var rewindCmd = async (args, deps) => {
6276
6530
  const flags = parseRewindFlags(args);
6277
6531
  const wpaths = resolveWstackPaths({ projectRoot: deps.projectRoot });
6278
- const sessionsDir = path20.join(wpaths.globalRoot, "sessions");
6532
+ const sessionsDir = path21.join(wpaths.globalRoot, "sessions");
6279
6533
  const rewind = new DefaultSessionRewinder(sessionsDir);
6280
6534
  let sessionId = args.find((a) => !a.startsWith("--"));
6281
6535
  if (!sessionId) {
@@ -6485,22 +6739,22 @@ function fmtDuration(ms) {
6485
6739
  const remMin = m - h * 60;
6486
6740
  return `${h}h${remMin}m`;
6487
6741
  }
6488
- function fmtTaskResultLine(r, color32) {
6742
+ function fmtTaskResultLine(r, color33) {
6489
6743
  const stats = `${r.iterations}it ${r.toolCalls}tc ${fmtDuration(r.durationMs)}`;
6490
6744
  const errMsg = typeof r.error === "string" ? r.error : r.error?.message;
6491
6745
  const errKind = typeof r.error === "object" ? r.error?.kind : void 0;
6492
6746
  const errTail = errMsg ? ` \u2014 ${errMsg.replace(/\s+/g, " ").slice(0, 80)}${errMsg.length > 80 ? "\u2026" : ""}` : "";
6493
- const errKindChip = errKind ? color32.dim(` [${errKind}]`) : "";
6494
- const errSnip = errMsg || errKind ? `${errKindChip}${color32.dim(errTail)}` : "";
6747
+ const errKindChip = errKind ? color33.dim(` [${errKind}]`) : "";
6748
+ const errSnip = errMsg || errKind ? `${errKindChip}${color33.dim(errTail)}` : "";
6495
6749
  switch (r.status) {
6496
6750
  case "success":
6497
- return { mark: color32.green("\u2713"), stats, tail: "" };
6751
+ return { mark: color33.green("\u2713"), stats, tail: "" };
6498
6752
  case "timeout":
6499
- return { mark: color32.yellow("\u23F1"), stats: `${color32.yellow("timeout")} ${stats}`, tail: errSnip };
6753
+ return { mark: color33.yellow("\u23F1"), stats: `${color33.yellow("timeout")} ${stats}`, tail: errSnip };
6500
6754
  case "stopped":
6501
- return { mark: color32.dim("\u2298"), stats: `${color32.dim("stopped")} ${stats}`, tail: errSnip };
6755
+ return { mark: color33.dim("\u2298"), stats: `${color33.dim("stopped")} ${stats}`, tail: errSnip };
6502
6756
  case "failed":
6503
- return { mark: color32.red("\u2717"), stats: `${color32.red("failed")} ${stats}`, tail: errSnip };
6757
+ return { mark: color33.red("\u2717"), stats: `${color33.red("failed")} ${stats}`, tail: errSnip };
6504
6758
  }
6505
6759
  }
6506
6760
 
@@ -6510,7 +6764,7 @@ function resolveBundledSkillsDir() {
6510
6764
  try {
6511
6765
  const req2 = createRequire(import.meta.url);
6512
6766
  const corePkg = req2.resolve("@wrongstack/core/package.json");
6513
- return path20.join(path20.dirname(corePkg), "skills");
6767
+ return path21.join(path21.dirname(corePkg), "skills");
6514
6768
  } catch {
6515
6769
  return void 0;
6516
6770
  }
@@ -7236,7 +7490,7 @@ async function execute(deps) {
7236
7490
  supportsVision,
7237
7491
  attachments,
7238
7492
  effectiveMaxContext,
7239
- projectName: path20.basename(projectRoot) || void 0,
7493
+ projectName: path21.basename(projectRoot) || void 0,
7240
7494
  getAutonomy,
7241
7495
  skillLoader
7242
7496
  });
@@ -7254,7 +7508,7 @@ async function execute(deps) {
7254
7508
  supportsVision,
7255
7509
  attachments,
7256
7510
  effectiveMaxContext,
7257
- projectName: path20.basename(projectRoot) || void 0,
7511
+ projectName: path21.basename(projectRoot) || void 0,
7258
7512
  getAutonomy,
7259
7513
  skillLoader
7260
7514
  });
@@ -7337,12 +7591,18 @@ var MultiAgentHost = class {
7337
7591
  // by passing maxToolCalls/maxIterations through the spawn tool.
7338
7592
  };
7339
7593
  if (this.opts.directorMode) {
7594
+ const defaultScratchpad = this.opts.sharedScratchpadPath || (this.opts.sessionsRoot && this.opts.directorRunId ? path21.join(this.opts.sessionsRoot, this.opts.directorRunId, "shared") : void 0);
7340
7595
  this.director = new Director({
7341
7596
  config: coordinatorConfig,
7342
7597
  manifestPath: this.opts.manifestPath,
7343
- sharedScratchpadPath: this.opts.sharedScratchpadPath,
7598
+ sharedScratchpadPath: defaultScratchpad,
7344
7599
  stateCheckpointPath: this.opts.stateCheckpointPath,
7345
7600
  sessionWriter: this.opts.sessionWriter,
7601
+ directorBudget: this.opts.directorBudget,
7602
+ maxBudgetExtensions: this.opts.maxBudgetExtensions,
7603
+ checkpointDebounceMs: this.opts.checkpointDebounceMs,
7604
+ sessionsRoot: this.opts.sessionsRoot,
7605
+ directorRunId: this.opts.directorRunId,
7346
7606
  // Autonomy: allow nested directors a few levels deep. Default
7347
7607
  // is 2 (root + one tier of workers), which trips the moment a
7348
7608
  // worker tries to recurse into "let me delegate the parser
@@ -7526,7 +7786,7 @@ var MultiAgentHost = class {
7526
7786
  model: opts?.model,
7527
7787
  tools: opts?.tools
7528
7788
  };
7529
- const transcriptPath = this.sessionFactory ? path20.join(this.sessionFactory.dir, `${subagentConfig.name}.jsonl`) : void 0;
7789
+ const transcriptPath = this.sessionFactory ? path21.join(this.sessionFactory.dir, `${subagentConfig.name}.jsonl`) : void 0;
7530
7790
  if (this.director) {
7531
7791
  const subagentId = await this.director.spawn(subagentConfig);
7532
7792
  const taskId2 = randomUUID();
@@ -7590,7 +7850,16 @@ var MultiAgentHost = class {
7590
7850
  });
7591
7851
  }
7592
7852
  status() {
7593
- const pending = Array.from(this.pending.entries()).map(([taskId, v]) => ({
7853
+ const activeSubagentIds = /* @__PURE__ */ new Set();
7854
+ if (this.coordinator) {
7855
+ const s = this.coordinator.getStatus();
7856
+ for (const a of s.subagents) {
7857
+ if (a.status === "running" || a.status === "idle") {
7858
+ activeSubagentIds.add(a.id);
7859
+ }
7860
+ }
7861
+ }
7862
+ const pending = Array.from(this.pending.entries()).filter(([, v]) => activeSubagentIds.has(v.subagentId)).map(([taskId, v]) => ({
7594
7863
  taskId,
7595
7864
  description: v.description,
7596
7865
  subagentId: v.subagentId
@@ -7686,16 +7955,16 @@ var MultiAgentHost = class {
7686
7955
  }
7687
7956
  this.opts.directorMode = true;
7688
7957
  if (this.opts.fleetRoot && !this.opts.manifestPath) {
7689
- this.opts.manifestPath = path20.join(this.opts.fleetRoot, "fleet.json");
7958
+ this.opts.manifestPath = path21.join(this.opts.fleetRoot, "fleet.json");
7690
7959
  }
7691
7960
  if (this.opts.fleetRoot && !this.opts.sharedScratchpadPath) {
7692
- this.opts.sharedScratchpadPath = path20.join(this.opts.fleetRoot, "shared");
7961
+ this.opts.sharedScratchpadPath = path21.join(this.opts.fleetRoot, "shared");
7693
7962
  }
7694
7963
  if (this.opts.fleetRoot && !this.opts.sessionsRoot) {
7695
- this.opts.sessionsRoot = path20.join(this.opts.fleetRoot, "subagents");
7964
+ this.opts.sessionsRoot = path21.join(this.opts.fleetRoot, "subagents");
7696
7965
  }
7697
7966
  if (this.opts.fleetRoot && !this.opts.stateCheckpointPath) {
7698
- this.opts.stateCheckpointPath = path20.join(this.opts.fleetRoot, "director-state.json");
7967
+ this.opts.stateCheckpointPath = path21.join(this.opts.fleetRoot, "director-state.json");
7699
7968
  }
7700
7969
  await this.ensureDirector();
7701
7970
  return this.director ?? null;
@@ -7816,11 +8085,11 @@ var SessionStats = class {
7816
8085
  if (e.name === "bash") this.bashCommands++;
7817
8086
  else if (e.name === "fetch") this.fetches++;
7818
8087
  if (!e.ok) return;
7819
- const path21 = typeof input?.path === "string" ? input.path : void 0;
7820
- if (e.name === "read" && path21) this.readPaths.add(path21);
7821
- else if (e.name === "edit" && path21) this.editedPaths.add(path21);
7822
- else if (e.name === "write" && path21) {
7823
- this.writtenPaths.add(path21);
8088
+ const path22 = typeof input?.path === "string" ? input.path : void 0;
8089
+ if (e.name === "read" && path22) this.readPaths.add(path22);
8090
+ else if (e.name === "edit" && path22) this.editedPaths.add(path22);
8091
+ else if (e.name === "write" && path22) {
8092
+ this.writtenPaths.add(path22);
7824
8093
  const content = typeof input?.content === "string" ? input.content : "";
7825
8094
  this.bytesWritten += Buffer.byteLength(content, "utf8");
7826
8095
  }
@@ -8151,12 +8420,12 @@ async function setupSession(params) {
8151
8420
  }
8152
8421
  const sessionRef = { current: session };
8153
8422
  await recoveryLock.write(session.id).catch(() => void 0);
8154
- const attachments = new DefaultAttachmentStore({ spoolDir: path20.join(wpaths.projectSessions, session.id, "attachments") });
8155
- const queueStore = new QueueStore({ dir: path20.join(wpaths.projectSessions, session.id) });
8423
+ const attachments = new DefaultAttachmentStore({ spoolDir: path21.join(wpaths.projectSessions, session.id, "attachments") });
8424
+ const queueStore = new QueueStore({ dir: path21.join(wpaths.projectSessions, session.id) });
8156
8425
  const ctxSignal = new AbortController().signal;
8157
8426
  const context = new Context({ systemPrompt, provider, session, signal: ctxSignal, tokenCounter, cwd, projectRoot, model: config.model });
8158
8427
  if (restoredMessages.length > 0) context.state.replaceMessages(restoredMessages);
8159
- const todosCheckpointPath = path20.join(wpaths.projectSessions, `${session.id}.todos.json`);
8428
+ const todosCheckpointPath = path21.join(wpaths.projectSessions, `${session.id}.todos.json`);
8160
8429
  if (resumeId) {
8161
8430
  try {
8162
8431
  const restoredTodos = await loadTodosCheckpoint(todosCheckpointPath);
@@ -8168,12 +8437,13 @@ async function setupSession(params) {
8168
8437
  }
8169
8438
  }
8170
8439
  const detachTodosCheckpoint = attachTodosCheckpoint(context.state, todosCheckpointPath, session.id);
8171
- const planPath = path20.join(wpaths.projectSessions, `${session.id}.plan.json`);
8440
+ const planPath = path21.join(wpaths.projectSessions, `${session.id}.plan.json`);
8172
8441
  context.state.setMeta("plan.path", planPath);
8442
+ let dirState;
8173
8443
  if (resumeId) {
8174
8444
  try {
8175
- const fleetRoot = path20.join(wpaths.projectSessions, session.id);
8176
- const dirState = await loadDirectorState(path20.join(fleetRoot, "director-state.json"));
8445
+ const fleetRoot = path21.join(wpaths.projectSessions, session.id);
8446
+ dirState = await loadDirectorState(path21.join(fleetRoot, "director-state.json"));
8177
8447
  if (dirState) {
8178
8448
  const tCounts = {};
8179
8449
  for (const t of dirState.tasks) tCounts[t.status] = (tCounts[t.status] ?? 0) + 1;
@@ -8192,7 +8462,7 @@ async function setupSession(params) {
8192
8462
  } catch {
8193
8463
  }
8194
8464
  }
8195
- return { session, sessionRef, context, restoredMessages, attachments, recoveryLock, queueStore, planPath, detachTodosCheckpoint };
8465
+ return { session, sessionRef, context, restoredMessages, attachments, recoveryLock, queueStore, planPath, detachTodosCheckpoint, priorFleetState: dirState ?? void 0 };
8196
8466
  }
8197
8467
 
8198
8468
  // src/index.ts
@@ -8200,7 +8470,7 @@ function resolveBundledSkillsDir2() {
8200
8470
  try {
8201
8471
  const req2 = createRequire(import.meta.url);
8202
8472
  const corePkg = req2.resolve("@wrongstack/core/package.json");
8203
- return path20.join(path20.dirname(corePkg), "skills");
8473
+ return path21.join(path21.dirname(corePkg), "skills");
8204
8474
  } catch {
8205
8475
  return void 0;
8206
8476
  }
@@ -8307,7 +8577,7 @@ async function main(argv) {
8307
8577
  modeId,
8308
8578
  modePrompt,
8309
8579
  modelCapabilities,
8310
- planPath: () => sessionRef.current ? path20.join(wpaths.projectSessions, `${sessionRef.current.id}.plan.json`) : void 0
8580
+ planPath: () => sessionRef.current ? path21.join(wpaths.projectSessions, `${sessionRef.current.id}.plan.json`) : void 0
8311
8581
  })
8312
8582
  );
8313
8583
  const toolRegistry = new ToolRegistry();
@@ -8335,7 +8605,7 @@ async function main(argv) {
8335
8605
  name: "session-store",
8336
8606
  check: async () => {
8337
8607
  try {
8338
- await fs3.access(wpaths.projectSessions);
8608
+ await fsp2.access(wpaths.projectSessions);
8339
8609
  return { status: "healthy" };
8340
8610
  } catch (e) {
8341
8611
  return { status: "unhealthy", detail: e instanceof Error ? e.message : "access denied" };
@@ -8352,7 +8622,7 @@ async function main(argv) {
8352
8622
  const dumpMetrics = () => {
8353
8623
  if (!metricsSink) return;
8354
8624
  try {
8355
- const out = path20.join(wpaths.projectSessions, "metrics.json");
8625
+ const out = path21.join(wpaths.projectSessions, "metrics.json");
8356
8626
  const snap = metricsSink.snapshot();
8357
8627
  writeFileSync(out, JSON.stringify(snap, null, 2));
8358
8628
  } catch {
@@ -8469,6 +8739,7 @@ async function main(argv) {
8469
8739
  const queueStore = sessResult.queueStore;
8470
8740
  const planPath = sessResult.planPath;
8471
8741
  const detachTodosCheckpoint = sessResult.detachTodosCheckpoint;
8742
+ const priorFleetState = sessResult.priorFleetState;
8472
8743
  const stats = new SessionStats(events, tokenCounter);
8473
8744
  const errorRing = [];
8474
8745
  events.on("error", (e) => {
@@ -8568,15 +8839,15 @@ async function main(argv) {
8568
8839
  return err instanceof Error ? err.message : String(err);
8569
8840
  }
8570
8841
  };
8571
- const directorMode = flags["director"] === true;
8842
+ const directorMode = flags["director"] === true || typeof flags["resume"] === "string";
8572
8843
  let director = null;
8573
8844
  let autonomyMode = "off";
8574
- const fleetRoot = directorMode ? path20.join(wpaths.projectSessions, session.id) : void 0;
8575
- const manifestPath = directorMode ? typeof process.env["WRONGSTACK_FLEET_MANIFEST"] === "string" ? process.env["WRONGSTACK_FLEET_MANIFEST"] : path20.join(fleetRoot, "fleet.json") : void 0;
8576
- const sharedScratchpadPath = directorMode ? path20.join(fleetRoot, "shared") : void 0;
8577
- const subagentSessionsRoot = directorMode ? path20.join(fleetRoot, "subagents") : void 0;
8578
- const stateCheckpointPath = directorMode ? path20.join(fleetRoot, "director-state.json") : void 0;
8579
- const fleetRootForPromotion = path20.join(wpaths.projectSessions, session.id);
8845
+ const fleetRoot = directorMode ? path21.join(wpaths.projectSessions, session.id) : void 0;
8846
+ const manifestPath = directorMode ? typeof process.env["WRONGSTACK_FLEET_MANIFEST"] === "string" ? process.env["WRONGSTACK_FLEET_MANIFEST"] : path21.join(fleetRoot, "fleet.json") : void 0;
8847
+ const sharedScratchpadPath = directorMode ? path21.join(fleetRoot, "shared") : void 0;
8848
+ const subagentSessionsRoot = directorMode ? path21.join(fleetRoot, "subagents") : void 0;
8849
+ const stateCheckpointPath = directorMode ? path21.join(fleetRoot, "director-state.json") : void 0;
8850
+ const fleetRootForPromotion = path21.join(wpaths.projectSessions, session.id);
8580
8851
  const multiAgentHost = new MultiAgentHost(
8581
8852
  {
8582
8853
  container,
@@ -8616,6 +8887,7 @@ async function main(argv) {
8616
8887
  if (directorMode) {
8617
8888
  director = await multiAgentHost.ensureDirector();
8618
8889
  if (director) {
8890
+ if (priorFleetState) director.setCheckpointState(priorFleetState);
8619
8891
  for (const tool of director.tools(FLEET_ROSTER)) {
8620
8892
  toolRegistry.register(tool);
8621
8893
  }
@@ -8759,32 +9031,32 @@ async function main(argv) {
8759
9031
  return `Unknown fleet action: ${action}`;
8760
9032
  },
8761
9033
  onFleetLog: async (subagentId, mode) => {
8762
- const subagentsRoot = path20.join(fleetRootForPromotion, "subagents");
9034
+ const subagentsRoot = path21.join(fleetRootForPromotion, "subagents");
8763
9035
  let runDirs;
8764
9036
  try {
8765
- runDirs = await fs3.readdir(subagentsRoot);
9037
+ runDirs = await fsp2.readdir(subagentsRoot);
8766
9038
  } catch {
8767
9039
  return "No fleet transcripts on disk \u2014 no subagents have been spawned for this session.";
8768
9040
  }
8769
9041
  const found = [];
8770
9042
  for (const runId of runDirs) {
8771
- const runDir = path20.join(subagentsRoot, runId);
9043
+ const runDir = path21.join(subagentsRoot, runId);
8772
9044
  let files;
8773
9045
  try {
8774
- files = await fs3.readdir(runDir);
9046
+ files = await fsp2.readdir(runDir);
8775
9047
  } catch {
8776
9048
  continue;
8777
9049
  }
8778
9050
  for (const f of files) {
8779
9051
  if (!f.endsWith(".jsonl")) continue;
8780
- const full = path20.join(runDir, f);
9052
+ const full = path21.join(runDir, f);
8781
9053
  try {
8782
- const stat2 = await fs3.stat(full);
9054
+ const stat3 = await fsp2.stat(full);
8783
9055
  found.push({
8784
9056
  runId,
8785
9057
  subagentId: f.replace(/\.jsonl$/, ""),
8786
9058
  file: full,
8787
- size: stat2.size
9059
+ size: stat3.size
8788
9060
  });
8789
9061
  } catch {
8790
9062
  }
@@ -8818,7 +9090,7 @@ async function main(argv) {
8818
9090
  ].join("\n");
8819
9091
  }
8820
9092
  const t = matches[0];
8821
- const raw = await fs3.readFile(t.file, "utf8");
9093
+ const raw = await fsp2.readFile(t.file, "utf8");
8822
9094
  if (mode === "raw") return raw;
8823
9095
  const lines = raw.split("\n").filter((l) => l.trim());
8824
9096
  const counts = {};
@@ -8874,7 +9146,7 @@ async function main(argv) {
8874
9146
  }
8875
9147
  const dir = await multiAgentHost.ensureDirector();
8876
9148
  if (!dir) return "Director is not available.";
8877
- const dirStatePath = path20.join(fleetRootForPromotion, "director-state.json");
9149
+ const dirStatePath = path21.join(fleetRootForPromotion, "director-state.json");
8878
9150
  const prior = await loadDirectorState(dirStatePath);
8879
9151
  if (!prior) {
8880
9152
  return "No prior director-state.json found \u2014 nothing to retry.";
@@ -8945,9 +9217,9 @@ async function main(argv) {
8945
9217
  for (const tool of director2.tools(FLEET_ROSTER)) {
8946
9218
  toolRegistry.register(tool);
8947
9219
  }
8948
- const mp = path20.join(fleetRootForPromotion, "fleet.json");
8949
- const sp = path20.join(fleetRootForPromotion, "shared");
8950
- const ss = path20.join(fleetRootForPromotion, "subagents");
9220
+ const mp = path21.join(fleetRootForPromotion, "fleet.json");
9221
+ const sp = path21.join(fleetRootForPromotion, "shared");
9222
+ const ss = path21.join(fleetRootForPromotion, "subagents");
8951
9223
  const lines = [
8952
9224
  `${color.green("\u2713")} Promoted to director mode.`,
8953
9225
  ` Roster: ${Object.keys(FLEET_ROSTER).join(", ")}`,