@wrongstack/cli 1.0.28 → 1.0.32

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 (135) hide show
  1. package/data/providers.json +8 -177
  2. package/dist/{acp-M4565YUW.js → acp-EDGUWU7N.js} +4 -7
  3. package/dist/{audit-46YK5DSC.js → audit-KCBTHUQI.js} +1 -1
  4. package/dist/{auth-TE55JF4Z.js → auth-SUHKFFO4.js} +136 -59
  5. package/dist/auth-menu/github-copilot-oauth.d.ts +1 -35
  6. package/dist/auth-menu/index-input.d.ts +3 -0
  7. package/dist/auth-menu/panel-flow-bridge.d.ts +29 -0
  8. package/dist/auth-menu/panel-service.d.ts +3 -34
  9. package/dist/auth-menu/provider-auth-login.d.ts +1 -1
  10. package/dist/auto-discover-providers-QIL34K3U.js +7 -0
  11. package/dist/automation-MCDFCIMV.js +369 -0
  12. package/dist/{bench-GTLPM22B.js → bench-MMZHFHDL.js} +152 -43
  13. package/dist/boot/brain-decision-log.d.ts +1 -1
  14. package/dist/boot/system-prompt-builder.d.ts +1 -1
  15. package/dist/boot/system-prompt-menu.d.ts +11 -2
  16. package/dist/boot/tui-coordinator-setup.d.ts +2 -0
  17. package/dist/boot/tui-startup-output.d.ts +11 -0
  18. package/dist/{boot-auto-thin-6Q56FY3F.js → boot-auto-thin-K2DHHYIW.js} +3 -3
  19. package/dist/{chronicle-UTFETHP6.js → chronicle-PBJS7BN6.js} +5 -3
  20. package/dist/{chunk-EPR42SWM.js → chunk-2EZ2DHOW.js} +60 -7
  21. package/dist/{chunk-7IQWQCBH.js → chunk-3LEFXLAW.js} +39 -39
  22. package/dist/{chunk-WSTVGC2C.js → chunk-4BX2YDTQ.js} +13 -6
  23. package/dist/{chunk-SFBFYIOW.js → chunk-4MDRHMX4.js} +3 -2
  24. package/dist/{chunk-RGFWGUAB.js → chunk-4UWCMBPG.js} +159 -3
  25. package/dist/{chunk-RDGGWMTI.js → chunk-65VNCAF6.js} +2 -22
  26. package/dist/{chunk-WQZW3RDP.js → chunk-7BNBD4PE.js} +2 -2
  27. package/dist/chunk-CFHWIFXL.js +123 -0
  28. package/dist/{chunk-RZ4ZDRYA.js → chunk-DIOODAYM.js} +2 -2
  29. package/dist/{chunk-L2RVEQWO.js → chunk-HHRYIDOW.js} +2 -2
  30. package/dist/chunk-LIZXJHZQ.js +61 -0
  31. package/dist/{chunk-YHYINL47.js → chunk-LKFKO4JW.js} +2 -2
  32. package/dist/{chunk-Q4INH2DG.js → chunk-MPQCHBDJ.js} +2 -1
  33. package/dist/{chunk-2ERX3RPN.js → chunk-P3GRLV47.js} +30 -17
  34. package/dist/{chunk-ZMX5HRLI.js → chunk-P3Q3KMFH.js} +6 -4
  35. package/dist/{chunk-KOEO4CJG.js → chunk-PGNERAZL.js} +4 -4
  36. package/dist/{chunk-ENRYW73H.js → chunk-RQ4UBKYH.js} +81 -10
  37. package/dist/{chunk-X756ZS72.js → chunk-SUDNPYWD.js} +2 -2
  38. package/dist/{chunk-LDCGZJTC.js → chunk-TWSQTQKR.js} +12 -4
  39. package/dist/chunk-TXAFIERF.js +37 -0
  40. package/dist/{chunk-UZ2TMHNH.js → chunk-UKP7H2U4.js} +10 -2
  41. package/dist/{chunk-5JYDKG5B.js → chunk-WHEYHDIE.js} +7 -2
  42. package/dist/{chunk-LBPLTTZ6.js → chunk-WTJDSTYD.js} +4 -4
  43. package/dist/{chunk-L5TD7UIG.js → chunk-WXJH4F6K.js} +7 -7
  44. package/dist/{chunk-IS2PPBQV.js → chunk-X4LW5CZM.js} +8 -4
  45. package/dist/{chunk-BBHWW6LR.js → chunk-YL4KCHZG.js} +18 -6
  46. package/dist/{chunk-LUMETJFO.js → chunk-ZYACRPLN.js} +2 -2
  47. package/dist/{cli-context-O2SHBDFH.js → cli-context-ITHGP2CE.js} +91 -84
  48. package/dist/cli-context.d.ts +3 -1
  49. package/dist/cli-infrastructure.d.ts +33 -0
  50. package/dist/{cli-main-BKG4ZVLN.js → cli-main-TQGLKB6D.js} +3783 -2753
  51. package/dist/config-doctor.d.ts +1 -1
  52. package/dist/{config-transfer-RUWLDCNK.js → config-transfer-UE37X4B5.js} +2 -2
  53. package/dist/{execution-THXWTHYT.js → execution-C2IECWF7.js} +5271 -5118
  54. package/dist/execution-chimera-handlers.d.ts +6 -0
  55. package/dist/execution-session-callbacks.d.ts +36 -0
  56. package/dist/execution-webui.d.ts +3 -0
  57. package/dist/execution.d.ts +1 -1
  58. package/dist/fleet/host-acp-runner.d.ts +15 -0
  59. package/dist/fleet/host-budget.d.ts +13 -0
  60. package/dist/fleet/host-context.d.ts +5 -0
  61. package/dist/fleet/host-explore-companion.d.ts +7 -16
  62. package/dist/fleet/host.d.ts +2 -0
  63. package/dist/fleet/status-broadcast.d.ts +1 -1
  64. package/dist/{hq-44F4OQH2.js → hq-KBFDKTDD.js} +13 -7
  65. package/dist/hq-publisher.d.ts +4 -1
  66. package/dist/hq-server/sage-sync-send.d.ts +5 -0
  67. package/dist/hq-server/server-lifecycle.d.ts +1 -1
  68. package/dist/hq-server/snapshot.d.ts +1 -1
  69. package/dist/{hq-server-UIB24LU6.js → hq-server-AVNKZ2PV.js} +2 -2
  70. package/dist/{hq-service-BMMJAHRT.js → hq-service-FGB7BY2D.js} +3 -3
  71. package/dist/hq-ttl-N4DAIAVX.js +7 -0
  72. package/dist/index.js +126 -10
  73. package/dist/{mailbox-serve-GNGXEQ2R.js → mailbox-serve-S536N66F.js} +4 -3
  74. package/dist/{modeldiag-W7XAE625.js → modeldiag-PQILD7TN.js} +26 -8
  75. package/dist/{per-subcommand-help-QDAQASPZ.js → per-subcommand-help-VKPV3OEY.js} +2 -2
  76. package/dist/{plugin-usage-CIGOOTX3.js → plugin-usage-3TZGROK7.js} +3 -3
  77. package/dist/{plugins-HQTXUD6A.js → plugins-ITH4SLO6.js} +4 -4
  78. package/dist/pre-launch/project-check.d.ts +2 -8
  79. package/dist/pre-launch.d.ts +1 -1
  80. package/dist/{project-manifest-7NSFVBM3.js → project-manifest-FTFDCCTZ.js} +2 -2
  81. package/dist/{project-picker-SVBXMPKX.js → project-picker-NZYJKQQC.js} +3 -3
  82. package/dist/provider-cloud-config.d.ts +4 -0
  83. package/dist/provider-config-utils.d.ts +1 -1
  84. package/dist/{providers-models-5Z2PJTEW.js → providers-models-W57I3QOA.js} +3 -3
  85. package/dist/{remote-GB5VXCCT.js → remote-C74BCNND.js} +5 -5
  86. package/dist/{rewind-JA3ZLCNM.js → rewind-7AULJS7F.js} +7 -5
  87. package/dist/sage-FFKUOCQL.js +475 -0
  88. package/dist/sage-connect.d.ts +62 -0
  89. package/dist/sage-hq-sync.d.ts +8 -0
  90. package/dist/sage-sync-ZMTHB477.js +69 -0
  91. package/dist/sandbox-TYGD6FI2.js +131 -0
  92. package/dist/services/sdd/project-context.d.ts +1 -1
  93. package/dist/{sessions-config-XHLXJ5C3.js → sessions-config-VE26SB56.js} +19 -8
  94. package/dist/short-circuit-flags-6LB3EGF7.js +10 -0
  95. package/dist/slash-commands/openai-quota.d.ts +12 -6
  96. package/dist/slash-commands/sandbox.d.ts +5 -0
  97. package/dist/slash-commands/scout-stats.d.ts +46 -0
  98. package/dist/slash-commands/sdd-inspect-commands.d.ts +9 -0
  99. package/dist/slash-commands/sdd-session-commands.d.ts +19 -0
  100. package/dist/slash-commands/sdd.d.ts +1 -1
  101. package/dist/slash-commands/zai-plan.d.ts +26 -0
  102. package/dist/{standalone-auto-update-TOTRGCSA.js → standalone-auto-update-VQC4GYCM.js} +3 -3
  103. package/dist/{standalone-update-LZO3MNLH.js → standalone-update-HZHDZZOR.js} +2 -2
  104. package/dist/subcommands/handlers/automation-credentials.d.ts +8 -0
  105. package/dist/subcommands/handlers/automation.d.ts +3 -0
  106. package/dist/subcommands/handlers/bench-experiments.d.ts +5 -0
  107. package/dist/subcommands/handlers/helpers.d.ts +1 -1
  108. package/dist/subcommands/handlers/sage-sync.d.ts +4 -0
  109. package/dist/subcommands/handlers/sage.d.ts +5 -0
  110. package/dist/subcommands/handlers/sandbox.d.ts +5 -0
  111. package/dist/{subcommands-SRRB3RAS.js → subcommands-QO7VYTSS.js} +2 -2
  112. package/dist/{tools-skills-GH24UCBY.js → tools-skills-33AI6K6S.js} +2 -2
  113. package/dist/tui-provider-quota-menu.d.ts +5 -0
  114. package/dist/{typesafe-WA5O3KVS.js → typesafe-NHC322W5.js} +27 -8
  115. package/dist/{typesafe-topic-replay-ZILIU3WS.js → typesafe-topic-replay-DB2AYL7V.js} +2 -2
  116. package/dist/{typesafe-triage-replay-FGAW7QM7.js → typesafe-triage-replay-27NDAZ3V.js} +2 -2
  117. package/dist/{update-TDZX4IL2.js → update-J5WHAFPE.js} +3 -3
  118. package/dist/{update-check-J5ZVKS73.js → update-check-VLVT4IV2.js} +2 -2
  119. package/dist/{version-help-XJJQ7YSH.js → version-help-ATOKGMTK.js} +2 -2
  120. package/dist/webui-server/prefs-seeding.d.ts +1 -0
  121. package/dist/webui-server/route-contexts.d.ts +1 -0
  122. package/dist/{webui-server-GCXIO3JY.js → webui-server-GQOVLQS3.js} +79 -40
  123. package/dist/webui-session-retirement.d.ts +10 -0
  124. package/dist/wiring/command-host-state.d.ts +2 -0
  125. package/dist/wiring/director-announcement.d.ts +3 -1
  126. package/dist/wiring/session-establishment.d.ts +10 -8
  127. package/dist/wiring/session-runtime.d.ts +1 -1
  128. package/dist/wiring/session.d.ts +3 -0
  129. package/package.json +30 -29
  130. package/dist/auto-discover-providers-DXR25GTG.js +0 -7
  131. package/dist/chunk-3ZTLPNEQ.js +0 -58
  132. package/dist/chunk-D5GB5MHA.js +0 -87
  133. package/dist/chunk-SIGUWXAA.js +0 -43
  134. package/dist/hq-ttl-VJR65OBJ.js +0 -7
  135. package/dist/short-circuit-flags-BSIPTAPD.js +0 -10
