@wrongstack/cli 1.1.2 → 1.1.5

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.
Files changed (117) hide show
  1. package/dist/{acp-HCGUTFNE.js → acp-NKUEYJDZ.js} +14 -5
  2. package/dist/acp-leader/acp-leader-confirm.d.ts +20 -0
  3. package/dist/acp-leader/acp-leader-context.d.ts +29 -0
  4. package/dist/acp-leader/acp-leader-fleet.d.ts +26 -0
  5. package/dist/acp-leader/acp-leader-host-binding.d.ts +17 -0
  6. package/dist/acp-leader/acp-leader-host.d.ts +82 -0
  7. package/dist/acp-leader/acp-leader-picker.d.ts +24 -0
  8. package/dist/acp-leader/acp-leader-provider.d.ts +85 -0
  9. package/dist/acp-leader/acp-leader-resume.d.ts +10 -0
  10. package/dist/acp-leader/acp-leader-stream.d.ts +83 -0
  11. package/dist/{auth-ANOVZVHE.js → auth-2ZG5DBHS.js} +62 -66
  12. package/dist/auth-menu/index.d.ts +1 -2
  13. package/dist/boot/dispatch-webui.d.ts +16 -0
  14. package/dist/boot/launch-menu-arrow.d.ts +20 -0
  15. package/dist/boot/launch-menu-types.d.ts +36 -0
  16. package/dist/boot/launch-menu.d.ts +1 -57
  17. package/dist/boot/tui-session-resume-rollback.d.ts +31 -0
  18. package/dist/{boot-auto-thin-7D4OVEWA.js → boot-auto-thin-N2CIGTXE.js} +3 -3
  19. package/dist/{chunk-TZPKOS5G.js → chunk-2XQ6SRKG.js} +2 -2
  20. package/dist/chunk-3LEIFO5D.js +65 -0
  21. package/dist/chunk-5SGMUDP5.js +752 -0
  22. package/dist/{chunk-3EXRPTAU.js → chunk-5TQ65PXQ.js} +17 -17
  23. package/dist/{chunk-GRAGMA4B.js → chunk-7BM4LGKQ.js} +18 -18
  24. package/dist/{chunk-VAQXOZKP.js → chunk-AJM4EFCM.js} +139 -136
  25. package/dist/{chunk-C2BBH4S4.js → chunk-E3MJFAFR.js} +2 -2
  26. package/dist/{chunk-5TRZZHMN.js → chunk-JCZ2D3VV.js} +4 -65
  27. package/dist/{chunk-AWRZWPJ3.js → chunk-JFYQGMMM.js} +99 -75
  28. package/dist/{chunk-BIGSVBPI.js → chunk-KNYIEQAY.js} +64 -61
  29. package/dist/chunk-LUEO5HLZ.js +50 -0
  30. package/dist/chunk-LYWOV4OX.js +252 -0
  31. package/dist/chunk-M7FNHCE3.js +2070 -0
  32. package/dist/{chunk-75OLD563.js → chunk-M7PSENGF.js} +3 -1
  33. package/dist/{chunk-NMXQFQ26.js → chunk-MEBXWI7U.js} +5 -5
  34. package/dist/{chunk-RAWHRRUJ.js → chunk-MKMM5RIW.js} +209 -201
  35. package/dist/{chunk-3R3OADC5.js → chunk-P7MEEUGT.js} +281 -252
  36. package/dist/chunk-QLYPIJ7X.js +258 -0
  37. package/dist/chunk-RN5CFAVQ.js +292 -0
  38. package/dist/{chunk-WDXNBYGD.js → chunk-TDP7CZGE.js} +6 -1
  39. package/dist/{chunk-6VPWQ4TG.js → chunk-UROB7MK5.js} +2 -1
  40. package/dist/chunk-VEESMPTX.js +254 -0
  41. package/dist/{chunk-IJLIAPCW.js → chunk-VPSAKGLK.js} +47 -47
  42. package/dist/{cli-context-YIT4FEDM.js → cli-context-CQYGIWOU.js} +254 -237
  43. package/dist/{cli-main-JIADJ5OL.js → cli-main-VRUJNUBX.js} +2081 -1594
  44. package/dist/cli-main-boot.d.ts +1 -1
  45. package/dist/config-doctor-known-keys.d.ts +33 -0
  46. package/dist/config-doctor.d.ts +2 -47
  47. package/dist/config-history-support.d.ts +36 -0
  48. package/dist/config-history.d.ts +1 -1
  49. package/dist/{config-transfer-Y7XJMJRN.js → config-transfer-B4GOZTFC.js} +2 -2
  50. package/dist/{execution-BAP566QC.js → execution-IV72RUSM.js} +5354 -5258
  51. package/dist/execution-tui.d.ts +30 -0
  52. package/dist/fleet/acp-live-steer.d.ts +28 -0
  53. package/dist/fleet/acp-permission-bridge.d.ts +49 -0
  54. package/dist/fleet/acp-quota-hold.d.ts +3 -0
  55. package/dist/fleet/acp-quota-reading.d.ts +3 -0
  56. package/dist/fleet/acp-turn-reminders.d.ts +15 -0
  57. package/dist/fleet/acp-wrongstack-bridge.d.ts +50 -0
  58. package/dist/fleet/host-acp.d.ts +23 -2
  59. package/dist/fleet/wrongforge-client.d.ts +116 -0
  60. package/dist/fleet/wrongforge-gateway.d.ts +20 -0
  61. package/dist/fleet/wrongforge-info.d.ts +32 -0
  62. package/dist/fleet/wrongforge-quota.d.ts +10 -0
  63. package/dist/fleet/wrongforge-runner.d.ts +37 -0
  64. package/dist/fleet/wrongforge-runtime.d.ts +10 -0
  65. package/dist/{hq-JD5AZVMG.js → hq-54PQYR5O.js} +311 -307
  66. package/dist/hq-server/sweeps.d.ts +28 -0
  67. package/dist/{hq-server-BI23EPM7.js → hq-server-YK7FBLL6.js} +3 -3
  68. package/dist/index.js +8 -5
  69. package/dist/mcp-22CFBX4H.js +236 -0
  70. package/dist/mcp-serve-project.d.ts +18 -0
  71. package/dist/mcp-serve.d.ts +0 -63
  72. package/dist/{modeldiag-HDIKG37X.js → modeldiag-5PBB777J.js} +4 -4
  73. package/dist/{per-subcommand-help-D6J4ZXW2.js → per-subcommand-help-MQGERD4E.js} +2 -2
  74. package/dist/plugin-llm-command.d.ts +9 -0
  75. package/dist/{plugin-usage-TYF5HY4K.js → plugin-usage-UWKYMNQU.js} +3 -3
  76. package/dist/{plugins-XGAXDLPT.js → plugins-VP7JQH47.js} +4 -4
  77. package/dist/{sdd-runtime-6MFUXWJK.js → sdd-runtime-HIJ4Z5TF.js} +2 -2
  78. package/dist/services/sdd/state.d.ts +2 -0
  79. package/dist/session-event-wiring-types.d.ts +62 -0
  80. package/dist/session-event-wiring.d.ts +2 -52
  81. package/dist/{sessions-config-SJVQXCIE.js → sessions-config-7MK742OW.js} +2 -2
  82. package/dist/short-circuit-flags-AGHURHMQ.js +11 -0
  83. package/dist/slash-commands/command-context-fleet.d.ts +187 -0
  84. package/dist/slash-commands/command-context-sdd-goal.d.ts +102 -0
  85. package/dist/slash-commands/command-context.d.ts +3 -282
  86. package/dist/slash-commands/project-switch-interactive.d.ts +11 -0
  87. package/dist/slash-commands/setmodel-helpers.d.ts +36 -0
  88. package/dist/subcommands/handlers/hq-token.d.ts +3 -0
  89. package/dist/subcommands/handlers/hq.d.ts +0 -21
  90. package/dist/subcommands/handlers/per-subcommand-help-operations.d.ts +8 -0
  91. package/dist/subcommands/handlers/tools-cli-args.d.ts +57 -0
  92. package/dist/subcommands/handlers/tools-cli.d.ts +5 -0
  93. package/dist/subcommands/handlers/tools-serve.d.ts +4 -0
  94. package/dist/{subcommands-VTMIZQBP.js → subcommands-OCJNO57E.js} +2 -2
  95. package/dist/tool-gateway-http.d.ts +30 -0
  96. package/dist/tool-gateway.d.ts +185 -0
  97. package/dist/tools-cli-44MLIUQO.js +509 -0
  98. package/dist/tools-serve-TRCET2M7.js +102 -0
  99. package/dist/{tools-skills-55QVTMSK.js → tools-skills-WDTMCE46.js} +7 -2
  100. package/dist/tuneup-runtime-checks.d.ts +7 -0
  101. package/dist/tuneup-types.d.ts +118 -0
  102. package/dist/tuneup.d.ts +3 -122
  103. package/dist/{typesafe-YBEADNAH.js → typesafe-QLSMFU7J.js} +1 -1
  104. package/dist/{version-help-RBZC5GZZ.js → version-help-X6CC4CFY.js} +2 -2
  105. package/dist/{webui-server-HIUY3RHD.js → webui-server-V2R5WQUK.js} +79 -3
  106. package/dist/wiring/provider-runtime-setup.d.ts +3 -1
  107. package/dist/wiring/session-runtime.d.ts +1 -1
  108. package/dist/wrongforge-gateway-UOFBK56J.js +92 -0
  109. package/dist/wrongforge-leader/wrongforge-leader-gateway.d.ts +9 -0
  110. package/dist/wrongforge-leader/wrongforge-leader-picker.d.ts +12 -0
  111. package/dist/wrongforge-leader/wrongforge-leader-provider.d.ts +49 -0
  112. package/package.json +34 -30
  113. package/dist/auth-menu/anthropic-oauth.d.ts +0 -43
  114. package/dist/chunk-XT3NAHRX.js +0 -337
  115. package/dist/chunk-ZNNFEKDZ.js +0 -319
  116. package/dist/mcp-2XWBJEQN.js +0 -464
  117. package/dist/short-circuit-flags-CPCT5MWB.js +0 -11
