@wrongstack/cli 0.41.0 → 0.51.3

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,22 +1,22 @@
1
1
  #!/usr/bin/env node
2
- import * as path9 from 'path';
2
+ import * as path8 from 'path';
3
3
  import { join } from 'path';
4
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, atomicWrite, DefaultPathResolver, TOKENS, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, SlashCommandRegistry, 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, AutoCompactionMiddleware, estimateRequestTokensCalibrated, Agent, loadPlugins, FleetManager, makeDirectorSessionFactory, Director, makeFleetEmitTool, makeFleetStatusTool, resolveModelMatrix, AutoApprovePermissionPolicy, PhaseStore, AutoPhasePlanner, PhaseGraphBuilder, WorktreeManager, PhaseOrchestrator, makeLLMClassifier, ParallelEternalEngine, EternalAutonomyEngine, allServers as allServers$1, resolveWstackPaths, DefaultSecretVault as DefaultSecretVault$1, migratePlaintextSecrets, DefaultConfigLoader, setRawMode, DefaultSessionReader, ToolAuditLog, DefaultSessionRewinder, DefaultSessionStore, DefaultPluginAPI, makeAgentSubagentRunner, NULL_FLEET_BUS, buildChildEnv, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, AGENTS_BY_PHASE, dispatchAgent, formatTodosList, SessionRecovery, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, pendingBtwCount, setBtwNote, MATRIX_PHASE_KEYS, AGENT_CATALOG, matrixKeyKind, onResize, decryptConfigSecrets as decryptConfigSecrets$1, encryptConfigSecrets as encryptConfigSecrets$1, InputBuilder, FsError, ERROR_CODES } from '@wrongstack/core';
5
+ import { color, writeErr, DefaultTaskStore, TaskTracker, renderProgress, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, renderTaskGraph, SpecVersioning, atomicWrite, DefaultPathResolver, TOKENS, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, 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, 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, makeAgentSubagentRunner, NULL_FLEET_BUS, buildChildEnv, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, AGENTS_BY_PHASE, dispatchAgent, formatTodosList, SessionRecovery, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, pendingBtwCount, setBtwNote, MATRIX_PHASE_KEYS, AGENT_CATALOG, matrixKeyKind, onResize, decryptConfigSecrets as decryptConfigSecrets$1, encryptConfigSecrets as encryptConfigSecrets$1, InputBuilder, FsError, ERROR_CODES } from '@wrongstack/core';
6
6
  import { createRequire } from 'module';
7
- import * as os3 from 'os';
8
- import os3__default from 'os';
7
+ import * as os2 from 'os';
8
+ import os2__default from 'os';
9
9
  import * as crypto2 from 'crypto';
10
10
  import { randomUUID } from 'crypto';
11
11
  import { DefaultSecretVault, decryptConfigSecrets, encryptConfigSecrets, isSecretField } from '@wrongstack/core/security';
12
12
  import { WebSocketServer, WebSocket } from 'ws';
13
13
  import { MCPRegistry } from '@wrongstack/mcp';
14
- import { buildProviderFactoriesFromRegistry, makeProviderFromConfig, capabilitiesFor } from '@wrongstack/providers';
14
+ import { capabilitiesFor, buildProviderFactoriesFromRegistry, makeProviderFromConfig } from '@wrongstack/providers';
15
15
  import { createDefaultContainer, routeImagesForModel, readClipboardImage } from '@wrongstack/runtime';
16
16
  import { builtinToolsPack, rememberTool, forgetTool } from '@wrongstack/tools';
17
17
  import { fileURLToPath } from 'url';
18
18
  import * as readline from 'readline';
19
- import * as fs11 from 'fs';
19
+ import * as fs10 from 'fs';
20
20
  import { writeFileSync, existsSync, readFileSync } from 'fs';
21
21
  import { WrongStackACPServer } from '@wrongstack/acp/agent';
22
22
  import { ACP_AGENT_COMMANDS, makeACPSubagentRunner, makeACPSubagentRunnerWithStop } from '@wrongstack/acp';