@@ -5,7 +5,7 @@ import {
5
5
  // src/subcommands/handlers/bench.ts
6
6
  import * as fs from "node:fs/promises";
7
7
  import { createRequire } from "node:module";
8
- import * as path2 from "node:path";
8
+ import * as path3 from "node:path";
9
9
  import {
10
10
  collectCellPredictions,
11
11
  compareReports,
@@ -20,7 +20,7 @@ import {
20
20
  gradeSwebench,
21
21
  loadBenchConfig as loadBenchConfig2,
22
22
  mineTranscript,
23
- readRunDir,
23
+ readRunDir as readRunDir2,
24
24
  renderComparisonMarkdown,
25
25
  renderMarkdownReport,
26
26
  reportHeaderLine,
@@ -30,8 +30,93 @@ import {
30
30
  } from "@wrongstack/bench";
31
31
  import { color, toErrorMessage } from "@wrongstack/core/utils";
32
32
 
33
- // src/subcommands/handlers/bench-run-config.ts
33
+ // src/subcommands/handlers/bench-experiments.ts
34
+ import { createHash } from "node:crypto";
35
+ import { open } from "node:fs/promises";
34
36
  import * as path from "node:path";
37
+ import {
38
+ compareQualityExperiment,
39
+ readRunDir,
40
+ reviewTranscript,
41
+ routingExperiment
42
+ } from "@wrongstack/bench";
43
+ async function boundedFile(file, limit) {
44
+ const handle = await open(file, "r");
45
+ try {
46
+ const info = await handle.stat();
47
+ if (!info.isFile() || info.size > limit)
48
+ throw new Error("Experiment input exceeds the size limit");
49
+ const buffer = Buffer.alloc(limit + 1);
50
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
51
+ if (bytesRead > limit) throw new Error("Experiment input exceeds the size limit");
52
+ return buffer.subarray(0, bytesRead).toString("utf8");
53
+ } finally {
54
+ await handle.close();
55
+ }
56
+ }
57
+ async function benchExperimentCommand(action, args, deps) {
58
+ const flag = (name) => typeof deps.flags?.[name] === "string" ? deps.flags[name] : void 0;
59
+ try {
60
+ const policyFile = flag("policy");
61
+ const policy = policyFile ? JSON.parse(await boundedFile(path.resolve(deps.cwd, policyFile), 128 * 1024)) : void 0;
62
+ let report;
63
+ if (action === "review") {
64
+ const transcript = flag("transcript");
65
+ if (!transcript)
66
+ throw new Error("Use bench review --transcript <session.jsonl> [--policy <json>]");
67
+ const raw = await boundedFile(path.resolve(deps.cwd, transcript), 32 * 1024 * 1024);
68
+ const events = [];
69
+ for (const line of raw.split("\n").filter((line2) => line2.trim())) {
70
+ const event = JSON.parse(line);
71
+ if (!event || typeof event !== "object" || Array.isArray(event))
72
+ throw new Error("Transcript contains a non-event");
73
+ events.push(event);
74
+ }
75
+ if (policy !== void 0 && (!policy || typeof policy !== "object" || Array.isArray(policy)))
76
+ throw new Error("Invalid review policy");
77
+ report = reviewTranscript(
78
+ events,
79
+ createHash("sha256").update(raw).digest("hex"),
80
+ policy
81
+ );
82
+ } else if (action === "route") {
83
+ if (!args[0] || !policy || typeof policy !== "object" || Array.isArray(policy))
84
+ throw new Error("Use bench route <run-dir> --policy <routing.json>");
85
+ report = routingExperiment(
86
+ await readRunDir(path.resolve(deps.cwd, args[0])),
87
+ policy
88
+ );
89
+ } else {
90
+ const dimension = flag("dimension");
91
+ if (!args[0] || !args[1] || dimension !== "compaction" && dimension !== "behavior")
92
+ throw new Error(
93
+ "Use bench experiment <baseline-dir> <candidate-dir> --dimension compaction|behavior"
94
+ );
95
+ const [baseline, candidate] = await Promise.all([
96
+ readRunDir(path.resolve(deps.cwd, args[0])),
97
+ readRunDir(path.resolve(deps.cwd, args[1]))
98
+ ]);
99
+ report = compareQualityExperiment(baseline, candidate, dimension);
100
+ }
101
+ deps.renderer.write(`${JSON.stringify(report, null, 2)}
102
+ `);
103
+ return 0;
104
+ } catch (error) {
105
+ deps.renderer.writeError(error instanceof Error ? error.message : "Experiment failed");
106
+ return 1;
107
+ }
108
+ }
109
+ async function readBenchReviewPolicy(file) {
110
+ const raw = JSON.parse(await boundedFile(file, 128 * 1024));
111
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
112
+ throw new Error("Invalid review policy");
113
+ const policy = raw;
114
+ reviewTranscript([], "0".repeat(64), policy);
115
+ return policy;
116
+ }
117
+
118
+ // src/subcommands/handlers/bench-run-config.ts
119
+ import * as path2 from "node:path";
35
120
  import {
36
121
  configFromCells,
37
122
  loadBenchConfig,
@@ -56,7 +141,7 @@ async function resolveBenchRunConfig(input) {
56
141
  }
57
142
  const modelsFlag = stringFlag(input.flags, "models");
58
143
  const modelsPath = modelsFlag ?? DEFAULT_BENCH_MODELS_FILE;
59
- const resolvedModels = path.resolve(input.cwd, modelsPath);
144
+ const resolvedModels = path2.resolve(input.cwd, modelsPath);
60
145
  const customModelsFile = modelsFlag !== void 0 && modelsFlag !== DEFAULT_BENCH_MODELS_FILE;
61
146
  try {
62
147
  return await loadBenchConfig(resolvedModels);
@@ -95,6 +180,10 @@ var benchCmd = async (args, deps) => {
95
180
  const sub = args[0];
96
181
  const rest = args.slice(1);
97
182
  switch (sub) {
183
+ case "review":
184
+ case "route":
185
+ case "experiment":
186
+ return benchExperimentCommand(sub, rest, deps);
98
187
  case "run":
99
188
  return benchRun(rest, deps);
100
189
  case "report":
@@ -120,6 +209,9 @@ function printUsage(deps) {
120
209
  " mine Copy a real session transcript and draft trace-eval cases",
121
210
  " report Re-render report.md from a finished run directory",
122
211
  " list Show available suites and configured model cells",
212
+ " review Review a transcript with advisory behavior/compaction evidence",
213
+ " route Recommend models in shadow mode from a finished run and category policy",
214
+ " experiment Compare paired behavior/compaction runs on an identical corpus",
123
215
  "",
124
216
  color.dim("Examples:"),
125
217
  color.dim(" wstack bench run --cell anthropic/claude-sonnet-4-6,openai/gpt-5.4"),
@@ -143,11 +235,20 @@ function flagBool(deps, name) {
143
235
  const v = deps.flags?.[name];
144
236
  return v === true || v === "true";
145
237
  }
238
+ function positiveIntegerFlag(deps, name) {
239
+ const raw = flagStr(deps, name);
240
+ if (raw === void 0) return void 0;
241
+ const value = Number(raw);
242
+ if (!/^\d+$/.test(raw.trim()) || !Number.isSafeInteger(value) || value < 1) {
243
+ throw new Error(`--${name} must be a positive safe integer.`);
244
+ }
245
+ return value;
246
+ }
146
247
  async function resolveWstackEntry() {
147
248
  try {
148
249
  const req = createRequire(import.meta.url);
149
250
  const pkgPath = req.resolve("@wrongstack/cli/package.json");
150
- const entry = path2.join(path2.dirname(pkgPath), "dist", "index.js");
251
+ const entry = path3.join(path3.dirname(pkgPath), "dist", "index.js");
151
252
  await fs.access(entry);
152
253
  return entry;
153
254
  } catch {
@@ -155,9 +256,28 @@ async function resolveWstackEntry() {
155
256
  }
156
257
  }
157
258
  async function benchRun(_args, deps) {
259
+ let reviewPolicy;
260
+ try {
261
+ if (flagStr(deps, "review-policy"))
262
+ reviewPolicy = await readBenchReviewPolicy(
263
+ path3.resolve(deps.cwd, flagStr(deps, "review-policy"))
264
+ );
265
+ } catch (error) {
266
+ deps.renderer.writeError(toErrorMessage(error));
267
+ return 1;
268
+ }
158
269
  const suiteId = flagStr(deps, "suite") ?? "core";
159
- const limitRaw = flagStr(deps, "limit");
160
- const limit = limitRaw ? Math.max(1, Number.parseInt(limitRaw, 10)) : void 0;
270
+ let limit;
271
+ let concurrency;
272
+ let repeats;
273
+ try {
274
+ limit = positiveIntegerFlag(deps, "limit");
275
+ concurrency = positiveIntegerFlag(deps, "concurrency");
276
+ repeats = positiveIntegerFlag(deps, "repeats");
277
+ } catch (error) {
278
+ deps.renderer.writeError(toErrorMessage(error));
279
+ return 1;
280
+ }
161
281
  const outBase = flagStr(deps, "out") ?? "bench-results";
162
282
  let config;
163
283
  try {
@@ -172,23 +292,11 @@ async function benchRun(_args, deps) {
172
292
  deps.renderer.writeError(toErrorMessage(err));
173
293
  return 1;
174
294
  }
175
- const concurrencyRaw = flagStr(deps, "concurrency");
176
- if (concurrencyRaw) {
177
- const c = Number.parseInt(concurrencyRaw, 10);
178
- if (c > 0) config.concurrency = c;
179
- }
180
- const repeatsRaw = flagStr(deps, "repeats");
181
- if (repeatsRaw) {
182
- const r = Number.parseInt(repeatsRaw, 10);
183
- if (!Number.isFinite(r) || r <= 0) {
184
- deps.renderer.writeError("--repeats must be a positive integer.");
185
- return 1;
186
- }
187
- config.repeats = r;
188
- }
295
+ if (concurrency !== void 0) config.concurrency = concurrency;
296
+ if (repeats !== void 0) config.repeats = repeats;
189
297
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
190
- const outDir = path2.resolve(deps.cwd, outBase, stamp);
191
- const predictionsDir = path2.join(outDir, "predictions");
298
+ const outDir = path3.resolve(deps.cwd, outBase, stamp);
299
+ const predictionsDir = path3.join(outDir, "predictions");
192
300
  let suite;
193
301
  let grade;
194
302
  let isSwebench = false;
@@ -206,14 +314,14 @@ async function benchRun(_args, deps) {
206
314
  }
207
315
  const languagesRaw = flagStr(deps, "languages");
208
316
  const languages = languagesRaw ? languagesRaw.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
209
- suite = createPolyglotSuite({ polyglotDir: path2.resolve(deps.cwd, polyglotDir), languages });
317
+ suite = createPolyglotSuite({ polyglotDir: path3.resolve(deps.cwd, polyglotDir), languages });
210
318
  grade = (a) => gradePolyglot(a);
211
319
  } else if (suiteId === "swebench") {
212
320
  isSwebench = true;
213
321
  const datasetDir = flagStr(deps, "dataset-dir");
214
322
  const docker = flagBool(deps, "docker");
215
323
  suite = createSwebenchSuite({
216
- datasetDir: datasetDir ? path2.resolve(deps.cwd, datasetDir) : void 0,
324
+ datasetDir: datasetDir ? path3.resolve(deps.cwd, datasetDir) : void 0,
217
325
  docker
218
326
  });
219
327
  grade = (a) => gradeSwebench({ ...a, predictionsDir });
@@ -226,8 +334,8 @@ async function benchRun(_args, deps) {
226
334
  );
227
335
  return 1;
228
336
  }
229
- const manifestFile = manifestRaw ? path2.resolve(deps.cwd, manifestRaw) : void 0;
230
- const suiteDir = suiteDirRaw ? path2.resolve(deps.cwd, suiteDirRaw) : path2.dirname(manifestFile);
337
+ const manifestFile = manifestRaw ? path3.resolve(deps.cwd, manifestRaw) : void 0;
338
+ const suiteDir = suiteDirRaw ? path3.resolve(deps.cwd, suiteDirRaw) : path3.dirname(manifestFile);
231
339
  suite = createLocalManifestSuite({ suiteDir, manifestFile });
232
340
  grade = (a) => gradeLocalManifest(a);
233
341
  } else {
@@ -242,7 +350,7 @@ async function benchRun(_args, deps) {
242
350
  const wstackEntry = await resolveWstackEntry();
243
351
  deps.renderer.writeInfo(`Running ${suiteId} across ${config.cells.length} model(s)\u2026`);
244
352
  await fs.mkdir(outDir, { recursive: true });
245
- const partialPath = path2.join(outDir, "results.jsonl");
353
+ const partialPath = path3.join(outDir, "results.jsonl");
246
354
  await fs.writeFile(partialPath, "", "utf8");
247
355
  let report;
248
356
  try {
@@ -250,6 +358,7 @@ async function benchRun(_args, deps) {
250
358
  suite,
251
359
  grade,
252
360
  config,
361
+ reviewPolicy,
253
362
  cliVersion: CLI_VERSION,
254
363
  toolNames,
255
364
  toolManifestHash,
@@ -267,7 +376,7 @@ async function benchRun(_args, deps) {
267
376
  }
268
377
  await writeJsonArtifacts(outDir, report);
269
378
  const md = renderMarkdownReport(report);
270
- await fs.writeFile(path2.join(outDir, "report.md"), md, "utf8");
379
+ await fs.writeFile(path3.join(outDir, "report.md"), md, "utf8");
271
380
  deps.renderer.write("\n" + md + "\n");
272
381
  if (isSwebench) {
273
382
  for (const cell of config.cells) {
@@ -280,7 +389,7 @@ async function benchRun(_args, deps) {
280
389
  "Grade with the official SWE-bench harness: python -m swebench.harness.run_evaluation --predictions_path <file> --run_id <id>"
281
390
  );
282
391
  }
283
- deps.renderer.writeInfo(`Report written to ${path2.join(outDir, "report.md")}`);
392
+ deps.renderer.writeInfo(`Report written to ${path3.join(outDir, "report.md")}`);
284
393
  const spawned = report.results.filter((row) => row.run.status !== "crashed").length;
285
394
  if (report.results.length > 0 && spawned === 0) {
286
395
  deps.renderer.writeError(
@@ -296,16 +405,16 @@ async function benchReport(args, deps) {
296
405
  deps.renderer.writeError("Usage: wstack bench report <run-directory>");
297
406
  return 1;
298
407
  }
299
- const outDir = path2.resolve(deps.cwd, dir);
408
+ const outDir = path3.resolve(deps.cwd, dir);
300
409
  let report;
301
410
  try {
302
- report = await readRunDir(outDir);
411
+ report = await readRunDir2(outDir);
303
412
  } catch (err) {
304
413
  deps.renderer.writeError(`cannot read run artifacts in ${outDir}: ${toErrorMessage(err)}`);
305
414
  return 1;
306
415
  }
307
416
  const md = renderMarkdownReport(report);
308
- await fs.writeFile(path2.join(outDir, "report.md"), md, "utf8");
417
+ await fs.writeFile(path3.join(outDir, "report.md"), md, "utf8");
309
418
  deps.renderer.write("\n" + md + "\n");
310
419
  return 0;
311
420
  }
@@ -317,12 +426,12 @@ async function benchCompare(args, deps) {
317
426
  deps.renderer.writeError("Usage: wstack bench compare <baseline-dir> <candidate-dir>");
318
427
  return 1;
319
428
  }
320
- const baselineDir = path2.resolve(deps.cwd, baselineRaw);
321
- const candidateDir = path2.resolve(deps.cwd, candidateRaw);
429
+ const baselineDir = path3.resolve(deps.cwd, baselineRaw);
430
+ const candidateDir = path3.resolve(deps.cwd, candidateRaw);
322
431
  let comparisonMd;
323
432
  try {
324
- const baseline = await readRunDir(baselineDir);
325
- const candidate = await readRunDir(candidateDir);
433
+ const baseline = await readRunDir2(baselineDir);
434
+ const candidate = await readRunDir2(candidateDir);
326
435
  const comparison = compareReports(baseline, candidate);
327
436
  comparisonMd = renderComparisonMarkdown(comparison);
328
437
  } catch (err) {
@@ -330,8 +439,8 @@ async function benchCompare(args, deps) {
330
439
  return 1;
331
440
  }
332
441
  const outRaw = flagStr(deps, "out");
333
- const outFile = outRaw ? path2.resolve(deps.cwd, outRaw) : path2.join(candidateDir, "compare.md");
334
- await fs.mkdir(path2.dirname(outFile), { recursive: true });
442
+ const outFile = outRaw ? path3.resolve(deps.cwd, outRaw) : path3.join(candidateDir, "compare.md");
443
+ await fs.mkdir(path3.dirname(outFile), { recursive: true });
335
444
  await fs.writeFile(outFile, comparisonMd, "utf8");
336
445
  deps.renderer.write("\n" + comparisonMd + "\n");
337
446
  deps.renderer.writeInfo(`Comparison written to ${outFile}`);
@@ -348,8 +457,8 @@ async function benchMine(args, deps) {
348
457
  const outRaw = flagStr(deps, "out") ?? "evals";
349
458
  try {
350
459
  const mined = await mineTranscript({
351
- transcriptPath: path2.resolve(deps.cwd, transcriptRaw),
352
- outDir: path2.resolve(deps.cwd, outRaw)
460
+ transcriptPath: path3.resolve(deps.cwd, transcriptRaw),
461
+ outDir: path3.resolve(deps.cwd, outRaw)
353
462
  });
354
463
  deps.renderer.writeInfo(
355
464
  `Mined ${mined.candidates.length} edit attempt(s) from ${mined.sessionId}.`
@@ -385,7 +494,7 @@ async function benchList(_args, deps) {
385
494
  const modelsPath = flagStr(deps, "models");
386
495
  if (modelsPath) {
387
496
  try {
388
- const config = await loadBenchConfig2(path2.resolve(deps.cwd, modelsPath));
497
+ const config = await loadBenchConfig2(path3.resolve(deps.cwd, modelsPath));
389
498
  deps.renderer.write("\n" + color.bold("Model cells\n"));
390
499
  for (const cell of config.cells) {
391
500
  deps.renderer.write(
@@ -414,4 +523,4 @@ async function benchList(_args, deps) {
414
523
  export {
415
524
  benchCmd
416
525
  };
417
- //# sourceMappingURL=bench-GTLPM22B.js.map
526
+ //# sourceMappingURL=bench-MMZHFHDL.js.map
@@ -45,7 +45,7 @@ export interface BrainDecisionEntry {
45
45
  * cast at the call site because the EventBus generic constraint is
46
46
  * narrower than the dynamic string event names we register here.
47
47
  */
48
- export declare function subscribeBrainDecisionLog(events: any): {
48
+ export declare function subscribeBrainDecisionLog(events: any, getMaxEntries?: () => number): {
49
49
  brainLog: BrainDecisionEntry[];
50
50
  pushBrainLog: (entry: BrainDecisionEntry) => void;
51
51
  /**
@@ -84,7 +84,7 @@ interface BindSystemPromptBuilderDeps {
84
84
  skillEagerMaxChars?: number | undefined;
85
85
  /** `config.features.tokenSavingMode` — forwarded so prompt guidance matches tool tiering. */
86
86
  tokenSavingMode?: TokenSavingTier | boolean | undefined;
87
- /** `config.systemPrompt.variant` — selects system.md, system-lite.md, or system-pro.md. */
87
+ /** `config.systemPrompt.variant` — selects system.md, system-lite.md, system-pro.md, or system-scout.md. */
88
88
  systemPromptVariant?: SystemInstructionVariant | undefined;
89
89
  /** `--append-system-prompt[-file]` text; appended to the host prompt only. */
90
90
  appendedInstructions?: string | undefined;
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Interactive system-prompt selection menu — Lite / Standard / Pro.
2
+ * Interactive system-prompt selection menu — Lite / Standard / Pro / Scout.
3
3
  *
4
4
  * Shown at startup when the user did not pin a variant via
5
- * `--system-lite`, `--system-pro`, or `--system-prompt <variant>`.
5
+ * `--system-lite`, `--system-pro`, `--system-scout`, or `--system-prompt <variant>`.
6
6
  * Each option displays the estimated token count of the identity block
7
7
  * that variant injects (resolved through the same bundled → global →
8
8
  * project instruction dirs the SystemPromptBuilder uses, so a project
@@ -56,6 +56,13 @@ export declare function runSystemPromptMenu(deps: {
56
56
  paths: SystemPromptMenuPaths;
57
57
  /** Saved variant from config — enables the summary gate. */
58
58
  lastVariant?: SystemInstructionVariant | undefined;
59
+ /**
60
+ * The launch folder is not a project (no manifest, no AGENTS.md, no git):
61
+ * the coding identities have nothing to work on, so Scout is preselected in
62
+ * the menu and the summary gate points at it. A saved choice is never
63
+ * replaced silently — the gate still defaults to it.
64
+ */
65
+ suggestScout?: boolean | undefined;
59
66
  }): Promise<SystemInstructionVariant>;
60
67
  /** Outcome of {@link maybeRunSystemPromptMenu}. */
61
68
  export interface SystemPromptMenuOutcome {
@@ -106,5 +113,7 @@ export declare function maybeRunSystemPromptMenu(opts: {
106
113
  * does not reliably honor for directory renames.
107
114
  */
108
115
  persist?: typeof persistSystemPromptVariant | undefined;
116
+ /** The launch folder is not a project — see `runSystemPromptMenu`. */
117
+ outsideProject?: boolean | undefined;
109
118
  }): Promise<SystemPromptMenuOutcome>;
110
119
  //# sourceMappingURL=system-prompt-menu.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import type { Context } from '@wrongstack/core/agent';
2
+ import type { BrainArbiter } from '@wrongstack/core/coordination';
2
3
  import { AutonomousCoordinator, type Director } from '@wrongstack/core/coordination';
3
4
  import type { EventBus } from '@wrongstack/core/kernel';
4
5
  import type { WstackPaths } from '@wrongstack/core/utils';
@@ -10,6 +11,7 @@ interface CoordinatorSetupContext {
10
11
  events: EventBus;
11
12
  /** The agent's Context — provides provider, model, session id, transcript path. */
12
13
  context: Context;
14
+ brain?: BrainArbiter | undefined;
13
15
  /** Resolved WrongStack paths — used for session-dir resolution. */
14
16
  wpaths: WstackPaths;
15
17
  /** The mailbox — cast to the core Mailbox interface for the coordinator. */
@@ -0,0 +1,11 @@
1
+ import type { Logger } from '@wrongstack/core/types';
2
+ export declare function shouldCaptureTuiStartup(flags: Record<string, string | boolean>, positional: readonly string[], interactive?: boolean): boolean;
3
+ /** Buffer diagnostics until the launch menu decides who owns the terminal.
4
+ * TUI logs go to its existing file logger; other surfaces replay normal output.
5
+ * Prompts, unstructured stderr and errors remain visible throughout boot.
6
+ */
7
+ export declare function startTuiStartupOutput(enabled: boolean): {
8
+ acceptTui(fileLogger: Logger): void;
9
+ stop(replay?: boolean): void;
10
+ };
11
+ //# sourceMappingURL=tui-startup-output.d.ts.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  persistConfigSetting
3
- } from "./chunk-SFBFYIOW.js";
3
+ } from "./chunk-4MDRHMX4.js";
4
4
  import {
5
5
  activeProfileConfigPath
6
6
  } from "./chunk-YMXXOOFN.js";
7
- import "./chunk-WSTVGC2C.js";
7
+ import "./chunk-4BX2YDTQ.js";
8
8
 
9
9
  // src/boot/boot-auto-thin.ts
10
10
  import {
@@ -99,4 +99,4 @@ async function runBootAutoThin(deps) {
99
99
  export {
100
100
  runBootAutoThin
101
101
  };
102
- //# sourceMappingURL=boot-auto-thin-6Q56FY3F.js.map
102
+ //# sourceMappingURL=boot-auto-thin-K2DHHYIW.js.map
@@ -82,9 +82,11 @@ var chronicleCmd = async (args, deps) => {
82
82
  const flags = deps.flags ?? {};
83
83
  const dryRun = args.includes("--dry-run") || args.includes("-n") || flags["dry-run"] === true || flags["dry-run"] === "true" || flags["n"] === true;
84
84
  const daysIndex = args.indexOf("--days");
85
+ const hasDaysFlag = daysIndex >= 0 || Object.hasOwn(flags, "days");
85
86
  const rawDays = daysIndex >= 0 && daysIndex + 1 < args.length ? args[daysIndex + 1] : typeof flags["days"] === "string" ? flags["days"] : void 0;
86
- const days = rawDays ? parseInt(rawDays, 10) : 30;
87
- if (!Number.isFinite(days) || days < 1) {
87
+ const trimmedDays = rawDays?.trim();
88
+ const days = !hasDaysFlag ? 30 : trimmedDays !== void 0 && /^\d+$/.test(trimmedDays) ? Number(trimmedDays) : Number.NaN;
89
+ if (!Number.isSafeInteger(days) || days < 1) {
88
90
  deps.renderer.writeError(
89
91
  `Invalid retention days: ${rawDays ?? ""}. Use --days N (positive integer).
90
92
  `
@@ -273,4 +275,4 @@ function tryStat(file) {
273
275
  export {
274
276
  chronicleCmd
275
277
  };
276
- //# sourceMappingURL=chronicle-UTFETHP6.js.map
278
+ //# sourceMappingURL=chronicle-PBJS7BN6.js.map
@@ -79,7 +79,7 @@ var BENCH_RUN_FLAGS = [
79
79
  {
80
80
  name: "limit",
81
81
  flag: "--limit <N>",
82
- description: "Cap the number of tasks per cell (useful for smoke tests).",
82
+ description: "Cap the number of tasks per cell (positive safe integer; useful for smoke tests).",
83
83
  group: "control",
84
84
  kind: "value"
85
85
  },
@@ -94,14 +94,14 @@ var BENCH_RUN_FLAGS = [
94
94
  {
95
95
  name: "concurrency",
96
96
  flag: "--concurrency <N>",
97
- description: "Override the per-cell concurrency from the model config.",
97
+ description: "Override the per-cell concurrency from the model config (positive safe integer).",
98
98
  group: "control",
99
99
  kind: "value"
100
100
  },
101
101
  {
102
102
  name: "repeats",
103
103
  flag: "--repeats <N>",
104
- description: "Attempts per (task x model). >1 adds pass@k and a flakiness count so run-to-run noise is visible.",
104
+ description: "Attempts per (task x model), a positive safe integer. >1 adds pass@k and a flakiness count.",
105
105
  group: "control",
106
106
  kind: "value",
107
107
  defaultValue: "1"
@@ -706,6 +706,20 @@ var deepHelpTable = {
706
706
 
707
707
  // src/subcommands/handlers/per-subcommand-help-table.ts
708
708
  var helpTable = {
709
+ automation: {
710
+ name: "automation",
711
+ title: "wstack automation \u2014 persistent agent jobs",
712
+ description: "Manage persistent schedules, signed GitHub intake, isolated runs and run history.",
713
+ usage: "wstack automation <add|preview|templates|import|export|list|run|enable|disable|cancel|serve|prune> [id] [options]",
714
+ seeAlso: "docs/subcommands/automation.md"
715
+ },
716
+ sandbox: {
717
+ name: "sandbox",
718
+ title: "wstack sandbox \u2014 isolated Docker execution",
719
+ description: "Run the full agent in a copied project workspace and retain a patch without editing the host project.",
720
+ usage: "wstack sandbox docker --image <trusted-image> --prompt <task> [--dry-run] [--env NAME,...] [--provider id] [--model id] [--out directory]",
721
+ seeAlso: "docs/subcommands/sandbox.md"
722
+ },
709
723
  init: {
710
724
  name: "init",
711
725
  title: "wstack init \u2014 DEPRECATED (use wstack auth)",
@@ -795,10 +809,14 @@ var helpTable = {
795
809
  name: "auth",
796
810
  title: "wstack auth \u2014 manage API keys and provider credentials",
797
811
  description: "Add, view, and remove provider API keys. The interactive menu supports a custom-URL path for self-hosted / local servers, a quick-shortcut path for Ollama / vLLM / LM Studio, and a catalog path for the well-known providers.",
798
- usage: "wstack auth [list|status|remove] [...] | wstack auth <provider> | wstack auth local [...]",
812
+ usage: "wstack auth [list|status|remove|cloud] [...] | wstack auth <provider> | wstack auth local [...]",
799
813
  subcommands: [
800
814
  { name: "list", description: "List saved providers and key status." },
801
815
  { name: "status <id>", description: "Show detail for one provider." },
816
+ {
817
+ name: "cloud <id>",
818
+ description: "Read or set native region/project/location/resource routing for a saved profile."
819
+ },
802
820
  { name: "remove <id>", description: "Remove a provider and its keys." },
803
821
  { name: "<provider>", description: "Add a key for a named provider (--label, --family, \u2026)." },
804
822
  {
@@ -995,8 +1013,12 @@ var helpTable = {
995
1013
  name: "modeldiag",
996
1014
  title: "wstack modeldiag \u2014 model benchmarks + heuristic diagnostics",
997
1015
  description: "Read-only diagnostics for the configured model: key check, capability scan (vision / tools / context window), heuristic strengths/weaknesses (bestFor / avoidFor), sequential live provider/model smoke tests, and real benchmarks against a small prompt suite. Smoke tests use tiny prompts and never print credentials.",
998
- usage: "wstack modeldiag [test|eval] [...]",
1016
+ usage: "wstack modeldiag [preflight|test|eval] [...]",
999
1017
  subcommands: [
1018
+ {
1019
+ name: "preflight [provider-profile]",
1020
+ description: "Check native cloud provider setup without model requests or exposing credential values."
1021
+ },
1000
1022
  {
1001
1023
  name: "<no subcommand>",
1002
1024
  description: "Print configured model capabilities, context limits, and recommendations."
@@ -1017,7 +1039,7 @@ var helpTable = {
1017
1039
  name: "bench",
1018
1040
  title: "wstack bench \u2014 run model-independent agentic benchmarks",
1019
1041
  description: "Run WrongStack against the bundled smoke suite, a local manifest, Aider polyglot, or SWE-bench Verified with deterministic graders. Default `bench run` is the bundled core edit-eval; pass --cell provider/model (or a saved model).",
1020
- usage: "wstack bench [run|compare|report|list] [...]",
1042
+ usage: "wstack bench [run|compare|report|list|mine|review|route|experiment] [...]",
1021
1043
  subcommands: [
1022
1044
  { name: "run", description: "Run a suite. Default: bundled smoke + --cell or saved model." },
1023
1045
  {
@@ -1025,6 +1047,18 @@ var helpTable = {
1025
1047
  description: "Diff two finished run directories (fingerprint-aware)."
1026
1048
  },
1027
1049
  { name: "report <dir>", description: "Render the Markdown report for a prior run." },
1050
+ {
1051
+ name: "review --transcript <file>",
1052
+ description: "Read-only transcript behavior/compaction evidence; optional --policy."
1053
+ },
1054
+ {
1055
+ name: "route <dir> --policy <file>",
1056
+ description: "Shadow routing recommendations from graded model-matrix evidence."
1057
+ },
1058
+ {
1059
+ name: "experiment <a> <b> --dimension compaction|behavior",
1060
+ description: "Compare paired task/model/attempt runs with explicit experiment provenance."
1061
+ },
1028
1062
  { name: "list", description: "List available suites and the model configs in the catalog." }
1029
1063
  ],
1030
1064
  seeAlso: "wstack modeldiag (read-only diagnostics; bench actually runs the model)"
@@ -1142,6 +1176,25 @@ var helpTable = {
1142
1176
  ],
1143
1177
  seeAlso: "wstack mcp list; --mcp-config (one-off servers without importing)"
1144
1178
  },
1179
+ sage: {
1180
+ name: "sage",
1181
+ title: "wstack sage \u2014 this project's SAGE memory in other coding agents",
1182
+ description: "Wire SAGE memory into Claude Code, Codex, Cursor or Antigravity over MCP: writes the MCP server entry plus a skill/rule telling the agent when to recall and how to propose. The server attaches to the SAGE daemon while wstack is open in this project and never starts one. Tools are read-only plus memory_candidates (list/propose); a proposal becomes memory only through WrongStack review. Search is lexical: semantic recall runs inside a WrongStack host.",
1183
+ usage: "wstack sage connect <claude-code|codex|cursor|antigravity|all|print> [--dry-run]",
1184
+ subcommands: [
1185
+ { name: "connect <client|all>", description: "Write the MCP entry and skill for a client." },
1186
+ { name: "connect print", description: "Print JSON/TOML config for any other MCP client." },
1187
+ { name: "disconnect <client|all>", description: "Remove what connect wrote." },
1188
+ { name: "mcp [--origin <name>]", description: "The stdio MCP server clients run." },
1189
+ {
1190
+ name: "sync [--restart-service]",
1191
+ description: "Run project memory sync with HQ; optionally restart this project\u2019s SAGE owner."
1192
+ },
1193
+ { name: "--dry-run", description: "Show the file changes without writing." },
1194
+ { name: "--command <path>", description: "Executable to launch instead of wstack." }
1195
+ ],
1196
+ seeAlso: "wstack mcp serve (all WrongStack tools over MCP)"
1197
+ },
1145
1198
  // -- Chronicle ──────────────────────────────────────────────────────
1146
1199
  chronicle: {
1147
1200
  name: "chronicle",
@@ -1243,4 +1296,4 @@ export {
1243
1296
  subcommandsWithFocusedHelp,
1244
1297
  renderGenericHelp
1245
1298
  };
1246
- //# sourceMappingURL=chunk-EPR42SWM.js.map
1299
+ //# sourceMappingURL=chunk-2EZ2DHOW.js.map