@@ -0,0 +1,28 @@
1
+ import type { createHqPersistence, HqCommandAuditLog, HqEventEnvelope } from '@wrongstack/core/hq';
2
+ import type { WebSocket } from '../ws-runtime.js';
3
+ import type { LoginAttemptStore } from './login-attempt-store.js';
4
+ import type { ConnectedClient, HqSessionEntry } from './types.js';
5
+ export declare const HQ_SESSION_CLEANUP_INTERVAL_MS = 60000;
6
+ /**
7
+ * Expire browser sessions (absolute max age, idle timeout, abandoned 2FA) and
8
+ * forget login-attempt counters older than 15 minutes.
9
+ */
10
+ export declare function sweepHqBrowserSessions(sessions: Map<string, HqSessionEntry>, loginAttempts: LoginAttemptStore, socketCredentials: {
11
+ closeSessionSockets(sessionId: string, reason: string): void;
12
+ }): void;
13
+ export interface StaleHqClientSweep {
14
+ clients: Map<WebSocket, ConnectedClient>;
15
+ browsers: Set<WebSocket>;
16
+ auditLog: HqCommandAuditLog;
17
+ eventLog: HqEventEnvelope[];
18
+ persistence: ReturnType<typeof createHqPersistence>;
19
+ clientTtlMs: number;
20
+ sessionSnapshotTtlMs: number;
21
+ }
22
+ /**
23
+ * Drop clients that stopped heartbeating, expire their stale session
24
+ * snapshots (and the fleets bound to them), and reap session-summary clients
25
+ * that have held no session past the TTL. Returns whether anything changed.
26
+ */
27
+ export declare function sweepStaleHqClients({ clients, browsers, auditLog, eventLog, persistence, clientTtlMs, sessionSnapshotTtlMs, }: StaleHqClientSweep): boolean;
28
+ //# sourceMappingURL=sweeps.d.ts.map
@@ -10,9 +10,9 @@ import {
10
10
  readLocalSubagentTranscript,
11
11
  sanitizeApiError,
12
12
  startHqServer
13
- } from "./chunk-AWRZWPJ3.js";
13
+ } from "./chunk-JFYQGMMM.js";
14
14
  import "./chunk-QVITQ425.js";
