@wrongstack/cli 0.9.1 → 0.9.4

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,12 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import * as path25 from 'path';
3
- import { join } from 'path';
2
+ import * as path24 from 'path';
4
3
  import * as fsp3 from 'fs/promises';
5
- import { readdir, readFile } from 'fs/promises';
6
- import { color, DefaultPathResolver, TOKENS, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, SlashCommandRegistry, createDelegateTool, FLEET_ROSTER, createMcpControlTool, EternalAutonomyEngine, DefaultLogger, DefaultModelsRegistry, ProviderRegistry, InMemoryMetricsSink, wireMetricsToEvents, DefaultHealthRegistry, startMetricsServer, RecoveryLock, DefaultAttachmentStore, QueueStore, Context, loadTodosCheckpoint, attachTodosCheckpoint, loadDirectorState, loadPlan, createDefaultPipelines, AutoCompactionMiddleware, estimateRequestTokens, Agent, loadPlugins, FleetManager, makeDirectorSessionFactory, Director, AutoApprovePermissionPolicy, PhaseStore, AutoPhasePlanner, PhaseGraphBuilder, WorktreeManager, PhaseOrchestrator, makeLLMClassifier, resolveWstackPaths, DefaultSecretVault, migratePlaintextSecrets, DefaultConfigLoader, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, atomicWrite, DefaultPluginAPI, makeAgentSubagentRunner, NULL_FLEET_BUS, buildChildEnv, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, AGENTS_BY_PHASE, dispatchAgent, formatTodosList, emptyPlan, clearPlan, savePlan, formatPlanTemplates, getPlanTemplate, addPlanItem, formatPlan, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, DefaultTaskStore, TaskTracker, renderProgress, renderTaskGraph, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, pendingBtwCount, setBtwNote, InputBuilder, FsError, ERROR_CODES, projectHash, WrongStackError, defaultOrchestrator, decryptConfigSecrets, encryptConfigSecrets as encryptConfigSecrets$1, SpecVersioning, ParallelEternalEngine, allServers as allServers$1 } from '@wrongstack/core';
4
+ import { color, DefaultPathResolver, TOKENS, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, SlashCommandRegistry, createDelegateTool, FLEET_ROSTER, createMcpControlTool, EternalAutonomyEngine, DefaultLogger, DefaultModelsRegistry, ProviderRegistry, InMemoryMetricsSink, wireMetricsToEvents, DefaultHealthRegistry, startMetricsServer, RecoveryLock, DefaultAttachmentStore, QueueStore, Context, loadTodosCheckpoint, attachTodosCheckpoint, loadDirectorState, loadPlan, createDefaultPipelines, AutoCompactionMiddleware, estimateRequestTokens, Agent, loadPlugins, FleetManager, makeDirectorSessionFactory, Director, AutoApprovePermissionPolicy, PhaseStore, AutoPhasePlanner, PhaseGraphBuilder, WorktreeManager, PhaseOrchestrator, makeLLMClassifier, resolveWstackPaths, DefaultSecretVault, migratePlaintextSecrets, DefaultConfigLoader, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, atomicWrite, DefaultPluginAPI, makeAgentSubagentRunner, NULL_FLEET_BUS, buildChildEnv, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, AGENTS_BY_PHASE, dispatchAgent, formatTodosList, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, DefaultTaskStore, TaskTracker, renderProgress, renderTaskGraph, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, pendingBtwCount, setBtwNote, decryptConfigSecrets, encryptConfigSecrets as encryptConfigSecrets$1, InputBuilder, FsError, ERROR_CODES, SpecVersioning, ParallelEternalEngine, allServers as allServers$1 } from '@wrongstack/core';
7
5
  import { createRequire } from 'module';
8
- import * as os4 from 'os';
9
- import os4__default from 'os';
6
+ import * as os3 from 'os';
7
+ import os3__default from 'os';
10
8
  import * as crypto2 from 'crypto';
11
9
  import { randomUUID } from 'crypto';
12
10
  import { DefaultSecretVault as DefaultSecretVault$1, encryptConfigSecrets, isSecretField, decryptConfigSecrets as decryptConfigSecrets$1 } from '@wrongstack/core/security';
@@ -15,14 +13,13 @@ import { MCPRegistry } from '@wrongstack/mcp';
15
13
  import { buildProviderFactoriesFromRegistry, makeProviderFromConfig, capabilitiesFor } from '@wrongstack/providers';
16
14
  import { createDefaultContainer, routeImagesForModel, readClipboardImage } from '@wrongstack/runtime';
17
15
  import { builtinToolsPack, rememberTool, forgetTool } from '@wrongstack/tools';
18
- import { spawn } from 'child_process';
19
- import { SkillInstaller } from '@wrongstack/core/skills';
20
16
  import * as readline from 'readline';
21
17
  import * as fs10 from 'fs';
22
18
  import { writeFileSync } from 'fs';
23
19
  import { WrongStackACPServer } from '@wrongstack/acp/agent';
24
20
  import { ACP_AGENT_COMMANDS, makeACPSubagentRunner, makeACPSubagentRunnerWithStop } from '@wrongstack/acp';
25
21
  import { ACP_AGENTS, SubagentBudget } from '@wrongstack/core/coordination';
22
+ import { spawn } from 'child_process';
26
23
  import { allServers } from '@wrongstack/core/infrastructure';
27
24
  import { createToolVisionAdapters } from '@wrongstack/runtime/vision';
28
25
  import { ToolExecutor } from '@wrongstack/core/execution';