@@ -1395,7 +1395,7 @@ function sddHelp() {
1395
1395
  async function gatherProjectContext2(projectRoot) {
1396
1396
  const parts = [];
1397
1397
  try {
1398
- const pkgPath = path9.join(projectRoot, "package.json");
1398
+ const pkgPath = path8.join(projectRoot, "package.json");
1399
1399
  const pkgRaw = await fsp3.readFile(pkgPath, "utf8");
1400
1400
  const pkg = JSON.parse(pkgRaw);
1401
1401
  parts.push(`Project: ${String(pkg.name ?? "unknown")}`);
@@ -1411,13 +1411,13 @@ async function gatherProjectContext2(projectRoot) {
1411
1411
  } catch {
1412
1412
  }
1413
1413
  try {
1414
- const tsconfigPath = path9.join(projectRoot, "tsconfig.json");
1414
+ const tsconfigPath = path8.join(projectRoot, "tsconfig.json");
1415
1415
  await fsp3.access(tsconfigPath);
1416
1416
  parts.push("Language: TypeScript");
1417
1417
  } catch {
1418
1418
  }
1419
1419
  try {
1420
- const srcDir = path9.join(projectRoot, "src");
1420
+ const srcDir = path8.join(projectRoot, "src");
1421
1421
  const entries = await fsp3.readdir(srcDir, { withFileTypes: true });
1422
1422
  const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
1423
1423
  if (dirs.length > 0) {
@@ -1573,7 +1573,7 @@ __export(update_check_exports, {
1573
1573
  getUpdateNotification: () => getUpdateNotification
1574
1574
  });
1575
1575
  function cachePath(homeFn = defaultHomeDir2) {
1576
- return path9.join(homeFn(), ".wrongstack", "update-cache.json");
1576
+ return path8.join(homeFn(), ".wrongstack", "update-cache.json");
1577
1577
  }
1578
1578
  function currentVersion() {
1579
1579
  const req2 = createRequire(import.meta.url);
@@ -1610,7 +1610,7 @@ async function readCache(homeFn = defaultHomeDir2) {
1610
1610
  }
1611
1611
  async function writeCache(entry, homeFn = defaultHomeDir2) {
1612
1612
  try {
1613
- const dir = path9.dirname(cachePath(homeFn));
1613
+ const dir = path8.dirname(cachePath(homeFn));
1614
1614
  await fsp3.mkdir(dir, { recursive: true });
1615
1615
  await fsp3.writeFile(cachePath(homeFn), JSON.stringify(entry, null, 2), "utf8");
1616
1616
  } catch {
@@ -1683,7 +1683,7 @@ async function getUpdateNotification(signal, homeFn) {
1683
1683
  var defaultHomeDir2, CACHE_TTL_MS;
1684
1684
  var init_update_check = __esm({
1685
1685
  "src/update-check.ts"() {
1686
- defaultHomeDir2 = () => os3.homedir();
1686
+ defaultHomeDir2 = () => os2.homedir();
1687
1687
  CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
1688
1688
  }
1689
1689
  });
@@ -1813,7 +1813,7 @@ async function runWebUI(opts) {
1813
1813
  );
1814
1814
  }
1815
1815
  }
1816
- return new Promise((resolve4) => {
1816
+ return new Promise((resolve3) => {
1817
1817
  wss.on("listening", () => {
1818
1818
  console.log(`[WebUI] WebSocket server running on ws://127.0.0.1:${port}`);
1819
1819
  setupEvents();
@@ -1914,7 +1914,7 @@ async function runWebUI(opts) {
1914
1914
  clients.clear();
1915
1915
  wss.close(() => {
1916
1916
  console.log("[WebUI] Server stopped");
1917
- resolve4();
1917
+ resolve3();
1918
1918
  });
1919
1919
  }
1920
1920
  process.on("SIGINT", shutdown);
@@ -2231,7 +2231,7 @@ async function runWebUI(opts) {
2231
2231
  return {};
2232
2232
  }
2233
2233
  if (!parsed.providers) return {};
2234
- const keyFile = path9.join(path9.dirname(opts.globalConfigPath), ".key");
2234
+ const keyFile = path8.join(path8.dirname(opts.globalConfigPath), ".key");
2235
2235
  const vault = new DefaultSecretVault({ keyFile });
2236
2236
  return decryptConfigSecrets(parsed.providers, vault);
2237
2237
  }
@@ -2264,7 +2264,7 @@ async function runWebUI(opts) {
2264
2264
  parsed = {};
2265
2265
  }
2266
2266
  parsed.providers = providers;
2267
- const keyFile = path9.join(path9.dirname(opts.globalConfigPath), ".key");
2267
+ const keyFile = path8.join(path8.dirname(opts.globalConfigPath), ".key");
2268
2268
  const vault = new DefaultSecretVault({ keyFile });
2269
2269
  const encrypted = encryptConfigSecrets(parsed, vault);
2270
2270
  await atomicWrite(opts.globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
@@ -2338,6 +2338,34 @@ function makeProviderClassifier(provider, model) {
2338
2338
  }
2339
2339
  });
2340
2340
  }
2341
+ async function resolveRuntimeMaxContext(input) {
2342
+ const explicitContext = positiveNumber(input.config.context?.effectiveMaxContext);
2343
+ if (explicitContext) return explicitContext;
2344
+ const providerConfig = input.runtimeProviderConfig ?? input.config.providers?.[input.providerId];
2345
+ const providerOverride = positiveNumber(readConfiguredMaxContext(providerConfig));
2346
+ if (providerOverride) return providerOverride;
2347
+ const topLevelBaseUrlApplies = input.providerId === input.config.provider;
2348
+ const hasCustomBaseUrl = Boolean(
2349
+ providerConfig?.baseUrl || topLevelBaseUrlApplies && input.config.baseUrl
2350
+ );
2351
+ if (input.modelsRegistry && !hasCustomBaseUrl) {
2352
+ const caps = await capabilitiesFor(input.modelsRegistry, input.providerId, input.modelId).catch(
2353
+ () => void 0
2354
+ );
2355
+ const catalogMax = positiveNumber(caps?.maxContext);
2356
+ if (catalogMax) return catalogMax;
2357
+ }
2358
+ return positiveNumber(input.provider.capabilities.maxContext) ?? 0;
2359
+ }
2360
+ function readConfiguredMaxContext(providerConfig) {
2361
+ if (!providerConfig || typeof providerConfig !== "object") return void 0;
2362
+ const capabilities = providerConfig.capabilities;
2363
+ if (!capabilities || typeof capabilities !== "object") return void 0;
2364
+ return capabilities.maxContext;
2365
+ }
2366
+ function positiveNumber(value) {
2367
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
2368
+ }
2341
2369
 
2342
2370
  // src/arg-parser.ts
2343
2371
  var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
@@ -2485,10 +2513,10 @@ async function detectPackageManager(root, declared) {
2485
2513
  const name = declared.split("@")[0];
2486
2514
  if (name) return name;
2487
2515
  }
2488
- if (await pathExists(path9.join(root, "pnpm-lock.yaml"))) return "pnpm";
2489
- if (await pathExists(path9.join(root, "bun.lockb"))) return "bun";
2490
- if (await pathExists(path9.join(root, "bun.lock"))) return "bun";
2491
- if (await pathExists(path9.join(root, "yarn.lock"))) return "yarn";
2516
+ if (await pathExists(path8.join(root, "pnpm-lock.yaml"))) return "pnpm";
2517
+ if (await pathExists(path8.join(root, "bun.lockb"))) return "bun";
2518
+ if (await pathExists(path8.join(root, "bun.lock"))) return "bun";
2519
+ if (await pathExists(path8.join(root, "yarn.lock"))) return "yarn";
2492
2520
  return "npm";
2493
2521
  }
2494
2522
  function hasUsableScript(scripts, name) {
@@ -2509,7 +2537,7 @@ function parseMakeTargets(makefile) {
2509
2537
  async function detectProjectFacts(root) {
2510
2538
  const facts = { hints: [] };
2511
2539
  try {
2512
- const pkg = JSON.parse(await fsp3.readFile(path9.join(root, "package.json"), "utf8"));
2540
+ const pkg = JSON.parse(await fsp3.readFile(path8.join(root, "package.json"), "utf8"));
2513
2541
  const scripts = pkg.scripts ?? {};
2514
2542
  const pm = await detectPackageManager(root, pkg.packageManager);
2515
2543
  if (hasUsableScript(scripts, "build")) facts.build = `${pm} run build`;
@@ -2523,14 +2551,14 @@ async function detectProjectFacts(root) {
2523
2551
  } catch {
2524
2552
  }
2525
2553
  try {
2526
- if (!await pathExists(path9.join(root, "pyproject.toml"))) throw new Error("not python");
2554
+ if (!await pathExists(path8.join(root, "pyproject.toml"))) throw new Error("not python");
2527
2555
  facts.test ??= "pytest";
2528
2556
  facts.lint ??= "ruff check .";
2529
2557
  facts.hints.push("pyproject.toml");
2530
2558
  } catch {
2531
2559
  }
2532
2560
  try {
2533
- if (!await pathExists(path9.join(root, "go.mod"))) throw new Error("not go");
2561
+ if (!await pathExists(path8.join(root, "go.mod"))) throw new Error("not go");
2534
2562
  facts.build ??= "go build ./...";
2535
2563
  facts.test ??= "go test ./...";
2536
2564
  facts.run ??= "go run .";
@@ -2538,7 +2566,7 @@ async function detectProjectFacts(root) {
2538
2566
  } catch {
2539
2567
  }
2540
2568
  try {
2541
- if (!await pathExists(path9.join(root, "Cargo.toml"))) throw new Error("not rust");
2569
+ if (!await pathExists(path8.join(root, "Cargo.toml"))) throw new Error("not rust");
2542
2570
  facts.build ??= "cargo build";
2543
2571
  facts.test ??= "cargo test";
2544
2572
  facts.lint ??= "cargo clippy";
@@ -2547,7 +2575,7 @@ async function detectProjectFacts(root) {
2547
2575
  } catch {
2548
2576
  }
2549
2577
  try {
2550
- const makefile = await fsp3.readFile(path9.join(root, "Makefile"), "utf8");
2578
+ const makefile = await fsp3.readFile(path8.join(root, "Makefile"), "utf8");
2551
2579
  const targets = parseMakeTargets(makefile);
2552
2580
  facts.build ??= targets.has("build") ? "make build" : "make";
2553
2581
  if (targets.has("test")) facts.test ??= "make test";
@@ -2729,8 +2757,16 @@ function buildAutonomyCommand(opts) {
2729
2757
  const goal = await loadGoal(goalFilePath(opts.projectRoot));
2730
2758
  if (goal) {
2731
2759
  const u = summarizeUsage(goal);
2732
- lines.push(color.dim(` Goal: ${goal.goal.length > 80 ? `${goal.goal.slice(0, 77)}\u2026` : goal.goal}`));
2733
- lines.push(color.dim(` Engine state: ${goal.engineState} \xB7 iterations: ${goal.iterations} \xB7 journal: ${goal.journal.length}`));
2760
+ lines.push(
2761
+ color.dim(
2762
+ ` Goal: ${goal.goal.length > 80 ? `${goal.goal.slice(0, 77)}\u2026` : goal.goal}`
2763
+ )
2764
+ );
2765
+ lines.push(
2766
+ color.dim(
2767
+ ` Engine state: ${goal.engineState} \xB7 iterations: ${goal.iterations} \xB7 journal: ${goal.journal.length}`
2768
+ )
2769
+ );
2734
2770
  if (u.iterationsWithUsage > 0) {
2735
2771
  lines.push(
2736
2772
  color.dim(
@@ -2741,7 +2777,9 @@ function buildAutonomyCommand(opts) {
2741
2777
  const recent = goal.journal.slice(-10);
2742
2778
  const failed = recent.filter((e) => e.status === "failure").length;
2743
2779
  if (failed > 0) {
2744
- lines.push(color.amber(` Recent failures: ${failed} of last ${recent.length} iterations`));
2780
+ lines.push(
2781
+ color.amber(` Recent failures: ${failed} of last ${recent.length} iterations`)
2782
+ );
2745
2783
  }
2746
2784
  }
2747
2785
  } catch {
@@ -2775,7 +2813,7 @@ function buildAutonomyCommand(opts) {
2775
2813
  }
2776
2814
  } catch {
2777
2815
  }
2778
- const msg2 = `${color.amber("Eternal/parallel mode stop requested.")} The current iteration will finish, then the loop exits.${summaryLine}`;
2816
+ const msg2 = `${color.amber("Eternal/parallel mode stop requested.")} In-flight eternal work is cancelled; parallel fan-out stops after the current tick cleans up.${summaryLine}`;
2779
2817
  opts.renderer.write(msg2);
2780
2818
  return { message: msg2 };
2781
2819
  }
@@ -2792,7 +2830,7 @@ function buildAutonomyCommand(opts) {
2792
2830
  newMode = "eternal-parallel";
2793
2831
  } else if (arg === "toggle" || arg === "cycle") {
2794
2832
  const current = opts.onAutonomy() ?? "off";
2795
- const cycle = ["off", "suggest", "auto", "eternal"];
2833
+ const cycle = ["off", "suggest", "auto", "eternal", "eternal-parallel"];
2796
2834
  newMode = cycle[(cycle.indexOf(current) + 1) % cycle.length] ?? "off";
2797
2835
  } else {
2798
2836
  const msg2 = `Unknown argument: ${arg}. Use /autonomy on, off, suggest, eternal, parallel, stop, or toggle.`;
@@ -2907,7 +2945,7 @@ function formatPhaseList(graph) {
2907
2945
  }
2908
2946
  async function gatherProjectContext(projectRoot) {
2909
2947
  try {
2910
- const raw = await fsp3.readFile(path9.join(projectRoot, "package.json"), "utf8");
2948
+ const raw = await fsp3.readFile(path8.join(projectRoot, "package.json"), "utf8");
2911
2949
  const pkg = JSON.parse(raw);
2912
2950
  const parts = [
2913
2951
  `Project: ${String(pkg.name ?? "unknown")}`,
@@ -4771,8 +4809,8 @@ function buildInitCommand(opts) {
4771
4809
  name: "init",
4772
4810
  description: "Create or update .wrongstack/AGENTS.md project context for the system prompt.",
4773
4811
  async run(_args, ctx) {
4774
- const dir = path9.join(ctx.projectRoot, ".wrongstack");
4775
- const file = path9.join(dir, "AGENTS.md");
4812
+ const dir = path8.join(ctx.projectRoot, ".wrongstack");
4813
+ const file = path8.join(dir, "AGENTS.md");
4776
4814
  const detected = await detectProjectFacts(ctx.projectRoot);
4777
4815
  const body = renderAgentsTemplate(detected);
4778
4816
  await fsp3.mkdir(dir, { recursive: true });
@@ -4963,18 +5001,18 @@ function stateBadge(state) {
4963
5001
  return color.dim(state);
4964
5002
  }
4965
5003
  }
4966
- async function readConfig(path26) {
5004
+ async function readConfig(path25) {
4967
5005
  try {
4968
- return JSON.parse(await fsp3.readFile(path26, "utf8"));
5006
+ return JSON.parse(await fsp3.readFile(path25, "utf8"));
4969
5007
  } catch {
4970
5008
  return {};
4971
5009
  }
4972
5010
  }
4973
- async function writeConfig(path26, cfg) {
5011
+ async function writeConfig(path25, cfg) {
4974
5012
  const raw = JSON.stringify(cfg, null, 2);
4975
- const tmp = path26 + ".tmp";
5013
+ const tmp = path25 + ".tmp";
4976
5014
  await fsp3.writeFile(tmp, raw, "utf8");
4977
- await fsp3.rename(tmp, path26);
5015
+ await fsp3.rename(tmp, path25);
4978
5016
  }
4979
5017
 
4980
5018
  // src/slash-commands/mcp.ts
@@ -5854,7 +5892,7 @@ var DEFAULTS = {
5854
5892
  cost: true
5855
5893
  };
5856
5894
  function resolveConfigPath() {
5857
- return process.env[CONFIG_ENV] ?? path9.join(process.env.HOME ?? "", ".wrongstack", "statusline.json");
5895
+ return process.env[CONFIG_ENV] ?? path8.join(process.env.HOME ?? "", ".wrongstack", "statusline.json");
5858
5896
  }
5859
5897
  async function loadStatuslineConfig() {
5860
5898
  const p = resolveConfigPath();
@@ -5868,7 +5906,7 @@ async function loadStatuslineConfig() {
5868
5906
  async function saveStatuslineConfig(cfg) {
5869
5907
  const p = resolveConfigPath();
5870
5908
  try {
5871
- await fsp3.mkdir(path9.dirname(p), { recursive: true });
5909
+ await fsp3.mkdir(path8.dirname(p), { recursive: true });
5872
5910
  await atomicWrite(p, JSON.stringify(cfg, null, 2));
5873
5911
  } catch (err) {
5874
5912
  throw new FsError({
@@ -6176,13 +6214,13 @@ var MANIFESTS = [
6176
6214
  ];
6177
6215
  async function detectProjectKind(projectRoot) {
6178
6216
  try {
6179
- await fsp3.access(path9.join(projectRoot, ".wrongstack", "AGENTS.md"));
6217
+ await fsp3.access(path8.join(projectRoot, ".wrongstack", "AGENTS.md"));
6180
6218
  return "initialized";
6181
6219
  } catch {
6182
6220
  }
6183
6221
  for (const m of MANIFESTS) {
6184
6222
  try {
6185
- await fsp3.access(path9.join(projectRoot, m));
6223
+ await fsp3.access(path8.join(projectRoot, m));
6186
6224
  return "project";
6187
6225
  } catch {
6188
6226
  }
@@ -6190,8 +6228,8 @@ async function detectProjectKind(projectRoot) {
6190
6228
  return "empty";
6191
6229
  }
6192
6230
  async function scaffoldAgentsMd(projectRoot) {
6193
- const dir = path9.join(projectRoot, ".wrongstack");
6194
- const file = path9.join(dir, "AGENTS.md");
6231
+ const dir = path8.join(projectRoot, ".wrongstack");
6232
+ const file = path8.join(dir, "AGENTS.md");
6195
6233
  const facts = await detectProjectFacts(projectRoot);
6196
6234
  const body = renderAgentsTemplate(facts);
6197
6235
  await fsp3.mkdir(dir, { recursive: true });
@@ -6204,7 +6242,7 @@ async function runProjectCheck(opts) {
6204
6242
  if (kind === "initialized") {
6205
6243
  renderer.write(
6206
6244
  `
6207
- ${color.green("\u2713")} Project initialized ${color.dim(`(${path9.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
6245
+ ${color.green("\u2713")} Project initialized ${color.dim(`(${path8.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
6208
6246
  `
6209
6247
  );
6210
6248
  return true;
@@ -6235,7 +6273,7 @@ async function runProjectCheck(opts) {
6235
6273
  }
6236
6274
  return true;
6237
6275
  }
6238
- const gitDir = path9.join(projectRoot, ".git");
6276
+ const gitDir = path8.join(projectRoot, ".git");
6239
6277
  let hasGit = false;
6240
6278
  try {
6241
6279
  await fsp3.access(gitDir);
@@ -6258,10 +6296,10 @@ async function runProjectCheck(opts) {
6258
6296
  if (answer2 === "y" || answer2 === "yes") {
6259
6297
  try {
6260
6298
  const { spawn: spawn3 } = await import('child_process');
6261
- await new Promise((resolve4, reject) => {
6299
+ await new Promise((resolve3, reject) => {
6262
6300
  const child = spawn3("git", ["init"], { cwd: projectRoot });
6263
6301
  child.on("error", reject);
6264
- child.on("close", (code) => code === 0 ? resolve4() : reject(new Error(`git init failed with ${code}`)));
6302
+ child.on("close", (code) => code === 0 ? resolve3() : reject(new Error(`git init failed with ${code}`)));
6265
6303
  });
6266
6304
  renderer.write(` ${color.green("\u2713")} Git repository initialized
6267
6305
  `);
@@ -6360,78 +6398,21 @@ async function runLaunchPrompts(opts) {
6360
6398
  return { mode, yolo, director, autonomy };
6361
6399
  }
6362
6400
  async function bootConfig(flags) {
6363
- const cwd = typeof flags["cwd"] === "string" ? path9.resolve(flags["cwd"]) : process.cwd();
6364
- const pathResolver = new DefaultPathResolver(cwd);
6365
- const projectRoot = pathResolver.projectRoot;
6366
- const userHome = os3.homedir();
6367
- const wpaths = resolveWstackPaths({ projectRoot, userHome });
6368
- await ensureProjectMeta(wpaths, projectRoot);
6369
- const vault = new DefaultSecretVault$1({ keyFile: wpaths.secretsKey });
6370
- for (const file of [wpaths.globalConfig, wpaths.projectLocalConfig]) {
6371
- try {
6372
- const { migrated } = await migratePlaintextSecrets(file, vault);
6373
- if (migrated > 0) {
6374
- writeErr(`[wstack] Encrypted ${migrated} plaintext secret(s) in ${file}
6375
- `);
6376
- }
6377
- } catch {
6378
- }
6379
- }
6380
- const configLoader = new DefaultConfigLoader({ paths: wpaths, vault });
6381
- let config = await configLoader.load({ cliFlags: flagsToConfigPatch(flags) });
6382
- const syncConfig = await configLoader.loadSyncConfig();
6383
- if (syncConfig) {
6384
- config = Object.freeze({ ...config, sync: syncConfig });
6385
- }
6401
+ const opts = { flags, appLabel: "wstack" };
6402
+ const { cwd, projectRoot, userHome, wpaths, pathResolver, config, vault } = await bootConfig$1(opts);
6386
6403
  return {
6387
6404
  paths: { cwd, projectRoot, userHome, wpaths, pathResolver },
6388
6405
  config,
6389
6406
  vault
6390
6407
  };
6391
6408
  }
6392
- function flagsToConfigPatch(flags) {
6393
- const patch = {};
6394
- if (typeof flags["provider"] === "string") patch.provider = flags["provider"];
6395
- if (typeof flags["model"] === "string") patch.model = flags["model"];
6396
- if (typeof flags["cwd"] === "string") patch.cwd = flags["cwd"];
6397
- if (typeof flags["log-level"] === "string") {
6398
- patch.log = { level: flags["log-level"] };
6399
- } else if (flags["verbose"]) {
6400
- patch.log = { level: "debug" };
6401
- } else if (flags["trace"]) {
6402
- patch.log = { level: "trace" };
6403
- }
6404
- if (flags["yolo"]) patch.yolo = true;
6405
- if (flags["no-features"]) {
6406
- patch.features = {
6407
- mcp: false,
6408
- plugins: false,
6409
- memory: false,
6410
- modelsRegistry: false,
6411
- skills: false
6412
- };
6413
- }
6414
- return patch;
6415
- }
6416
- async function ensureProjectMeta(paths, projectRoot) {
6417
- try {
6418
- await fsp3.mkdir(paths.projectDir, { recursive: true });
6419
- const meta = {
6420
- hash: paths.projectHash,
6421
- root: projectRoot,
6422
- lastSeen: (/* @__PURE__ */ new Date()).toISOString()
6423
- };
6424
- await fsp3.writeFile(paths.projectMeta, JSON.stringify(meta, null, 2));
6425
- } catch {
6426
- }
6427
- }
6428
6409
  var ReadlineInputReader = class {
6429
6410
  rl;
6430
6411
  historyFile;
6431
6412
  history = [];
6432
6413
  pending = false;
6433
6414
  constructor(opts = {}) {
6434
- this.historyFile = opts.historyFile ?? path9.join(os3.homedir(), ".wrongstack", "history");
6415
+ this.historyFile = opts.historyFile ?? path8.join(os2.homedir(), ".wrongstack", "history");
6435
6416
  }
6436
6417
  async loadHistory() {
6437
6418
  try {
@@ -6443,7 +6424,7 @@ var ReadlineInputReader = class {
6443
6424
  }
6444
6425
  async saveHistory() {
6445
6426
  try {
6446
- await fsp3.mkdir(path9.dirname(this.historyFile), { recursive: true });
6427
+ await fsp3.mkdir(path8.dirname(this.historyFile), { recursive: true });
6447
6428
  await fsp3.writeFile(this.historyFile, this.history.slice(-1e3).join("\n"));
6448
6429
  } catch {
6449
6430
  }
@@ -6462,7 +6443,7 @@ var ReadlineInputReader = class {
6462
6443
  async readLine(prompt) {
6463
6444
  if (this.history.length === 0) await this.loadHistory();
6464
6445
  while (this.pending) {
6465
- await new Promise((resolve4) => setTimeout(resolve4, 50));
6446
+ await new Promise((resolve3) => setTimeout(resolve3, 50));
6466
6447
  }
6467
6448
  this.pending = true;
6468
6449
  try {
@@ -6472,15 +6453,15 @@ var ReadlineInputReader = class {
6472
6453
  this.rl = void 0;
6473
6454
  }
6474
6455
  const fresh = this.ensure();
6475
- return new Promise((resolve4) => {
6456
+ return new Promise((resolve3) => {
6476
6457
  fresh.question(prompt ?? "> ", (line) => {
6477
6458
  if (line.trim()) {
6478
6459
  this.history.push(line);
6479
6460
  void this.saveHistory();
6480
6461
  }
6481
- resolve4(line);
6462
+ resolve3(line);
6482
6463
  });
6483
- fresh.once("close", () => resolve4(""));
6464
+ fresh.once("close", () => resolve3(""));
6484
6465
  }).then((result) => {
6485
6466
  this.rl?.close();
6486
6467
  this.rl = void 0;
@@ -6492,7 +6473,7 @@ var ReadlineInputReader = class {
6492
6473
  }
6493
6474
  async readKey(prompt, options) {
6494
6475
  writeOut(prompt);
6495
- return new Promise((resolve4) => {
6476
+ return new Promise((resolve3) => {
6496
6477
  const stdin = process.stdin;
6497
6478
  const wasRaw = stdin.isRaw;
6498
6479
  const wasPaused = stdin.isPaused();
@@ -6503,7 +6484,7 @@ var ReadlineInputReader = class {
6503
6484
  if (key === "") {
6504
6485
  cleanup();
6505
6486
  writeOut("\n");
6506
- resolve4("");
6487
+ resolve3("");
6507
6488
  return;
6508
6489
  }
6509
6490
  const opt = options.find(
@@ -6513,12 +6494,12 @@ var ReadlineInputReader = class {
6513
6494
  cleanup();
6514
6495
  writeOut(`${opt.key}
6515
6496
  `);
6516
- resolve4(opt.value);
6497
+ resolve3(opt.value);
6517
6498
  }
6518
6499
  };
6519
6500
  const onClose = () => {
6520
6501
  cleanup();
6521
- resolve4("");
6502
+ resolve3("");
6522
6503
  };
6523
6504
  const cleanup = () => {
6524
6505
  stdin.off("data", onData);
@@ -6546,7 +6527,7 @@ var ReadlineInputReader = class {
6546
6527
  this.rl?.close();
6547
6528
  this.rl = void 0;
6548
6529
  writeOut(prompt);
6549
- return new Promise((resolve4) => {
6530
+ return new Promise((resolve3) => {
6550
6531
  let buf = "";
6551
6532
  const wasRaw = stdin.isRaw;
6552
6533
  setRawMode(stdin, true);
@@ -6564,7 +6545,7 @@ var ReadlineInputReader = class {
6564
6545
  cleanup();
6565
6546
  writeOut(` ${dim(`[${buf.length} chars]`)}
6566
6547
  `);
6567
- resolve4(buf);
6548
+ resolve3(buf);
6568
6549
  return;
6569
6550
  }
6570
6551
  if (ch === "") {
@@ -6661,7 +6642,7 @@ async function buildPickableProviders(modelsRegistry, config) {
6661
6642
  }
6662
6643
  return out;
6663
6644
  }
6664
- var defaultUidFn = () => os3__default.userInfo().uid;
6645
+ var defaultUidFn = () => os2__default.userInfo().uid;
6665
6646
  async function getFileUid(filePath) {
6666
6647
  try {
6667
6648
  const stat4 = await fsp3.stat(filePath);
@@ -6671,7 +6652,7 @@ async function getFileUid(filePath) {
6671
6652
  }
6672
6653
  }
6673
6654
  async function checkConfigOwnership(homeFn, uidFn = defaultUidFn) {
6674
- if (os3__default.platform() === "win32") return true;
6655
+ if (os2__default.platform() === "win32") return true;
6675
6656
  const cfg = configPath(homeFn);
6676
6657
  const fileUid = await getFileUid(cfg);
6677
6658
  if (fileUid === void 0) return true;
@@ -6688,20 +6669,20 @@ function assertSafeToDelete(filename, parentDir) {
6688
6669
  if (PROTECTED_BASENAMES.has(filename)) {
6689
6670
  throw new Error(`Refusing to delete protected file: ${filename}`);
6690
6671
  }
6691
- if (filename !== path9.basename(filename)) {
6672
+ if (filename !== path8.basename(filename)) {
6692
6673
  throw new Error(`Refusing to delete path with traversal: ${filename}`);
6693
6674
  }
6694
6675
  if (!filename.startsWith("config.json.") || !filename.endsWith(".bak")) {
6695
6676
  throw new Error(`Refusing to delete unknown file: ${filename}`);
6696
6677
  }
6697
- const resolvedParent = path9.resolve(parentDir);
6678
+ const resolvedParent = path8.resolve(parentDir);
6698
6679
  if (!resolvedParent.endsWith(".wrongstack")) {
6699
6680
  throw new Error(`Unexpected parent directory for bak prune: ${resolvedParent}`);
6700
6681
  }
6701
6682
  }
6702
6683
  async function safeDelete(filePath) {
6703
- const dir = path9.dirname(filePath);
6704
- const filename = path9.basename(filePath);
6684
+ const dir = path8.dirname(filePath);
6685
+ const filename = path8.basename(filePath);
6705
6686
  try {
6706
6687
  assertSafeToDelete(filename, dir);
6707
6688
  await fsp3.unlink(filePath);
@@ -6744,18 +6725,18 @@ function diffSummary(oldCfg, newCfg) {
6744
6725
  }
6745
6726
  return changes.length > 0 ? changes.slice(0, 5).join(", ") : "no changes";
6746
6727
  }
6747
- var defaultHomeDir = () => os3__default.homedir();
6728
+ var defaultHomeDir = () => os2__default.homedir();
6748
6729
  function historyDir(homeFn = defaultHomeDir) {
6749
- return path9.join(homeFn(), ".wrongstack", "config.history", "entries");
6730
+ return path8.join(homeFn(), ".wrongstack", "config.history", "entries");
6750
6731
  }
6751
6732
  function historyIndexPath(homeFn = defaultHomeDir) {
6752
- return path9.join(homeFn(), ".wrongstack", "config.history", "index.json");
6733
+ return path8.join(homeFn(), ".wrongstack", "config.history", "index.json");
6753
6734
  }
6754
6735
  function configPath(homeFn = defaultHomeDir) {
6755
- return path9.join(homeFn(), ".wrongstack", "config.json");
6736
+ return path8.join(homeFn(), ".wrongstack", "config.json");
6756
6737
  }
6757
6738
  function backupLastPath(homeFn = defaultHomeDir) {
6758
- return path9.join(homeFn(), ".wrongstack", "config.json.last");
6739
+ return path8.join(homeFn(), ".wrongstack", "config.json.last");
6759
6740
  }
6760
6741
  function entryId(ts) {
6761
6742
  return ts.replace(/[:.]/g, "-").slice(0, 19);
@@ -6810,17 +6791,17 @@ async function backupCurrent(homeFn = defaultHomeDir) {
6810
6791
  }
6811
6792
  if (content !== void 0) {
6812
6793
  try {
6813
- const bakPath = path9.join(homeFn(), ".wrongstack", `config.json.${ts}.bak`);
6794
+ const bakPath = path8.join(homeFn(), ".wrongstack", `config.json.${ts}.bak`);
6814
6795
  await atomicWrite(bakPath, content);
6815
6796
  } catch {
6816
6797
  }
6817
6798
  }
6818
6799
  try {
6819
- const dir = path9.join(homeFn(), ".wrongstack");
6800
+ const dir = path8.join(homeFn(), ".wrongstack");
6820
6801
  const files = await fsp3.readdir(dir);
6821
6802
  const baks = files.filter((f) => f.startsWith("config.json.") && f.endsWith(".bak")).sort().reverse();
6822
6803
  for (const f of baks.slice(10)) {
6823
- await safeDelete(path9.join(dir, f));
6804
+ await safeDelete(path8.join(dir, f));
6824
6805
  }
6825
6806
  } catch {
6826
6807
  }
@@ -6838,7 +6819,7 @@ async function appendHistory(oldCfg, newCfg, description, homeFn = defaultHomeDi
6838
6819
  };
6839
6820
  try {
6840
6821
  await fsp3.writeFile(
6841
- path9.join(historyDir(homeFn), `${id}.json`),
6822
+ path8.join(historyDir(homeFn), `${id}.json`),
6842
6823
  JSON.stringify(entry, null, 2),
6843
6824
  "utf8"
6844
6825
  );
@@ -6846,7 +6827,7 @@ async function appendHistory(oldCfg, newCfg, description, homeFn = defaultHomeDi
6846
6827
  throw new FsError({
6847
6828
  message: err instanceof Error ? err.message : String(err),
6848
6829
  code: ERROR_CODES.FS_WRITE_FAILED,
6849
- path: path9.join(historyDir(homeFn), `${id}.json`),
6830
+ path: path8.join(historyDir(homeFn), `${id}.json`),
6850
6831
  cause: err
6851
6832
  });
6852
6833
  }
@@ -6861,7 +6842,7 @@ async function listHistory(homeFn = defaultHomeDir) {
6861
6842
  }
6862
6843
  async function getHistoryEntry(id, homeFn = defaultHomeDir) {
6863
6844
  try {
6864
- const raw = await fsp3.readFile(path9.join(historyDir(homeFn), `${id}.json`), "utf8");
6845
+ const raw = await fsp3.readFile(path8.join(historyDir(homeFn), `${id}.json`), "utf8");
6865
6846
  return JSON.parse(raw);
6866
6847
  } catch {
6867
6848
  return null;
@@ -6927,10 +6908,10 @@ var theme = { primary: color.amber };
6927
6908
  async function saveToGlobalConfig(configPath2, provider, model, homeFn = () => process.env.HOME ?? __require("os").homedir()) {
6928
6909
  try {
6929
6910
  const { atomicWrite: atomicWrite10 } = await import('@wrongstack/core');
6930
- const fs23 = await import('fs/promises');
6911
+ const fs22 = await import('fs/promises');
6931
6912
  let existing = {};
6932
6913
  try {
6933
- const raw = await fs23.readFile(configPath2, "utf8");
6914
+ const raw = await fs22.readFile(configPath2, "utf8");
6934
6915
  existing = JSON.parse(raw);
6935
6916
  } catch {
6936
6917
  }
@@ -7261,12 +7242,12 @@ function pickGroupIndex(opts) {
7261
7242
  try {
7262
7243
  let current = 0;
7263
7244
  try {
7264
- const parsed = Number.parseInt(fs11.readFileSync(opts.cursorFile, "utf8").trim(), 10);
7245
+ const parsed = Number.parseInt(fs10.readFileSync(opts.cursorFile, "utf8").trim(), 10);
7265
7246
  if (Number.isFinite(parsed)) current = wrap(parsed);
7266
7247
  } catch {
7267
7248
  }
7268
- fs11.mkdirSync(path9.dirname(opts.cursorFile), { recursive: true });
7269
- fs11.writeFileSync(opts.cursorFile, String(wrap(current + 1)));
7249
+ fs10.mkdirSync(path8.dirname(opts.cursorFile), { recursive: true });
7250
+ fs10.writeFileSync(opts.cursorFile, String(wrap(current + 1)));
7270
7251
  return current;
7271
7252
  } catch {
7272
7253
  }
@@ -7601,14 +7582,14 @@ function summarize(value, name) {
7601
7582
  if (typeof v === "object" && v !== null) {
7602
7583
  const o = v;
7603
7584
  if (name === "edit") {
7604
- const path26 = typeof o["path"] === "string" ? o["path"] : "";
7585
+ const path25 = typeof o["path"] === "string" ? o["path"] : "";
7605
7586
  const reps = typeof o["replacements"] === "number" ? o["replacements"] : 0;
7606
- return `${path26} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
7587
+ return `${path25} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
7607
7588
  }
7608
7589
  if (name === "write") {
7609
- const path26 = typeof o["path"] === "string" ? o["path"] : "";
7590
+ const path25 = typeof o["path"] === "string" ? o["path"] : "";
7610
7591
  const bytes = typeof o["bytes"] === "number" ? o["bytes"] : void 0;
7611
- return bytes !== void 0 ? `${path26} ${bytes}B` : path26;
7592
+ return bytes !== void 0 ? `${path25} ${bytes}B` : path25;
7612
7593
  }
7613
7594
  if (typeof o["count"] === "number") {
7614
7595
  return `${o["count"]} match${o["count"] === 1 ? "" : "es"}`;
@@ -8468,7 +8449,7 @@ var updateCmd = async (args, deps) => {
8468
8449
  deps.renderer.write(`Updating wrongstack from v${info.current} to v${info.latest}...
8469
8450
  `);
8470
8451
  try {
8471
- const result = await new Promise((resolve4, reject) => {
8452
+ const result = await new Promise((resolve3, reject) => {
8472
8453
  const child = spawn("npm", ["install", "-g", "wrongstack@latest"], {
8473
8454
  cwd,
8474
8455
  stdio: "pipe"
@@ -8478,7 +8459,7 @@ var updateCmd = async (args, deps) => {
8478
8459
  _stderr += d;
8479
8460
  });
8480
8461
  child.on("error", reject);
8481
- child.on("close", (code) => resolve4({ code: code ?? 0 }));
8462
+ child.on("close", (code) => resolve3({ code: code ?? 0 }));
8482
8463
  });
8483
8464
  if (result.code === 0) {
8484
8465
  deps.renderer.write(`
@@ -8539,7 +8520,7 @@ var diagCmd = async (_args, deps) => {
8539
8520
  ` modelsCache: ${deps.paths.modelsCache}`,
8540
8521
  ` cacheAge: ${isFinite(age) ? `${Math.round(age / 60)}m` : "never"}`,
8541
8522
  ` node: ${process.version}`,
8542
- ` os: ${os3.platform()} ${os3.release()}`,
8523
+ ` os: ${os2.platform()} ${os2.release()}`,
8543
8524
  ` provider: ${cfg.provider ?? "<unset>"}`,
8544
8525
  ` model: ${cfg.model ?? "<unset>"}`,
8545
8526
  ` tools: ${deps.toolRegistry?.list().length ?? 0}`,
@@ -8618,7 +8599,7 @@ var doctorCmd = async (_args, deps) => {
8618
8599
  }
8619
8600
  try {
8620
8601
  await fsp3.mkdir(deps.paths.projectSessions, { recursive: true });
8621
- const probe = path9.join(deps.paths.projectSessions, `.probe-${Date.now()}`);
8602
+ const probe = path8.join(deps.paths.projectSessions, `.probe-${Date.now()}`);
8622
8603
  await fsp3.writeFile(probe, "");
8623
8604
  await fsp3.unlink(probe);
8624
8605
  checks.push({ name: "sessions writable", status: "ok", detail: deps.paths.projectSessions });
@@ -8721,8 +8702,8 @@ var exportCmd = async (args, deps) => {
8721
8702
  return 1;
8722
8703
  }
8723
8704
  if (output) {
8724
- await fsp3.mkdir(path9.dirname(path9.resolve(deps.cwd, output)), { recursive: true });
8725
- await fsp3.writeFile(path9.resolve(deps.cwd, output), rendered, "utf8");
8705
+ await fsp3.mkdir(path8.dirname(path8.resolve(deps.cwd, output)), { recursive: true });
8706
+ await fsp3.writeFile(path8.resolve(deps.cwd, output), rendered, "utf8");
8726
8707
  deps.renderer.write(`Wrote ${rendered.length} bytes to ${output}
8727
8708
  `);
8728
8709
  } else {
@@ -8795,8 +8776,8 @@ var initCmd = async (_args, deps) => {
8795
8776
  const vault = new DefaultSecretVault({ keyFile: deps.paths.secretsKey });
8796
8777
  const encrypted = encryptConfigSecrets(config, vault);
8797
8778
  await atomicWrite(deps.paths.globalConfig, JSON.stringify(encrypted, null, 2), { mode: 384 });
8798
- await fsp3.mkdir(path9.join(deps.projectRoot, ".wrongstack"), { recursive: true });
8799
- const agentsFile = path9.join(deps.projectRoot, ".wrongstack", "AGENTS.md");
8779
+ await fsp3.mkdir(path8.join(deps.projectRoot, ".wrongstack"), { recursive: true });
8780
+ const agentsFile = path8.join(deps.projectRoot, ".wrongstack", "AGENTS.md");
8800
8781
  const projectFacts = await detectProjectFacts(deps.projectRoot);
8801
8782
  await atomicWrite(agentsFile, renderAgentsTemplate(projectFacts));
8802
8783
  deps.renderer.writeInfo(`Wrote ${deps.paths.globalConfig}`);
@@ -9102,7 +9083,7 @@ var usageCmd = async (_args, deps) => {
9102
9083
  return 0;
9103
9084
  };
9104
9085
  var projectsCmd = async (_args, deps) => {
9105
- const projectsRoot = path9.join(deps.paths.globalRoot, "projects");
9086
+ const projectsRoot = path8.join(deps.paths.globalRoot, "projects");
9106
9087
  try {
9107
9088
  const entries = await fsp3.readdir(projectsRoot);
9108
9089
  if (entries.length === 0) {
@@ -9112,7 +9093,7 @@ var projectsCmd = async (_args, deps) => {
9112
9093
  for (const hash of entries) {
9113
9094
  try {
9114
9095
  const meta = JSON.parse(
9115
- await fsp3.readFile(path9.join(projectsRoot, hash, "meta.json"), "utf8")
9096
+ await fsp3.readFile(path8.join(projectsRoot, hash, "meta.json"), "utf8")
9116
9097
  );
9117
9098
  deps.renderer.write(
9118
9099
  ` ${color.dim(hash)} ${color.dim(meta.lastSeen ?? "")} ${meta.root ?? "?"}
@@ -9271,7 +9252,7 @@ async function listFleetRuns(deps) {
9271
9252
  }
9272
9253
  const runs = [];
9273
9254
  for (const id of entries) {
9274
- const runDir = path9.join(deps.paths.projectSessions, id);
9255
+ const runDir = path8.join(deps.paths.projectSessions, id);
9275
9256
  let stat4;
9276
9257
  try {
9277
9258
  stat4 = await fsp3.stat(runDir);
@@ -9284,17 +9265,17 @@ async function listFleetRuns(deps) {
9284
9265
  let subagentCount = 0;
9285
9266
  let subagentsDir;
9286
9267
  try {
9287
- await fsp3.access(path9.join(runDir, "fleet.json"));
9268
+ await fsp3.access(path8.join(runDir, "fleet.json"));
9288
9269
  manifest = true;
9289
9270
  } catch {
9290
9271
  }
9291
9272
  try {
9292
- await fsp3.access(path9.join(runDir, "checkpoint.json"));
9273
+ await fsp3.access(path8.join(runDir, "checkpoint.json"));
9293
9274
  checkpoint = true;
9294
9275
  } catch {
9295
9276
  }
9296
9277
  try {
9297
- subagentsDir = path9.join(runDir, "subagents");
9278
+ subagentsDir = path8.join(runDir, "subagents");
9298
9279
  const files = await fsp3.readdir(subagentsDir);
9299
9280
  subagentCount = files.filter((f) => f.endsWith(".jsonl")).length;
9300
9281
  } catch {
@@ -9323,7 +9304,7 @@ async function listFleetRuns(deps) {
9323
9304
  return 0;
9324
9305
  }
9325
9306
  async function showFleetRun(runId, deps) {
9326
- const runDir = path9.join(deps.paths.projectSessions, runId);
9307
+ const runDir = path8.join(deps.paths.projectSessions, runId);
9327
9308
  let stat4;
9328
9309
  try {
9329
9310
  stat4 = await fsp3.stat(runDir);
@@ -9340,7 +9321,7 @@ async function showFleetRun(runId, deps) {
9340
9321
  deps.renderer.write(color.bold(`
9341
9322
  Fleet Run: ${runId}
9342
9323
  `) + "\n");
9343
- const manifestPath = path9.join(runDir, "fleet.json");
9324
+ const manifestPath = path8.join(runDir, "fleet.json");
9344
9325
  let manifestData = null;
9345
9326
  try {
9346
9327
  manifestData = await fsp3.readFile(manifestPath, "utf8");
@@ -9356,7 +9337,7 @@ Fleet Run: ${runId}
9356
9337
  deps.renderer.write(` ${color.dim("\u25CB")} fleet.json \u2014 not found
9357
9338
  `);
9358
9339
  }
9359
- const checkpointPath = path9.join(runDir, "checkpoint.json");
9340
+ const checkpointPath = path8.join(runDir, "checkpoint.json");
9360
9341
  let checkpointData = null;
9361
9342
  try {
9362
9343
  checkpointData = await fsp3.readFile(checkpointPath, "utf8");
@@ -9403,7 +9384,7 @@ Fleet Run: ${runId}
9403
9384
  } catch {
9404
9385
  }
9405
9386
  }
9406
- const subagentsDir = path9.join(runDir, "subagents");
9387
+ const subagentsDir = path8.join(runDir, "subagents");
9407
9388
  let subagentFiles = [];
9408
9389
  try {
9409
9390
  subagentFiles = await fsp3.readdir(subagentsDir);
@@ -9415,7 +9396,7 @@ Fleet Run: ${runId}
9415
9396
  Subagent transcripts (${subagentFiles.length}):
9416
9397
  `);
9417
9398
  for (const f of subagentFiles.sort()) {
9418
- const filePath = path9.join(subagentsDir, f);
9399
+ const filePath = path8.join(subagentsDir, f);
9419
9400
  let size;
9420
9401
  try {
9421
9402
  const s = await fsp3.stat(filePath);
@@ -9432,7 +9413,7 @@ Fleet Run: ${runId}
9432
9413
  ${color.dim("\u25CB")} No subagent transcripts
9433
9414
  `);
9434
9415
  }
9435
- const sharedDir = path9.join(runDir, "shared");
9416
+ const sharedDir = path8.join(runDir, "shared");
9436
9417
  try {
9437
9418
  const files = await fsp3.readdir(sharedDir);
9438
9419
  deps.renderer.write(`
@@ -9599,7 +9580,7 @@ function findSessionId(args) {
9599
9580
  var rewindCmd = async (args, deps) => {
9600
9581
  const flags = parseRewindFlags(args);
9601
9582
  const wpaths = resolveWstackPaths({ projectRoot: deps.projectRoot });
9602
- const sessionsDir = path9.join(wpaths.globalRoot, "sessions");
9583
+ const sessionsDir = path8.join(wpaths.globalRoot, "sessions");
9603
9584
  const rewind = new DefaultSessionRewinder(sessionsDir, deps.projectRoot);
9604
9585
  let sessionId = findSessionId(args);
9605
9586
  if (!sessionId) {
@@ -9834,10 +9815,10 @@ var auditCmd = async (args, deps) => {
9834
9815
  return verify.ok ? 0 : 1;
9835
9816
  };
9836
9817
  async function listAudits(log, dir, deps) {
9837
- const fs23 = await import('fs/promises');
9818
+ const fs22 = await import('fs/promises');
9838
9819
  let entries;
9839
9820
  try {
9840
- entries = await fs23.readdir(dir);
9821
+ entries = await fs22.readdir(dir);
9841
9822
  } catch {
9842
9823
  deps.renderer.write(
9843
9824
  color.dim(`No sessions dir found at ${dir}. Run a session first.`) + "\n"
@@ -9892,7 +9873,7 @@ var skillsCmd = async (_args, deps) => {
9892
9873
  };
9893
9874
  var versionCmd = async (_args, deps) => {
9894
9875
  deps.renderer.write(
9895
- `WrongStack ${CLI_VERSION} (apiVersion ${API_VERSION}, node ${process.version}, ${os3.platform()})
9876
+ `WrongStack ${CLI_VERSION} (apiVersion ${API_VERSION}, node ${process.version}, ${os2.platform()})
9896
9877
  `
9897
9878
  );
9898
9879
  return 0;
@@ -10007,7 +9988,7 @@ function resolveBundledSkillsDir() {
10007
9988
  try {
10008
9989
  const req2 = createRequire(import.meta.url);
10009
9990
  const corePkg = req2.resolve("@wrongstack/core/package.json");
10010
- return path9.join(path9.dirname(corePkg), "skills");
9991
+ return path8.join(path8.dirname(corePkg), "skills");
10011
9992
  } catch {
10012
9993
  return void 0;
10013
9994
  }
@@ -10038,7 +10019,12 @@ async function boot(argv) {
10038
10019
  const reader = new ReadlineInputReader({ historyFile: wpaths.historyFile });
10039
10020
  const modelsRegistry = new DefaultModelsRegistry({
10040
10021
  cacheFile: wpaths.modelsCache,
10041
- ttlSeconds: 24 * 3600,
10022
+ // Force a refresh attempt once per CLI process. Model metadata changes faster
10023
+ // than releases (new model ids, corrected context windows), and stale cache
10024
+ // here directly affects runtime behavior like context bars and compaction.
10025
+ // If the network is unavailable, DefaultModelsRegistry still falls back to
10026
+ // stale cache or the bundled overlay instead of failing startup.
10027
+ ttlSeconds: 0,
10042
10028
  // Curated overlay merged on top of models.dev: fetched from GitHub raw for
10043
10029
  // freshness, with the bundled file as the offline floor.
10044
10030
  overlayUrl: GITHUB_PROVIDERS_OVERLAY_URL,
@@ -10143,7 +10129,8 @@ async function boot(argv) {
10143
10129
  else if (flags["no-director"] === true) directorPinned = false;
10144
10130
  let autonomyPinned;
10145
10131
  if (flags["no-autonomy"] === true) autonomyPinned = "off";
10146
- else if (flags["eternal"] === true) autonomyPinned = "off";
10132
+ else if (flags["eternal"] === true)
10133
+ autonomyPinned = "off";
10147
10134
  else if (typeof flags["autonomy"] === "string") {
10148
10135
  const v = flags["autonomy"].toLowerCase();
10149
10136
  autonomyPinned = v === "off" || v === "no" || v === "false" ? "off" : "auto";
@@ -10178,7 +10165,7 @@ async function boot(argv) {
10178
10165
  if (choices.director) flags["director"] = true;
10179
10166
  flags["autonomy"] = choices.autonomy;
10180
10167
  printLaunchHints(renderer, flags, {
10181
- cursorFile: path9.join(wpaths.cacheDir, "hint-cursor")
10168
+ cursorFile: path8.join(wpaths.cacheDir, "hint-cursor")
10182
10169
  });
10183
10170
  }
10184
10171
  return {
@@ -10556,7 +10543,7 @@ async function runRepl(opts) {
10556
10543
  `[eternal] ${err instanceof Error ? err.message : String(err)}`
10557
10544
  );
10558
10545
  }
10559
- await new Promise((resolve4) => setTimeout(resolve4, 250));
10546
+ await new Promise((resolve3) => setTimeout(resolve3, 250));
10560
10547
  continue;
10561
10548
  }
10562
10549
  } else if (opts.getAutonomy?.() === "eternal-parallel") {
@@ -10602,7 +10589,7 @@ async function runRepl(opts) {
10602
10589
  `[parallel] ${err instanceof Error ? err.message : String(err)}`
10603
10590
  );
10604
10591
  }
10605
- await new Promise((resolve4) => setTimeout(resolve4, 250));
10592
+ await new Promise((resolve3) => setTimeout(resolve3, 250));
10606
10593
  continue;
10607
10594
  }
10608
10595
  }
@@ -11256,6 +11243,11 @@ async function execute(deps) {
11256
11243
  "phase.taskCompleted",
11257
11244
  "phase.taskFailed",
11258
11245
  "phase.taskRetrying",
11246
+ "phase.verifying",
11247
+ "phase.verifyFailed",
11248
+ "phase.repairing",
11249
+ "phase.conflictResolving",
11250
+ "phase.conflictResolved",
11259
11251
  "autonomous.tick",
11260
11252
  "graph.completed",
11261
11253
  "graph.failed",
@@ -11383,10 +11375,18 @@ async function execute(deps) {
11383
11375
  return getActiveSDDContext2();
11384
11376
  },
11385
11377
  onSDDOutput: async (output) => {
11386
- const { trySaveSpecFromAIOutput: trySaveSpecFromAIOutput2, trySaveImplementationPlan: trySaveImplementationPlan2, trySaveTasksFromAIOutput: trySaveTasksFromAIOutput2, autoDetectTaskCompletion: autoDetectTaskCompletion2, getTaskProgress: getTaskProgress2, getActiveSDDPhase: getActiveSDDPhase2 } = (init_sdd(), __toCommonJS(sdd_exports));
11378
+ const {
11379
+ trySaveSpecFromAIOutput: trySaveSpecFromAIOutput2,
11380
+ trySaveImplementationPlan: trySaveImplementationPlan2,
11381
+ trySaveTasksFromAIOutput: trySaveTasksFromAIOutput2,
11382
+ autoDetectTaskCompletion: autoDetectTaskCompletion2,
11383
+ getTaskProgress: getTaskProgress2,
11384
+ getActiveSDDPhase: getActiveSDDPhase2
11385
+ } = (init_sdd(), __toCommonJS(sdd_exports));
11387
11386
  const messages = [];
11388
11387
  const specSaved = await trySaveSpecFromAIOutput2(output);
11389
- if (specSaved) messages.push("\u2713 Spec detected and saved! Use /sdd approve to continue.");
11388
+ if (specSaved)
11389
+ messages.push("\u2713 Spec detected and saved! Use /sdd approve to continue.");
11390
11390
  const planSaved = trySaveImplementationPlan2(output);
11391
11391
  if (planSaved) messages.push("\u2713 Implementation plan saved!");
11392
11392
  const tasksSaved = await trySaveTasksFromAIOutput2(output);
@@ -11401,7 +11401,9 @@ async function execute(deps) {
11401
11401
  if (autoCompleted > 0) {
11402
11402
  const progress = getTaskProgress2();
11403
11403
  if (progress) {
11404
- messages.push(`\u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`);
11404
+ messages.push(
11405
+ `\u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`
11406
+ );
11405
11407
  }
11406
11408
  }
11407
11409
  }
@@ -11433,7 +11435,7 @@ async function execute(deps) {
11433
11435
  supportsVision,
11434
11436
  attachments,
11435
11437
  effectiveMaxContext,
11436
- projectName: path9.basename(projectRoot) || void 0,
11438
+ projectName: path8.basename(projectRoot) || void 0,
11437
11439
  projectRoot,
11438
11440
  getAutonomy,
11439
11441
  onAutonomy,
@@ -11461,7 +11463,7 @@ async function execute(deps) {
11461
11463
  supportsVision,
11462
11464
  attachments,
11463
11465
  effectiveMaxContext,
11464
- projectName: path9.basename(projectRoot) || void 0,
11466
+ projectName: path8.basename(projectRoot) || void 0,
11465
11467
  getAutonomy,
11466
11468
  onAutonomy,
11467
11469
  getNextPredict,
@@ -11562,7 +11564,8 @@ var MultiAgentHost = class {
11562
11564
  directorBudget: this.opts.directorBudget,
11563
11565
  manifestDebounceMs: 2e3,
11564
11566
  checkpointDebounceMs: this.opts.checkpointDebounceMs ?? 250,
11565
- maxSpawnDepth: 5
11567
+ maxSpawnDepth: 5,
11568
+ maxContext: this.opts.getLeaderMaxContext
11566
11569
  });
11567
11570
  this.fleetManager = fleetManager;
11568
11571
  if (this.opts.sessionsRoot && !this.sessionFactory) {
@@ -11576,7 +11579,7 @@ var MultiAgentHost = class {
11576
11579
  doneCondition: { type: "all_tasks_done" },
11577
11580
  maxConcurrent: this.opts.maxConcurrent ?? 4
11578
11581
  };
11579
- const defaultScratchpad = this.opts.sharedScratchpadPath || (this.opts.sessionsRoot && this.opts.directorRunId ? path9.join(this.opts.sessionsRoot, this.opts.directorRunId, "shared") : void 0);
11582
+ const defaultScratchpad = this.opts.sharedScratchpadPath || (this.opts.sessionsRoot && this.opts.directorRunId ? path8.join(this.opts.sessionsRoot, this.opts.directorRunId, "shared") : void 0);
11580
11583
  this.director = new Director({
11581
11584
  config: coordinatorConfig,
11582
11585
  manifestPath: this.opts.manifestPath,
@@ -11589,11 +11592,13 @@ var MultiAgentHost = class {
11589
11592
  sessionsRoot: this.opts.sessionsRoot,
11590
11593
  directorRunId: this.opts.directorRunId,
11591
11594
  maxSpawnDepth: 5,
11595
+ maxContext: this.opts.getLeaderMaxContext,
11592
11596
  // Live getter (not a snapshot) so a mid-session `/setmodel` takes
11593
11597
  // effect on the next spawn — the director is built lazily + once.
11594
11598
  modelMatrix: () => this.deps.configStore.get().modelMatrix,
11595
- fleetManager
11599
+ fleetManager,
11596
11600
  // pass so director.fleetManager is never undefined
11601
+ brain: this.opts.brain
11597
11602
  });
11598
11603
  this.director.on("task.completed", ({ task, result }) => {
11599
11604
  this.fleetManager?.removePendingTask(task.id);
@@ -11779,9 +11784,18 @@ var MultiAgentHost = class {
11779
11784
  subagentId: subCfg.id ?? subCfg.name ?? "subagent"
11780
11785
  });
11781
11786
  });
11787
+ const offCtxBridge = events.on("ctx.pct", (e) => {
11788
+ hostEvents.emit("subagent.ctx_pct", {
11789
+ subagentId: subCfg.id ?? subCfg.name ?? "subagent",
11790
+ load: e.load,
11791
+ tokens: e.tokens,
11792
+ maxContext: e.maxContext
11793
+ });
11794
+ });
11782
11795
  const dispose = async () => {
11783
11796
  offToolBridge();
11784
11797
  offSummaryBridge();
11798
+ offCtxBridge();
11785
11799
  try {
11786
11800
  await subSession.close?.();
11787
11801
  } catch {
@@ -11815,22 +11829,28 @@ var MultiAgentHost = class {
11815
11829
  * use the leader and the calling code can decide to error later).
11816
11830
  */
11817
11831
  async buildSubagentProvider(config, overrideId, model) {
11818
- const providerId = overrideId && config.providers?.[overrideId] ? overrideId : config.provider;
11832
+ const requestedProviderId = overrideId ?? config.provider;
11833
+ const providerId = requestedProviderId === config.provider || config.providers?.[requestedProviderId] !== void 0 || this.deps.providerRegistry.has(requestedProviderId) ? requestedProviderId : config.provider;
11819
11834
  const newCfg = config.providers?.[providerId] ?? {
11820
11835
  type: providerId,
11821
11836
  apiKey: config.apiKey,
11822
11837
  baseUrl: config.baseUrl
11823
11838
  };
11824
- const provider = makeProviderFromConfig(providerId, {
11839
+ const cfgWithType = {
11825
11840
  ...newCfg,
11826
11841
  type: providerId
11827
- });
11842
+ };
11843
+ const provider = this.deps.providerRegistry.has(providerId) ? this.deps.providerRegistry.create(cfgWithType) : makeProviderFromConfig(providerId, cfgWithType);
11828
11844
  if (this.deps.modelsRegistry) {
11829
11845
  const resolvedModel = model ?? config.model;
11830
- const caps = await capabilitiesFor(this.deps.modelsRegistry, providerId, resolvedModel).catch(
11831
- () => void 0
11832
- );
11833
- const mc = caps?.maxContext ?? config.context?.effectiveMaxContext ?? provider.capabilities.maxContext;
11846
+ const mc = await resolveRuntimeMaxContext({
11847
+ modelsRegistry: this.deps.modelsRegistry,
11848
+ config,
11849
+ provider,
11850
+ runtimeProviderConfig: cfgWithType,
11851
+ providerId,
11852
+ modelId: resolvedModel
11853
+ });
11834
11854
  if (mc && mc > 0) provider.capabilities.maxContext = mc;
11835
11855
  }
11836
11856
  return provider;
@@ -12025,16 +12045,16 @@ var MultiAgentHost = class {
12025
12045
  if (this.director) return this.director;
12026
12046
  this.opts.directorMode = true;
12027
12047
  if (this.opts.fleetRoot && !this.opts.manifestPath) {
12028
- this.opts.manifestPath = path9.join(this.opts.fleetRoot, "fleet.json");
12048
+ this.opts.manifestPath = path8.join(this.opts.fleetRoot, "fleet.json");
12029
12049
  }
12030
12050
  if (this.opts.fleetRoot && !this.opts.sharedScratchpadPath) {
12031
- this.opts.sharedScratchpadPath = path9.join(this.opts.fleetRoot, "shared");
12051
+ this.opts.sharedScratchpadPath = path8.join(this.opts.fleetRoot, "shared");
12032
12052
  }
12033
12053
  if (this.opts.fleetRoot && !this.opts.sessionsRoot) {
12034
- this.opts.sessionsRoot = path9.join(this.opts.fleetRoot, "subagents");
12054
+ this.opts.sessionsRoot = path8.join(this.opts.fleetRoot, "subagents");
12035
12055
  }
12036
12056
  if (this.opts.fleetRoot && !this.opts.stateCheckpointPath) {
12037
- this.opts.stateCheckpointPath = path9.join(this.opts.fleetRoot, "director-state.json");
12057
+ this.opts.stateCheckpointPath = path8.join(this.opts.fleetRoot, "director-state.json");
12038
12058
  }
12039
12059
  await this.ensureDirector();
12040
12060
  return this.director ?? null;
@@ -12220,11 +12240,11 @@ var SessionStats = class {
12220
12240
  if (e.name === "bash") this.bashCommands++;
12221
12241
  else if (e.name === "fetch") this.fetches++;
12222
12242
  if (!e.ok) return;
12223
- const path26 = typeof input?.path === "string" ? input.path : void 0;
12224
- if (e.name === "read" && path26) this.readPaths.add(path26);
12225
- else if (e.name === "edit" && path26) this.editedPaths.add(path26);
12226
- else if (e.name === "write" && path26) {
12227
- this.writtenPaths.add(path26);
12243
+ const path25 = typeof input?.path === "string" ? input.path : void 0;
12244
+ if (e.name === "read" && path25) this.readPaths.add(path25);
12245
+ else if (e.name === "edit" && path25) this.editedPaths.add(path25);
12246
+ else if (e.name === "write" && path25) {
12247
+ this.writtenPaths.add(path25);
12228
12248
  const content = typeof input?.content === "string" ? input.content : "";
12229
12249
  this.bytesWritten += Buffer.byteLength(content, "utf8");
12230
12250
  }
@@ -12330,7 +12350,7 @@ function samplePaths(set) {
12330
12350
  }
12331
12351
  var WORKTREE_PHASE_CONCURRENCY = 4;
12332
12352
  function gitText(args, cwd) {
12333
- return new Promise((resolve4) => {
12353
+ return new Promise((resolve3) => {
12334
12354
  let out = "";
12335
12355
  const child = spawn("git", args, {
12336
12356
  cwd,
@@ -12343,8 +12363,8 @@ function gitText(args, cwd) {
12343
12363
  child.stderr?.on("data", (c) => {
12344
12364
  out += c.toString();
12345
12365
  });
12346
- child.on("error", () => resolve4({ code: 1, out }));
12347
- child.on("close", (code) => resolve4({ code: code ?? 1, out: out.trim() }));
12366
+ child.on("error", () => resolve3({ code: 1, out }));
12367
+ child.on("close", (code) => resolve3({ code: code ?? 1, out: out.trim() }));
12348
12368
  });
12349
12369
  }
12350
12370
  async function isGitRepo(cwd) {
@@ -12352,7 +12372,7 @@ async function isGitRepo(cwd) {
12352
12372
  return code === 0 && out.trim() === "true";
12353
12373
  }
12354
12374
  function runCmd(cmd, args, cwd, shell = false) {
12355
- return new Promise((resolve4) => {
12375
+ return new Promise((resolve3) => {
12356
12376
  let out = "";
12357
12377
  const child = spawn(cmd, args, {
12358
12378
  cwd,
@@ -12366,8 +12386,8 @@ function runCmd(cmd, args, cwd, shell = false) {
12366
12386
  child.stderr?.on("data", (c) => {
12367
12387
  out += c.toString();
12368
12388
  });
12369
- child.on("error", (e) => resolve4({ code: 1, out: `${out}${String(e)}` }));
12370
- child.on("close", (code) => resolve4({ code: code ?? 1, out: out.trim() }));
12389
+ child.on("error", (e) => resolve3({ code: 1, out: `${out}${String(e)}` }));
12390
+ child.on("close", (code) => resolve3({ code: code ?? 1, out: out.trim() }));
12371
12391
  });
12372
12392
  }
12373
12393
  function detectPackageManager2(root) {
@@ -12572,6 +12592,7 @@ ${res.out}` };
12572
12592
  return false;
12573
12593
  }
12574
12594
  } : void 0,
12595
+ brain: deps.brain,
12575
12596
  onPhaseComplete: (phase) => {
12576
12597
  log(`\u2705 Phase completed: ${phase.name}`);
12577
12598
  void persist(graph);
@@ -12593,11 +12614,20 @@ ${res.out}` };
12593
12614
  });
12594
12615
  const onUntyped = deps.events.on;
12595
12616
  const offUntyped = deps.events.off;
12617
+ const finalizeActiveRun = () => {
12618
+ if (active?.graph.id !== graph.id) return;
12619
+ active.unsubscribe();
12620
+ active = null;
12621
+ };
12596
12622
  const onDone = () => {
12597
12623
  log(`\u{1F389} AutoPhase complete: ${graph.title}`);
12598
12624
  void persist(graph);
12625
+ finalizeActiveRun();
12626
+ };
12627
+ const onFailed = () => {
12628
+ void persist(graph);
12629
+ finalizeActiveRun();
12599
12630
  };
12600
- const onFailed = () => void persist(graph);
12601
12631
  onUntyped("graph.completed", onDone);
12602
12632
  onUntyped("graph.failed", onFailed);
12603
12633
  const unsubscribe = () => {
@@ -12607,6 +12637,8 @@ ${res.out}` };
12607
12637
  active = { graph, orchestrator, abort, unsubscribe };
12608
12638
  void orchestrator.start().catch((err) => {
12609
12639
  log(`\u{1F4A5} AutoPhase aborted: ${err instanceof Error ? err.message : String(err)}`);
12640
+ void persist(graph);
12641
+ finalizeActiveRun();
12610
12642
  });
12611
12643
  return { ok: true, graph };
12612
12644
  },
@@ -12781,9 +12813,25 @@ function setupPipelines(params) {
12781
12813
  return pipelines;
12782
12814
  }
12783
12815
  async function setupCompaction(params) {
12784
- const { compactor, events, modelsRegistry, context, config, provider, pipelines, fullConfig, sessionWriter, sessionBridge: providedBridge } = params;
12785
- const resolvedCaps = await capabilitiesFor(modelsRegistry, provider.id, context.model).catch(() => void 0);
12786
- const effectiveMaxContext = config.context.effectiveMaxContext ?? resolvedCaps?.maxContext ?? provider.capabilities.maxContext;
12816
+ const {
12817
+ compactor,
12818
+ events,
12819
+ modelsRegistry,
12820
+ context,
12821
+ config,
12822
+ provider,
12823
+ pipelines,
12824
+ fullConfig,
12825
+ sessionWriter,
12826
+ sessionBridge: providedBridge
12827
+ } = params;
12828
+ const effectiveMaxContext = await resolveRuntimeMaxContext({
12829
+ modelsRegistry,
12830
+ config,
12831
+ provider,
12832
+ providerId: config.provider ?? provider.id,
12833
+ modelId: config.model ?? context.model
12834
+ });
12787
12835
  let autoCompactor;
12788
12836
  if (config.context.autoCompact !== false) {
12789
12837
  const auditLevel = resolveAuditLevel(fullConfig ?? config);
@@ -12872,7 +12920,7 @@ function setupMetrics(params) {
12872
12920
  const dumpMetrics = () => {
12873
12921
  if (!metricsSink) return;
12874
12922
  try {
12875
- const out = path9.join(wpaths.projectSessions, "metrics.json");
12923
+ const out = path8.join(wpaths.projectSessions, "metrics.json");
12876
12924
  const snap = metricsSink.snapshot();
12877
12925
  writeFileSync(out, JSON.stringify(snap, null, 2));
12878
12926
  } catch {
@@ -13131,12 +13179,12 @@ async function setupSession(params) {
13131
13179
  }
13132
13180
  const sessionRef = { current: session };
13133
13181
  await recoveryLock.write(session.id).catch(() => void 0);
13134
- const attachments = new DefaultAttachmentStore({ spoolDir: path9.join(wpaths.projectSessions, session.id, "attachments") });
13135
- const queueStore = new QueueStore({ dir: path9.join(wpaths.projectSessions, session.id) });
13182
+ const attachments = new DefaultAttachmentStore({ spoolDir: path8.join(wpaths.projectSessions, session.id, "attachments") });
13183
+ const queueStore = new QueueStore({ dir: path8.join(wpaths.projectSessions, session.id) });
13136
13184
  const ctxSignal = new AbortController().signal;
13137
13185
  const context = new Context({ systemPrompt, provider, session, signal: ctxSignal, tokenCounter, cwd, projectRoot, model: config.model });
13138
13186
  if (restoredMessages.length > 0) context.state.replaceMessages(restoredMessages);
13139
- const todosCheckpointPath = path9.join(wpaths.projectSessions, `${session.id}.todos.json`);
13187
+ const todosCheckpointPath = path8.join(wpaths.projectSessions, `${session.id}.todos.json`);
13140
13188
  if (resumeId) {
13141
13189
  try {
13142
13190
  const restoredTodos = await loadTodosCheckpoint(todosCheckpointPath);
@@ -13148,13 +13196,13 @@ async function setupSession(params) {
13148
13196
  }
13149
13197
  }
13150
13198
  const detachTodosCheckpoint = attachTodosCheckpoint(context.state, todosCheckpointPath, session.id);
13151
- const planPath = path9.join(wpaths.projectSessions, `${session.id}.plan.json`);
13199
+ const planPath = path8.join(wpaths.projectSessions, `${session.id}.plan.json`);
13152
13200
  context.state.setMeta("plan.path", planPath);
13153
13201
  let dirState;
13154
13202
  if (resumeId) {
13155
13203
  try {
13156
- const fleetRoot = path9.join(wpaths.projectSessions, session.id);
13157
- dirState = await loadDirectorState(path9.join(fleetRoot, "director-state.json"));
13204
+ const fleetRoot = path8.join(wpaths.projectSessions, session.id);
13205
+ dirState = await loadDirectorState(path8.join(fleetRoot, "director-state.json"));
13158
13206
  if (dirState) {
13159
13207
  const tCounts = {};
13160
13208
  for (const t of dirState.tasks) tCounts[t.status] = (tCounts[t.status] ?? 0) + 1;
@@ -13179,7 +13227,7 @@ function resolveBundledSkillsDir2() {
13179
13227
  try {
13180
13228
  const req2 = createRequire(import.meta.url);
13181
13229
  const corePkg = req2.resolve("@wrongstack/core/package.json");
13182
- return path9.join(path9.dirname(corePkg), "skills");
13230
+ return path8.join(path8.dirname(corePkg), "skills");
13183
13231
  } catch {
13184
13232
  return void 0;
13185
13233
  }
@@ -13304,7 +13352,6 @@ var resolveSessionLoggingConfig = (cfg) => ({
13304
13352
  }
13305
13353
  }
13306
13354
  });
13307
- var stageListeners = /* @__PURE__ */ new Set();
13308
13355
  async function main(argv) {
13309
13356
  const ctx = await boot(argv);
13310
13357
  if (typeof ctx === "number") return ctx;
@@ -13334,7 +13381,10 @@ async function main(argv) {
13334
13381
  forceAllYolo: flags["force-all-yolo"] === true,
13335
13382
  promptDelegate: makePromptDelegate(reader)
13336
13383
  },
13337
- compactor: { preserveK: config.context.preserveK, eliseThreshold: config.context.eliseThreshold },
13384
+ compactor: {
13385
+ preserveK: config.context.preserveK,
13386
+ eliseThreshold: config.context.eliseThreshold
13387
+ },
13338
13388
  bundledSkillsDir: config.features.skills ? resolveBundledSkillsDir2() : void 0
13339
13389
  });
13340
13390
  const replayFlag = flags["replay"];
@@ -13349,9 +13399,7 @@ async function main(argv) {
13349
13399
  mode,
13350
13400
  logger
13351
13401
  });
13352
- logger.info(
13353
- `replay: ProviderRunner bound in '${mode}' mode for session ${sessionId}`
13354
- );
13402
+ logger.info(`replay: ProviderRunner bound in '${mode}' mode for session ${sessionId}`);
13355
13403
  }
13356
13404
  const configStore = container.resolve(TOKENS.ConfigStore);
13357
13405
  container.bind(TOKENS.PathResolver, () => pathResolver);
@@ -13375,12 +13423,15 @@ async function main(argv) {
13375
13423
  }
13376
13424
  const modeId = activeMode?.id ?? "default";
13377
13425
  const modePrompt = activeMode?.prompt ?? "";
13378
- const resolvedModel = await modelsRegistry.getModel(config.provider, config.model);
13379
- const modelCapabilities = resolvedModel?.capabilities ? {
13380
- maxContextTokens: resolvedModel.capabilities.maxContext,
13381
- supportsTools: resolvedModel.capabilities.tools,
13382
- supportsVision: resolvedModel.capabilities.vision,
13383
- supportsReasoning: resolvedModel.capabilities.reasoning
13426
+ const [resolvedCaps, resolvedModel] = await Promise.all([
13427
+ capabilitiesFor(modelsRegistry, provider.id, config.model).catch(() => void 0),
13428
+ modelsRegistry.getModel(config.provider, config.model).catch(() => void 0)
13429
+ ]);
13430
+ const modelCapabilities = resolvedCaps ? {
13431
+ maxContextTokens: resolvedCaps.maxContext,
13432
+ supportsTools: resolvedCaps.tools,
13433
+ supportsVision: resolvedCaps.vision,
13434
+ supportsReasoning: resolvedModel?.capabilities.reasoning ?? false
13384
13435
  } : void 0;
13385
13436
  const memoryStore = container.resolve(TOKENS.MemoryStore);
13386
13437
  const skillLoader = container.resolve(TOKENS.SkillLoader);
@@ -13396,15 +13447,15 @@ async function main(argv) {
13396
13447
  modeId,
13397
13448
  modePrompt,
13398
13449
  modelCapabilities,
13399
- planPath: () => sessionRef.current ? path9.join(wpaths.projectSessions, `${sessionRef.current.id}.plan.json`) : void 0,
13450
+ planPath: () => sessionRef.current ? path8.join(wpaths.projectSessions, `${sessionRef.current.id}.plan.json`) : void 0,
13400
13451
  contributors: [
13401
13452
  // Injects the ETERNAL AUTONOMY block when the user has activated
13402
- // `/autonomy eternal`. Without this, the per-iteration directive
13403
- // is the only place the model sees the rules — compaction can
13404
- // drop it and the model forgets it's in autonomy mode.
13453
+ // a long-running autonomy engine. Without this, the per-iteration
13454
+ // directive is the only place the model sees the rules — compaction
13455
+ // can drop it and the model forgets it's in autonomy mode.
13405
13456
  makeAutonomyPromptContributor({
13406
13457
  goalPath: goalPathForPrompt,
13407
- enabled: () => autonomyModeRef.current === "eternal"
13458
+ enabled: () => autonomyModeRef.current === "eternal" || autonomyModeRef.current === "eternal-parallel"
13408
13459
  })
13409
13460
  ]
13410
13461
  })
@@ -13421,7 +13472,13 @@ async function main(argv) {
13421
13472
  const events = new EventBus();
13422
13473
  events.setLogger(logger);
13423
13474
  const { metricsSink, healthRegistry } = (() => {
13424
- const ms = setupMetrics({ flags, wpaths, events, logger, config: { provider: config.provider, model: config.model } });
13475
+ const ms = setupMetrics({
13476
+ flags,
13477
+ wpaths,
13478
+ events,
13479
+ logger,
13480
+ config: { provider: config.provider, model: config.model }
13481
+ });
13425
13482
  return ms;
13426
13483
  })();
13427
13484
  const spinner = new Spinner();
@@ -13587,7 +13644,7 @@ async function main(argv) {
13587
13644
  });
13588
13645
  const pipelines = setupPipelines({ events, logger });
13589
13646
  const compactor = container.resolve(TOKENS.Compactor);
13590
- const { effectiveMaxContext, autoCompactor } = await setupCompaction({
13647
+ const compactionSetup = await setupCompaction({
13591
13648
  compactor,
13592
13649
  events,
13593
13650
  modelsRegistry,
@@ -13599,18 +13656,39 @@ async function main(argv) {
13599
13656
  sessionBridge
13600
13657
  // share the same bridge for consistent audit logging (compaction + errors + future)
13601
13658
  });
13602
- const refreshMaxContext = async (providerId, modelId) => {
13603
- if (!autoCompactor) return;
13604
- const cap = await capabilitiesFor(modelsRegistry, providerId, modelId).catch(() => void 0);
13605
- const mc = cap?.maxContext ?? config.context.effectiveMaxContext ?? 2e5;
13606
- autoCompactor.setMaxContext(mc);
13659
+ let effectiveMaxContext = compactionSetup.effectiveMaxContext;
13660
+ context.provider.capabilities.maxContext = effectiveMaxContext;
13661
+ const { autoCompactor } = compactionSetup;
13662
+ const refreshMaxContext = async (providerId, modelId, runtimeProviderConfig) => {
13663
+ const mc = await resolveRuntimeMaxContext({
13664
+ modelsRegistry,
13665
+ config,
13666
+ provider: context.provider,
13667
+ runtimeProviderConfig,
13668
+ providerId,
13669
+ modelId
13670
+ });
13671
+ effectiveMaxContext = mc > 0 ? mc : 2e5;
13672
+ context.provider.capabilities.maxContext = effectiveMaxContext;
13673
+ autoCompactor?.setMaxContext(effectiveMaxContext);
13674
+ events.emit("ctx.max_context", { providerId, modelId, maxContext: effectiveMaxContext });
13675
+ updateSpinnerContext();
13607
13676
  };
13608
13677
  const updateSpinnerContext = () => {
13609
13678
  if (effectiveMaxContext > 0 && lastInputTokens > 0) {
13610
13679
  spinner.setContext({ used: lastInputTokens, max: effectiveMaxContext });
13611
13680
  } else spinner.setContext(void 0);
13612
13681
  };
13613
- const agent = createAgent({ container, tools: toolRegistry, providers: providerRegistry, events, pipelines, context, config, confirmAwaiter: makeConfirmAwaiter(reader) });
13682
+ const agent = createAgent({
13683
+ container,
13684
+ tools: toolRegistry,
13685
+ providers: providerRegistry,
13686
+ events,
13687
+ pipelines,
13688
+ context,
13689
+ config,
13690
+ confirmAwaiter: makeConfirmAwaiter(reader)
13691
+ });
13614
13692
  const mcpRegistry = new MCPRegistry({ toolRegistry, events, log: logger });
13615
13693
  if (config.features.mcp) {
13616
13694
  for (const cfg of Object.values(config.mcpServers ?? {})) {
@@ -13655,7 +13733,7 @@ async function main(argv) {
13655
13733
  context.model = modelId;
13656
13734
  config = patchConfig(config, { provider: providerId, model: modelId });
13657
13735
  configStore.update({ provider: providerId, model: modelId });
13658
- void refreshMaxContext(resolvedProviderId, modelId);
13736
+ void refreshMaxContext(resolvedProviderId, modelId, cfgWithType);
13659
13737
  return null;
13660
13738
  } catch (err) {
13661
13739
  return err instanceof Error ? err.message : String(err);
@@ -13684,12 +13762,26 @@ async function main(argv) {
13684
13762
  }
13685
13763
  }
13686
13764
  };
13687
- const fleetRoot = directorMode ? path9.join(wpaths.projectSessions, session.id) : void 0;
13688
- const manifestPath = directorMode ? typeof process.env["WRONGSTACK_FLEET_MANIFEST"] === "string" ? process.env["WRONGSTACK_FLEET_MANIFEST"] : path9.join(fleetRoot, "fleet.json") : void 0;
13689
- const sharedScratchpadPath = directorMode ? path9.join(fleetRoot, "shared") : void 0;
13690
- const subagentSessionsRoot = directorMode ? path9.join(fleetRoot, "subagents") : void 0;
13691
- const stateCheckpointPath = directorMode ? path9.join(fleetRoot, "director-state.json") : void 0;
13692
- const fleetRootForPromotion = path9.join(wpaths.projectSessions, session.id);
13765
+ const stageListeners = /* @__PURE__ */ new Set();
13766
+ const broadcastAutonomyStage = (stage) => {
13767
+ for (const fn of stageListeners) {
13768
+ try {
13769
+ fn(stage);
13770
+ } catch {
13771
+ }
13772
+ }
13773
+ };
13774
+ const fleetRoot = directorMode ? path8.join(wpaths.projectSessions, session.id) : void 0;
13775
+ const manifestPath = directorMode ? typeof process.env["WRONGSTACK_FLEET_MANIFEST"] === "string" ? process.env["WRONGSTACK_FLEET_MANIFEST"] : path8.join(fleetRoot, "fleet.json") : void 0;
13776
+ const sharedScratchpadPath = directorMode ? path8.join(fleetRoot, "shared") : void 0;
13777
+ const subagentSessionsRoot = directorMode ? path8.join(fleetRoot, "subagents") : void 0;
13778
+ const stateCheckpointPath = directorMode ? path8.join(fleetRoot, "director-state.json") : void 0;
13779
+ const fleetRootForPromotion = path8.join(wpaths.projectSessions, session.id);
13780
+ const brainQueue = new BrainDecisionQueue(events);
13781
+ const brain = new ObservableBrainArbiter(
13782
+ new HumanEscalatingBrainArbiter(new DefaultBrainArbiter(), brainQueue),
13783
+ events
13784
+ );
13693
13785
  const multiAgentHost = new MultiAgentHost(
13694
13786
  {
13695
13787
  container,
@@ -13714,7 +13806,9 @@ async function main(argv) {
13714
13806
  fleetRoot: fleetRootForPromotion,
13715
13807
  stateCheckpointPath,
13716
13808
  sessionWriter: session,
13717
- maxConcurrent
13809
+ maxConcurrent,
13810
+ getLeaderMaxContext: () => effectiveMaxContext,
13811
+ brain
13718
13812
  }
13719
13813
  );
13720
13814
  toolRegistry.register(
@@ -13785,6 +13879,7 @@ async function main(argv) {
13785
13879
  events,
13786
13880
  storeDir: wpaths.projectAutophase,
13787
13881
  projectRoot,
13882
+ brain,
13788
13883
  log: (line) => renderer.write(`${line}
13789
13884
  `)
13790
13885
  });
@@ -13881,7 +13976,9 @@ async function main(argv) {
13881
13976
  for (const a of s.live) {
13882
13977
  if (a.status === "running" || a.status === "idle") {
13883
13978
  const task = a.task ? ` \u2014 ${a.task.slice(0, 60)}` : "";
13884
- lines.push(` ${STATUS_ICON[a.status] ?? "?"} ${a.subagentId.slice(0, 8)} ${a.status}${task}`);
13979
+ lines.push(
13980
+ ` ${STATUS_ICON[a.status] ?? "?"} ${a.subagentId.slice(0, 8)} ${a.status}${task}`
13981
+ );
13885
13982
  }
13886
13983
  }
13887
13984
  for (const p of s.pending) {
@@ -14015,7 +14112,8 @@ async function main(argv) {
14015
14112
  }
14016
14113
  },
14017
14114
  onFleetSpawn: async (role) => {
14018
- if (!director) throw new Error("No director active \u2014 start with --director or use /autonomy parallel.");
14115
+ if (!director)
14116
+ throw new Error("No director active \u2014 start with --director or use /autonomy parallel.");
14019
14117
  const cfg = FLEET_ROSTER[role] ?? {
14020
14118
  id: `manual-${Date.now()}`,
14021
14119
  name: role,
@@ -14025,7 +14123,7 @@ async function main(argv) {
14025
14123
  return director.spawn(cfg);
14026
14124
  },
14027
14125
  onFleetLog: async (subagentId, mode) => {
14028
- const subagentsRoot = path9.join(fleetRootForPromotion, "subagents");
14126
+ const subagentsRoot = path8.join(fleetRootForPromotion, "subagents");
14029
14127
  let runDirs;
14030
14128
  try {
14031
14129
  runDirs = await fsp3.readdir(subagentsRoot);
@@ -14034,7 +14132,7 @@ async function main(argv) {
14034
14132
  }
14035
14133
  const found = [];
14036
14134
  for (const runId of runDirs) {
14037
- const runDir = path9.join(subagentsRoot, runId);
14135
+ const runDir = path8.join(subagentsRoot, runId);
14038
14136
  let files;
14039
14137
  try {
14040
14138
  files = await fsp3.readdir(runDir);
@@ -14043,7 +14141,7 @@ async function main(argv) {
14043
14141
  }
14044
14142
  for (const f of files) {
14045
14143
  if (!f.endsWith(".jsonl")) continue;
14046
- const full = path9.join(runDir, f);
14144
+ const full = path8.join(runDir, f);
14047
14145
  try {
14048
14146
  const stat4 = await fsp3.stat(full);
14049
14147
  found.push({
@@ -14068,7 +14166,9 @@ async function main(argv) {
14068
14166
  ` ${color.cyan(t2.subagentId.padEnd(18))} ${color.dim(t2.runId.slice(0, 18))} ${color.dim(`${(t2.size / 1024).toFixed(1)} KB`)}`
14069
14167
  );
14070
14168
  }
14071
- lines2.push("Use `/fleet log <subagentId>` for a summary, or append `raw` for the full JSONL.");
14169
+ lines2.push(
14170
+ "Use `/fleet log <subagentId>` for a summary, or append `raw` for the full JSONL."
14171
+ );
14072
14172
  return lines2.join("\n");
14073
14173
  }
14074
14174
  const matches = found.filter(
@@ -14097,7 +14197,9 @@ async function main(argv) {
14097
14197
  const ev = JSON.parse(line);
14098
14198
  counts[ev.type] = (counts[ev.type] ?? 0) + 1;
14099
14199
  if (ev.type === "user_input" && !firstUser) {
14100
- const txt = typeof ev.content === "string" ? ev.content : Array.isArray(ev.content) ? ev.content.filter((b) => b.type === "text").map((b) => b.text).join(" ") : "";
14200
+ const txt = typeof ev.content === "string" ? ev.content : Array.isArray(ev.content) ? ev.content.filter(
14201
+ (b) => b.type === "text"
14202
+ ).map((b) => b.text).join(" ") : "";
14101
14203
  firstUser = txt.slice(0, 120);
14102
14204
  }
14103
14205
  if (ev.type === "llm_response") {
@@ -14140,7 +14242,7 @@ async function main(argv) {
14140
14242
  }
14141
14243
  const dir = await multiAgentHost.ensureDirector();
14142
14244
  if (!dir) return "Director is not available.";
14143
- const dirStatePath = path9.join(fleetRootForPromotion, "director-state.json");
14245
+ const dirStatePath = path8.join(fleetRootForPromotion, "director-state.json");
14144
14246
  const prior = await loadDirectorState(dirStatePath);
14145
14247
  if (!prior) {
14146
14248
  return "No prior director-state.json found \u2014 nothing to retry.";
@@ -14165,9 +14267,7 @@ async function main(argv) {
14165
14267
  lines.push("Run `/fleet retry <taskId>` or `/fleet retry all` to re-assign.");
14166
14268
  return lines.join("\n");
14167
14269
  }
14168
- const targets = taskId === "all" ? interrupted : interrupted.filter(
14169
- (t) => t.taskId === taskId || t.taskId.startsWith(taskId)
14170
- );
14270
+ const targets = taskId === "all" ? interrupted : interrupted.filter((t) => t.taskId === taskId || t.taskId.startsWith(taskId));
14171
14271
  if (targets.length === 0) {
14172
14272
  return `No interrupted task matched "${taskId}".`;
14173
14273
  }
@@ -14211,9 +14311,9 @@ async function main(argv) {
14211
14311
  for (const tool of director2.tools(FLEET_ROSTER)) {
14212
14312
  toolRegistry.register(tool);
14213
14313
  }
14214
- const mp = path9.join(fleetRootForPromotion, "fleet.json");
14215
- const sp = path9.join(fleetRootForPromotion, "shared");
14216
- const ss = path9.join(fleetRootForPromotion, "subagents");
14314
+ const mp = path8.join(fleetRootForPromotion, "fleet.json");
14315
+ const sp = path8.join(fleetRootForPromotion, "shared");
14316
+ const ss = path8.join(fleetRootForPromotion, "subagents");
14217
14317
  const lines = [
14218
14318
  `${color.green("\u2713")} Promoted to director mode.`,
14219
14319
  ` Roster: ${Object.keys(FLEET_ROSTER).join(", ")}`,
@@ -14284,17 +14384,19 @@ Restart WrongStack to load or unload plugin code in this session.`;
14284
14384
  const effectiveMode = mode ?? "eternal";
14285
14385
  if (effectiveMode === "eternal-parallel") {
14286
14386
  if (!parallelEngine) {
14287
- parallelEngine = new ParallelEternalEngine({
14387
+ const parallelOptions = {
14288
14388
  agent,
14289
14389
  projectRoot,
14290
14390
  compactor: container.resolve(TOKENS.Compactor),
14291
14391
  maxContextTokens: effectiveMaxContext > 0 ? effectiveMaxContext : void 0,
14292
14392
  onIteration: broadcastEternalIteration,
14393
+ onStage: broadcastAutonomyStage,
14293
14394
  // Real per-role factory: each dispatched slot runs as a fresh,
14294
14395
  // isolated agent with the role's filtered tools + persona prompt
14295
14396
  // (instead of sharing the leader agent's Context).
14296
14397
  subagentFactory: multiAgentHost.makeSubagentFactory(config)
14297
- });
14398
+ };
14399
+ parallelEngine = new ParallelEternalEngine(parallelOptions);
14298
14400
  }
14299
14401
  void parallelEngine.prime?.();
14300
14402
  } else {
@@ -14304,7 +14406,8 @@ Restart WrongStack to load or unload plugin code in this session.`;
14304
14406
  projectRoot,
14305
14407
  compactor: container.resolve(TOKENS.Compactor),
14306
14408
  maxContextTokens: effectiveMaxContext > 0 ? effectiveMaxContext : void 0,
14307
- onIteration: broadcastEternalIteration
14409
+ onIteration: broadcastEternalIteration,
14410
+ onStage: broadcastAutonomyStage
14308
14411
  });
14309
14412
  }
14310
14413
  void eternalEngine.prime();
@@ -14315,20 +14418,26 @@ Restart WrongStack to load or unload plugin code in this session.`;
14315
14418
  parallelEngine?.stop();
14316
14419
  },
14317
14420
  onExit: () => {
14421
+ brainQueue.dispose();
14318
14422
  void mcpRegistry.stopAll();
14319
14423
  },
14320
14424
  onBeforeExit: async () => {
14321
14425
  const { spawn: spawn3 } = await import('child_process');
14322
14426
  const cwd2 = projectRoot;
14323
- const statusResult = await new Promise((resolve4, reject) => {
14324
- const child = spawn3("git", ["status", "--porcelain"], { cwd: cwd2, stdio: ["ignore", "pipe", "pipe"] });
14325
- let stdout = "";
14326
- child.stdout?.on("data", (d) => {
14327
- stdout += d;
14328
- });
14329
- child.on("error", reject);
14330
- child.on("close", (code) => resolve4({ stdout, code: code ?? 0 }));
14331
- });
14427
+ const statusResult = await new Promise(
14428
+ (resolve3, reject) => {
14429
+ const child = spawn3("git", ["status", "--porcelain"], {
14430
+ cwd: cwd2,
14431
+ stdio: ["ignore", "pipe", "pipe"]
14432
+ });
14433
+ let stdout = "";
14434
+ child.stdout?.on("data", (d) => {
14435
+ stdout += d;
14436
+ });
14437
+ child.on("error", reject);
14438
+ child.on("close", (code) => resolve3({ stdout, code: code ?? 0 }));
14439
+ }
14440
+ );
14332
14441
  if (statusResult.stdout.trim().length > 0) {
14333
14442
  const lines = statusResult.stdout.split("\n").filter(Boolean);
14334
14443
  return {
@@ -14405,8 +14514,10 @@ Restart WrongStack to load or unload plugin code in this session.`;
14405
14514
  parallelSlots: opts?.parallelSlots,
14406
14515
  subagentFactory,
14407
14516
  onProgress: (p) => {
14408
- renderer.write(` \u2591 wave ${p.wave + 1} \xB7 ${p.completed}/${p.total} tasks \xB7 ${p.percent}% done
14409
- `);
14517
+ renderer.write(
14518
+ ` \u2591 wave ${p.wave + 1} \xB7 ${p.completed}/${p.total} tasks \xB7 ${p.percent}% done
14519
+ `
14520
+ );
14410
14521
  }
14411
14522
  });
14412
14523
  globalThis.__sddParallelRun = run;