15
- import "./chunk-3EXRPTAU.js";
15
+ import "./chunk-5TQ65PXQ.js";
16
16
  import "./chunk-OGVSKS4Q.js";
17
17
  import "./chunk-OZCYZYN2.js";
18
18
  import "./chunk-W23PY4IJ.js";
@@ -29,4 +29,4 @@ export {
29
29
  sanitizeApiError,
30
30
  startHqServer
31
31
  };
32
- //# sourceMappingURL=hq-server-BI23EPM7.js.map
32
+ //# sourceMappingURL=hq-server-YK7FBLL6.js.map
package/dist/index.js CHANGED
@@ -5,7 +5,10 @@ import {
5
5
  } from "./chunk-CVVQ5NCN.js";
6
6
  import {
7
7
  parseArgs
8
- } from "./chunk-75OLD563.js";
8
+ } from "./chunk-M7PSENGF.js";
9
+ import {
10
+ closeAcpLeaderSessions
11
+ } from "./chunk-LUEO5HLZ.js";
9
12
  import {
10
13
  CLI_VERSION
11
14
  } from "./chunk-HKMOIIPQ.js";
@@ -122,7 +125,7 @@ async function main(argv) {
122
125
  applyAsciiMode(earlyFlags);
123
126
  }
124
127
  if (earlyFlags["help"] === true || earlyFlags["version"] === true) {
125
- const { handleHelpVersionShortCircuit } = await import("./short-circuit-flags-CPCT5MWB.js");
128
+ const { handleHelpVersionShortCircuit } = await import("./short-circuit-flags-AGHURHMQ.js");
126
129
  const earlyExit = await handleHelpVersionShortCircuit(argv);
127
130
  if (earlyExit !== null) return earlyExit;
128
131
  }
@@ -131,7 +134,7 @@ async function main(argv) {
131
134
  shouldCaptureTuiStartup(parsed.flags, parsed.positional)
132
135
  );