@@ -384,6 +381,7 @@ function buildSddCommand(opts) {
384
381
  description: "AI-driven SDD: /sdd [new|approve|execute|cancel|status|list|show|templates]",
385
382
  async run(args) {
386
383
  opts.context;
384
+ if (!opts.paths) return { message: "SDD not available \u2014 paths not configured." };
387
385
  const specsDir = opts.paths.projectSpecs;
388
386
  const graphsDir = opts.paths.projectTaskGraphs;
389
387
  const specStore = new SpecStore({ baseDir: specsDir });
@@ -1398,7 +1396,7 @@ function sddHelp() {
1398
1396
  async function gatherProjectContext(projectRoot) {
1399
1397
  const parts = [];
1400
1398
  try {
1401
- const pkgPath = path25.join(projectRoot, "package.json");
1399
+ const pkgPath = path24.join(projectRoot, "package.json");
1402
1400
  const pkgRaw = await fsp3.readFile(pkgPath, "utf8");
1403
1401
  const pkg = JSON.parse(pkgRaw);
1404
1402
  parts.push(`Project: ${String(pkg.name ?? "unknown")}`);
@@ -1414,13 +1412,13 @@ async function gatherProjectContext(projectRoot) {
1414
1412
  } catch {
1415
1413
  }
1416
1414
  try {
1417
- const tsconfigPath = path25.join(projectRoot, "tsconfig.json");
1415
+ const tsconfigPath = path24.join(projectRoot, "tsconfig.json");
1418
1416
  await fsp3.access(tsconfigPath);
1419
1417
  parts.push("Language: TypeScript");
1420
1418
  } catch {
1421
1419
  }
1422
1420
  try {
1423
- const srcDir = path25.join(projectRoot, "src");
1421
+ const srcDir = path24.join(projectRoot, "src");
1424
1422
  const entries = await fsp3.readdir(srcDir, { withFileTypes: true });
1425
1423
  const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
1426
1424
  if (dirs.length > 0) {
@@ -1576,7 +1574,7 @@ __export(update_check_exports, {
1576
1574
  getUpdateNotification: () => getUpdateNotification
1577
1575
  });
1578
1576
  function cachePath(homeFn = defaultHomeDir2) {
1579
- return path25.join(homeFn(), ".wrongstack", "update-cache.json");
1577
+ return path24.join(homeFn(), ".wrongstack", "update-cache.json");
1580
1578
  }
1581
1579
  function currentVersion() {
1582
1580
  const req2 = createRequire(import.meta.url);
@@ -1613,7 +1611,7 @@ async function readCache(homeFn = defaultHomeDir2) {
1613
1611
  }
1614
1612
  async function writeCache(entry, homeFn = defaultHomeDir2) {
1615
1613
  try {
1616
- const dir = path25.dirname(cachePath(homeFn));
1614
+ const dir = path24.dirname(cachePath(homeFn));
1617
1615
  await fsp3.mkdir(dir, { recursive: true });
1618
1616
  await fsp3.writeFile(cachePath(homeFn), JSON.stringify(entry, null, 2), "utf8");
1619
1617
  } catch {
@@ -1686,7 +1684,7 @@ async function getUpdateNotification(signal, homeFn) {
1686
1684
  var defaultHomeDir2, CACHE_TTL_MS;
1687
1685
  var init_update_check = __esm({
1688
1686
  "src/update-check.ts"() {
1689
- defaultHomeDir2 = () => os4.homedir();
1687
+ defaultHomeDir2 = () => os3.homedir();
1690
1688
  CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
1691
1689
  }
1692
1690
  });
@@ -2234,7 +2232,7 @@ async function runWebUI(opts) {
2234
2232
  return {};
2235
2233
  }
2236
2234
  if (!parsed.providers) return {};
2237
- const keyFile = path25.join(path25.dirname(opts.globalConfigPath), ".key");
2235
+ const keyFile = path24.join(path24.dirname(opts.globalConfigPath), ".key");
2238
2236
  const vault = new DefaultSecretVault$1({ keyFile });
2239
2237
  return decryptConfigSecrets$1(parsed.providers, vault);
2240
2238
  }
@@ -2267,7 +2265,7 @@ async function runWebUI(opts) {
2267
2265
  parsed = {};
2268
2266
  }
2269
2267
  parsed.providers = providers;
2270
- const keyFile = path25.join(path25.dirname(opts.globalConfigPath), ".key");
2268
+ const keyFile = path24.join(path24.dirname(opts.globalConfigPath), ".key");
2271
2269
  const vault = new DefaultSecretVault$1({ keyFile });
2272
2270
  const encrypted = encryptConfigSecrets(parsed, vault);
2273
2271
  await atomicWrite(opts.globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
@@ -2487,10 +2485,10 @@ async function detectPackageManager(root, declared) {
2487
2485
  const name = declared.split("@")[0];
2488
2486
  if (name) return name;
2489
2487
  }
2490
- if (await pathExists(path25.join(root, "pnpm-lock.yaml"))) return "pnpm";
2491
- if (await pathExists(path25.join(root, "bun.lockb"))) return "bun";
2492
- if (await pathExists(path25.join(root, "bun.lock"))) return "bun";
2493
- if (await pathExists(path25.join(root, "yarn.lock"))) return "yarn";
2488
+ if (await pathExists(path24.join(root, "pnpm-lock.yaml"))) return "pnpm";
2489
+ if (await pathExists(path24.join(root, "bun.lockb"))) return "bun";
2490
+ if (await pathExists(path24.join(root, "bun.lock"))) return "bun";
2491
+ if (await pathExists(path24.join(root, "yarn.lock"))) return "yarn";
2494
2492
  return "npm";
2495
2493
  }
2496
2494
  function hasUsableScript(scripts, name) {
@@ -2511,7 +2509,7 @@ function parseMakeTargets(makefile) {
2511
2509
  async function detectProjectFacts(root) {
2512
2510
  const facts = { hints: [] };
2513
2511
  try {
2514
- const pkg = JSON.parse(await fsp3.readFile(path25.join(root, "package.json"), "utf8"));
2512
+ const pkg = JSON.parse(await fsp3.readFile(path24.join(root, "package.json"), "utf8"));
2515
2513
  const scripts = pkg.scripts ?? {};
2516
2514
  const pm = await detectPackageManager(root, pkg.packageManager);
2517
2515
  if (hasUsableScript(scripts, "build")) facts.build = `${pm} run build`;
@@ -2525,14 +2523,14 @@ async function detectProjectFacts(root) {
2525
2523
  } catch {
2526
2524
  }
2527
2525
  try {
2528
- if (!await pathExists(path25.join(root, "pyproject.toml"))) throw new Error("not python");
2526
+ if (!await pathExists(path24.join(root, "pyproject.toml"))) throw new Error("not python");
2529
2527
  facts.test ??= "pytest";
2530
2528
  facts.lint ??= "ruff check .";
2531
2529
  facts.hints.push("pyproject.toml");
2532
2530
  } catch {
2533
2531
  }
2534
2532
  try {
2535
- if (!await pathExists(path25.join(root, "go.mod"))) throw new Error("not go");
2533
+ if (!await pathExists(path24.join(root, "go.mod"))) throw new Error("not go");
2536
2534
  facts.build ??= "go build ./...";
2537
2535
  facts.test ??= "go test ./...";
2538
2536
  facts.run ??= "go run .";
@@ -2540,7 +2538,7 @@ async function detectProjectFacts(root) {
2540
2538
  } catch {
2541
2539
  }
2542
2540
  try {
2543
- if (!await pathExists(path25.join(root, "Cargo.toml"))) throw new Error("not rust");
2541
+ if (!await pathExists(path24.join(root, "Cargo.toml"))) throw new Error("not rust");
2544
2542
  facts.build ??= "cargo build";
2545
2543
  facts.test ??= "cargo test";
2546
2544
  facts.lint ??= "cargo clippy";
@@ -2549,7 +2547,7 @@ async function detectProjectFacts(root) {
2549
2547
  } catch {
2550
2548
  }
2551
2549
  try {
2552
- const makefile = await fsp3.readFile(path25.join(root, "Makefile"), "utf8");
2550
+ const makefile = await fsp3.readFile(path24.join(root, "Makefile"), "utf8");
2553
2551
  const targets = parseMakeTargets(makefile);
2554
2552
  facts.build ??= targets.has("build") ? "make build" : "make";
2555
2553
  if (targets.has("test")) facts.test ??= "make test";
@@ -2674,11 +2672,6 @@ function estimateTokens(messages) {
2674
2672
  }
2675
2673
  return total;
2676
2674
  }
2677
- function statusIcon(status) {
2678
- if (status === "healthy") return color.green("\u25CF");
2679
- if (status === "degraded") return color.yellow("\u25CF");
2680
- return color.red("\u25CF");
2681
- }
2682
2675
 
2683
2676
  // src/slash-commands/clear.ts
2684
2677
  function buildClearCommand(opts) {
@@ -2717,203 +2710,6 @@ function buildClearCommand(opts) {
2717
2710
  }
2718
2711
  };
2719
2712
  }
2720
- async function runGit(args, cwd) {
2721
- try {
2722
- return await new Promise((resolve4, reject) => {
2723
- const child = spawn("git", args, {
2724
- cwd,
2725
- stdio: ["ignore", "pipe", "pipe"]
2726
- });
2727
- let stdout = "";
2728
- let stderr = "";
2729
- child.stdout?.on("data", (d) => {
2730
- stdout += d;
2731
- });
2732
- child.stderr?.on("data", (d) => {
2733
- stderr += d;
2734
- });
2735
- child.on("error", (err) => {
2736
- reject(new WrongStackError({
2737
- message: `Failed to run git: ${err.message}`,
2738
- code: ERROR_CODES.TOOL_EXECUTION_FAILED,
2739
- subsystem: "tool",
2740
- context: { command: "git", args, cwd },
2741
- cause: err
2742
- }));
2743
- });
2744
- child.on("close", (code) => resolve4({ stdout, stderr, code: code ?? 0 }));
2745
- });
2746
- } catch (err) {
2747
- if (err instanceof WrongStackError) throw err;
2748
- throw new WrongStackError({
2749
- message: err instanceof Error ? err.message : String(err),
2750
- code: ERROR_CODES.TOOL_EXECUTION_FAILED,
2751
- subsystem: "tool",
2752
- context: { command: "git", args, cwd },
2753
- cause: err
2754
- });
2755
- }
2756
- }
2757
- function detectCommitType(stats) {
2758
- const lines = stats.split("\n");
2759
- const hasTestFiles = lines.some(
2760
- (l) => l.includes("_test.") || l.includes(".test.") || l.includes(".spec.")
2761
- );
2762
- const hasDocs = lines.some(
2763
- (l) => l.includes("README") || l.includes("CHANGELOG") || l.includes("docs/") || l.includes(".md")
2764
- );
2765
- const hasConfig = lines.some(
2766
- (l) => l.includes("config") || l.includes("tsconfig") || l.includes(".json")
2767
- );
2768
- if (hasTestFiles) return "test";
2769
- if (hasDocs) return "docs";
2770
- if (hasConfig) return "chore";
2771
- return "feat";
2772
- }
2773
- async function generateCommitMessageHeuristics(cwd) {
2774
- const statsResult = await runGit(["diff", "--stat"], cwd);
2775
- if (statsResult.code !== 0) return "chore: update";
2776
- const nameResult = await runGit(["diff", "--name-only"], cwd);
2777
- const files = nameResult.stdout.split("\n").filter(Boolean);
2778
- const commitType = detectCommitType(statsResult.stdout);
2779
- let scope = "";
2780
- if (files.length > 0) {
2781
- const primary = files[0].split("/")[0];
2782
- if (primary && primary !== "packages" && primary !== "apps" && primary !== "node_modules") {
2783
- scope = `(${primary})`;
2784
- }
2785
- }
2786
- if (files.length === 0) {
2787
- return `${commitType}${scope}: update`;
2788
- }
2789
- if (files.length <= 3) {
2790
- const summary2 = files.map((f) => f.split("/").pop()).join(", ");
2791
- return `${commitType}${scope}: ${summary2}`;
2792
- }
2793
- const summary = files.slice(0, 3).map((f) => f.split("/").pop()).join(", ") + ` and ${files.length - 3} more`;
2794
- return `${commitType}${scope}: ${summary}`;
2795
- }
2796
- async function hasUncommittedChanges(cwd) {
2797
- const result = await runGit(["status", "--porcelain"], cwd);
2798
- return result.stdout.trim().length > 0;
2799
- }
2800
- async function isGitRepo(cwd) {
2801
- const result = await runGit(["rev-parse", "--git-dir"], cwd);
2802
- return result.code === 0;
2803
- }
2804
- function buildCommitCommand(_opts, generateCommitMessage) {
2805
- return {
2806
- name: "commit",
2807
- description: "Stage all changes and commit with auto-generated message.",
2808
- aliases: ["gc"],
2809
- async run(args, ctx) {
2810
- const cwd = ctx?.cwd ?? process.cwd();
2811
- if (!await isGitRepo(cwd)) {
2812
- return { message: "Not a git repository." };
2813
- }
2814
- if (!await hasUncommittedChanges(cwd)) {
2815
- return { message: "Nothing to commit (working tree clean)." };
2816
- }
2817
- const dryRun = args.includes("--dry-run") || args.includes("-n");
2818
- args.includes("--no-llm");
2819
- let message;
2820
- {
2821
- message = await generateCommitMessageHeuristics(cwd);
2822
- }
2823
- if (dryRun) {
2824
- return {
2825
- message: `Would commit:
2826
-
2827
- ${color.green(message)}
2828
-
2829
- ${color.dim("(dry-run \u2014 no actual commit)")}`
2830
- };
2831
- }
2832
- const stageResult = await runGit(["add", "."], cwd);
2833
- if (stageResult.code !== 0) {
2834
- return { message: `Stage failed: ${stageResult.stderr}` };
2835
- }
2836
- const commitResult = await runGit(["commit", "-m", message], cwd);
2837
- if (commitResult.code !== 0) {
2838
- return { message: `Commit failed: ${commitResult.stderr}` };
2839
- }
2840
- const hashResult = await runGit(["rev-parse", "--short", "HEAD"], cwd);
2841
- const hash = hashResult.stdout.trim();
2842
- const pushResult = await runGit(["remote"], cwd);
2843
- const hasRemote = pushResult.stdout.trim().length > 0;
2844
- let pushMsg = "";
2845
- if (hasRemote) {
2846
- pushMsg = `
2847
-
2848
- ${color.dim("Tip: Run /push to push to remote")}`;
2849
- }
2850
- return {
2851
- message: `${color.green("\u2713")} Committed: ${color.bold(message)}
2852
- ${color.dim(hash)}${pushMsg}`
2853
- };
2854
- }
2855
- };
2856
- }
2857
- function buildGitcheckCommand(_opts) {
2858
- return {
2859
- name: "gitcheck",
2860
- description: "Check for uncommitted changes (for system prompt integration).",
2861
- aliases: ["gcstatus"],
2862
- async run(_args, ctx) {
2863
- const cwd = ctx?.cwd ?? process.cwd();
2864
- if (!await isGitRepo(cwd)) {
2865
- return { message: "" };
2866
- }
2867
- if (!await hasUncommittedChanges(cwd)) {
2868
- return { message: "" };
2869
- }
2870
- const statusResult = await runGit(["status", "--porcelain"], cwd);
2871
- const lines = statusResult.stdout.split("\n").filter(Boolean);
2872
- const count = lines.length;
2873
- if (count === 0) return { message: "" };
2874
- return {
2875
- message: `\u26A0 ${color.yellow(`${count} uncommitted change${count > 1 ? "s" : ""}`)} \u2014 consider /commit`
2876
- };
2877
- }
2878
- };
2879
- }
2880
- function buildPushCommand(_opts) {
2881
- return {
2882
- name: "push",
2883
- description: "Push to remote after commit.",
2884
- async run(args, ctx) {
2885
- const cwd = ctx?.cwd ?? process.cwd();
2886
- if (!await isGitRepo(cwd)) {
2887
- return { message: "Not a git repository." };
2888
- }
2889
- const dryRun = args.includes("--dry-run") || args.includes("-n");
2890
- const force = args.includes("--force") || args.includes("-f");
2891
- const remoteResult = await runGit(["remote"], cwd);
2892
- const remotes = remoteResult.stdout.split("\n").filter(Boolean);
2893
- if (remotes.length === 0) {
2894
- return { message: "No remote configured. Add one with: git remote add origin <url>" };
2895
- }
2896
- if (dryRun) {
2897
- return {
2898
- message: `Would push to ${remotes.join(", ")}${force ? " (force)" : ""}
2899
- ${color.dim("(dry-run)")}`
2900
- };
2901
- }
2902
- const branchResult = await runGit(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
2903
- const branch = branchResult.stdout.trim() || "main";
2904
- const pushArgs = ["push"];
2905
- if (force) pushArgs.push("--force");
2906
- pushArgs.push(...remotes, branch);
2907
- const pushResult = await runGit(pushArgs, cwd);
2908
- if (pushResult.code !== 0) {
2909
- return { message: `Push failed: ${pushResult.stderr}` };
2910
- }
2911
- return {
2912
- message: `${color.green("\u2713")} Pushed to ${remotes.join(", ")} (${branch})`
2913
- };
2914
- }
2915
- };
2916
- }
2917
2713
 
2918
2714
  // src/slash-commands/compact.ts
2919
2715
  function buildCompactCommand(opts) {
@@ -3355,25 +3151,6 @@ function buildFleetCommand(opts) {
3355
3151
  }
3356
3152
  };
3357
3153
  }
3358
- function buildHealthCommand(opts) {
3359
- return {
3360
- name: "health",
3361
- description: "Run health checks (requires --metrics flag).",
3362
- async run() {
3363
- if (!opts.healthRegistry)
3364
- return { message: "Health checks not enabled. Restart with --metrics." };
3365
- const result = await opts.healthRegistry.run();
3366
- const lines = [
3367
- `${statusIcon(result.status)} overall: ${result.status}`,
3368
- ...result.checks.map((c) => {
3369
- const detail = c.detail ? color.dim(` \u2014 ${c.detail}`) : "";
3370
- return ` ${statusIcon(c.status)} ${c.name}: ${c.status}${detail}`;
3371
- })
3372
- ];
3373
- return { message: lines.join("\n") };
3374
- }
3375
- };
3376
- }
3377
3154
 
3378
3155
  // src/slash-commands/help.ts
3379
3156
  function buildHelpCommand(opts) {
@@ -3441,8 +3218,8 @@ function buildInitCommand(opts) {
3441
3218
  name: "init",
3442
3219
  description: "Create or update .wrongstack/AGENTS.md project context for the system prompt.",
3443
3220
  async run(_args, ctx) {
3444
- const dir = path25.join(ctx.projectRoot, ".wrongstack");
3445
- const file = path25.join(dir, "AGENTS.md");
3221
+ const dir = path24.join(ctx.projectRoot, ".wrongstack");
3222
+ const file = path24.join(dir, "AGENTS.md");
3446
3223
  const detected = await detectProjectFacts(ctx.projectRoot);
3447
3224
  const body = renderAgentsTemplate(detected);
3448
3225
  await fsp3.mkdir(dir, { recursive: true });
@@ -3633,18 +3410,18 @@ function stateBadge(state) {
3633
3410
  return color.dim(state);
3634
3411
  }
3635
3412
  }
3636
- async function readConfig(path26) {
3413
+ async function readConfig(path25) {
3637
3414
  try {
3638
- return JSON.parse(await fsp3.readFile(path26, "utf8"));
3415
+ return JSON.parse(await fsp3.readFile(path25, "utf8"));
3639
3416
  } catch {
3640
3417
  return {};
3641
3418
  }
3642
3419
  }
3643
- async function writeConfig(path26, cfg) {
3420
+ async function writeConfig(path25, cfg) {
3644
3421
  const raw = JSON.stringify(cfg, null, 2);
3645
- const tmp = path26 + ".tmp";
3422
+ const tmp = path25 + ".tmp";
3646
3423
  await fsp3.writeFile(tmp, raw, "utf8");
3647
- await fsp3.rename(tmp, path26);
3424
+ await fsp3.rename(tmp, path25);
3648
3425
  }
3649
3426
 
3650
3427
  // src/slash-commands/mcp.ts
@@ -3726,150 +3503,6 @@ function buildMemoryCommand(opts) {
3726
3503
  }
3727
3504
  };
3728
3505
  }
3729
- function buildMetricsCommand(opts) {
3730
- return {
3731
- name: "metrics",
3732
- description: "Show metrics snapshot (requires --metrics flag).",
3733
- async run() {
3734
- if (!opts.metricsSink)
3735
- return { message: "Metrics not enabled. Restart with --metrics to collect." };
3736
- const snap = opts.metricsSink.snapshot();
3737
- if (snap.series.length === 0) return { message: "No metrics recorded yet." };
3738
- const lines = [];
3739
- const byName = /* @__PURE__ */ new Map();
3740
- for (const s of snap.series) {
3741
- const bucket = byName.get(s.name) ?? [];
3742
- bucket.push(s);
3743
- byName.set(s.name, bucket);
3744
- }
3745
- for (const [name, series] of [...byName.entries()].sort()) {
3746
- lines.push(color.dim(`# ${name}`));
3747
- for (const s of series) {
3748
- const labels = Object.entries(s.labels).map(([k, v]) => `${k}=${v}`).join(" ");
3749
- const labelStr = labels ? color.dim(` {${labels}}`) : "";
3750
- if (s.type === "histogram")
3751
- lines.push(
3752
- ` count=${s.values.count} sum=${s.values.sum} min=${s.values.min} max=${s.values.max} p50=${s.values.p50} p95=${s.values.p95} p99=${s.values.p99}${labelStr}`
3753
- );
3754
- else lines.push(` ${s.values.value}${labelStr}`);
3755
- }
3756
- }
3757
- return { message: lines.join("\n") };
3758
- }
3759
- };
3760
- }
3761
- function buildPlanCommand(opts) {
3762
- return {
3763
- name: "plan",
3764
- description: "Strategic plan board: /plan [show|add <title>|start <id|#>|done <id|#>|remove <id|#>|promote <id|#> [subtask ...]|derive <id|#>|template [list|use <name>]|clear]",
3765
- async run(args) {
3766
- const planPath = opts.paths?.projectPlan ?? opts.planPath;
3767
- if (!planPath) return { message: "Plan storage is not configured for this session." };
3768
- const ctx = opts.context;
3769
- const sessionId = ctx?.session.id ?? "unknown";
3770
- const [verb, ...rest] = args.trim().split(/\s+/);
3771
- const restJoined = rest.join(" ").trim();
3772
- const plan = await loadPlan(planPath) ?? emptyPlan(sessionId);
3773
- switch (verb) {
3774
- case "":
3775
- case "show":
3776
- case "list": {
3777
- return { message: formatPlan(plan) };
3778
- }
3779
- case "add": {
3780
- if (!restJoined) return { message: "Usage: /plan add <title>" };
3781
- const { plan: updated, item } = addPlanItem(plan, restJoined);
3782
- await savePlan(planPath, updated);
3783
- return { message: `Added: ${item.title}
3784
- ${formatPlan(updated)}` };
3785
- }
3786
- case "start":
3787
- case "progress": {
3788
- if (!restJoined) return { message: "Usage: /plan start <id|index>" };
3789
- const updated = setPlanItemStatus(plan, restJoined, "in_progress");
3790
- await savePlan(planPath, updated);
3791
- return { message: formatPlan(updated) };
3792
- }
3793
- case "done":
3794
- case "complete": {
3795
- if (!restJoined) return { message: "Usage: /plan done <id|index>" };
3796
- const updated = setPlanItemStatus(plan, restJoined, "done");
3797
- await savePlan(planPath, updated);
3798
- return { message: formatPlan(updated) };
3799
- }
3800
- case "remove":
3801
- case "delete":
3802
- case "rm": {
3803
- if (!restJoined) return { message: "Usage: /plan remove <id|index>" };
3804
- const updated = removePlanItem(plan, restJoined);
3805
- await savePlan(planPath, updated);
3806
- return { message: formatPlan(updated) };
3807
- }
3808
- case "promote": {
3809
- if (!restJoined) return { message: "Usage: /plan promote <id|index> [subtask ...]" };
3810
- const [target, ...subtasks] = restJoined.split(/\s+/);
3811
- if (!target) return { message: "Usage: /plan promote <id|index> [subtask ...]" };
3812
- const derived = deriveTodosFromPlanItem(plan, target, subtasks.length > 0 ? subtasks : void 0);
3813
- if (!derived) return { message: `No plan item matched "${target}".` };
3814
- await savePlan(planPath, derived.plan);
3815
- if (ctx) {
3816
- ctx.state.replaceTodos(derived.todos);
3817
- }
3818
- return {
3819
- message: `Promoted to ${derived.todos.length} todo(s):
3820
- ${formatTodosList(derived.todos)}
3821
-
3822
- ${formatPlan(derived.plan)}`
3823
- };
3824
- }
3825
- case "derive": {
3826
- if (!restJoined) return { message: "Usage: /plan derive <id|index>" };
3827
- const derived = deriveTodosFromPlanItem(plan, restJoined);
3828
- if (!derived) return { message: `No plan item matched "${restJoined}".` };
3829
- await savePlan(planPath, derived.plan);
3830
- if (ctx) {
3831
- ctx.state.replaceTodos(derived.todos);
3832
- }
3833
- return {
3834
- message: `Derived ${derived.todos.length} todo(s):
3835
- ${formatTodosList(derived.todos)}
3836
-
3837
- ${formatPlan(derived.plan)}`
3838
- };
3839
- }
3840
- case "template": {
3841
- const subVerb = rest[0] ?? "";
3842
- const subRest = rest.slice(1).join(" ").trim();
3843
- if (subVerb === "" || subVerb === "list") {
3844
- return { message: formatPlanTemplates() };
3845
- }
3846
- if (subVerb === "use") {
3847
- if (!subRest) return { message: "Usage: /plan template use <template-name>" };
3848
- const template = getPlanTemplate(subRest);
3849
- if (!template) return { message: `Unknown template "${subRest}". Use /plan template list to see available templates.` };
3850
- let updated = plan;
3851
- for (const item of template.items) {
3852
- ({ plan: updated } = addPlanItem(updated, item.title, item.details));
3853
- }
3854
- await savePlan(planPath, updated);
3855
- return { message: `Applied template "${template.name}" (${template.items.length} items):
3856
- ${formatPlan(updated)}` };
3857
- }
3858
- return { message: `Unknown template subcommand "${subVerb}". Try: list | use <name>` };
3859
- }
3860
- case "clear": {
3861
- const updated = clearPlan(plan);
3862
- await savePlan(planPath, updated);
3863
- return { message: "Plan cleared." };
3864
- }
3865
- default:
3866
- return {
3867
- message: `Unknown subcommand "${verb}". Try: show | add <title> | start <id|#> | done <id|#> | remove <id|#> | promote <id|#> | derive <id|#> | template [list|use <name>] | clear`
3868
- };
3869
- }
3870
- }
3871
- };
3872
- }
3873
3506
 
3874
3507
  // src/slash-commands/plugin.ts
3875
3508
  function buildPluginCommand(opts) {
@@ -3956,30 +3589,6 @@ function buildExitCommand(opts) {
3956
3589
  }
3957
3590
  };
3958
3591
  }
3959
- function buildSkillCommand(opts) {
3960
- return {
3961
- name: "skill",
3962
- description: "Show skill details or list available skills. Use /skill-gen to create new skills.",
3963
- async run(args) {
3964
- if (!opts.skillLoader) return { message: "No skill loader configured." };
3965
- if (!args.trim()) {
3966
- const entries = await opts.skillLoader.listEntries();
3967
- if (entries.length === 0) return { message: "No skills found." };
3968
- const lines = entries.map((e) => {
3969
- const scopeTag = e.scope.length > 0 ? ` ${color.dim(`(${e.scope.slice(0, 3).join(", ")})`)}` : "";
3970
- return ` ${color.bold(e.name)}${scopeTag}
3971
- Use when: ${e.trigger}`;
3972
- });
3973
- return { message: `Available skills:
3974
- ${lines.join("\n\n")}
3975
- ` };
3976
- }
3977
- const skill = await opts.skillLoader.find(args.trim());
3978
- if (!skill) return { message: `Skill "${args.trim()}" not found.` };
3979
- return { message: await opts.skillLoader.readBody(skill.name) };
3980
- }
3981
- };
3982
- }
3983
3592
 
3984
3593
  // src/slash-commands/spawn-agents.ts
3985
3594
  function buildSpawnCommand(opts) {
@@ -4439,6 +4048,7 @@ function buildGoalCommand(opts) {
4439
4048
  const [verbRaw, ...rest] = trimmed.split(/\s+/);
4440
4049
  const verb = (verbRaw ?? "").toLowerCase();
4441
4050
  const restJoined = rest.join(" ").trim();
4051
+ if (!opts.paths) return { message: "Goal not available \u2014 paths not configured." };
4442
4052
  const goalPath = opts.paths.projectGoal;
4443
4053
  const verbForDispatch = verb && !KNOWN_VERBS.has(verb) ? "set" : verb;
4444
4054
  const setText = verbForDispatch === "set" && !KNOWN_VERBS.has(verb) ? trimmed : restJoined;
@@ -4616,290 +4226,6 @@ ${targetMode.description}`
4616
4226
 
4617
4227
  // src/slash-commands/index.ts
4618
4228
  init_sdd();
4619
-
4620
- // src/slash-commands/skill-generator.ts
4621
- function buildSkillGeneratorCommand(opts) {
4622
- return {
4623
- name: "skill-gen",
4624
- description: "Create a new AI skill interactively. The AI will guide you.",
4625
- help: [
4626
- "\u2554\u2550\u2550\u2550 Skill Generator \u2550\u2550\u2550\u2557",
4627
- "",
4628
- "Create new AI skills with AI guidance.",
4629
- "",
4630
- "Usage:",
4631
- " /skill-gen Start skill creation",
4632
- " /skill-gen list List existing skills",
4633
- " /skill-gen edit <name> View an existing skill",
4634
- "",
4635
- "The AI will ask you questions and create the skill file.",
4636
- "Skills are saved to .wrongstack/skills/<name>/SKILL.md"
4637
- ].join("\n"),
4638
- async run(args) {
4639
- const trimmed = args.trim();
4640
- if (trimmed === "list" || trimmed === "ls") {
4641
- if (!opts.skillLoader) return { message: "No skill loader configured." };
4642
- const entries = await opts.skillLoader.listEntries();
4643
- if (entries.length === 0) return { message: "No skills found." };
4644
- const lines = entries.map((e) => {
4645
- const src = e.source === "project" ? "\u{1F4C1}" : e.source === "user" ? "\u{1F464}" : "\u{1F4E6}";
4646
- return ` ${src} ${e.name}
4647
- ${e.trigger}`;
4648
- });
4649
- return { message: `Available Skills:
4650
- ${lines.join("\n\n")}
4651
- ` };
4652
- }
4653
- if (trimmed.startsWith("edit ")) {
4654
- const skillName = trimmed.slice(5).trim();
4655
- if (!opts.skillLoader) return { message: "No skill loader configured." };
4656
- const skill = await opts.skillLoader.find(skillName);
4657
- if (!skill) return { message: `Skill "${skillName}" not found.` };
4658
- const body = await opts.skillLoader.readBody(skillName);
4659
- return {
4660
- message: [
4661
- `Skill: ${skillName}`,
4662
- `Path: ${skill.path}`,
4663
- "",
4664
- body
4665
- ].join("\n")
4666
- };
4667
- }
4668
- return {
4669
- message: "\u2554\u2550\u2550\u2550 Skill Generator \u2550\u2550\u2550\u2557\n\nThe AI will guide you through creating a new skill.\nAnswer its questions naturally.",
4670
- runText: "I want to create a new AI skill. Read the skill-creator skill and guide me through the process. Ask me questions one at a time \u2014 name, description, what to cover \u2014 then create the SKILL.md file."
4671
- };
4672
- }
4673
- };
4674
- }
4675
- function getProviderFromContext(ctx, opts) {
4676
- if (opts.llmProvider && typeof opts.llmProvider.complete === "function") {
4677
- return { provider: opts.llmProvider, model: opts.llmModel };
4678
- }
4679
- if (ctx.provider && typeof ctx.provider.complete === "function") {
4680
- return { provider: ctx.provider, model: ctx.model };
4681
- }
4682
- return null;
4683
- }
4684
- function buildSecurityCommand(opts) {
4685
- return {
4686
- name: "security",
4687
- description: "Security scanning: scan, audit, report",
4688
- argsHint: "[scan|audit|report] [options]",
4689
- help: `
4690
- # /security \u2014 Security Scanner
4691
-
4692
- Automated security scanning with tech stack detection.
4693
-
4694
- ## Commands
4695
-
4696
- ### /security scan [options]
4697
- Run a full security scan on the current project.
4698
- Options:
4699
- --depth quick|standard|deep Scan depth (default: standard)
4700
- --format markdown|json|html Report format (default: markdown)
4701
-
4702
- ### /security audit
4703
- Run dependency audit + security scan.
4704
-
4705
- ### /security report [id]
4706
- List or view security reports.
4707
-
4708
- ## Examples
4709
-
4710
- /security scan
4711
- /security scan --depth deep --format html
4712
- /security audit
4713
- /security report
4714
- `,
4715
- async run(args, ctx) {
4716
- const parts = args.trim().split(/\s+/);
4717
- const subcommand = parts[0] || "";
4718
- switch (subcommand) {
4719
- case "scan":
4720
- return handleScan(parts.slice(1).join(" "), ctx, opts);
4721
- case "audit":
4722
- return handleAudit(ctx, opts);
4723
- case "report":
4724
- return handleReport(parts[1] || "");
4725
- default:
4726
- return { message: getHelpMessage() };
4727
- }
4728
- }
4729
- };
4730
- }
4731
- async function handleScan(args, ctx, opts) {
4732
- const options = parseArgs2(args);
4733
- const projectRoot = ctx.projectRoot || opts.projectRoot;
4734
- try {
4735
- const providerInfo = getProviderFromContext(ctx, opts);
4736
- if (!providerInfo) {
4737
- return { message: "\u274C Security scan requires an active LLM provider. No provider configured." };
4738
- }
4739
- const result = await defaultOrchestrator.run(providerInfo, {
4740
- projectRoot,
4741
- scanOptions: {
4742
- depth: options.depth || "standard",
4743
- includeSecrets: true,
4744
- includeInjection: true,
4745
- includeConfig: true
4746
- },
4747
- reportOptions: {
4748
- format: options.format || "markdown"
4749
- }
4750
- });
4751
- const summary = result.scanResult.summary;
4752
- const status = summary.total === 0 ? "\u2705 No issues found" : `\u26A0\uFE0F Found ${summary.total} issues`;
4753
- const reportContent = result.synthesizedReport || `# Security Scan Complete
4754
-
4755
- **Project:** ${projectRoot}
4756
- **Tech Stack:** ${result.detectionResult.detectedStacks[0]?.stack || "unknown"}
4757
- **Scanned Files:** ${result.scanResult.scannedFiles}
4758
- **Duration:** ${result.scanResult.scanDurationMs}ms
4759
-
4760
- ## Summary
4761
-
4762
- | Severity | Count |
4763
- |----------|-------|
4764
- | \u{1F534} Critical | ${summary.critical} |
4765
- | \u{1F7E0} High | ${summary.high} |
4766
- | \u{1F7E1} Medium | ${summary.medium} |
4767
- | \u{1F7E2} Low | ${summary.low} |
4768
-
4769
- **Status:** ${status}
4770
-
4771
- **Report:** ${result.reportPath}
4772
- `;
4773
- return {
4774
- message: reportContent,
4775
- metadata: {
4776
- scanResult: result.scanResult,
4777
- reportPath: result.reportPath,
4778
- techStack: result.detectionResult.detectedStacks[0]
4779
- }
4780
- };
4781
- } catch (error) {
4782
- return { message: `\u274C Scan failed: ${error}` };
4783
- }
4784
- }
4785
- async function handleAudit(ctx, opts) {
4786
- const projectRoot = ctx.projectRoot || opts.projectRoot;
4787
- try {
4788
- const providerInfo = getProviderFromContext(ctx, opts);
4789
- if (!providerInfo) {
4790
- return { message: "\u274C Security audit requires an active LLM provider. No provider configured." };
4791
- }
4792
- const result = await defaultOrchestrator.run(providerInfo, {
4793
- projectRoot,
4794
- reportOptions: { format: "markdown" }
4795
- });
4796
- const summary = result.scanResult.summary;
4797
- const depIssues = summary.critical + summary.high;
4798
- const reportContent = result.synthesizedReport || `# Security Audit Complete
4799
-
4800
- **Project:** ${projectRoot}
4801
- **Tech Stack:** ${result.detectionResult.detectedStacks[0]?.stack || "unknown"}
4802
-
4803
- ## Dependency Health
4804
-
4805
- | Status | Count |
4806
- |--------|-------|
4807
- | Critical Issues | ${summary.critical} |
4808
- | High Priority | ${summary.high} |
4809
- | Medium Priority | ${summary.medium} |
4810
- | Low Priority | ${summary.low} |
4811
-
4812
- ${depIssues === 0 ? "\u2705 No known vulnerabilities detected" : `\u26A0\uFE0F ${depIssues} vulnerabilities need attention`}
4813
-
4814
- **Full Report:** ${result.reportPath}
4815
- `;
4816
- return {
4817
- message: reportContent,
4818
- metadata: {
4819
- scanResult: result.scanResult,
4820
- reportPath: result.reportPath
4821
- }
4822
- };
4823
- } catch (error) {
4824
- return { message: `\u274C Audit failed: ${error}` };
4825
- }
4826
- }
4827
- async function handleReport(reportId) {
4828
- const reportsDir = "security-reports";
4829
- try {
4830
- const files = await readdir(reportsDir);
4831
- const reports = files.filter((f) => f.startsWith("security-report-") && (f.endsWith(".md") || f.endsWith(".json"))).sort().reverse();
4832
- if (!reportId) {
4833
- if (reports.length === 0) {
4834
- return { message: "\u{1F4ED} No security reports found. Run `/security scan` first." };
4835
- }
4836
- const list = reports.map((r, i) => {
4837
- const date = r.replace("security-report-", "").replace(/\.(md|json)$/, "");
4838
- return ` ${i + 1}. ${date}`;
4839
- }).join("\n");
4840
- return { message: `# Available Security Reports
4841
-
4842
- ${list}
4843
-
4844
- Use \`/security report <number>\` to view a specific report.` };
4845
- }
4846
- const index = Number.parseInt(reportId, 10) - 1;
4847
- if (!Number.isNaN(index) && reports[index]) {
4848
- const content = await readFile(join(reportsDir, reports[index]), "utf-8");
4849
- return { message: `# Security Report
4850
-
4851
- ${content}` };
4852
- }
4853
- const match = reports.find((r) => r.includes(reportId));
4854
- if (match) {
4855
- const content = await readFile(join(reportsDir, match), "utf-8");
4856
- return { message: `# Security Report
4857
-
4858
- ${content}` };
4859
- }
4860
- return { message: `\u274C Report "${reportId}" not found. Use \`/security report\` to see available reports.` };
4861
- } catch {
4862
- return { message: "\u{1F4ED} No security reports found. Run `/security scan` first." };
4863
- }
4864
- }
4865
- function parseArgs2(args) {
4866
- const result = {};
4867
- const parts = args.split(/\s+/);
4868
- for (let i = 0; i < parts.length; i++) {
4869
- const part = parts[i];
4870
- if (!part || !part.startsWith("--")) continue;
4871
- const key = part.slice(2);
4872
- const next = parts[i + 1];
4873
- if (next && !next.startsWith("--")) {
4874
- result[key] = next;
4875
- i++;
4876
- } else {
4877
- result[key] = "true";
4878
- }
4879
- }
4880
- return result;
4881
- }
4882
- function getHelpMessage() {
4883
- return `# /security \u2014 Security Scanner
4884
-
4885
- **Available Commands:**
4886
-
4887
- 1. **/security scan** \u2014 Run full security scan
4888
- \`/security scan --depth deep --format html\`
4889
-
4890
- 2. **/security audit** \u2014 Run dependency audit + security scan
4891
-
4892
- 3. **/security report** \u2014 List available reports
4893
-
4894
- **Features:**
4895
- - Automatic tech stack detection
4896
- - Dynamic security skill generation
4897
- - Secrets, injection, and config vulnerability scanning
4898
- - Markdown/JSON/HTML reports
4899
- - .gitignore auto-update
4900
-
4901
- Run \`/security scan\` to start.`;
4902
- }
4903
4229
  var CONFIG_ENV = "WRONGSTACK_STATUSLINE_CONFIG";
4904
4230
  var DEFAULTS = {
4905
4231
  todos: true,
@@ -4911,7 +4237,7 @@ var DEFAULTS = {
4911
4237
  cost: true
4912
4238
  };
4913
4239
  function resolveConfigPath() {
4914
- return process.env[CONFIG_ENV] ?? path25.join(process.env.HOME ?? "", ".wrongstack", "statusline.json");
4240
+ return process.env[CONFIG_ENV] ?? path24.join(process.env.HOME ?? "", ".wrongstack", "statusline.json");
4915
4241
  }
4916
4242
  async function loadStatuslineConfig() {
4917
4243
  const p = resolveConfigPath();
@@ -4925,7 +4251,7 @@ async function loadStatuslineConfig() {
4925
4251
  async function saveStatuslineConfig(cfg) {
4926
4252
  const p = resolveConfigPath();
4927
4253
  try {
4928
- await fsp3.mkdir(path25.dirname(p), { recursive: true });
4254
+ await fsp3.mkdir(path24.dirname(p), { recursive: true });
4929
4255
  await atomicWrite(p, JSON.stringify(cfg, null, 2));
4930
4256
  } catch (err) {
4931
4257
  throw new FsError({
@@ -5823,168 +5149,8 @@ When the error confidence is low (< 0.85) or the problem spans multiple files,
5823
5149
  }
5824
5150
  };
5825
5151
  }
5826
- function makeInstaller(opts, projectRoot, global) {
5827
- const globalRoot = path25.join(os4.homedir(), ".wrongstack");
5828
- return new SkillInstaller({
5829
- manifestPath: path25.join(globalRoot, "installed-skills.json"),
5830
- projectSkillsDir: path25.join(projectRoot, ".wrongstack", "skills"),
5831
- globalSkillsDir: path25.join(globalRoot, "skills"),
5832
- projectHash: projectHash(projectRoot),
5833
- skillLoader: opts.skillLoader
5834
- });
5835
- }
5836
- function buildSkillInstallCommand(opts) {
5837
- return {
5838
- name: "skill-install",
5839
- description: "Install skills from a GitHub repository.",
5840
- argsHint: "<user/repo[@ref]> [--global]",
5841
- help: [
5842
- "\u2554\u2550\u2550\u2550 Skill Install \u2550\u2550\u2550\u2557",
5843
- "",
5844
- "Install skills from a GitHub repository.",
5845
- "",
5846
- "Usage:",
5847
- " /skill-install <user/repo> Install from default branch (main)",
5848
- " /skill-install <user/repo@ref> Install specific tag/branch/commit",
5849
- " /skill-install <user/repo> --global Install to user-global skills",
5850
- "",
5851
- "Supports both single-skill repos (SKILL.md at root)",
5852
- "and multi-skill repos (skills/ subdirectory).",
5853
- "",
5854
- "Examples:",
5855
- " /skill-install wrongstack/awesome-skills",
5856
- " /skill-install wrongstack/skills@v1.0",
5857
- " /skill-install user/my-skills --global"
5858
- ].join("\n"),
5859
- async run(args, ctx) {
5860
- const parts = args.trim().split(/\s+/);
5861
- const ref = parts.find((p) => !p.startsWith("--"));
5862
- const isGlobal = parts.includes("--global");
5863
- if (!ref) {
5864
- return { message: "Usage: /skill-install <user/repo[@ref]> [--global]" };
5865
- }
5866
- const installer = makeInstaller(opts, ctx.projectRoot);
5867
- try {
5868
- const results = await installer.install(ref, { global: isGlobal });
5869
- if (results.length === 0) {
5870
- return { message: "No skills found in the repository." };
5871
- }
5872
- const scope = isGlobal ? "user-global" : "project";
5873
- const lines = [`Installed ${results.length} skill(s) [${scope}]:`];
5874
- for (const r of results) {
5875
- lines.push(` \u2713 ${r.name} (${r.source}@${r.ref})`);
5876
- lines.push(` \u2192 ${r.path}`);
5877
- }
5878
- return { message: lines.join("\n") };
5879
- } catch (err) {
5880
- const msg = err instanceof Error ? err.message : String(err);
5881
- opts.renderer.writeError(`Install failed: ${msg}`);
5882
- return { message: `\u2717 Install failed: ${msg}` };
5883
- }
5884
- }
5885
- };
5886
- }
5887
- function buildSkillUpdateCommand(opts) {
5888
- return {
5889
- name: "skill-update",
5890
- description: "Update installed skills from their GitHub source.",
5891
- argsHint: "[name|ref] [--global]",
5892
- help: [
5893
- "\u2554\u2550\u2550\u2550 Skill Update \u2550\u2550\u2550\u2557",
5894
- "",
5895
- "Update installed skills from their GitHub source.",
5896
- "",
5897
- "Usage:",
5898
- " /skill-update Update all installed skills",
5899
- " /skill-update <name> Update a specific skill",
5900
- " /skill-update <user/repo@ref> Update to a different ref",
5901
- " /skill-update <name> --global Update a global skill"
5902
- ].join("\n"),
5903
- async run(args, ctx) {
5904
- const parts = args.trim().split(/\s+/);
5905
- const nameOrRef = parts.find((p) => !p.startsWith("--"));
5906
- const isGlobal = parts.includes("--global");
5907
- const installer = makeInstaller(opts, ctx.projectRoot);
5908
- try {
5909
- const result = await installer.update(nameOrRef, { global: isGlobal });
5910
- const lines = [];
5911
- if (result.updated.length > 0) {
5912
- lines.push(`Updated ${result.updated.length} skill(s):`);
5913
- for (const u of result.updated) {
5914
- if (u.oldRef !== u.newRef) {
5915
- lines.push(` \u2713 ${u.name} (${u.oldRef} \u2192 ${u.newRef})`);
5916
- } else {
5917
- lines.push(` \u2713 ${u.name} (refreshed)`);
5918
- }
5919
- }
5920
- }
5921
- if (result.unchanged.length > 0) {
5922
- lines.push(`Up to date: ${result.unchanged.join(", ")}`);
5923
- }
5924
- if (result.errors.length > 0) {
5925
- for (const e of result.errors) {
5926
- lines.push(` \u2717 ${e.name}: ${e.error}`);
5927
- }
5928
- }
5929
- if (lines.length === 0) {
5930
- return { message: "No installed skills to update." };
5931
- }
5932
- return { message: lines.join("\n") };
5933
- } catch (err) {
5934
- const msg = err instanceof Error ? err.message : String(err);
5935
- return { message: `\u2717 Update failed: ${msg}` };
5936
- }
5937
- }
5938
- };
5939
- }
5940
- function buildSkillUninstallCommand(opts) {
5941
- return {
5942
- name: "skill-uninstall",
5943
- description: "Remove an installed skill.",
5944
- argsHint: "<name> [--global]",
5945
- help: [
5946
- "\u2554\u2550\u2550\u2550 Skill Uninstall \u2550\u2550\u2550\u2557",
5947
- "",
5948
- "Remove an installed skill and its files.",
5949
- "",
5950
- "Usage:",
5951
- " /skill-uninstall <name> Remove from project skills",
5952
- " /skill-uninstall <name> --global Remove from user-global skills"
5953
- ].join("\n"),
5954
- async run(args, ctx) {
5955
- const parts = args.trim().split(/\s+/);
5956
- const name = parts.find((p) => !p.startsWith("--"));
5957
- const isGlobal = parts.includes("--global");
5958
- if (!name) {
5959
- const installer2 = makeInstaller(opts, ctx.projectRoot);
5960
- const installed = await installer2.listInstalled();
5961
- if (installed.length === 0) {
5962
- return { message: "No installed skills found." };
5963
- }
5964
- const scope = isGlobal ? "user" : "project";
5965
- const filtered = installed.filter((s) => s.scope === scope);
5966
- if (filtered.length === 0) {
5967
- return { message: `No installed skills found (${scope} scope).` };
5968
- }
5969
- const lines = [`Installed skills (${scope}):`];
5970
- for (const s of filtered) {
5971
- lines.push(` ${s.name} ${s.source}@${s.ref} (${s.installedAt.slice(0, 10)})`);
5972
- }
5973
- lines.push("", "Use /skill-uninstall <name> to remove.");
5974
- return { message: lines.join("\n") };
5975
- }
5976
- const installer = makeInstaller(opts, ctx.projectRoot);
5977
- try {
5978
- await installer.uninstall(name, { global: isGlobal });
5979
- return { message: `\u2713 Skill "${name}" uninstalled.` };
5980
- } catch (err) {
5981
- const msg = err instanceof Error ? err.message : String(err);
5982
- return { message: `\u2717 Uninstall failed: ${msg}` };
5983
- }
5984
- }
5985
- };
5986
- }
5987
5152
  function getStore(opts) {
5153
+ if (!opts.paths) throw new Error("PhaseStore not available \u2014 paths not configured.");
5988
5154
  return new PhaseStore({ baseDir: opts.paths.projectAutophase });
5989
5155
  }
5990
5156
  function formatProgress(p) {
@@ -6022,7 +5188,7 @@ function formatPhaseList(graph) {
6022
5188
  }
6023
5189
  async function gatherProjectContext2(projectRoot) {
6024
5190
  try {
6025
- const raw = await fsp3.readFile(path25.join(projectRoot, "package.json"), "utf8");
5191
+ const raw = await fsp3.readFile(path24.join(projectRoot, "package.json"), "utf8");
6026
5192
  const pkg = JSON.parse(raw);
6027
5193
  const parts = [
6028
5194
  `Project: ${String(pkg.name ?? "unknown")}`,
@@ -6185,127 +5351,7 @@ function buildWorktreeCommand(opts) {
6185
5351
  }
6186
5352
  };
6187
5353
  }
6188
- async function runSettingsMenu(deps) {
6189
- for (; ; ) {
6190
- const config = deps.configStore.get();
6191
- renderSettingsTopMenu(deps.renderer, config);
6192
- const choice = (await deps.reader.readLine(`
6193
- ${color.amber("?")} Pick setting to edit: `)).trim().toLowerCase();
6194
- if (!choice || choice === "q" || choice === "quit" || choice === "exit") {
6195
- deps.renderer.write(color.dim("Done.\n"));
6196
- return 0;
6197
- }
6198
- switch (choice) {
6199
- case "1":
6200
- await editAutoProceedDelay(deps);
6201
- break;
6202
- case "2":
6203
- await editDefaultAutonomy(deps);
6204
- break;
6205
- case "d":
6206
- await showDefaults(deps);
6207
- break;
6208
- default:
6209
- deps.renderer.writeError(`Unknown selection: "${choice}". Try 1, 2, or q to quit.`);
6210
- }
6211
- }
6212
- }
6213
- function renderSettingsTopMenu(renderer, config) {
6214
- const delay = config.autonomy?.autoProceedDelayMs ?? 45e3;
6215
- const defMode = config.autonomy?.defaultMode ?? "off";
6216
- renderer.write(`
6217
- ${color.bold("WrongStack")} ${color.dim("\u2014 Settings")}
6218
-
6219
- `);
6220
- renderer.write(` ${color.bold("1.")} auto-proceed delay: ${color.cyan(formatDelay(delay))} (in auto mode, wait before continuing)
6221
- `);
6222
- renderer.write(` ${color.bold("2.")} default autonomy mode: ${color.cyan(defMode)}
6223
- `);
6224
- renderer.write(`
6225
- ${color.dim("Actions:")}
6226
- `);
6227
- renderer.write(` ${color.bold("1")} Edit auto-proceed delay
6228
- `);
6229
- renderer.write(` ${color.bold("2")} Edit default autonomy mode
6230
- `);
6231
- renderer.write(` ${color.bold("d")} Show all defaults
6232
- `);
6233
- renderer.write(` ${color.bold("q")} Quit
6234
- `);
6235
- }
6236
- async function editAutoProceedDelay(deps) {
6237
- deps.renderer.write(`
6238
- ${color.bold("Auto-proceed delay")} ${color.dim("\u2014 wait time before auto-continuing in auto mode")}
6239
- `);
6240
- deps.renderer.write(color.dim(` Current: ${formatDelay(deps.configStore.get().autonomy?.autoProceedDelayMs ?? 45e3)}
6241
- `));
6242
- deps.renderer.write(color.dim(` Enter value in SECONDS (e.g. 30 for 30 seconds, 0 to disable)
6243
- `));
6244
- const raw = (await deps.reader.readLine(` ${color.amber("?")} Delay (seconds): `)).trim();
6245
- if (!raw || raw === "q") return;
6246
- const seconds = Number.parseFloat(raw);
6247
- if (Number.isNaN(seconds) || seconds < 0) {
6248
- deps.renderer.writeError(`Invalid number: "${raw}"`);
6249
- return;
6250
- }
6251
- const ms = Math.round(seconds * 1e3);
6252
- await mutateAutonomyConfig(deps, (autonomy) => {
6253
- autonomy.autoProceedDelayMs = ms;
6254
- });
6255
- deps.renderer.write(` ${color.green("\u2713")} auto-proceed delay \u2192 ${formatDelay(ms)}
6256
- `);
6257
- }
6258
- async function editDefaultAutonomy(deps) {
6259
- deps.renderer.write(`
6260
- ${color.bold("Default Autonomy Mode")}
6261
-
6262
- `);
6263
- deps.renderer.write(` ${color.bold("1.")} off \u2014 agent stops after each turn (normal)
6264
- `);
6265
- deps.renderer.write(` ${color.bold("2.")} suggest \u2014 shows next-step suggestions
6266
- `);
6267
- deps.renderer.write(` ${color.bold("3.")} auto \u2014 self-driving, agent continues automatically
6268
- `);
6269
- deps.renderer.write(` ${color.bold("q")} Quit without changing
6270
- `);
6271
- const raw = (await deps.reader.readLine(` ${color.amber("?")} Default mode: `)).trim().toLowerCase();
6272
- if (!raw || raw === "q") return;
6273
- const modes = ["off", "suggest", "auto"];
6274
- let selected = null;
6275
- if (raw === "1") selected = "off";
6276
- else if (raw === "2") selected = "suggest";
6277
- else if (raw === "3") selected = "auto";
6278
- else if (modes.includes(raw)) selected = raw;
6279
- if (!selected) {
6280
- deps.renderer.writeError(`Invalid mode: "${raw}". Use off, suggest, or auto.`);
6281
- return;
6282
- }
6283
- await mutateAutonomyConfig(deps, (autonomy) => {
6284
- autonomy.defaultMode = selected;
6285
- });
6286
- deps.renderer.write(` ${color.green("\u2713")} default autonomy \u2192 ${color.bold(selected)}
6287
- `);
6288
- }
6289
- async function showDefaults(deps) {
6290
- deps.renderer.write(`
6291
- ${color.bold("Default Values")}
6292
-
6293
- `);
6294
- deps.renderer.write(` auto-proceed delay: ${color.cyan("45s")} (WRONGSTACK_AUTO_PROCEED_DELAY_MS env)
6295
- `);
6296
- deps.renderer.write(` default autonomy mode: ${color.cyan("off")}
6297
- `);
6298
- deps.renderer.write(` iteration timeout: ${color.cyan("5 min")}
6299
- `);
6300
- deps.renderer.write(` session timeout: ${color.cyan("30 min")}
6301
- `);
6302
- deps.renderer.write(` max iterations: ${color.cyan("100")}
6303
- `);
6304
- deps.renderer.write(`
6305
- ${color.dim(" Press Enter to continue...")}`);
6306
- await deps.reader.readLine("");
6307
- }
6308
- async function mutateAutonomyConfig(deps, mutator) {
5354
+ async function persistAutonomySetting(deps, mutator) {
6309
5355
  let raw;
6310
5356
  let fileExists = true;
6311
5357
  try {
@@ -6334,11 +5380,6 @@ async function mutateAutonomyConfig(deps, mutator) {
6334
5380
  await atomicWrite(deps.globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
6335
5381
  deps.configStore.update({ autonomy: decrypted.autonomy });
6336
5382
  }
6337
- function formatDelay(ms) {
6338
- if (ms >= 6e4) return `${Math.round(ms / 6e4)}m`;
6339
- if (ms === 0) return "disabled";
6340
- return `${Math.round(ms / 1e3)}s`;
6341
- }
6342
5383
 
6343
5384
  // src/slash-commands/settings.ts
6344
5385
  var noOpVault = {
@@ -6346,42 +5387,106 @@ var noOpVault = {
6346
5387
  decrypt: (v) => v,
6347
5388
  isEncrypted: () => false
6348
5389
  };
5390
+ function formatDelay(ms) {
5391
+ if (ms >= 6e4) return `${Math.round(ms / 6e4)}m`;
5392
+ if (ms === 0) return "disabled";
5393
+ return `${Math.round(ms / 1e3)}s`;
5394
+ }
6349
5395
  function buildSettingsCommand(opts) {
6350
- return {
6351
- name: "settings",
6352
- description: "Open interactive settings menu (auto-proceed delay, defaults, etc.).",
6353
- help: [
6354
- "Usage:",
6355
- " /settings Open interactive settings menu",
5396
+ const help = [
5397
+ "Usage:",
5398
+ " /settings Show current settings",
5399
+ " /settings delay <seconds> Auto-proceed delay in auto mode (0 disables)",
5400
+ " /settings mode <off|suggest|auto> Default autonomy mode at startup",
5401
+ " /settings defaults Show built-in default values",
5402
+ "",
5403
+ "Settings are persisted to ~/.wrongstack/config.json."
5404
+ ].join("\n");
5405
+ function currentView() {
5406
+ const autonomy = opts.configStore.get().autonomy;
5407
+ const delay = autonomy?.autoProceedDelayMs ?? 45e3;
5408
+ const mode = autonomy?.defaultMode ?? "off";
5409
+ return [
5410
+ `${color.bold("WrongStack")} ${color.dim("\u2014 Settings")}`,
6356
5411
  "",
6357
- "Configurable settings:",
6358
- " auto-proceed delay \u2014 wait time before auto-continuing in auto mode",
6359
- " default autonomy mode \u2014 startup autonomy mode",
5412
+ ` auto-proceed delay: ${color.cyan(formatDelay(delay))} ${color.dim("change: /settings delay <seconds>")}`,
5413
+ ` default autonomy mode: ${color.cyan(mode)} ${color.dim("change: /settings mode off|suggest|auto")}`,
6360
5414
  "",
6361
- "Settings are persisted to ~/.wrongstack/config.json."
6362
- ].join("\n"),
5415
+ color.dim(" Persisted to ~/.wrongstack/config.json \xB7 /settings help for more")
5416
+ ].join("\n");
5417
+ }
5418
+ return {
5419
+ name: "settings",
5420
+ description: "View or change settings (auto-proceed delay, default autonomy mode).",
5421
+ help,
6363
5422
  async run(args) {
6364
- const trimmed = args.trim().toLowerCase();
6365
- if (trimmed === "help" || trimmed === "--help") {
5423
+ const parts = args.trim().split(/\s+/).filter(Boolean);
5424
+ const sub = (parts[0] ?? "").toLowerCase();
5425
+ if (sub === "help" || sub === "--help") {
6366
5426
  return { message: this.help ?? "" };
6367
5427
  }
6368
5428
  if (!opts.configStore || !opts.paths) {
6369
5429
  return { message: `${color.red("Error")} config store not available.` };
6370
5430
  }
6371
- if (!opts.reader || !opts.renderer) {
6372
- return { message: `${color.red("Error")} settings menu requires a terminal (not available in headless mode).` };
5431
+ if (!sub) {
5432
+ return { message: currentView() };
6373
5433
  }
5434
+ if (sub === "defaults") {
5435
+ return {
5436
+ message: [
5437
+ `${color.bold("Default Values")}`,
5438
+ "",
5439
+ ` auto-proceed delay: ${color.cyan("45s")} ${color.dim("(WRONGSTACK_AUTO_PROCEED_DELAY_MS env)")}`,
5440
+ ` default autonomy mode: ${color.cyan("off")}`,
5441
+ ` iteration timeout: ${color.cyan("5 min")}`,
5442
+ ` session timeout: ${color.cyan("30 min")}`,
5443
+ ` max iterations: ${color.cyan("100")}`
5444
+ ].join("\n")
5445
+ };
5446
+ }
5447
+ const persistDeps = {
5448
+ configStore: opts.configStore,
5449
+ globalConfigPath: opts.paths.globalConfig,
5450
+ vault: noOpVault
5451
+ };
6374
5452
  try {
6375
- await runSettingsMenu({
6376
- renderer: opts.renderer,
6377
- reader: opts.reader,
6378
- configStore: opts.configStore,
6379
- globalConfigPath: opts.paths.globalConfig,
6380
- vault: noOpVault
6381
- });
6382
- return { message: `${color.green("Settings saved.")}` };
5453
+ if (sub === "delay") {
5454
+ const raw = parts[1];
5455
+ if (raw === void 0) {
5456
+ return {
5457
+ message: `${color.amber("Usage:")} /settings delay <seconds> ${color.dim("(0 disables)")}`
5458
+ };
5459
+ }
5460
+ const seconds = Number.parseFloat(raw);
5461
+ if (Number.isNaN(seconds) || seconds < 0) {
5462
+ return {
5463
+ message: `${color.red("Invalid number")}: "${raw}". Enter seconds, e.g. /settings delay 30`
5464
+ };
5465
+ }
5466
+ const ms = Math.round(seconds * 1e3);
5467
+ await persistAutonomySetting(persistDeps, (autonomy) => {
5468
+ autonomy.autoProceedDelayMs = ms;
5469
+ });
5470
+ return { message: `${color.green("\u2713")} auto-proceed delay \u2192 ${formatDelay(ms)}` };
5471
+ }
5472
+ if (sub === "mode") {
5473
+ const raw = (parts[1] ?? "").toLowerCase();
5474
+ const modes = ["off", "suggest", "auto"];
5475
+ if (!modes.includes(raw)) {
5476
+ return { message: `${color.amber("Usage:")} /settings mode off|suggest|auto` };
5477
+ }
5478
+ await persistAutonomySetting(persistDeps, (autonomy) => {
5479
+ autonomy.defaultMode = raw;
5480
+ });
5481
+ return { message: `${color.green("\u2713")} default autonomy \u2192 ${color.bold(raw)}` };
5482
+ }
5483
+ return {
5484
+ message: `${color.red("Unknown setting")} "${sub}". Try ${color.dim("/settings")}, ${color.dim("/settings delay <s>")}, or ${color.dim("/settings mode <m>")}.`
5485
+ };
6383
5486
  } catch (err) {
6384
- return { message: `${color.red("Settings error")}: ${err instanceof Error ? err.message : String(err)}` };
5487
+ return {
5488
+ message: `${color.red("Settings error")}: ${err instanceof Error ? err.message : String(err)}`
5489
+ };
6385
5490
  }
6386
5491
  }
6387
5492
  };
@@ -6396,11 +5501,6 @@ function buildBuiltinSlashCommands(opts) {
6396
5501
  buildCompactCommand(opts),
6397
5502
  buildContextCommand(opts),
6398
5503
  buildToolsCommand(opts),
6399
- buildSkillCommand(opts),
6400
- buildSkillGeneratorCommand(opts),
6401
- buildSkillInstallCommand(opts),
6402
- buildSkillUpdateCommand(opts),
6403
- buildSkillUninstallCommand(opts),
6404
5504
  buildPluginCommand(opts),
6405
5505
  buildMcpSlashCommand(opts),
6406
5506
  buildDiagCommand(opts),
@@ -6409,11 +5509,8 @@ function buildBuiltinSlashCommands(opts) {
6409
5509
  buildAgentsCommand(opts),
6410
5510
  buildDirectorCommand(opts),
6411
5511
  buildFleetCommand(opts),
6412
- buildMetricsCommand(opts),
6413
- buildHealthCommand(opts),
6414
5512
  buildMemoryCommand(opts),
6415
5513
  buildTodosCommand(opts),
6416
- buildPlanCommand(opts),
6417
5514
  buildSddCommand(opts),
6418
5515
  buildSaveCommand(opts),
6419
5516
  buildLoadCommand(opts),
@@ -6423,10 +5520,6 @@ function buildBuiltinSlashCommands(opts) {
6423
5520
  buildBtwCommand(opts),
6424
5521
  buildModeCommand(opts),
6425
5522
  buildExitCommand(opts),
6426
- buildCommitCommand(),
6427
- buildGitcheckCommand(),
6428
- buildPushCommand(),
6429
- buildSecurityCommand(opts),
6430
5523
  buildFixCommand(opts),
6431
5524
  buildAutoPhaseCommand(opts),
6432
5525
  buildWorktreeCommand(opts),
@@ -6458,13 +5551,13 @@ var MANIFESTS = [
6458
5551
  ];
6459
5552
  async function detectProjectKind(projectRoot) {
6460
5553
  try {
6461
- await fsp3.access(path25.join(projectRoot, ".wrongstack", "AGENTS.md"));
5554
+ await fsp3.access(path24.join(projectRoot, ".wrongstack", "AGENTS.md"));
6462
5555
  return "initialized";
6463
5556
  } catch {
6464
5557
  }
6465
5558
  for (const m of MANIFESTS) {
6466
5559
  try {
6467
- await fsp3.access(path25.join(projectRoot, m));
5560
+ await fsp3.access(path24.join(projectRoot, m));
6468
5561
  return "project";
6469
5562
  } catch {
6470
5563
  }
@@ -6472,8 +5565,8 @@ async function detectProjectKind(projectRoot) {
6472
5565
  return "empty";
6473
5566
  }
6474
5567
  async function scaffoldAgentsMd(projectRoot) {
6475
- const dir = path25.join(projectRoot, ".wrongstack");
6476
- const file = path25.join(dir, "AGENTS.md");
5568
+ const dir = path24.join(projectRoot, ".wrongstack");
5569
+ const file = path24.join(dir, "AGENTS.md");
6477
5570
  const facts = await detectProjectFacts(projectRoot);
6478
5571
  const body = renderAgentsTemplate(facts);
6479
5572
  await fsp3.mkdir(dir, { recursive: true });
@@ -6486,7 +5579,7 @@ async function runProjectCheck(opts) {
6486
5579
  if (kind === "initialized") {
6487
5580
  renderer.write(
6488
5581
  `
6489
- ${color.green("\u2713")} Project initialized ${color.dim(`(${path25.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
5582
+ ${color.green("\u2713")} Project initialized ${color.dim(`(${path24.join(projectRoot, ".wrongstack", "AGENTS.md")})`)}
6490
5583
  `
6491
5584
  );
6492
5585
  return true;
@@ -6517,7 +5610,7 @@ async function runProjectCheck(opts) {
6517
5610
  }
6518
5611
  return true;
6519
5612
  }
6520
- const gitDir = path25.join(projectRoot, ".git");
5613
+ const gitDir = path24.join(projectRoot, ".git");
6521
5614
  let hasGit = false;
6522
5615
  try {
6523
5616
  await fsp3.access(gitDir);
@@ -6539,9 +5632,9 @@ async function runProjectCheck(opts) {
6539
5632
  }
6540
5633
  if (answer2 === "y" || answer2 === "yes") {
6541
5634
  try {
6542
- const { spawn: spawn4 } = await import('child_process');
5635
+ const { spawn: spawn3 } = await import('child_process');
6543
5636
  await new Promise((resolve4, reject) => {
6544
- const child = spawn4("git", ["init"], { cwd: projectRoot });
5637
+ const child = spawn3("git", ["init"], { cwd: projectRoot });
6545
5638
  child.on("error", reject);
6546
5639
  child.on("close", (code) => code === 0 ? resolve4() : reject(new Error(`git init failed with ${code}`)));
6547
5640
  });
@@ -6642,10 +5735,10 @@ async function runLaunchPrompts(opts) {
6642
5735
  return { mode, yolo, director, autonomy };
6643
5736
  }
6644
5737
  async function bootConfig(flags) {
6645
- const cwd = typeof flags["cwd"] === "string" ? path25.resolve(flags["cwd"]) : process.cwd();
5738
+ const cwd = typeof flags["cwd"] === "string" ? path24.resolve(flags["cwd"]) : process.cwd();
6646
5739
  const pathResolver = new DefaultPathResolver(cwd);
6647
5740
  const projectRoot = pathResolver.projectRoot;
6648
- const userHome = os4.homedir();
5741
+ const userHome = os3.homedir();
6649
5742
  const wpaths = resolveWstackPaths({ projectRoot, userHome });
6650
5743
  await ensureProjectMeta(wpaths, projectRoot);
6651
5744
  const vault = new DefaultSecretVault({ keyFile: wpaths.secretsKey });
@@ -6709,7 +5802,7 @@ var ReadlineInputReader = class {
6709
5802
  history = [];
6710
5803
  pending = false;
6711
5804
  constructor(opts = {}) {
6712
- this.historyFile = opts.historyFile ?? path25.join(os4.homedir(), ".wrongstack", "history");
5805
+ this.historyFile = opts.historyFile ?? path24.join(os3.homedir(), ".wrongstack", "history");
6713
5806
  }
6714
5807
  async loadHistory() {
6715
5808
  try {
@@ -6721,7 +5814,7 @@ var ReadlineInputReader = class {
6721
5814
  }
6722
5815
  async saveHistory() {
6723
5816
  try {
6724
- await fsp3.mkdir(path25.dirname(this.historyFile), { recursive: true });
5817
+ await fsp3.mkdir(path24.dirname(this.historyFile), { recursive: true });
6725
5818
  await fsp3.writeFile(this.historyFile, this.history.slice(-1e3).join("\n"));
6726
5819
  } catch {
6727
5820
  }
@@ -6939,7 +6032,7 @@ async function buildPickableProviders(modelsRegistry, config) {
6939
6032
  }
6940
6033
  return out;
6941
6034
  }
6942
- var defaultUidFn = () => os4__default.userInfo().uid;
6035
+ var defaultUidFn = () => os3__default.userInfo().uid;
6943
6036
  async function getFileUid(filePath) {
6944
6037
  try {
6945
6038
  const stat4 = await fsp3.stat(filePath);
@@ -6949,7 +6042,7 @@ async function getFileUid(filePath) {
6949
6042
  }
6950
6043
  }
6951
6044
  async function checkConfigOwnership(homeFn, uidFn = defaultUidFn) {
6952
- if (os4__default.platform() === "win32") return true;
6045
+ if (os3__default.platform() === "win32") return true;
6953
6046
  const cfg = configPath(homeFn);
6954
6047
  const fileUid = await getFileUid(cfg);
6955
6048
  if (fileUid === void 0) return true;
@@ -6966,20 +6059,20 @@ function assertSafeToDelete(filename, parentDir) {
6966
6059
  if (PROTECTED_BASENAMES.has(filename)) {
6967
6060
  throw new Error(`Refusing to delete protected file: ${filename}`);
6968
6061
  }
6969
- if (filename !== path25.basename(filename)) {
6062
+ if (filename !== path24.basename(filename)) {
6970
6063
  throw new Error(`Refusing to delete path with traversal: ${filename}`);
6971
6064
  }
6972
6065
  if (!filename.startsWith("config.json.") || !filename.endsWith(".bak")) {
6973
6066
  throw new Error(`Refusing to delete unknown file: ${filename}`);
6974
6067
  }
6975
- const resolvedParent = path25.resolve(parentDir);
6068
+ const resolvedParent = path24.resolve(parentDir);
6976
6069
  if (!resolvedParent.endsWith(".wrongstack")) {
6977
6070
  throw new Error(`Unexpected parent directory for bak prune: ${resolvedParent}`);
6978
6071
  }
6979
6072
  }
6980
6073
  async function safeDelete(filePath) {
6981
- const dir = path25.dirname(filePath);
6982
- const filename = path25.basename(filePath);
6074
+ const dir = path24.dirname(filePath);
6075
+ const filename = path24.basename(filePath);
6983
6076
  try {
6984
6077
  assertSafeToDelete(filename, dir);
6985
6078
  await fsp3.unlink(filePath);
@@ -7022,18 +6115,18 @@ function diffSummary(oldCfg, newCfg) {
7022
6115
  }
7023
6116
  return changes.length > 0 ? changes.slice(0, 5).join(", ") : "no changes";
7024
6117
  }
7025
- var defaultHomeDir = () => os4__default.homedir();
6118
+ var defaultHomeDir = () => os3__default.homedir();
7026
6119
  function historyDir(homeFn = defaultHomeDir) {
7027
- return path25.join(homeFn(), ".wrongstack", "config.history", "entries");
6120
+ return path24.join(homeFn(), ".wrongstack", "config.history", "entries");
7028
6121
  }
7029
6122
  function historyIndexPath(homeFn = defaultHomeDir) {
7030
- return path25.join(homeFn(), ".wrongstack", "config.history", "index.json");
6123
+ return path24.join(homeFn(), ".wrongstack", "config.history", "index.json");
7031
6124
  }
7032
6125
  function configPath(homeFn = defaultHomeDir) {
7033
- return path25.join(homeFn(), ".wrongstack", "config.json");
6126
+ return path24.join(homeFn(), ".wrongstack", "config.json");
7034
6127
  }
7035
6128
  function backupLastPath(homeFn = defaultHomeDir) {
7036
- return path25.join(homeFn(), ".wrongstack", "config.json.last");
6129
+ return path24.join(homeFn(), ".wrongstack", "config.json.last");
7037
6130
  }
7038
6131
  function entryId(ts) {
7039
6132
  return ts.replace(/[:.]/g, "-").slice(0, 19);
@@ -7088,17 +6181,17 @@ async function backupCurrent(homeFn = defaultHomeDir) {
7088
6181
  }
7089
6182
  if (content !== void 0) {
7090
6183
  try {
7091
- const bakPath = path25.join(homeFn(), ".wrongstack", `config.json.${ts}.bak`);
6184
+ const bakPath = path24.join(homeFn(), ".wrongstack", `config.json.${ts}.bak`);
7092
6185
  await atomicWrite(bakPath, content);
7093
6186
  } catch {
7094
6187
  }
7095
6188
  }
7096
6189
  try {
7097
- const dir = path25.join(homeFn(), ".wrongstack");
6190
+ const dir = path24.join(homeFn(), ".wrongstack");
7098
6191
  const files = await fsp3.readdir(dir);
7099
6192
  const baks = files.filter((f) => f.startsWith("config.json.") && f.endsWith(".bak")).sort().reverse();
7100
6193
  for (const f of baks.slice(10)) {
7101
- await safeDelete(path25.join(dir, f));
6194
+ await safeDelete(path24.join(dir, f));
7102
6195
  }
7103
6196
  } catch {
7104
6197
  }
@@ -7116,7 +6209,7 @@ async function appendHistory(oldCfg, newCfg, description, homeFn = defaultHomeDi
7116
6209
  };
7117
6210
  try {
7118
6211
  await fsp3.writeFile(
7119
- path25.join(historyDir(homeFn), `${id}.json`),
6212
+ path24.join(historyDir(homeFn), `${id}.json`),
7120
6213
  JSON.stringify(entry, null, 2),
7121
6214
  "utf8"
7122
6215
  );
@@ -7124,7 +6217,7 @@ async function appendHistory(oldCfg, newCfg, description, homeFn = defaultHomeDi
7124
6217
  throw new FsError({
7125
6218
  message: err instanceof Error ? err.message : String(err),
7126
6219
  code: ERROR_CODES.FS_WRITE_FAILED,
7127
- path: path25.join(historyDir(homeFn), `${id}.json`),
6220
+ path: path24.join(historyDir(homeFn), `${id}.json`),
7128
6221
  cause: err
7129
6222
  });
7130
6223
  }
@@ -7139,7 +6232,7 @@ async function listHistory(homeFn = defaultHomeDir) {
7139
6232
  }
7140
6233
  async function getHistoryEntry(id, homeFn = defaultHomeDir) {
7141
6234
  try {
7142
- const raw = await fsp3.readFile(path25.join(historyDir(homeFn), `${id}.json`), "utf8");
6235
+ const raw = await fsp3.readFile(path24.join(historyDir(homeFn), `${id}.json`), "utf8");
7143
6236
  return JSON.parse(raw);
7144
6237
  } catch {
7145
6238
  return null;
@@ -7543,7 +6636,7 @@ function pickGroupIndex(opts) {
7543
6636
  if (Number.isFinite(parsed)) current = wrap(parsed);
7544
6637
  } catch {
7545
6638
  }
7546
- fs10.mkdirSync(path25.dirname(opts.cursorFile), { recursive: true });
6639
+ fs10.mkdirSync(path24.dirname(opts.cursorFile), { recursive: true });
7547
6640
  fs10.writeFileSync(opts.cursorFile, String(wrap(current + 1)));
7548
6641
  return current;
7549
6642
  } catch {
@@ -7879,14 +6972,14 @@ function summarize(value, name) {
7879
6972
  if (typeof v === "object" && v !== null) {
7880
6973
  const o = v;
7881
6974
  if (name === "edit") {
7882
- const path26 = typeof o["path"] === "string" ? o["path"] : "";
6975
+ const path25 = typeof o["path"] === "string" ? o["path"] : "";
7883
6976
  const reps = typeof o["replacements"] === "number" ? o["replacements"] : 0;
7884
- return `${path26} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
6977
+ return `${path25} ${reps} replacement${reps === 1 ? "" : "s"}`.trim();
7885
6978
  }
7886
6979
  if (name === "write") {
7887
- const path26 = typeof o["path"] === "string" ? o["path"] : "";
6980
+ const path25 = typeof o["path"] === "string" ? o["path"] : "";
7888
6981
  const bytes = typeof o["bytes"] === "number" ? o["bytes"] : void 0;
7889
- return bytes !== void 0 ? `${path26} ${bytes}B` : path26;
6982
+ return bytes !== void 0 ? `${path25} ${bytes}B` : path25;
7890
6983
  }
7891
6984
  if (typeof o["count"] === "number") {
7892
6985
  return `${o["count"]} match${o["count"] === 1 ? "" : "es"}`;
@@ -8817,7 +7910,7 @@ var diagCmd = async (_args, deps) => {
8817
7910
  ` modelsCache: ${deps.paths.modelsCache}`,
8818
7911
  ` cacheAge: ${isFinite(age) ? `${Math.round(age / 60)}m` : "never"}`,
8819
7912
  ` node: ${process.version}`,
8820
- ` os: ${os4.platform()} ${os4.release()}`,
7913
+ ` os: ${os3.platform()} ${os3.release()}`,
8821
7914
  ` provider: ${cfg.provider ?? "<unset>"}`,
8822
7915
  ` model: ${cfg.model ?? "<unset>"}`,
8823
7916
  ` tools: ${deps.toolRegistry?.list().length ?? 0}`,
@@ -8896,7 +7989,7 @@ var doctorCmd = async (_args, deps) => {
8896
7989
  }
8897
7990
  try {
8898
7991
  await fsp3.mkdir(deps.paths.projectSessions, { recursive: true });
8899
- const probe = path25.join(deps.paths.projectSessions, `.probe-${Date.now()}`);
7992
+ const probe = path24.join(deps.paths.projectSessions, `.probe-${Date.now()}`);
8900
7993
  await fsp3.writeFile(probe, "");
8901
7994
  await fsp3.unlink(probe);
8902
7995
  checks.push({ name: "sessions writable", status: "ok", detail: deps.paths.projectSessions });
@@ -8999,8 +8092,8 @@ var exportCmd = async (args, deps) => {
8999
8092
  return 1;
9000
8093
  }
9001
8094
  if (output) {
9002
- await fsp3.mkdir(path25.dirname(path25.resolve(deps.cwd, output)), { recursive: true });
9003
- await fsp3.writeFile(path25.resolve(deps.cwd, output), rendered, "utf8");
8095
+ await fsp3.mkdir(path24.dirname(path24.resolve(deps.cwd, output)), { recursive: true });
8096
+ await fsp3.writeFile(path24.resolve(deps.cwd, output), rendered, "utf8");
9004
8097
  deps.renderer.write(`Wrote ${rendered.length} bytes to ${output}
9005
8098
  `);
9006
8099
  } else {
@@ -9073,8 +8166,8 @@ var initCmd = async (_args, deps) => {
9073
8166
  const vault = new DefaultSecretVault$1({ keyFile: deps.paths.secretsKey });
9074
8167
  const encrypted = encryptConfigSecrets(config, vault);
9075
8168
  await atomicWrite(deps.paths.globalConfig, JSON.stringify(encrypted, null, 2), { mode: 384 });
9076
- await fsp3.mkdir(path25.join(deps.projectRoot, ".wrongstack"), { recursive: true });
9077
- const agentsFile = path25.join(deps.projectRoot, ".wrongstack", "AGENTS.md");
8169
+ await fsp3.mkdir(path24.join(deps.projectRoot, ".wrongstack"), { recursive: true });
8170
+ const agentsFile = path24.join(deps.projectRoot, ".wrongstack", "AGENTS.md");
9078
8171
  const projectFacts = await detectProjectFacts(deps.projectRoot);
9079
8172
  await atomicWrite(agentsFile, renderAgentsTemplate(projectFacts));
9080
8173
  deps.renderer.writeInfo(`Wrote ${deps.paths.globalConfig}`);
@@ -9380,7 +8473,7 @@ var usageCmd = async (_args, deps) => {
9380
8473
  return 0;
9381
8474
  };
9382
8475
  var projectsCmd = async (_args, deps) => {
9383
- const projectsRoot = path25.join(deps.paths.globalRoot, "projects");
8476
+ const projectsRoot = path24.join(deps.paths.globalRoot, "projects");
9384
8477
  try {
9385
8478
  const entries = await fsp3.readdir(projectsRoot);
9386
8479
  if (entries.length === 0) {
@@ -9390,7 +8483,7 @@ var projectsCmd = async (_args, deps) => {
9390
8483
  for (const hash of entries) {
9391
8484
  try {
9392
8485
  const meta = JSON.parse(
9393
- await fsp3.readFile(path25.join(projectsRoot, hash, "meta.json"), "utf8")
8486
+ await fsp3.readFile(path24.join(projectsRoot, hash, "meta.json"), "utf8")
9394
8487
  );
9395
8488
  deps.renderer.write(
9396
8489
  ` ${color.dim(hash)} ${color.dim(meta.lastSeen ?? "")} ${meta.root ?? "?"}
@@ -9549,7 +8642,7 @@ async function listFleetRuns(deps) {
9549
8642
  }
9550
8643
  const runs = [];
9551
8644
  for (const id of entries) {
9552
- const runDir = path25.join(deps.paths.projectSessions, id);
8645
+ const runDir = path24.join(deps.paths.projectSessions, id);
9553
8646
  let stat4;
9554
8647
  try {
9555
8648
  stat4 = await fsp3.stat(runDir);
@@ -9562,17 +8655,17 @@ async function listFleetRuns(deps) {
9562
8655
  let subagentCount = 0;
9563
8656
  let subagentsDir;
9564
8657
  try {
9565
- await fsp3.access(path25.join(runDir, "fleet.json"));
8658
+ await fsp3.access(path24.join(runDir, "fleet.json"));
9566
8659
  manifest = true;
9567
8660
  } catch {
9568
8661
  }
9569
8662
  try {
9570
- await fsp3.access(path25.join(runDir, "checkpoint.json"));
8663
+ await fsp3.access(path24.join(runDir, "checkpoint.json"));
9571
8664
  checkpoint = true;
9572
8665
  } catch {
9573
8666
  }
9574
8667
  try {
9575
- subagentsDir = path25.join(runDir, "subagents");
8668
+ subagentsDir = path24.join(runDir, "subagents");
9576
8669
  const files = await fsp3.readdir(subagentsDir);
9577
8670
  subagentCount = files.filter((f) => f.endsWith(".jsonl")).length;
9578
8671
  } catch {
@@ -9601,7 +8694,7 @@ async function listFleetRuns(deps) {
9601
8694
  return 0;
9602
8695
  }
9603
8696
  async function showFleetRun(runId, deps) {
9604
- const runDir = path25.join(deps.paths.projectSessions, runId);
8697
+ const runDir = path24.join(deps.paths.projectSessions, runId);
9605
8698
  let stat4;
9606
8699
  try {
9607
8700
  stat4 = await fsp3.stat(runDir);
@@ -9618,7 +8711,7 @@ async function showFleetRun(runId, deps) {
9618
8711
  deps.renderer.write(color.bold(`
9619
8712
  Fleet Run: ${runId}
9620
8713
  `) + "\n");
9621
- const manifestPath = path25.join(runDir, "fleet.json");
8714
+ const manifestPath = path24.join(runDir, "fleet.json");
9622
8715
  let manifestData = null;
9623
8716
  try {
9624
8717
  manifestData = await fsp3.readFile(manifestPath, "utf8");
@@ -9634,7 +8727,7 @@ Fleet Run: ${runId}
9634
8727
  deps.renderer.write(` ${color.dim("\u25CB")} fleet.json \u2014 not found
9635
8728
  `);
9636
8729
  }
9637
- const checkpointPath = path25.join(runDir, "checkpoint.json");
8730
+ const checkpointPath = path24.join(runDir, "checkpoint.json");
9638
8731
  let checkpointData = null;
9639
8732
  try {
9640
8733
  checkpointData = await fsp3.readFile(checkpointPath, "utf8");
@@ -9681,7 +8774,7 @@ Fleet Run: ${runId}
9681
8774
  } catch {
9682
8775
  }
9683
8776
  }
9684
- const subagentsDir = path25.join(runDir, "subagents");
8777
+ const subagentsDir = path24.join(runDir, "subagents");
9685
8778
  let subagentFiles = [];
9686
8779
  try {
9687
8780
  subagentFiles = await fsp3.readdir(subagentsDir);
@@ -9693,7 +8786,7 @@ Fleet Run: ${runId}
9693
8786
  Subagent transcripts (${subagentFiles.length}):
9694
8787
  `);
9695
8788
  for (const f of subagentFiles.sort()) {
9696
- const filePath = path25.join(subagentsDir, f);
8789
+ const filePath = path24.join(subagentsDir, f);
9697
8790
  let size;
9698
8791
  try {
9699
8792
  const s = await fsp3.stat(filePath);
@@ -9710,7 +8803,7 @@ Fleet Run: ${runId}
9710
8803
  ${color.dim("\u25CB")} No subagent transcripts
9711
8804
  `);
9712
8805
  }
9713
- const sharedDir = path25.join(runDir, "shared");
8806
+ const sharedDir = path24.join(runDir, "shared");
9714
8807
  try {
9715
8808
  const files = await fsp3.readdir(sharedDir);
9716
8809
  deps.renderer.write(`
@@ -9877,7 +8970,7 @@ function findSessionId(args) {
9877
8970
  var rewindCmd = async (args, deps) => {
9878
8971
  const flags = parseRewindFlags(args);
9879
8972
  const wpaths = resolveWstackPaths({ projectRoot: deps.projectRoot });
9880
- const sessionsDir = path25.join(wpaths.globalRoot, "sessions");
8973
+ const sessionsDir = path24.join(wpaths.globalRoot, "sessions");
9881
8974
  const rewind = new DefaultSessionRewinder(sessionsDir, deps.projectRoot);
9882
8975
  let sessionId = findSessionId(args);
9883
8976
  if (!sessionId) {
@@ -10009,7 +9102,7 @@ var skillsCmd = async (_args, deps) => {
10009
9102
  };
10010
9103
  var versionCmd = async (_args, deps) => {
10011
9104
  deps.renderer.write(
10012
- `WrongStack ${CLI_VERSION} (apiVersion ${API_VERSION}, node ${process.version}, ${os4.platform()})
9105
+ `WrongStack ${CLI_VERSION} (apiVersion ${API_VERSION}, node ${process.version}, ${os3.platform()})
10013
9106
  `
10014
9107
  );
10015
9108
  return 0;
@@ -10089,22 +9182,22 @@ function fmtDuration(ms) {
10089
9182
  const remMin = m - h * 60;
10090
9183
  return `${h}h${remMin}m`;
10091
9184
  }
10092
- function fmtTaskResultLine(r, color41) {
9185
+ function fmtTaskResultLine(r, color37) {
10093
9186
  const stats = `${r.iterations}it ${r.toolCalls}tc ${fmtDuration(r.durationMs)}`;
10094
9187
  const errMsg = typeof r.error === "string" ? r.error : r.error?.message;
10095
9188
  const errKind = typeof r.error === "object" ? r.error?.kind : void 0;
10096
9189
  const errTail = errMsg ? ` \u2014 ${errMsg.replace(/\s+/g, " ").slice(0, 80)}${errMsg.length > 80 ? "\u2026" : ""}` : "";
10097
- const errKindChip = errKind ? color41.dim(` [${errKind}]`) : "";
10098
- const errSnip = errMsg || errKind ? `${errKindChip}${color41.dim(errTail)}` : "";
9190
+ const errKindChip = errKind ? color37.dim(` [${errKind}]`) : "";
9191
+ const errSnip = errMsg || errKind ? `${errKindChip}${color37.dim(errTail)}` : "";
10099
9192
  switch (r.status) {
10100
9193
  case "success":
10101
- return { mark: color41.green("\u2713"), stats, tail: "" };
9194
+ return { mark: color37.green("\u2713"), stats, tail: "" };
10102
9195
  case "timeout":
10103
- return { mark: color41.yellow("\u23F1"), stats: `${color41.yellow("timeout")} ${stats}`, tail: errSnip };
9196
+ return { mark: color37.yellow("\u23F1"), stats: `${color37.yellow("timeout")} ${stats}`, tail: errSnip };
10104
9197
  case "stopped":
10105
- return { mark: color41.dim("\u2298"), stats: `${color41.dim("stopped")} ${stats}`, tail: errSnip };
9198
+ return { mark: color37.dim("\u2298"), stats: `${color37.dim("stopped")} ${stats}`, tail: errSnip };
10106
9199
  case "failed":
10107
- return { mark: color41.red("\u2717"), stats: `${color41.red("failed")} ${stats}`, tail: errSnip };
9200
+ return { mark: color37.red("\u2717"), stats: `${color37.red("failed")} ${stats}`, tail: errSnip };
10108
9201
  }
10109
9202
  }
10110
9203
 
@@ -10114,7 +9207,7 @@ function resolveBundledSkillsDir() {
10114
9207
  try {
10115
9208
  const req2 = createRequire(import.meta.url);
10116
9209
  const corePkg = req2.resolve("@wrongstack/core/package.json");
10117
- return path25.join(path25.dirname(corePkg), "skills");
9210
+ return path24.join(path24.dirname(corePkg), "skills");
10118
9211
  } catch {
10119
9212
  return void 0;
10120
9213
  }
@@ -10276,7 +9369,7 @@ async function boot(argv) {
10276
9369
  if (choices.director) flags["director"] = true;
10277
9370
  flags["autonomy"] = choices.autonomy;
10278
9371
  printLaunchHints(renderer, flags, {
10279
- cursorFile: path25.join(wpaths.cacheDir, "hint-cursor")
9372
+ cursorFile: path24.join(wpaths.cacheDir, "hint-cursor")
10280
9373
  });
10281
9374
  }
10282
9375
  return {
@@ -10961,9 +10054,9 @@ async function renderGoalBanner(opts) {
10961
10054
  );
10962
10055
  if (goal.journal.length > 0) {
10963
10056
  const lastEntry = goal.journal[goal.journal.length - 1];
10964
- const statusIcon2 = lastEntry.status === "success" ? "\u2713" : lastEntry.status === "failure" ? "\u2717" : lastEntry.status === "aborted" ? "\u2298" : lastEntry.status === "skipped" ? "\u229D" : "\xB7";
10057
+ const statusIcon = lastEntry.status === "success" ? "\u2713" : lastEntry.status === "failure" ? "\u2717" : lastEntry.status === "aborted" ? "\u2298" : lastEntry.status === "skipped" ? "\u229D" : "\xB7";
10965
10058
  opts.renderer.write(
10966
- color.dim(` Last: ${statusIcon2} ${lastEntry.task} (${lastEntry.status})`) + "\n"
10059
+ color.dim(` Last: ${statusIcon} ${lastEntry.task} (${lastEntry.status})`) + "\n"
10967
10060
  );
10968
10061
  }
10969
10062
  if (goal.engineState === "running") {
@@ -11066,6 +10159,7 @@ async function execute(deps) {
11066
10159
  attachments,
11067
10160
  tokenCounter,
11068
10161
  config,
10162
+ configStore,
11069
10163
  renderer,
11070
10164
  reader,
11071
10165
  session,
@@ -11265,6 +10359,30 @@ async function execute(deps) {
11265
10359
  onAutonomy?.(mode);
11266
10360
  return null;
11267
10361
  },
10362
+ getSettings: () => {
10363
+ const autonomy = configStore.get().autonomy;
10364
+ const rawMode = autonomy?.defaultMode;
10365
+ const mode = rawMode === "suggest" || rawMode === "auto" ? rawMode : "off";
10366
+ return { mode, delayMs: autonomy?.autoProceedDelayMs ?? 45e3 };
10367
+ },
10368
+ async saveSettings(s) {
10369
+ try {
10370
+ await persistAutonomySetting(
10371
+ {
10372
+ configStore,
10373
+ globalConfigPath: wpaths.globalConfig,
10374
+ vault: { encrypt: (v) => v, decrypt: (v) => v, isEncrypted: () => false }
10375
+ },
10376
+ (autonomy) => {
10377
+ autonomy.defaultMode = s.mode;
10378
+ autonomy.autoProceedDelayMs = s.delayMs;
10379
+ }
10380
+ );
10381
+ return null;
10382
+ } catch (err) {
10383
+ return err instanceof Error ? err.message : String(err);
10384
+ }
10385
+ },
11268
10386
  effectiveMaxContext,
11269
10387
  // Default OFF so the terminal's native scrollback works for chat
11270
10388
  // history out of the box (mouse wheel / Shift+PgUp). Users who hit
@@ -11345,7 +10463,7 @@ async function execute(deps) {
11345
10463
  supportsVision,
11346
10464
  attachments,
11347
10465
  effectiveMaxContext,
11348
- projectName: path25.basename(projectRoot) || void 0,
10466
+ projectName: path24.basename(projectRoot) || void 0,
11349
10467
  projectRoot,
11350
10468
  getAutonomy,
11351
10469
  onAutonomy,
@@ -11369,7 +10487,7 @@ async function execute(deps) {
11369
10487
  supportsVision,
11370
10488
  attachments,
11371
10489
  effectiveMaxContext,
11372
- projectName: path25.basename(projectRoot) || void 0,
10490
+ projectName: path24.basename(projectRoot) || void 0,
11373
10491
  getAutonomy,
11374
10492
  onAutonomy,
11375
10493
  getEternalEngine,
@@ -11473,7 +10591,7 @@ var MultiAgentHost = class {
11473
10591
  doneCondition: { type: "all_tasks_done" },
11474
10592
  maxConcurrent: this.opts.maxConcurrent ?? 4
11475
10593
  };
11476
- const defaultScratchpad = this.opts.sharedScratchpadPath || (this.opts.sessionsRoot && this.opts.directorRunId ? path25.join(this.opts.sessionsRoot, this.opts.directorRunId, "shared") : void 0);
10594
+ const defaultScratchpad = this.opts.sharedScratchpadPath || (this.opts.sessionsRoot && this.opts.directorRunId ? path24.join(this.opts.sessionsRoot, this.opts.directorRunId, "shared") : void 0);
11477
10595
  this.director = new Director({
11478
10596
  config: coordinatorConfig,
11479
10597
  manifestPath: this.opts.manifestPath,
@@ -11719,7 +10837,7 @@ var MultiAgentHost = class {
11719
10837
  model: opts?.model,
11720
10838
  tools: opts?.tools
11721
10839
  };
11722
- const transcriptPath = this.sessionFactory ? path25.join(this.sessionFactory.dir, `${subagentConfig.name}.jsonl`) : void 0;
10840
+ const transcriptPath = this.sessionFactory ? path24.join(this.sessionFactory.dir, `${subagentConfig.name}.jsonl`) : void 0;
11723
10841
  const { subagentId, taskId } = await this._spawnAndAssign(subagentConfig);
11724
10842
  this.fleetManager?.addPendingTask(taskId, subagentId, description);
11725
10843
  this.deps.events.emit("subagent.spawned", {
@@ -11862,16 +10980,16 @@ var MultiAgentHost = class {
11862
10980
  if (this.director) return this.director;
11863
10981
  this.opts.directorMode = true;
11864
10982
  if (this.opts.fleetRoot && !this.opts.manifestPath) {
11865
- this.opts.manifestPath = path25.join(this.opts.fleetRoot, "fleet.json");
10983
+ this.opts.manifestPath = path24.join(this.opts.fleetRoot, "fleet.json");
11866
10984
  }
11867
10985
  if (this.opts.fleetRoot && !this.opts.sharedScratchpadPath) {
11868
- this.opts.sharedScratchpadPath = path25.join(this.opts.fleetRoot, "shared");
10986
+ this.opts.sharedScratchpadPath = path24.join(this.opts.fleetRoot, "shared");
11869
10987
  }
11870
10988
  if (this.opts.fleetRoot && !this.opts.sessionsRoot) {
11871
- this.opts.sessionsRoot = path25.join(this.opts.fleetRoot, "subagents");
10989
+ this.opts.sessionsRoot = path24.join(this.opts.fleetRoot, "subagents");
11872
10990
  }
11873
10991
  if (this.opts.fleetRoot && !this.opts.stateCheckpointPath) {
11874
- this.opts.stateCheckpointPath = path25.join(this.opts.fleetRoot, "director-state.json");
10992
+ this.opts.stateCheckpointPath = path24.join(this.opts.fleetRoot, "director-state.json");
11875
10993
  }
11876
10994
  await this.ensureDirector();
11877
10995
  return this.director ?? null;
@@ -12037,11 +11155,11 @@ var SessionStats = class {
12037
11155
  if (e.name === "bash") this.bashCommands++;
12038
11156
  else if (e.name === "fetch") this.fetches++;
12039
11157
  if (!e.ok) return;
12040
- const path26 = typeof input?.path === "string" ? input.path : void 0;
12041
- if (e.name === "read" && path26) this.readPaths.add(path26);
12042
- else if (e.name === "edit" && path26) this.editedPaths.add(path26);
12043
- else if (e.name === "write" && path26) {
12044
- this.writtenPaths.add(path26);
11158
+ const path25 = typeof input?.path === "string" ? input.path : void 0;
11159
+ if (e.name === "read" && path25) this.readPaths.add(path25);
11160
+ else if (e.name === "edit" && path25) this.editedPaths.add(path25);
11161
+ else if (e.name === "write" && path25) {
11162
+ this.writtenPaths.add(path25);
12045
11163
  const content = typeof input?.content === "string" ? input.content : "";
12046
11164
  this.bytesWritten += Buffer.byteLength(content, "utf8");
12047
11165
  }
@@ -12160,7 +11278,7 @@ function gitText(args, cwd) {
12160
11278
  child.on("close", (code) => resolve4({ code: code ?? 1, out: out.trim() }));
12161
11279
  });
12162
11280
  }
12163
- async function isGitRepo2(cwd) {
11281
+ async function isGitRepo(cwd) {
12164
11282
  const { code, out } = await gitText(["rev-parse", "--is-inside-work-tree"], cwd);
12165
11283
  return code === 0 && out.trim() === "true";
12166
11284
  }
@@ -12237,7 +11355,7 @@ function createAutoPhaseHost(deps) {
12237
11355
  await persist(graph);
12238
11356
  const worktreesEnabled = deps.worktrees !== false && process.env["WRONGSTACK_AUTOPHASE_WORKTREES"] !== "0";
12239
11357
  let worktrees;
12240
- if (worktreesEnabled && await isGitRepo2(deps.projectRoot)) {
11358
+ if (worktreesEnabled && await isGitRepo(deps.projectRoot)) {
12241
11359
  worktrees = new WorktreeManager({ projectRoot: deps.projectRoot, events: deps.events });
12242
11360
  log(`\u{1F33F} Worktree isolation on \u2014 up to ${deps.maxConcurrentPhases ?? WORKTREE_PHASE_CONCURRENCY} phases run in parallel.`);
12243
11361
  }
@@ -12317,7 +11435,7 @@ function createAutoPhaseHost(deps) {
12317
11435
  },
12318
11436
  async onWorktree(action, target) {
12319
11437
  const root = deps.projectRoot;
12320
- if (!await isGitRepo2(root)) return "\u26A0 Not a git repository \u2014 worktrees unavailable.";
11438
+ if (!await isGitRepo(root)) return "\u26A0 Not a git repository \u2014 worktrees unavailable.";
12321
11439
  switch (action) {
12322
11440
  case "list": {
12323
11441
  const { out } = await gitText(["worktree", "list"], root);
@@ -12541,7 +11659,7 @@ function setupMetrics(params) {
12541
11659
  const dumpMetrics = () => {
12542
11660
  if (!metricsSink) return;
12543
11661
  try {
12544
- const out = path25.join(wpaths.projectSessions, "metrics.json");
11662
+ const out = path24.join(wpaths.projectSessions, "metrics.json");
12545
11663
  const snap = metricsSink.snapshot();
12546
11664
  writeFileSync(out, JSON.stringify(snap, null, 2));
12547
11665
  } catch {
@@ -12576,6 +11694,36 @@ function createApi(ownerName, base) {
12576
11694
  }
12577
11695
 
12578
11696
  // src/wiring/plugins.ts
11697
+ var BUILTIN_PLUGIN_FACTORIES = [
11698
+ async () => {
11699
+ const { createPromptsPlugin } = await import('@wrongstack/core');
11700
+ return createPromptsPlugin();
11701
+ },
11702
+ async () => {
11703
+ const { createSyncPlugin } = await import('@wrongstack/core');
11704
+ return createSyncPlugin();
11705
+ },
11706
+ async () => {
11707
+ const { createGitPlugin } = await import('@wrongstack/core');
11708
+ return createGitPlugin();
11709
+ },
11710
+ async () => {
11711
+ const { createObservabilityPlugin } = await import('@wrongstack/core');
11712
+ return createObservabilityPlugin();
11713
+ },
11714
+ async () => {
11715
+ const { createSecurityPlugin } = await import('@wrongstack/core');
11716
+ return createSecurityPlugin();
11717
+ },
11718
+ async () => {
11719
+ const { createSkillsPlugin } = await import('@wrongstack/core');
11720
+ return createSkillsPlugin();
11721
+ },
11722
+ async () => {
11723
+ const { createPlanPlugin } = await import('@wrongstack/core');
11724
+ return createPlanPlugin();
11725
+ }
11726
+ ];
12579
11727
  async function setupPlugins(params) {
12580
11728
  const {
12581
11729
  config,
@@ -12589,28 +11737,65 @@ async function setupPlugins(params) {
12589
11737
  agent,
12590
11738
  sessionWriter,
12591
11739
  metricsSink,
11740
+ healthRegistry,
11741
+ skillLoader,
12592
11742
  configStore,
12593
- pipelines
11743
+ pipelines,
11744
+ paths
12594
11745
  } = params;
12595
- if (!config.features.plugins || !config.plugins || config.plugins.length === 0) return;
12596
- const resolvedPlugins = [];
12597
- for (const p of config.plugins) {
12598
- if (typeof p === "object" && p.enabled === false) continue;
12599
- const spec = typeof p === "string" ? p : p.name;
12600
- try {
12601
- const mod = await import(spec);
12602
- if (mod.default) resolvedPlugins.push(mod.default);
12603
- } catch (err) {
12604
- log.warn(`Plugin "${spec}" failed to load`, err);
11746
+ const builtinPlugins = [];
11747
+ const disabledBuiltins = new Set(
11748
+ (config.plugins ?? []).filter(
11749
+ (p) => typeof p === "object" && p.enabled === false
11750
+ ).map((p) => p.name)
11751
+ );
11752
+ if (paths && config.features?.plugins !== false) {
11753
+ for (const factory of BUILTIN_PLUGIN_FACTORIES) {
11754
+ try {
11755
+ const plugin = await factory();
11756
+ if (!plugin) continue;
11757
+ if (disabledBuiltins.has(plugin.name)) {
11758
+ log.info(`[setupPlugins] built-in plugin "${plugin.name}" disabled by config`);
11759
+ continue;
11760
+ }
11761
+ builtinPlugins.push(plugin);
11762
+ } catch (err) {
11763
+ log.warn("[setupPlugins] builtin plugin failed to load:", err);
11764
+ }
12605
11765
  }
12606
11766
  }
12607
- if (resolvedPlugins.length === 0) return;
11767
+ const userPlugins = [];
11768
+ if (config.features?.plugins !== false) {
11769
+ for (const p of config.plugins ?? []) {
11770
+ if (typeof p === "object" && p.enabled === false) continue;
11771
+ const spec = typeof p === "string" ? p : p.name;
11772
+ try {
11773
+ const mod = await import(spec);
11774
+ if (mod.default) userPlugins.push(mod.default);
11775
+ } catch (err) {
11776
+ log.warn(`Plugin "${spec}" failed to load`, err);
11777
+ }
11778
+ }
11779
+ }
11780
+ const allPlugins = [...builtinPlugins, ...userPlugins];
11781
+ if (allPlugins.length === 0) return;
12608
11782
  const pluginOptions = buildPluginOptions(config);
12609
- const pluginConfig = Object.keys(pluginOptions).length > 0 ? patchConfig(config, { extensions: pluginOptions }) : config;
12610
- await loadPlugins(resolvedPlugins, {
11783
+ const pluginConfig = patchConfig(config, {
11784
+ extensions: pluginOptions,
11785
+ paths,
11786
+ configStore,
11787
+ metricsSink,
11788
+ healthRegistry,
11789
+ skillLoader
11790
+ });
11791
+ await loadPlugins(allPlugins, {
12611
11792
  log,
12612
11793
  pluginOptions,
12613
11794
  apiFactory: (plugin) => createApi(plugin.name, {
11795
+ // First-party plugins come from BUILTIN_PLUGIN_FACTORIES — trust them
11796
+ // ("official") so they can claim bare slash command names (/prompts,
11797
+ // /sync) and override built-ins. User plugins stay namespaced.
11798
+ official: builtinPlugins.includes(plugin),
12614
11799
  container,
12615
11800
  events,
12616
11801
  pipelines,
@@ -12629,6 +11814,7 @@ async function setupPlugins(params) {
12629
11814
  configStore
12630
11815
  })
12631
11816
  });
11817
+ log.info(`[setupPlugins] loaded ${builtinPlugins.length} built-in, ${userPlugins.length} user plugin(s)`);
12632
11818
  }
12633
11819
  function buildPluginOptions(config) {
12634
11820
  const options = {};
@@ -12732,12 +11918,12 @@ async function setupSession(params) {
12732
11918
  }
12733
11919
  const sessionRef = { current: session };
12734
11920
  await recoveryLock.write(session.id).catch(() => void 0);
12735
- const attachments = new DefaultAttachmentStore({ spoolDir: path25.join(wpaths.projectSessions, session.id, "attachments") });
12736
- const queueStore = new QueueStore({ dir: path25.join(wpaths.projectSessions, session.id) });
11921
+ const attachments = new DefaultAttachmentStore({ spoolDir: path24.join(wpaths.projectSessions, session.id, "attachments") });
11922
+ const queueStore = new QueueStore({ dir: path24.join(wpaths.projectSessions, session.id) });
12737
11923
  const ctxSignal = new AbortController().signal;
12738
11924
  const context = new Context({ systemPrompt, provider, session, signal: ctxSignal, tokenCounter, cwd, projectRoot, model: config.model });
12739
11925
  if (restoredMessages.length > 0) context.state.replaceMessages(restoredMessages);
12740
- const todosCheckpointPath = path25.join(wpaths.projectSessions, `${session.id}.todos.json`);
11926
+ const todosCheckpointPath = path24.join(wpaths.projectSessions, `${session.id}.todos.json`);
12741
11927
  if (resumeId) {
12742
11928
  try {
12743
11929
  const restoredTodos = await loadTodosCheckpoint(todosCheckpointPath);
@@ -12749,13 +11935,13 @@ async function setupSession(params) {
12749
11935
  }
12750
11936
  }
12751
11937
  const detachTodosCheckpoint = attachTodosCheckpoint(context.state, todosCheckpointPath, session.id);
12752
- const planPath = path25.join(wpaths.projectSessions, `${session.id}.plan.json`);
11938
+ const planPath = path24.join(wpaths.projectSessions, `${session.id}.plan.json`);
12753
11939
  context.state.setMeta("plan.path", planPath);
12754
11940
  let dirState;
12755
11941
  if (resumeId) {
12756
11942
  try {
12757
- const fleetRoot = path25.join(wpaths.projectSessions, session.id);
12758
- dirState = await loadDirectorState(path25.join(fleetRoot, "director-state.json"));
11943
+ const fleetRoot = path24.join(wpaths.projectSessions, session.id);
11944
+ dirState = await loadDirectorState(path24.join(fleetRoot, "director-state.json"));
12759
11945
  if (dirState) {
12760
11946
  const tCounts = {};
12761
11947
  for (const t of dirState.tasks) tCounts[t.status] = (tCounts[t.status] ?? 0) + 1;
@@ -12782,7 +11968,7 @@ function resolveBundledSkillsDir2() {
12782
11968
  try {
12783
11969
  const req2 = createRequire(import.meta.url);
12784
11970
  const corePkg = req2.resolve("@wrongstack/core/package.json");
12785
- return path25.join(path25.dirname(corePkg), "skills");
11971
+ return path24.join(path24.dirname(corePkg), "skills");
12786
11972
  } catch {
12787
11973
  return void 0;
12788
11974
  }
@@ -12882,7 +12068,7 @@ async function main(argv) {
12882
12068
  modeId,
12883
12069
  modePrompt,
12884
12070
  modelCapabilities,
12885
- planPath: () => sessionRef.current ? path25.join(wpaths.projectSessions, `${sessionRef.current.id}.plan.json`) : void 0,
12071
+ planPath: () => sessionRef.current ? path24.join(wpaths.projectSessions, `${sessionRef.current.id}.plan.json`) : void 0,
12886
12072
  contributors: [
12887
12073
  // Injects the ETERNAL AUTONOMY block when the user has activated
12888
12074
  // `/autonomy eternal`. Without this, the per-iteration directive
@@ -13041,7 +12227,10 @@ async function main(argv) {
13041
12227
  agent,
13042
12228
  sessionWriter: context.session,
13043
12229
  metricsSink,
13044
- configStore
12230
+ healthRegistry,
12231
+ skillLoader: config.features.skills ? skillLoader : void 0,
12232
+ configStore,
12233
+ paths: wpaths
13045
12234
  });
13046
12235
  const switchProviderAndModel = (providerId, modelId) => {
13047
12236
  try {
@@ -13086,12 +12275,12 @@ async function main(argv) {
13086
12275
  }
13087
12276
  }
13088
12277
  };
13089
- const fleetRoot = directorMode ? path25.join(wpaths.projectSessions, session.id) : void 0;
13090
- const manifestPath = directorMode ? typeof process.env["WRONGSTACK_FLEET_MANIFEST"] === "string" ? process.env["WRONGSTACK_FLEET_MANIFEST"] : path25.join(fleetRoot, "fleet.json") : void 0;
13091
- const sharedScratchpadPath = directorMode ? path25.join(fleetRoot, "shared") : void 0;
13092
- const subagentSessionsRoot = directorMode ? path25.join(fleetRoot, "subagents") : void 0;
13093
- const stateCheckpointPath = directorMode ? path25.join(fleetRoot, "director-state.json") : void 0;
13094
- const fleetRootForPromotion = path25.join(wpaths.projectSessions, session.id);
12278
+ const fleetRoot = directorMode ? path24.join(wpaths.projectSessions, session.id) : void 0;
12279
+ const manifestPath = directorMode ? typeof process.env["WRONGSTACK_FLEET_MANIFEST"] === "string" ? process.env["WRONGSTACK_FLEET_MANIFEST"] : path24.join(fleetRoot, "fleet.json") : void 0;
12280
+ const sharedScratchpadPath = directorMode ? path24.join(fleetRoot, "shared") : void 0;
12281
+ const subagentSessionsRoot = directorMode ? path24.join(fleetRoot, "subagents") : void 0;
12282
+ const stateCheckpointPath = directorMode ? path24.join(fleetRoot, "director-state.json") : void 0;
12283
+ const fleetRootForPromotion = path24.join(wpaths.projectSessions, session.id);
13095
12284
  const multiAgentHost = new MultiAgentHost(
13096
12285
  {
13097
12286
  container,
@@ -13426,7 +12615,7 @@ async function main(argv) {
13426
12615
  return director.spawn(cfg);
13427
12616
  },
13428
12617
  onFleetLog: async (subagentId, mode) => {
13429
- const subagentsRoot = path25.join(fleetRootForPromotion, "subagents");
12618
+ const subagentsRoot = path24.join(fleetRootForPromotion, "subagents");
13430
12619
  let runDirs;
13431
12620
  try {
13432
12621
  runDirs = await fsp3.readdir(subagentsRoot);
@@ -13435,7 +12624,7 @@ async function main(argv) {
13435
12624
  }
13436
12625
  const found = [];
13437
12626
  for (const runId of runDirs) {
13438
- const runDir = path25.join(subagentsRoot, runId);
12627
+ const runDir = path24.join(subagentsRoot, runId);
13439
12628
  let files;
13440
12629
  try {
13441
12630
  files = await fsp3.readdir(runDir);
@@ -13444,7 +12633,7 @@ async function main(argv) {
13444
12633
  }
13445
12634
  for (const f of files) {
13446
12635
  if (!f.endsWith(".jsonl")) continue;
13447
- const full = path25.join(runDir, f);
12636
+ const full = path24.join(runDir, f);
13448
12637
  try {
13449
12638
  const stat4 = await fsp3.stat(full);
13450
12639
  found.push({
@@ -13541,7 +12730,7 @@ async function main(argv) {
13541
12730
  }
13542
12731
  const dir = await multiAgentHost.ensureDirector();
13543
12732
  if (!dir) return "Director is not available.";
13544
- const dirStatePath = path25.join(fleetRootForPromotion, "director-state.json");
12733
+ const dirStatePath = path24.join(fleetRootForPromotion, "director-state.json");
13545
12734
  const prior = await loadDirectorState(dirStatePath);
13546
12735
  if (!prior) {
13547
12736
  return "No prior director-state.json found \u2014 nothing to retry.";
@@ -13612,9 +12801,9 @@ async function main(argv) {
13612
12801
  for (const tool of director2.tools(FLEET_ROSTER)) {
13613
12802
  toolRegistry.register(tool);
13614
12803
  }
13615
- const mp = path25.join(fleetRootForPromotion, "fleet.json");
13616
- const sp = path25.join(fleetRootForPromotion, "shared");
13617
- const ss = path25.join(fleetRootForPromotion, "subagents");
12804
+ const mp = path24.join(fleetRootForPromotion, "fleet.json");
12805
+ const sp = path24.join(fleetRootForPromotion, "shared");
12806
+ const ss = path24.join(fleetRootForPromotion, "subagents");
13618
12807
  const lines = [
13619
12808
  `${color.green("\u2713")} Promoted to director mode.`,
13620
12809
  ` Roster: ${Object.keys(FLEET_ROSTER).join(", ")}`,
@@ -13711,10 +12900,10 @@ Restart WrongStack to load or unload plugin code in this session.`;
13711
12900
  void mcpRegistry.stopAll();
13712
12901
  },
13713
12902
  onBeforeExit: async () => {
13714
- const { spawn: spawn4 } = await import('child_process');
12903
+ const { spawn: spawn3 } = await import('child_process');
13715
12904
  const cwd2 = projectRoot;
13716
12905
  const statusResult = await new Promise((resolve4, reject) => {
13717
- const child = spawn4("git", ["status", "--porcelain"], { cwd: cwd2, stdio: ["ignore", "pipe", "pipe"] });
12906
+ const child = spawn3("git", ["status", "--porcelain"], { cwd: cwd2, stdio: ["ignore", "pipe", "pipe"] });
13718
12907
  let stdout = "";
13719
12908
  child.stdout?.on("data", (d) => {
13720
12909
  stdout += d;
@@ -13858,6 +13047,7 @@ Restart WrongStack to load or unload plugin code in this session.`;
13858
13047
  attachments,
13859
13048
  tokenCounter,
13860
13049
  config,
13050
+ configStore,
13861
13051
  renderer,
13862
13052
  reader,
13863
13053
  session,