133
136
  try {
134
- const { initializeCli } = await import("./cli-context-YIT4FEDM.js");
137
+ const { initializeCli } = await import("./cli-context-CQYGIWOU.js");
135
138
  const cliCtx = await initializeCli(argv, {
136
139
  onNonTuiLaunch: () => startupOutput.stop()
137
140
  });
@@ -141,7 +144,7 @@ async function main(argv) {
141
144
  } else {
142
145
  startupOutput.stop();
143
146
  }
144
- const { runInteractive } = await import("./cli-main-JIADJ5OL.js");
147
+ const { runInteractive } = await import("./cli-main-VRUJNUBX.js");
145
148
  return await runInteractive(cliCtx);
146
149
  } finally {
147
150
  startupOutput.stop();
@@ -252,7 +255,7 @@ function runCliProcess(mainFn) {
252
255
  mainFn(process.argv.slice(2)).then(
253
256
  (c) => {
254
257
  process.exitCode = c;
255
- scheduleForcedExit(c);
258
+ void closeAcpLeaderSessions().finally(() => scheduleForcedExit(c));
256
259
  },
257
260
  (err) => {
258
261
  runFatalSalvageSync();
@@ -0,0 +1,236 @@
1
+ import {
2
+ serveMcpStdio
3
+ } from "./chunk-QLYPIJ7X.js";
4
+ import "./chunk-LYWOV4OX.js";
5
+ import {
6
+ activeProfileConfigPath
7
+ } from "./chunk-SPSHEZ46.js";
8
+ import {
9
+ restoreFlags
10
+ } from "./chunk-QC6CLAK7.js";
11
+ import "./chunk-W23PY4IJ.js";
12
+
13
+ // src/subcommands/handlers/mcp.ts
14
+ import { allServers, resolveMcpServerConfig } from "@wrongstack/core/infrastructure";
15
+ import {
16
+ expectDefined,
17
+ jsonObjectFileExists,
18
+ readJsonObjectFile,
19
+ removeJsonPath,
20
+ setJsonPath,
21
+ updateJsonObjectFile
22
+ } from "@wrongstack/core/utils";
23
+
24
+ // src/mcp-serve-project.ts
25
+ var PROJECT_MCP_SERVERS = [
26
+ "mailbox",
27
+ "kanban",
28
+ "codebase-index",
29
+ "requirement-intake",
30
+ "sage"
31
+ ];
32
+ function isProjectMcpServer(value) {
33
+ return PROJECT_MCP_SERVERS.includes(value);
34
+ }
35
+ var SERVER_FLAGS = [
36
+ "project-root",
37
+ "actor",
38
+ "session-id",
39
+ "name",
40
+ "role",
41
+ "writable",
42
+ "admin",
43
+ "destructive",
44
+ "http",
45
+ "stdio",
46
+ "port",
47
+ "host",
48
+ "token",
49
+ "index-dir",
50
+ "origin",
51
+ "watch"
52
+ ];
53
+ var SWITCHES = /* @__PURE__ */ new Set([
54
+ "--writable",
55
+ "--admin",
56
+ "--destructive",
57
+ "--http",
58
+ "--stdio",
59
+ "--watch"
60
+ ]);
61
+ function normalizeSwitches(args) {
62
+ const out = [];
63
+ for (let i = 0; i < args.length; i++) {
64
+ const arg = args[i];
65
+ const eq = arg.indexOf("=");
66
+ const flag = eq === -1 ? arg : arg.slice(0, eq);
67
+ if (!SWITCHES.has(flag)) {
68
+ out.push(arg);
69
+ continue;
70
+ }
71
+ const value = eq === -1 ? void 0 : arg.slice(eq + 1);
72
+ if (value === "false") continue;
73
+ out.push(flag);
74
+ if (eq === -1 && args[i + 1] === "true") i++;
75
+ }
76
+ return out;
77
+ }
78
+ function optionValue(args, name) {
79
+ const flag = `--${name}`;
80
+ for (let i = 0; i < args.length; i++) {
81
+ const arg = args[i];
82
+ if (arg === flag) {
83
+ const next = args[i + 1];
84
+ return next !== void 0 && !next.startsWith("--") ? next : void 0;
85
+ }
86
+ if (arg.startsWith(`${flag}=`)) return arg.slice(flag.length + 1);
87
+ }
88
+ return void 0;
89
+ }
90
+ async function serveProjectMcp(server, rawArgs, deps) {
91
+ const args = normalizeSwitches(restoreFlags(rawArgs, deps, SERVER_FLAGS));
92
+ if (server === "sage") {
93
+ const { serveAttachedSageMcpStdio } = await import("@wrongstack/sage-mcp");
94
+ await serveAttachedSageMcpStdio({
95
+ // A client may start this server from any directory; an explicit root wins.
96
+ projectRoot: optionValue(args, "project-root") ?? deps.projectRoot,
97
+ directory: deps.config.Sage?.storage?.directory,
98
+ origin: optionValue(args, "origin")?.trim() || "mcp-client"
99
+ });
100
+ return 0;
101
+ }
102
+ const argv = optionValue(args, "project-root") === void 0 ? [...args, "--project-root", deps.projectRoot] : args;
103
+ if (server === "mailbox") {
104
+ const { runMailboxMcpServer } = await import("@wrongstack/mailbox-mcp");
105
+ return runMailboxMcpServer(argv);
106
+ }
107
+ if (server === "kanban") {
108
+ const { runKanbanMcpServer } = await import("@wrongstack/kanban-mcp");
109
+ return runKanbanMcpServer(argv);
110
+ }
111
+ if (server === "requirement-intake") {
112
+ const { runRequirementIntakeMcpServer } = await import("@wrongstack/requirement-intake-mcp");
113
+ return runRequirementIntakeMcpServer(argv);
114
+ }
115
+ const { runCodebaseIndexMcpServer } = await import("@wrongstack/codebase-index-mcp");
116
+ return runCodebaseIndexMcpServer(argv);
117
+ }
118
+
119
+ // src/subcommands/handlers/mcp.ts
120
+ var BUILT_IN_MCP = allServers();
121
+ var mcpCmd = async (args, deps) => {
122
+ args = restoreFlags(args, deps, ["enable", "e", "transport", "url", "command"]);
123
+ const sub = args[0];
124
+ if (sub === "serve") {
125
+ if (isProjectMcpServer(args[1])) return serveProjectMcp(args[1], args.slice(2), deps);
126
+ return serveMcpStdio(deps, args.slice(1));
127
+ }
128
+ if (!sub || sub === "list") {
129
+ const servers = deps.config.mcpServers ?? {};
130
+ if (Object.keys(servers).length === 0) {
131
+ deps.renderer.write("No MCP servers configured.\n");
132
+ deps.renderer.write("Use `wstack mcp add <name>` or set mcpServers in your config.\n");
133
+ return 0;
134
+ }
135
+ for (const [name, entry] of Object.entries(servers)) {
136
+ const cfg = resolveMcpServerConfig(name, entry);
137
+ const status = entry?.enabled === false ? "disabled" : "enabled";
138
+ const description = cfg?.description ?? entry?.description;
139
+ const desc = description ? ` # ${description}` : "";
140
+ const transport = cfg?.transport ?? "invalid (no transport)";
141
+ deps.renderer.write(` ${name.padEnd(20)} ${transport.padEnd(16)} ${status}${desc}
142
+ `);
143
+ }
144
+ return 0;
145
+ }
146
+ if (sub === "add") {
147
+ return addMcpServer(args, deps);
148
+ }
149
+ if (sub === "remove") {
150
+ const name = args[1];
151
+ if (!name) {
152
+ deps.renderer.writeError("Usage: wstack mcp remove <name>\n");
153
+ return 1;
154
+ }
155
+ return removeMcpServer(name, deps);
156
+ }
157
+ if (sub === "restart") {
158
+ deps.renderer.writeWarning(
159
+ "mcp restart is only available in REPL mode. Use /mcp restart instead."
160
+ );
161
+ return 0;
162
+ }
163
+ deps.renderer.writeError(`Unknown mcp subcommand: ${sub}`);
164
+ return 1;
165
+ };
166
+ async function addMcpServer(args, deps) {
167
+ const configPath = activeProfileConfigPath(deps.paths, deps.config);
168
+ const name = args[1];
169
+ const enable = args.includes("--enable") || args.includes("-e");
170
+ if (!name) {
171
+ deps.renderer.writeError("Usage: wstack mcp add <name>\n");
172
+ deps.renderer.write("Available servers:\n");
173
+ for (const [sname, scfg] of Object.entries(deps.config.mcpServers ?? {}))
174
+ deps.renderer.write(` ${sname.padEnd(20)} ${scfg.description ?? scfg.transport}
175
+ `);
176
+ if (Object.keys(deps.config.mcpServers ?? {}).length === 0)
177
+ for (const k of Object.keys(BUILT_IN_MCP)) {
178
+ const s = expectDefined(BUILT_IN_MCP[k]);
179
+ deps.renderer.write(` ${k.padEnd(20)} ${s.description}
180
+ `);
181
+ }
182
+ deps.renderer.write("\nRun `wstack mcp add <name> --enable` to enable immediately.\n");
183
+ return 1;
184
+ }
185
+ const factory = Object.hasOwn(BUILT_IN_MCP, name) ? BUILT_IN_MCP[name] : void 0;
186
+ if (!factory) {
187
+ deps.renderer.writeError(
188
+ `Unknown server "${name}". Run \`wstack mcp add\` without args to see available servers.
189
+ `
190
+ );
191
+ return 1;
192
+ }
193
+ const serverCfg = { ...factory };
194
+ serverCfg.enabled = enable;
195
+ const existing = await readJsonObjectFile(configPath);
196
+ const mcpServers = isRecord(existing.mcpServers) ? existing.mcpServers : {};
197
+ if (Object.hasOwn(mcpServers, name))
198
+ deps.renderer.writeWarning(`Server "${name}" already in config. Updating.
199
+ `);
200
+ await updateJsonObjectFile(configPath, (config) => {
201
+ setJsonPath(config, ["mcpServers", name], serverCfg);
202
+ });
203
+ const verb = enable ? "Enabled" : "Added (disabled \u2014 set enabled:true to activate)";
204
+ deps.renderer.writeInfo(
205
+ `${verb} "${name}" (${serverCfg.transport}). Config written to ${configPath}.
206
+ `
207
+ );
208
+ return 0;
209
+ }
210
+ async function removeMcpServer(name, deps) {
211
+ const configPath = activeProfileConfigPath(deps.paths, deps.config);
212
+ if (!await jsonObjectFileExists(configPath)) {
213
+ deps.renderer.writeError("No config file found.\n");
214
+ return 1;
215
+ }
216
+ const existing = await readJsonObjectFile(configPath);
217
+ const mcpServers = isRecord(existing.mcpServers) ? existing.mcpServers : {};
218
+ if (!Object.hasOwn(mcpServers, name)) {
219
+ deps.renderer.writeError(`Server "${name}" not in config.
220
+ `);
221
+ return 1;
222
+ }
223
+ await updateJsonObjectFile(configPath, (config) => {
224
+ removeJsonPath(config, ["mcpServers", name]);
225
+ });
226
+ deps.renderer.writeInfo(`Removed "${name}" from config.
227
+ `);
228
+ return 0;
229
+ }
230
+ function isRecord(value) {
231
+ return typeof value === "object" && value !== null && !Array.isArray(value);
232
+ }
233
+ export {
234
+ mcpCmd
235
+ };
236
+ //# sourceMappingURL=mcp-22CFBX4H.js.map
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `wstack mcp serve <mailbox|kanban|codebase-index|requirement-intake|sage>` — run one of
3
+ * WrongStack's project MCP servers from inside `wstack` itself.
4
+ *
5
+ * Mailbox, Kanban, Codebase Index and Requirements Intake also ship as their own npm bins
6
+ * (`wstack-mailbox-mcp`, …), but the standalone binary carries none of them,
7
+ * so this is the launch path that works in every install. Each server is bound
8
+ * to one project: `--project-root` defaults to the project this command runs
9
+ * in, and every server only attaches to that project's running owner.
10
+ *
11
+ * stdout is the JSON-RPC channel; everything else goes to stderr.
12
+ */
13
+ import type { SubcommandDeps } from './subcommands/contracts.js';
14
+ export declare const PROJECT_MCP_SERVERS: readonly ['mailbox', 'kanban', 'codebase-index', 'requirement-intake', 'sage'];
15
+ export type ProjectMcpServer = (typeof PROJECT_MCP_SERVERS)[number];
16
+ export declare function isProjectMcpServer(value: string | undefined): value is ProjectMcpServer;
17
+ export declare function serveProjectMcp(server: ProjectMcpServer, rawArgs: string[], deps: SubcommandDeps): Promise<number>;
18
+ //# sourceMappingURL=mcp-serve-project.d.ts.map
@@ -1,39 +1,5 @@
1
- import { Context } from '@wrongstack/core/agent';
2
- import { ToolRegistry } from '@wrongstack/core/registry';
3
- import { AutoApprovePermissionPolicy } from '@wrongstack/core/security';
4
- import type { PermissionPolicy, Tool } from '@wrongstack/core/types';
5
1
  import { type MCPServerPrompt, type MCPServerResource } from '@wrongstack/mcp';
6
2
  import type { SubcommandDeps } from './subcommands/contracts.js';
7
- /**
8
- * `--yolo` for `mcp serve`: widen the CAPABILITY allowlist, keep every guard.
9
- *
10
- * This replaced an `AllowAllPermissionPolicy extends AutoApprovePermissionPolicy`
11
- * whose `evaluate()` returned `{ permission: 'auto' }` unconditionally. That
12
- * override skipped the whole base implementation — the sensitive-read denial,
13
- * the leader deny rules, the destructive-command classifier, the agent-state
14
- * write guard, and `LOCKED_DESTRUCTIVE_KINDS`. It was the only place in the
15
- * codebase where `agent-state` and `credential-bind` could be un-gated, so a
16
- * third-party MCP client could have written `hooks` into config.json (boot-time
17
- * RCE) or `auto: true` into trust.json.
18
- *
19
- * It did not actually get there — but only by accident, and the accident is the
20
- * reason this is a rewrite rather than a patch. The override returned
21
- * `source: 'default'` where the base class returns `source: 'yolo'`, so
22
- * `ToolExecutor.capabilityDowngraded` re-armed and forced `confirm`; `mcp serve`
23
- * has no confirmAwaiter, so the call hard-errored. Changing that one string
24
- * literal to `'yolo'` — which reads as a trivial consistency cleanup — would
25
- * have made the bypass live. Safety must not rest on a string nobody knows is
26
- * load-bearing.
27
- *
28
- * Granting every capability is what `--yolo` actually means, and it is what
29
- * lets `ToolExecutor` trust an `auto` instead of downgrading it (see the
30
- * `dangerousNotAllowed` reasoning in `auto-approve-policy.ts`). The destructive
31
- * classifier is deliberately NOT relaxed: `yoloConfirmKinds` is left at its
32
- * default, which gates every destructive kind. Destructive calls therefore
33
- * still require a confirmation this surface cannot answer, exactly as before —
34
- * this change removes a latent bypass without widening anything.
35
- */
36
- export declare function yoloServePolicy(): AutoApprovePermissionPolicy;
37
3
  /**
38
4
  * Resolve the `--tools` whitelist for `mcp serve`.
39
5
  *
@@ -60,35 +26,6 @@ interface SelectedMcpServeContent {
60
26
  }
61
27
  /** Load only files explicitly named by trusted CLI flags; nothing is auto-discovered. */
62
28
  export declare function loadSelectedMcpServeContent(flags: Record<string, string | boolean>, cwd: string): Promise<SelectedMcpServeContent>;
63
- /**
64
- * Whether the file tools are confined to the project root for `mcp serve`.
65
- *
66
- * `mcp serve` is the one surface where the file tools are driven by a REMOTE
67
- * caller, so an unset config must inherit containment rather than invert it —
68
- * an unset value here previously became `false`, which short-circuited
69
- * `ensureInsideRoot` and let `tools/call read` return `~/.ssh/id_rsa`.
70
- *
71
- * This lives in one exported function rather than as a literal repeated at each
72
- * call site so the invariant is testable and a third call site cannot quietly
73
- * reintroduce the wrong default. Only a trusted user config can opt out:
74
- * `tools.restrictToProjectRoot` is on the in-project denylist, so a
75
- * checked-out repository cannot reach it.
76
- */
77
- export declare function resolveServeFsRestriction(config: {
78
- tools?: {
79
- restrictToProjectRoot?: boolean | undefined;
80
- } | undefined;
81
- }): boolean;
82
- /** Minimal run context — tools read cwd/projectRoot/signal; provider/session are stubs. */
83
- export declare function makeServeContext(cwd: string, projectRoot: string, signal: AbortSignal, restrictFsToRoot?: boolean): Context;
84
- /**
85
- * Compute the set of tools an MCP-serve session exposes: a tool is included
86
- * only if it passes the whitelist (when set) AND the permission policy returns
87
- * `auto`. With `AutoApprovePermissionPolicy` this withholds shell/write/edit and
88
- * dangerous-capability tools; with the `--yolo` policy everything passes.
89
- * Exported for testing — the live path calls it inside `serveMcpStdio`.
90
- */
91
- export declare function selectExposedTools(registry: ToolRegistry, ctx: Context, policy: PermissionPolicy, whitelist: Set<string> | null): Promise<Tool[]>;
92
29
  export declare function serveMcpStdio(deps: SubcommandDeps, positional?: readonly string[]): Promise<number>;
93
30
  export {};
94
31
  //# sourceMappingURL=mcp-serve.d.ts.map
@@ -1,9 +1,6 @@
1
1
  import {
2
2
  applyProviderOAuthRefresh
3
3
  } from "./chunk-TXWL3BZ5.js";
4
- import {
5
- discoverAndMergeProviders
6
- } from "./chunk-RBZVDWTL.js";
7
4
  import {
8
5
  checkMark,
9
6
  costLabel,
@@ -18,6 +15,9 @@ import {
18
15
  scoreBar,
19
16
  speedLabel
20
17
  } from "./chunk-FPUB5WWP.js";
18
+ import {
19
+ discoverAndMergeProviders
20
+ } from "./chunk-RBZVDWTL.js";
21
21
  import {
22
22
  mutateConfigProviders
23
23
  } from "./chunk-ZCXZGYO5.js";
@@ -844,4 +844,4 @@ var modeldiagCmd = async (args, deps) => {
844
844
  export {
845
845
  modeldiagCmd
846
846
  };
847
- //# sourceMappingURL=modeldiag-HDIKG37X.js.map
847
+ //# sourceMappingURL=modeldiag-5PBB777J.js.map
@@ -7,7 +7,7 @@ import {
7
7
  renderFocusedHelpToString,
8
8
  renderGenericHelp,
9
9
  subcommandsWithFocusedHelp
10
- } from "./chunk-3R3OADC5.js";
10
+ } from "./chunk-P7MEEUGT.js";
11
11
  import "./chunk-ZXX3MJRL.js";
12
12
  import "./chunk-W23PY4IJ.js";
13
13
  export {
@@ -20,4 +20,4 @@ export {
20
20
  renderGenericHelp,
21
21
  subcommandsWithFocusedHelp
22
22
  };
23
- //# sourceMappingURL=per-subcommand-help-D6J4ZXW2.js.map
23
+ //# sourceMappingURL=per-subcommand-help-MQGERD4E.js.map
@@ -0,0 +1,9 @@
1
+ import type { PluginManagementDeps, PluginManagementResult } from './plugin-management-types.js';
2
+ /**
3
+ * `wstack plugin llm …` — per-plugin LLM routing. The chat leader's
4
+ * provider/model stays the DEFAULT; this stores an override under
5
+ * `config.extensions[<plugin>].llm = { provider?, model? }` which
6
+ * `api.llm` resolves ahead of the session default on every call.
7
+ */
8
+ export declare function runPluginLlmCommand(args: string[], deps: PluginManagementDeps): Promise<PluginManagementResult>;
9
+ //# sourceMappingURL=plugin-llm-command.d.ts.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  runPluginManagementCommand
3
- } from "./chunk-VAQXOZKP.js";
3
+ } from "./chunk-AJM4EFCM.js";
4
4
  import {
5
5
  activeProfileConfigPath
6
6
  } from "./chunk-SPSHEZ46.js";
7
- import "./chunk-BIGSVBPI.js";
7
+ import "./chunk-KNYIEQAY.js";
8
8
  import {
9
9
  restoreFlags
10
10
  } from "./chunk-QC6CLAK7.js";
@@ -42,4 +42,4 @@ export {
42
42
  pluginCmd,
43
43
  usageCmd
44
44
  };
45
- //# sourceMappingURL=plugin-usage-TYF5HY4K.js.map
45
+ //# sourceMappingURL=plugin-usage-UWKYMNQU.js.map
@@ -7,10 +7,10 @@ import {
7
7
  pluginNameFromSpec,
8
8
  setupPlugins,
9
9
  warnIfDeprecatedPluginName
10
- } from "./chunk-TZPKOS5G.js";
10
+ } from "./chunk-2XQ6SRKG.js";
11
11
  import "./chunk-P24ZPPYH.js";
12
- import "./chunk-VAQXOZKP.js";
13
- import "./chunk-BIGSVBPI.js";
12
+ import "./chunk-AJM4EFCM.js";
13
+ import "./chunk-KNYIEQAY.js";
14
14
  import "./chunk-W23PY4IJ.js";
15
15
  export {
16
16
  BUILTIN_PLUGIN_FACTORIES,
@@ -22,4 +22,4 @@ export {
22
22
  setupPlugins,
23
23
  warnIfDeprecatedPluginName
24
24
  };
25
- //# sourceMappingURL=plugins-XGAXDLPT.js.map
25
+ //# sourceMappingURL=plugins-VP7JQH47.js.map
@@ -14,7 +14,7 @@ import {
14
14
  trySaveImplementationPlan,
15
15
  trySaveSpecFromAIOutput,
16
16
  trySaveTasksFromAIOutput
17
- } from "./chunk-WDXNBYGD.js";
17
+ } from "./chunk-TDP7CZGE.js";
18
18
  import "./chunk-W23PY4IJ.js";
19
19
  export {
20
20
  advanceToNextTask,
@@ -32,4 +32,4 @@ export {
32
32
  trySaveSpecFromAIOutput,
33
33
  trySaveTasksFromAIOutput
34
34
  };
35
- //# sourceMappingURL=sdd-runtime-6MFUXWJK.js.map
35
+ //# sourceMappingURL=sdd-runtime-HIJ4Z5TF.js.map
@@ -24,6 +24,8 @@ export declare class SDDState {
24
24
  getSessionElapsed(): number;
25
25
  getPhaseElapsed(): number;
26
26
  getVersioning(): SpecVersioning;
27
+ /** Drain fire-and-forget tracker writes before deleting or replacing the store. */
28
+ flushTaskWrites(): Promise<void>;
27
29
  clearTaskState(): void;
28
30
  getContext(): string | null;
29
31
  getPhase(): AISpecPhase | null;
@@ -0,0 +1,62 @@
1
+ import type { ChronicleEventJournalHandle, ChronicleEventSink } from '@wrongstack/core/chronicle';
2
+ import { createChronicleEventJournal } from '@wrongstack/core/chronicle';
3
+ import type { EventBus } from '@wrongstack/core/kernel';
4
+ import type { SessionEventBridge } from '@wrongstack/core/storage';
5
+ export interface ErrorEntry {
6
+ ts: string;
7
+ phase: string;
8
+ code: string;
9
+ message: string;
10
+ }
11
+ export interface WireSessionEventsDeps {
12
+ evOn: (event: string, handler: (...args: any[]) => void) => void;
13
+ /** Concrete bus is required for Chronicle lifecycle subscriptions. */
14
+ events?: EventBus | undefined;
15
+ config: Record<string, unknown>;
16
+ context: Record<string, unknown>;
17
+ session: {
18
+ id: string;
19
+ };
20
+ sessionRef: {
21
+ current?: {
22
+ id: string;
23
+ } | undefined;
24
+ };
25
+ wpaths: {
26
+ globalRoot: string;
27
+ projectSlug: string;
28
+ projectHash?: string | undefined;
29
+ projectDir?: string | undefined;
30
+ };
31
+ projectRoot: string;
32
+ renderer?: {
33
+ writeInfo?: (msg: string) => void;
34
+ };
35
+ tuiOwnsScreen?: boolean;
36
+ }
37
+ export interface WireSessionEventsResult {
38
+ errorRing: ErrorEntry[];
39
+ sessionBridge: SessionEventBridge;
40
+ appendSessionEvent: (sessionId: string | undefined, event: Parameters<SessionEventBridge['append']>[0]) => void;
41
+ chronicleJournal?: ChronicleEventSink | undefined;
42
+ disposeChronicle: () => Promise<void>;
43
+ }
44
+ /** `0` disables auto-purge; positive values are floored at 7 days so a
45
+ * project-committed config cannot flush recent evidence. */
46
+ export declare function resolveChronicleRetentionDays(config: Record<string, unknown>): number;
47
+ /** Read a positive numeric `chronicle.*` knob, or undefined to keep the default. */
48
+ export declare function chronicleLimit(config: Record<string, unknown>, key: string): number | undefined;
49
+ /**
50
+ * Open the Chronicle journal, or give up on telemetry for this session.
51
+ *
52
+ * `createChronicleEventJournal` fails closed: rather than quietly handing this
53
+ * process its own hash chain when the daemon build cannot be located, it
54
+ * raises. Chronicle is observability, though — losing it must never stop a
55
+ * user from working. So the failure is absorbed here, once, and reported.
56
+ *
57
+ * Note what is *not* done: no silent retry into an inline journal. Telemetry is
58
+ * either recorded by the project's single owner or not recorded at all, and the
59
+ * operator is told which.
60
+ */
61
+ export declare function tryCreateChronicleJournal(options: Parameters<typeof createChronicleEventJournal>[0]): ChronicleEventJournalHandle | undefined;
62
+ //# sourceMappingURL=session-event-wiring-types.d.ts.map
@@ -1,57 +1,7 @@
1
- /**
2
- * session-event-wiring — EventBus subscriptions for session audit logging,
3
- * error tracking, and file-author recording. Also owns the
4
- * SessionEventBridge and appendSessionEvent helper that gates on session
5
- * identity so stale sessions don't pollute the current log.
6
- *
7
- * Extracted from cli-main.ts's monolithic main() to reduce cognitive load
8
- * and enable focused testing.
9
- */
10
- import type { ChronicleEventSink } from '@wrongstack/core/chronicle';
11
- import type { EventBus } from '@wrongstack/core/kernel';
12
- import type { SessionEventBridge } from '@wrongstack/core/storage';
13
- export interface ErrorEntry {
14
- ts: string;
15
- phase: string;
16
- code: string;
17
- message: string;
18
- }
19
- interface WireSessionEventsDeps {
20
- evOn: (event: string, handler: (...args: any[]) => void) => void;
21
- /** Concrete bus is required for Chronicle lifecycle subscriptions. */
22
- events?: EventBus | undefined;
23
- config: Record<string, unknown>;
24
- context: Record<string, unknown>;
25
- session: {
26
- id: string;
27
- };
28
- sessionRef: {
29
- current?: {
30
- id: string;
31
- } | undefined;
32
- };
33
- wpaths: {
34
- globalRoot: string;
35
- projectSlug: string;
36
- projectHash?: string | undefined;
37
- projectDir?: string | undefined;
38
- };
39
- projectRoot: string;
40
- renderer?: {
41
- writeInfo?: (msg: string) => void;
42
- };
43
- tuiOwnsScreen?: boolean;
44
- }
45
- interface WireSessionEventsResult {
46
- errorRing: ErrorEntry[];
47
- sessionBridge: SessionEventBridge;
48
- appendSessionEvent: (sessionId: string | undefined, event: Parameters<SessionEventBridge['append']>[0]) => void;
49
- chronicleJournal?: ChronicleEventSink | undefined;
50
- disposeChronicle: () => Promise<void>;
51
- }
1
+ import type { WireSessionEventsDeps, WireSessionEventsResult } from './session-event-wiring-types.js';
2
+ export type { ErrorEntry } from './session-event-wiring-types.js';
52
3
  /** Wire SessionEventBridge, appendSessionEvent, error ring, and tool-lifecycle
53
4
  * session audit events. Returns the sessionBridge (for compaction / audit-level
54
5
  * changes) and the error ring array (for /diag). */
55
6
  export declare function wireSessionEvents(deps: WireSessionEventsDeps): WireSessionEventsResult;
56
- export {};
57
7
  //# sourceMappingURL=session-event-wiring.d.ts.map