crosscheck-mcp 0.2.26 → 0.2.28

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/embed.cjs CHANGED
@@ -37,7 +37,10 @@ __export(embed_exports, {
37
37
  __KEY_ENV: () => KEY_ENV,
38
38
  __MODEL_ENV: () => MODEL_ENV,
39
39
  __test_internals: () => __test_internals,
40
- createEmbeddedEngine: () => createEmbeddedEngine
40
+ createEmbeddedEngine: () => createEmbeddedEngine,
41
+ isAlive: () => isAlive,
42
+ listProcesses: () => listProcesses,
43
+ processRegistryPath: () => processRegistryPath
41
44
  });
42
45
  module.exports = __toCommonJS(embed_exports);
43
46
 
@@ -46,16 +49,16 @@ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${_
46
49
  var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
47
50
 
48
51
  // src/entrypoints/embed.ts
49
- var import_node_fs15 = require("fs");
50
- var import_node_path14 = __toESM(require("path"), 1);
52
+ var import_node_fs16 = require("fs");
53
+ var import_node_path15 = __toESM(require("path"), 1);
51
54
  var import_node_url2 = require("url");
52
55
 
53
56
  // src/core/pricing.ts
54
57
  var import_node_fs = require("fs");
55
- function loadPricing(path12) {
58
+ function loadPricing(path13) {
56
59
  let raw;
57
60
  try {
58
- raw = (0, import_node_fs.readFileSync)(path12, "utf8");
61
+ raw = (0, import_node_fs.readFileSync)(path13, "utf8");
59
62
  } catch {
60
63
  return {};
61
64
  }
@@ -72,20 +75,30 @@ function modelPricing(pricing, provider, model) {
72
75
  const block = pricing[provider];
73
76
  if (!block || typeof block !== "object" || Array.isArray(block)) return null;
74
77
  const table = block;
78
+ if (model.startsWith("_")) return null;
75
79
  let entry = table[model];
76
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
77
- const best = Object.keys(table).filter((k) => model.startsWith(k)).sort((a, b) => b.length - a.length)[0];
78
- entry = best !== void 0 ? table[best] : void 0;
80
+ let match = "exact";
81
+ if (!isRates(entry)) {
82
+ const best = Object.keys(table).filter((k) => !k.startsWith("_")).filter((k) => model.startsWith(k) && DATE_STAMP.test(model.slice(k.length))).sort((a, b) => b.length - a.length)[0];
83
+ if (best !== void 0) {
84
+ entry = table[best];
85
+ match = "stamp";
86
+ }
79
87
  }
80
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) return null;
88
+ if (!isRates(entry)) return null;
81
89
  const e = entry;
82
90
  return {
83
91
  prompt_per_1k: numberOrZero(e["prompt_per_1k"]),
84
92
  completion_per_1k: numberOrZero(e["completion_per_1k"]),
85
93
  cached_per_1k: numberOrZero(e["cached_per_1k"]),
86
- ...e["estimated"] === true ? { estimated: true } : {}
94
+ ...e["estimated"] === true ? { estimated: true } : {},
95
+ match
87
96
  };
88
97
  }
98
+ var DATE_STAMP = /^-\d{8}$/;
99
+ function isRates(v) {
100
+ return Boolean(v) && typeof v === "object" && !Array.isArray(v);
101
+ }
89
102
  function numberOrZero(v) {
90
103
  if (typeof v === "number" && Number.isFinite(v)) return v;
91
104
  if (typeof v === "string") {
@@ -165,8 +178,20 @@ var PROVIDER_CAPS = {
165
178
  gemini: {
166
179
  family: "gemini",
167
180
  system_role: "separate",
168
- supports_temperature: true,
169
- reasoning_prefixes: ["gemini-3.1-pro", "gemini-3.5-flash", "gemini-2.5-pro"]
181
+ // No sampling, on any Gemini model. Ignored since 3.6 Flash and rejected
182
+ // by upcoming models (Google, 2026-10). "model" means "omit for reasoning
183
+ // models", and every Gemini model is reasoning-class (below) — so this
184
+ // resolves to never, through the same rule the other providers use. The
185
+ // adapter also never sends it; this keeps the record honest for anything
186
+ // else that reads it.
187
+ supports_temperature: "model",
188
+ // EVERY Gemini model is reasoning-class. The old list named three
189
+ // families and missed gemini-3.8-flash — the DEFAULT — so the default
190
+ // model got the small non-reasoning budgets (768 tokens for an audit)
191
+ // while spending up to ~480 tokens of each call thinking. Google's docs
192
+ // say thinking cannot be switched off on current models, so a list of
193
+ // which ones think is a list that can only ever be incomplete.
194
+ reasoning_prefixes: ["gemini-"]
170
195
  },
171
196
  // Qwen's "Max" tier (qwen-v3.8, qwen-v3.7) is a standard instruct/chat
172
197
  // model, not a visible-reasoning model like QwQ — normal temperature and
@@ -289,6 +314,73 @@ function httpFailureToProviderError(provider, status, bodyText, retryAfterS, mod
289
314
  );
290
315
  }
291
316
 
317
+ // src/providers/network-errors.ts
318
+ function codeOf(e) {
319
+ if (!e || typeof e !== "object") return null;
320
+ const c = e.code;
321
+ return typeof c === "string" && c.length > 0 ? c : null;
322
+ }
323
+ function rootCause(e, depth = 0) {
324
+ if (depth > 5 || !e || typeof e !== "object") return e;
325
+ const o = e;
326
+ if (Array.isArray(o.errors) && o.errors.length > 0) {
327
+ const coded = o.errors.find((x) => codeOf(x) !== null);
328
+ return rootCause(coded ?? o.errors[0], depth + 1);
329
+ }
330
+ if (o.cause !== void 0 && o.cause !== null) return rootCause(o.cause, depth + 1);
331
+ return e;
332
+ }
333
+ var BY_CODE = {
334
+ ENOTFOUND: { cause: "dns", detail: "the provider's hostname did not resolve \u2014 DNS, or a typo'd base URL", transient: false, kind: "network" },
335
+ EAI_AGAIN: { cause: "dns", detail: "DNS lookup failed temporarily \u2014 resolver or network is flapping", transient: true, kind: "network" },
336
+ ECONNREFUSED: { cause: "refused", detail: "the connection was refused \u2014 nothing is listening, or a proxy blocked it", transient: false, kind: "network" },
337
+ ECONNRESET: { cause: "reset", detail: "the peer closed the connection mid-request \u2014 flaky path, or an upstream error behind a proxy", transient: true, kind: "network" },
338
+ EPIPE: { cause: "reset", detail: "the connection closed while we were still writing", transient: true, kind: "network" },
339
+ ETIMEDOUT: { cause: "connect_timeout", detail: "the connection timed out before it was established", transient: true, kind: "timeout" },
340
+ EHOSTUNREACH: { cause: "unreachable", detail: "no route to the provider \u2014 VPN, or offline", transient: true, kind: "network" },
341
+ ENETUNREACH: { cause: "unreachable", detail: "the network is unreachable \u2014 offline, or a routing change", transient: true, kind: "network" },
342
+ ENETDOWN: { cause: "unreachable", detail: "the local network is down", transient: true, kind: "network" },
343
+ EPROTO: { cause: "tls", detail: "the TLS handshake failed \u2014 an intercepting proxy, or a protocol mismatch", transient: false, kind: "network" },
344
+ ERR_TLS_CERT_ALTNAME_INVALID: { cause: "tls", detail: "the certificate did not match the hostname \u2014 traffic is being intercepted", transient: false, kind: "network" },
345
+ CERT_HAS_EXPIRED: { cause: "tls", detail: "the server certificate has expired, or this machine's clock is wrong", transient: false, kind: "network" },
346
+ UNABLE_TO_VERIFY_LEAF_SIGNATURE: { cause: "tls", detail: "the certificate chain could not be verified \u2014 a corporate proxy's root is probably not trusted here", transient: false, kind: "network" },
347
+ UND_ERR_CONNECT_TIMEOUT: { cause: "connect_timeout", detail: "could not open a connection within the timeout \u2014 firewall, or the host is down", transient: true, kind: "timeout" },
348
+ UND_ERR_HEADERS_TIMEOUT: { cause: "read_timeout", detail: "connected, but the provider sent no response headers in time \u2014 it is overloaded or thinking too long", transient: true, kind: "timeout" },
349
+ UND_ERR_BODY_TIMEOUT: { cause: "read_timeout", detail: "the response body stalled mid-stream", transient: true, kind: "timeout" },
350
+ UND_ERR_SOCKET: { cause: "reset", detail: "the socket closed unexpectedly", transient: true, kind: "network" },
351
+ UND_ERR_ABORTED: { cause: "aborted", detail: "the request was cancelled", transient: false, kind: "network" },
352
+ ABORT_ERR: { cause: "aborted", detail: "the request was cancelled", transient: false, kind: "network" }
353
+ };
354
+ function diagnoseNetworkError(e) {
355
+ const root = rootCause(e);
356
+ const code = codeOf(root) ?? codeOf(e);
357
+ if (code && BY_CODE[code]) return { ...BY_CODE[code], code };
358
+ const name = root && typeof root === "object" ? root.name : void 0;
359
+ if (name === "AbortError" || name === "TimeoutError") {
360
+ return {
361
+ cause: name === "TimeoutError" ? "read_timeout" : "aborted",
362
+ code: code ?? String(name),
363
+ detail: name === "TimeoutError" ? "the request exceeded its timeout" : "the request was cancelled",
364
+ transient: name === "TimeoutError",
365
+ kind: name === "TimeoutError" ? "timeout" : "network"
366
+ };
367
+ }
368
+ return {
369
+ cause: "unknown",
370
+ code,
371
+ detail: code ? `the connection failed with ${code}` : "the connection failed and the underlying error carried no code",
372
+ transient: true,
373
+ kind: "network"
374
+ };
375
+ }
376
+ function looksLikeNetworkFailure(d) {
377
+ return d.code !== null || d.cause !== "unknown";
378
+ }
379
+ function networkErrorMessage(provider, d) {
380
+ const code = d.code ? ` [${d.code}]` : "";
381
+ return `${provider}: ${d.detail}${code}`;
382
+ }
383
+
292
384
  // src/providers/retry.ts
293
385
  var override = null;
294
386
  function resolveRetryConfig() {
@@ -611,7 +703,11 @@ async function sendAnthropic(args) {
611
703
  try {
612
704
  respLike = await doFetch(url, init);
613
705
  } catch (e) {
614
- throw new ProviderError("network", `anthropic: fetch failed: ${e.message}`);
706
+ const d = diagnoseNetworkError(e);
707
+ if (!looksLikeNetworkFailure(d)) throw e;
708
+ throw new ProviderError(d.kind, networkErrorMessage("anthropic", d), {
709
+ transient: d.transient
710
+ });
615
711
  }
616
712
  const status = respLike.status;
617
713
  if (status >= 200 && status < 300) {
@@ -684,6 +780,11 @@ function jsonSchemaToGeminiSchema(schema) {
684
780
  }
685
781
  return out;
686
782
  }
783
+ var GEMINI_THINKING_HEADROOM_TOKENS = 16384;
784
+ function thinkingHeadroom() {
785
+ const raw = Number(process.env["CROSSCHECK_GEMINI_THINKING_HEADROOM_TOKENS"]);
786
+ return Number.isFinite(raw) && raw >= 0 ? Math.trunc(raw) : GEMINI_THINKING_HEADROOM_TOKENS;
787
+ }
687
788
  function buildGeminiRequest(opts) {
688
789
  const contents = [];
689
790
  let systemText = null;
@@ -702,8 +803,9 @@ function buildGeminiRequest(opts) {
702
803
  const body = {
703
804
  contents,
704
805
  generationConfig: {
705
- maxOutputTokens: opts.maxTokens,
706
- temperature: opts.temperature
806
+ // Answer budget + thinking headroom. No temperature / topP / topK /
807
+ // thinkingBudget, on any model — see the header note.
808
+ maxOutputTokens: opts.maxTokens + thinkingHeadroom()
707
809
  }
708
810
  };
709
811
  if (systemText !== null && systemText !== "") {
@@ -713,8 +815,8 @@ function buildGeminiRequest(opts) {
713
815
  body.generationConfig.responseMimeType = "application/json";
714
816
  body.generationConfig.responseSchema = jsonSchemaToGeminiSchema(opts.jsonSchema);
715
817
  }
716
- const url = `${GEMINI_API_URL_BASE}/${encodeURIComponent(opts.model)}:generateContent?key=${encodeURIComponent(opts.apiKey)}`;
717
- return { url, headers: {}, body };
818
+ const url = `${GEMINI_API_URL_BASE}/${encodeURIComponent(opts.model)}:generateContent`;
819
+ return { url, headers: { "x-goog-api-key": opts.apiKey }, body };
718
820
  }
719
821
  function parseGeminiResponse(opts) {
720
822
  const r = opts.resp ?? {};
@@ -744,16 +846,19 @@ function parseGeminiResponse(opts) {
744
846
  }
745
847
  try {
746
848
  const first = cands[0];
747
- const content = first["content"];
748
- const parts = content["parts"];
849
+ const finishReason = typeof first["finishReason"] === "string" ? first["finishReason"] : void 0;
850
+ const content = first["content"] ?? {};
851
+ const parts = Array.isArray(content["parts"]) ? content["parts"] : [];
749
852
  let text = "";
750
853
  for (const p of parts) {
751
854
  if (p && typeof p === "object") {
752
- const t = p["text"];
855
+ const part = p;
856
+ if (part["thought"] === true) continue;
857
+ const t = part["text"];
753
858
  if (typeof t === "string") text += t;
754
859
  }
755
860
  }
756
- return { text, usage };
861
+ return { text, usage, ...finishReason ? { finishReason } : {} };
757
862
  } catch (e) {
758
863
  throw new ProviderError(
759
864
  "parse",
@@ -782,7 +887,8 @@ async function sendGemini(args) {
782
887
  apiKey: args.apiKey,
783
888
  messages: args.messages,
784
889
  maxTokens: args.maxTokens,
785
- temperature: args.temperature,
890
+ // args.temperature is deliberately NOT forwarded: Gemini ignores it and
891
+ // upcoming models reject it. See the header note.
786
892
  ...args.jsonSchema ? { jsonSchema: args.jsonSchema } : {}
787
893
  });
788
894
  const doFetch = args.fetchImpl ?? globalThis.fetch;
@@ -797,7 +903,11 @@ async function sendGemini(args) {
797
903
  try {
798
904
  respLike = await doFetch(url, init);
799
905
  } catch (e) {
800
- throw new ProviderError("network", `gemini: fetch failed: ${e.message}`);
906
+ const d = diagnoseNetworkError(e);
907
+ if (!looksLikeNetworkFailure(d)) throw e;
908
+ throw new ProviderError(d.kind, networkErrorMessage("gemini", d), {
909
+ transient: d.transient
910
+ });
801
911
  }
802
912
  const status = respLike.status;
803
913
  if (status >= 200 && status < 300) {
@@ -807,11 +917,18 @@ async function sendGemini(args) {
807
917
  } catch (e) {
808
918
  throw new ProviderError("parse", `gemini: response body not JSON: ${e.message}`);
809
919
  }
810
- const { text, usage } = parseGeminiResponse({
920
+ const { text, usage, finishReason } = parseGeminiResponse({
811
921
  resp: parsed,
812
922
  model: args.model,
813
923
  purpose: args.purpose ?? "worker"
814
924
  });
925
+ if (text.trim() === "" && finishReason === "MAX_TOKENS") {
926
+ throw new ProviderError(
927
+ "parse",
928
+ `gemini: the answer was cut off before any visible text \u2014 thinking used the whole output budget (${usage.completion_tokens} tokens). Raise CROSSCHECK_GEMINI_THINKING_HEADROOM_TOKENS or the purpose's budget.`,
929
+ { transient: false }
930
+ );
931
+ }
815
932
  return { text, attempts: 1, usage: applyPricing2(usage, args.pricing) };
816
933
  }
817
934
  const bodyText = await respLike.text().catch(() => "");
@@ -978,7 +1095,11 @@ async function sendOpenAICompatible(args) {
978
1095
  try {
979
1096
  respLike = await doFetch(url, init);
980
1097
  } catch (e) {
981
- throw new ProviderError("network", `${args.provider}: fetch failed: ${e.message}`);
1098
+ const d = diagnoseNetworkError(e);
1099
+ if (!looksLikeNetworkFailure(d)) throw e;
1100
+ throw new ProviderError(d.kind, networkErrorMessage(args.provider, d), {
1101
+ transient: d.transient
1102
+ });
982
1103
  }
983
1104
  const status = respLike.status;
984
1105
  if (status >= 200 && status < 300) {
@@ -1006,7 +1127,7 @@ async function sendOpenAICompatible(args) {
1006
1127
  // src/providers/registry.ts
1007
1128
  var DEFAULT_MODELS = {
1008
1129
  anthropic: "claude-opus-5-5",
1009
- openai: "gpt-5.6-sol",
1130
+ openai: "gpt-6-sol",
1010
1131
  xai: "grok-4-latest",
1011
1132
  mistral: "mistral-large-latest",
1012
1133
  groq: "llama-3.3-70b-versatile",
@@ -1152,7 +1273,7 @@ var import_zod = require("zod");
1152
1273
 
1153
1274
  // src/server-meta.ts
1154
1275
  var SERVER_NAME = "crosscheck-agent";
1155
- var SERVER_VERSION = true ? "0.2.26" : "0.0.0-dev";
1276
+ var SERVER_VERSION = true ? "0.2.28" : "0.0.0-dev";
1156
1277
 
1157
1278
  // src/tools/audit.ts
1158
1279
  var import_node_fs4 = require("fs");
@@ -1213,27 +1334,27 @@ function extractJson(text) {
1213
1334
  }
1214
1335
 
1215
1336
  // src/core/json-schema.ts
1216
- function validateSchema(value, schema, path12 = "") {
1337
+ function validateSchema(value, schema, path13 = "") {
1217
1338
  const errs = [];
1218
1339
  if ("anyOf" in schema) {
1219
1340
  const subs = schema["anyOf"].map(
1220
- (s) => validateSchema(value, s, path12)
1341
+ (s) => validateSchema(value, s, path13)
1221
1342
  );
1222
1343
  if (!subs.some((e) => e.length === 0)) {
1223
- errs.push(`${path12 || "<root>"}: did not match anyOf`);
1344
+ errs.push(`${path13 || "<root>"}: did not match anyOf`);
1224
1345
  }
1225
1346
  return errs;
1226
1347
  }
1227
1348
  if ("oneOf" in schema) {
1228
- const passed = schema["oneOf"].filter((s) => validateSchema(value, s, path12).length === 0).length;
1349
+ const passed = schema["oneOf"].filter((s) => validateSchema(value, s, path13).length === 0).length;
1229
1350
  if (passed !== 1) {
1230
- errs.push(`${path12 || "<root>"}: matched ${passed} of oneOf, expected 1`);
1351
+ errs.push(`${path13 || "<root>"}: matched ${passed} of oneOf, expected 1`);
1231
1352
  }
1232
1353
  return errs;
1233
1354
  }
1234
1355
  if ("const" in schema && !deepEqual(value, schema["const"])) {
1235
1356
  errs.push(
1236
- `${path12 || "<root>"}: expected const ${pyRepr(schema["const"])}, got ${pyRepr(value)}`
1357
+ `${path13 || "<root>"}: expected const ${pyRepr(schema["const"])}, got ${pyRepr(value)}`
1237
1358
  );
1238
1359
  return errs;
1239
1360
  }
@@ -1243,7 +1364,7 @@ function validateSchema(value, schema, path12 = "") {
1243
1364
  const ok = types.some((tt) => matchesType(value, String(tt)));
1244
1365
  if (!ok) {
1245
1366
  errs.push(
1246
- `${path12 || "<root>"}: expected type ${pyReprType(t)}, got ${pyTypeName(value)}`
1367
+ `${path13 || "<root>"}: expected type ${pyReprType(t)}, got ${pyTypeName(value)}`
1247
1368
  );
1248
1369
  return errs;
1249
1370
  }
@@ -1252,29 +1373,29 @@ function validateSchema(value, schema, path12 = "") {
1252
1373
  if ("enum" in schema) {
1253
1374
  const en = schema["enum"];
1254
1375
  if (!en.some((x) => deepEqual(x, value))) {
1255
- errs.push(`${path12 || "<root>"}: value ${pyRepr(value)} not in enum`);
1376
+ errs.push(`${path13 || "<root>"}: value ${pyRepr(value)} not in enum`);
1256
1377
  }
1257
1378
  }
1258
1379
  if ("minLength" in schema && value.length < schema["minLength"]) {
1259
- errs.push(`${path12 || "<root>"}: shorter than minLength ${schema["minLength"]}`);
1380
+ errs.push(`${path13 || "<root>"}: shorter than minLength ${schema["minLength"]}`);
1260
1381
  }
1261
1382
  }
1262
1383
  if (typeof value === "number" && !Number.isNaN(value)) {
1263
1384
  if ("minimum" in schema && value < schema["minimum"]) {
1264
- errs.push(`${path12 || "<root>"}: ${value} < minimum ${schema["minimum"]}`);
1385
+ errs.push(`${path13 || "<root>"}: ${value} < minimum ${schema["minimum"]}`);
1265
1386
  }
1266
1387
  if ("maximum" in schema && value > schema["maximum"]) {
1267
- errs.push(`${path12 || "<root>"}: ${value} > maximum ${schema["maximum"]}`);
1388
+ errs.push(`${path13 || "<root>"}: ${value} > maximum ${schema["maximum"]}`);
1268
1389
  }
1269
1390
  }
1270
1391
  if (Array.isArray(value)) {
1271
1392
  if ("minItems" in schema && value.length < schema["minItems"]) {
1272
- errs.push(`${path12 || "<root>"}: fewer items than minItems ${schema["minItems"]}`);
1393
+ errs.push(`${path13 || "<root>"}: fewer items than minItems ${schema["minItems"]}`);
1273
1394
  }
1274
1395
  const itemSchema = schema["items"];
1275
1396
  if (isObj(itemSchema)) {
1276
1397
  for (let i = 0; i < value.length; i++) {
1277
- errs.push(...validateSchema(value[i], itemSchema, `${path12}[${i}]`));
1398
+ errs.push(...validateSchema(value[i], itemSchema, `${path13}[${i}]`));
1278
1399
  }
1279
1400
  }
1280
1401
  }
@@ -1283,19 +1404,19 @@ function validateSchema(value, schema, path12 = "") {
1283
1404
  const required = schema["required"] ?? [];
1284
1405
  for (const r of required) {
1285
1406
  if (!(r in value)) {
1286
- errs.push(`${path12 || "<root>"}: missing required key ${pyRepr(r)}`);
1407
+ errs.push(`${path13 || "<root>"}: missing required key ${pyRepr(r)}`);
1287
1408
  }
1288
1409
  }
1289
1410
  if (schema["additionalProperties"] === false) {
1290
1411
  for (const k of Object.keys(value)) {
1291
1412
  if (!(k in props)) {
1292
- errs.push(`${path12 || "<root>"}: unknown key ${pyRepr(k)}`);
1413
+ errs.push(`${path13 || "<root>"}: unknown key ${pyRepr(k)}`);
1293
1414
  }
1294
1415
  }
1295
1416
  }
1296
1417
  for (const [k, v] of Object.entries(value)) {
1297
1418
  const ps = props[k];
1298
- if (ps) errs.push(...validateSchema(v, ps, path12 ? `${path12}.${k}` : k));
1419
+ if (ps) errs.push(...validateSchema(v, ps, path13 ? `${path13}.${k}` : k));
1299
1420
  }
1300
1421
  }
1301
1422
  return errs;
@@ -1375,6 +1496,31 @@ function pyReprType(t) {
1375
1496
  return String(t);
1376
1497
  }
1377
1498
 
1499
+ // src/core/session.ts
1500
+ var import_node_crypto = require("crypto");
1501
+ var processSessionId = null;
1502
+ var startedAt = null;
1503
+ function engineSessionId() {
1504
+ if (processSessionId === null) {
1505
+ processSessionId = (0, import_node_crypto.randomUUID)();
1506
+ startedAt = Date.now();
1507
+ }
1508
+ return processSessionId;
1509
+ }
1510
+ function resolveSessionId(callerSupplied) {
1511
+ const trimmed = typeof callerSupplied === "string" ? callerSupplied.trim() : "";
1512
+ return trimmed.length > 0 ? trimmed : engineSessionId();
1513
+ }
1514
+ function localSessionRecordingEnabled(env = globalThis.process?.env ?? {}) {
1515
+ const v = (env["CROSSCHECK_RECORD_SESSIONS"] ?? "").trim().toLowerCase();
1516
+ return !["0", "false", "off", "no"].includes(v);
1517
+ }
1518
+ function recordingSessionId(callerSupplied) {
1519
+ if (localSessionRecordingEnabled()) return resolveSessionId(callerSupplied);
1520
+ const trimmed = typeof callerSupplied === "string" ? callerSupplied.trim() : "";
1521
+ return trimmed.length > 0 ? trimmed : null;
1522
+ }
1523
+
1378
1524
  // src/core/usage.ts
1379
1525
  function emptyUsage(provider, model, purpose = "worker") {
1380
1526
  return {
@@ -1480,11 +1626,11 @@ function withCommas(n) {
1480
1626
  function renderRunSummary(opts) {
1481
1627
  const endedAt = opts.endedAtS ?? Math.trunc(Date.now() / 1e3);
1482
1628
  let scope = "call";
1483
- let startedAt = null;
1629
+ let startedAt2 = null;
1484
1630
  let rows = [];
1485
1631
  if (opts.sessionScope && opts.sessionScope.rows.length > 0) {
1486
1632
  scope = "session";
1487
- startedAt = opts.sessionScope.startedAt;
1633
+ startedAt2 = opts.sessionScope.startedAt;
1488
1634
  rows = opts.sessionScope.rows.map((r) => ({ ...r }));
1489
1635
  } else {
1490
1636
  const byPurpose = /* @__PURE__ */ new Map();
@@ -1515,6 +1661,7 @@ function renderRunSummary(opts) {
1515
1661
  row.cpu_ms += a.cpu_ms ?? 0;
1516
1662
  if (a.cache_hit) row.cache_hits += 1;
1517
1663
  if (a.error) row.errors += 1;
1664
+ if (a.usage?.estimated) row.estimated = true;
1518
1665
  }
1519
1666
  rows = Array.from(byPurpose.values());
1520
1667
  }
@@ -1527,16 +1674,18 @@ function renderRunSummary(opts) {
1527
1674
  wall_ms: rows.reduce((s, r) => s + r.wall_ms, 0),
1528
1675
  cpu_ms: rows.reduce((s, r) => s + r.cpu_ms, 0),
1529
1676
  cache_hits: rows.reduce((s, r) => s + r.cache_hits, 0),
1530
- errors: rows.reduce((s, r) => s + r.errors, 0)
1677
+ errors: rows.reduce((s, r) => s + r.errors, 0),
1678
+ ...rows.some((r) => r.estimated) ? { estimated: true } : {}
1531
1679
  };
1532
1680
  const titleLeft = scope === "session" ? `session: ${opts.sessionId ?? ""}` : `call: ${opts.toolName}`;
1533
- const header = `${titleLeft} (${totals.calls} calls, ${withCommas(totals.total_tokens)} tokens, $${totals.cost_usd.toFixed(4)}, ${(totals.wall_ms / 1e3).toFixed(1)}s wall, ${(totals.cpu_ms / 1e3).toFixed(3)}s cpu)`;
1681
+ const costText = totals.estimated ? `$${totals.cost_usd.toFixed(4)}+ (some calls unpriced)` : `$${totals.cost_usd.toFixed(4)}`;
1682
+ const header = `${titleLeft} (${totals.calls} calls, ${withCommas(totals.total_tokens)} tokens, ${costText}, ${(totals.wall_ms / 1e3).toFixed(1)}s wall, ${(totals.cpu_ms / 1e3).toFixed(3)}s cpu)`;
1534
1683
  const bodyLines = [];
1535
1684
  for (let i = 0; i < rows.length; i++) {
1536
1685
  const r = rows[i];
1537
1686
  const glyph = i === rows.length - 1 ? "`-" : "|-";
1538
1687
  bodyLines.push(
1539
- `${glyph} purpose: ${r.purpose} (calls=${r.calls} tokens=${withCommas(r.total_tokens)} cost=$${r.cost_usd.toFixed(4)} wall=${(r.wall_ms / 1e3).toFixed(1)}s cpu=${(r.cpu_ms / 1e3).toFixed(3)}s)`
1688
+ `${glyph} purpose: ${r.purpose} (calls=${r.calls} tokens=${withCommas(r.total_tokens)} cost=$${r.cost_usd.toFixed(4)}${r.estimated ? "+" : ""} wall=${(r.wall_ms / 1e3).toFixed(1)}s cpu=${(r.cpu_ms / 1e3).toFixed(3)}s)`
1540
1689
  );
1541
1690
  }
1542
1691
  const callByModel = rollupSpendByModel(
@@ -1584,7 +1733,7 @@ function renderRunSummary(opts) {
1584
1733
  tool: opts.toolName,
1585
1734
  scope,
1586
1735
  currency: "USD",
1587
- started_at: startedAt,
1736
+ started_at: startedAt2,
1588
1737
  ended_at: endedAt,
1589
1738
  rows,
1590
1739
  totals,
@@ -1709,14 +1858,15 @@ async function attachUsageBlock(result, answers, opts) {
1709
1858
  delete result["_suppress_run_summary"];
1710
1859
  }
1711
1860
  async function appendUsageLog(storage, sessionId, toolName, answers, nowS) {
1712
- if (!sessionId || answers.length === 0) return;
1861
+ const sid = recordingSessionId(sessionId);
1862
+ if (!sid || answers.length === 0) return;
1713
1863
  const now = nowS ?? Math.trunc(Date.now() / 1e3);
1714
1864
  const rows = [];
1715
1865
  for (const a of answers) {
1716
1866
  const u = a.usage;
1717
1867
  if (!u || typeof u.provider !== "string" || u.provider === "") continue;
1718
1868
  rows.push({
1719
- session_id: sessionId,
1869
+ session_id: sid,
1720
1870
  ts: now,
1721
1871
  tool: toolName,
1722
1872
  purpose: u.purpose ?? "worker",
@@ -1739,13 +1889,14 @@ async function appendUsageLog(storage, sessionId, toolName, answers, nowS) {
1739
1889
  }
1740
1890
  }
1741
1891
  async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, nowS) {
1742
- if (!sessionId) return;
1892
+ const sid = recordingSessionId(sessionId);
1893
+ if (!sid) return;
1743
1894
  const now = nowS ?? Math.trunc(Date.now() / 1e3);
1744
1895
  try {
1745
- let existing = await storage.getSession(sessionId);
1896
+ let existing = await storage.getSession(sid);
1746
1897
  if (!existing) {
1747
1898
  await storage.upsertSession({
1748
- session_id: sessionId,
1899
+ session_id: sid,
1749
1900
  started_at: now,
1750
1901
  last_at: now,
1751
1902
  calls: 0,
@@ -1758,7 +1909,7 @@ async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, now
1758
1909
  total_cost_usd: 0,
1759
1910
  total_cpu_ms: 0
1760
1911
  });
1761
- existing = await storage.getSession(sessionId);
1912
+ existing = await storage.getSession(sid);
1762
1913
  }
1763
1914
  if (!existing) return;
1764
1915
  let promptDelta = 0;
@@ -1778,7 +1929,7 @@ async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, now
1778
1929
  }
1779
1930
  if (a.cache_hit) cacheHitDelta += 1;
1780
1931
  }
1781
- await storage.accumulateSessionTotals(sessionId, {
1932
+ await storage.accumulateSessionTotals(sid, {
1782
1933
  calls: answers.length,
1783
1934
  wall_ms: wallMs,
1784
1935
  cache_hits: cacheHitDelta,
@@ -2160,7 +2311,7 @@ function buildPersonaInjection(opts) {
2160
2311
  }
2161
2312
 
2162
2313
  // src/core/canary.ts
2163
- var import_node_crypto = require("crypto");
2314
+ var import_node_crypto2 = require("crypto");
2164
2315
 
2165
2316
  // src/core/injection.ts
2166
2317
  var INJECTION_PHRASES_RE = new RegExp(
@@ -2178,8 +2329,8 @@ var UNTRUSTED_SYSTEM_NOTE = "Some inputs in this conversation are wrapped in <un
2178
2329
  function mintCanary() {
2179
2330
  const t = process.hrtime.bigint().toString();
2180
2331
  const pid = String(process.pid);
2181
- const r = (0, import_node_crypto.randomBytes)(16).toString("hex");
2182
- const hex = (0, import_node_crypto.createHash)("sha256").update(`${t}-${pid}-${r}`).digest("hex").slice(0, 16).toUpperCase();
2332
+ const r = (0, import_node_crypto2.randomBytes)(16).toString("hex");
2333
+ const hex = (0, import_node_crypto2.createHash)("sha256").update(`${t}-${pid}-${r}`).digest("hex").slice(0, 16).toUpperCase();
2183
2334
  return `CC_CANARY_${hex}`;
2184
2335
  }
2185
2336
  function wrapUntrusted(content, canary) {
@@ -2366,7 +2517,7 @@ var import_node_fs3 = require("fs");
2366
2517
  var import_node_path2 = __toESM(require("path"), 1);
2367
2518
 
2368
2519
  // src/core/redact.ts
2369
- var import_node_crypto2 = require("crypto");
2520
+ var import_node_crypto3 = require("crypto");
2370
2521
  function builtinRedactionRules() {
2371
2522
  return [
2372
2523
  { pattern: /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g, label: "EMAIL", prefix_group: false },
@@ -2393,7 +2544,7 @@ function hmacSuffix(cfg, label, value) {
2393
2544
  const sid = cfg.session_id ?? "";
2394
2545
  const sidBytes = Buffer.from(sid, "utf8");
2395
2546
  const key = Buffer.concat([Buffer.from(secret), sidBytes]);
2396
- const digest = (0, import_node_crypto2.createHmac)("sha256", key).update(`${label}:${value}`, "utf8").digest("hex");
2547
+ const digest = (0, import_node_crypto3.createHmac)("sha256", key).update(`${label}:${value}`, "utf8").digest("hex");
2397
2548
  return digest.slice(0, 8);
2398
2549
  }
2399
2550
  function redactText(s, cfg) {
@@ -2726,13 +2877,25 @@ function numberOrNull(v) {
2726
2877
  var import_node_perf_hooks = require("perf_hooks");
2727
2878
 
2728
2879
  // src/core/co-reason.ts
2729
- var CO_REASON_MODEL = "gpt-5.6-sol";
2880
+ var CO_REASON_MODEL = "gpt-6-sol";
2881
+ var CO_REASON_ALTERNATE = "gpt-6-astra";
2882
+ var LABELS = {
2883
+ "gpt-6-sol": "GPT-6 Sol",
2884
+ "gpt-6-astra": "GPT-6 Astra",
2885
+ "gpt-5.6-sol": "GPT-5.6 Sol"
2886
+ };
2887
+ function coReasonLabel(model) {
2888
+ return LABELS[model] ?? model;
2889
+ }
2890
+ var CO_REASON_LABEL = coReasonLabel(CO_REASON_MODEL);
2730
2891
  var CO_REASON_PROVIDER = "openai";
2731
- var CO_REASON_LABEL = "GPT-5.6";
2732
- function pickCoReasoner(providers, upgradeRequested) {
2892
+ function pickCoReasoner(providers, upgradeRequested, openAiSeatModel) {
2733
2893
  if (!upgradeRequested) return null;
2734
2894
  const base = providers[CO_REASON_PROVIDER];
2735
- return base ? retargetProvider(base, CO_REASON_MODEL) : null;
2895
+ if (!base) return null;
2896
+ const seat = openAiSeatModel ?? base.model;
2897
+ const model = seat === CO_REASON_MODEL ? CO_REASON_ALTERNATE : CO_REASON_MODEL;
2898
+ return retargetProvider(base, model);
2736
2899
  }
2737
2900
  async function coReasonThenInject(opts) {
2738
2901
  const { provider, messages, maxTokens } = opts;
@@ -2958,7 +3121,7 @@ function buildSuggestedUpgrade(toolName, assessment) {
2958
3121
  model: UPGRADE_MODEL,
2959
3122
  label: UPGRADE_LABEL,
2960
3123
  reason: assessment.reason,
2961
- how: `re-run \`${toolName}\` with reasoning:"max" (or upgrade:true) to route the lead reasoning seat to ${UPGRADE_LABEL}, and \u2014 when an OpenAI key is configured \u2014 add a GPT-5.6 second-opinion pass that ${UPGRADE_LABEL} weighs before finalizing. Other panel seats stay on their normal models.`
3124
+ how: `re-run \`${toolName}\` with reasoning:"max" (or upgrade:true) to route the lead reasoning seat to ${UPGRADE_LABEL}, and \u2014 when an OpenAI key is configured \u2014 add an OpenAI second-opinion pass that ${UPGRADE_LABEL} weighs before finalizing (the result names which model ran). Other panel seats stay on their normal models.`
2962
3125
  };
2963
3126
  }
2964
3127
 
@@ -3261,8 +3424,9 @@ ${rubricText}`;
3261
3424
  const upgradeRequested = isUpgradeRequested(args);
3262
3425
  const upgraded = upgradeRequested && opts.providers["anthropic"] !== void 0;
3263
3426
  const auditorForCall = upgraded ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : auditor;
3427
+ const coProvider = pickCoReasoner(opts.providers, upgradeRequested);
3264
3428
  const coReason = await coReasonThenInject({
3265
- provider: pickCoReasoner(opts.providers, upgradeRequested),
3429
+ provider: coProvider,
3266
3430
  messages: msgs,
3267
3431
  maxTokens: 2048,
3268
3432
  purpose: "audit-coreason"
@@ -3346,7 +3510,7 @@ ${rubricText}`;
3346
3510
  model: UPGRADE_MODEL,
3347
3511
  label: UPGRADE_LABEL,
3348
3512
  seat: "auditor",
3349
- ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
3513
+ ...coReasoned ? { co_reasoner: { model: coProvider.model, label: coReasonLabel(coProvider.model) } } : {}
3350
3514
  };
3351
3515
  } else if (upgradeRequested) {
3352
3516
  result["reasoning_upgrade"] = {
@@ -4077,8 +4241,12 @@ var SUPER_MODELS = {
4077
4241
  // Fable 5.1 verified present on the account; 5 as the fallback for accounts
4078
4242
  // that haven't been granted 5.1 yet.
4079
4243
  anthropic: ["claude-fable-5-1", UPGRADE_MODEL],
4080
- // Astra when it exists; gpt-5.6 until then. See the note above.
4081
- openai: ["gpt-6-astra", CO_REASON_MODEL],
4244
+ // Astra is live (verified against the account's model list 2026-09-23).
4245
+ // The fallback is named explicitly rather than reusing CO_REASON_MODEL:
4246
+ // that constant means "OpenAI's top reasoning model" for the max-reasoning
4247
+ // co-reasoner, which is a different question from "what should super fall
4248
+ // back to". Sharing the symbol silently coupled two unrelated decisions.
4249
+ openai: ["gpt-6-astra", "gpt-6-sol"],
4082
4250
  // Explicitly left as-is per product decision. Note grok-4-latest is not in
4083
4251
  // xAI's published model list, but it resolves in practice — real panel calls
4084
4252
  // on it succeeded as recently as 2026-08-30 — so it is an unlisted alias
@@ -4693,10 +4861,6 @@ If you need supporting evidence, you may emit ONE \`<tool_call>...</tool_call>\`
4693
4861
  }
4694
4862
 
4695
4863
  // src/tools/confer.ts
4696
- var DEFERRED_OPTS = [
4697
- // empty — every confer opt runs natively except worker_tools, which
4698
- // is gated below (non-empty list → defer).
4699
- ];
4700
4864
  async function runConfer(args, opts) {
4701
4865
  const callStartedWall = import_node_perf_hooks2.performance.now();
4702
4866
  const callStartedCpu = process.cpuUsage();
@@ -4712,16 +4876,11 @@ async function runConfer(args, opts) {
4712
4876
  rejectedWorkerTools.push(t);
4713
4877
  }
4714
4878
  }
4715
- const workerToolsNeedsBridge = acceptedWorkerTools.length > 0 && !opts.innerCallers;
4716
- const needsBridge = DEFERRED_OPTS.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
4717
- if (needsBridge) {
4718
- if (opts.bridge && opts.bridge.toolNames.has("confer")) {
4719
- return await deferConfer(args, opts.bridge);
4720
- }
4879
+ if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
4721
4880
  return errorEnvelope2(
4722
4881
  "CONFER_OPT_NOT_NATIVE",
4723
4882
  "worker_tools requested but innerCallers are not wired",
4724
- "Native confer covers untrusted_input + early_stop + extract_claims + inject_session_memory + auto_panel. worker_tools needs innerCallers wired by the host (or CROSSCHECK_BRIDGE_PYTHON=1 as a backstop)."
4883
+ "Native confer covers untrusted_input + early_stop + extract_claims + inject_session_memory + auto_panel. worker_tools needs innerCallers wired by the host."
4725
4884
  );
4726
4885
  }
4727
4886
  const question = typeof args["question"] === "string" ? args["question"] : String(args["question"] ?? "");
@@ -5072,21 +5231,6 @@ function unknownProviderError(unknownNames, available) {
5072
5231
  available_now: Object.keys(available).sort()
5073
5232
  };
5074
5233
  }
5075
- async function deferConfer(args, bridge) {
5076
- const r = await bridge.callTool("confer", args);
5077
- const text = r.content[0]?.text;
5078
- if (typeof text === "string") {
5079
- try {
5080
- return JSON.parse(text);
5081
- } catch {
5082
- }
5083
- }
5084
- return errorEnvelope2(
5085
- "CONFER_BRIDGE_BAD_ENVELOPE",
5086
- "bridge returned an unparseable envelope for confer",
5087
- "Check that the Python child is healthy."
5088
- );
5089
- }
5090
5234
  function errorEnvelope2(code, message, hint) {
5091
5235
  return {
5092
5236
  tool: "confer",
@@ -5458,7 +5602,7 @@ function errorEnvelope3(code, message, hint) {
5458
5602
  transient: false
5459
5603
  };
5460
5604
  }
5461
- async function runVerify(args, bridge, fetchConfig) {
5605
+ async function runVerify(args, fetchConfig) {
5462
5606
  const checks = args["checks"];
5463
5607
  if (!Array.isArray(checks) || checks.length === 0) {
5464
5608
  return {
@@ -5470,7 +5614,6 @@ async function runVerify(args, bridge, fetchConfig) {
5470
5614
  )
5471
5615
  };
5472
5616
  }
5473
- void bridge;
5474
5617
  const allowShell = Boolean(args["allow_shell"] ?? false);
5475
5618
  const wallStart = import_node_perf_hooks3.performance.now();
5476
5619
  const cpuStart = process.cpuUsage();
@@ -5772,7 +5915,6 @@ async function runBench(args, opts) {
5772
5915
  const innerOpts = {
5773
5916
  providers: opts.providers,
5774
5917
  allowlist: opts.allowlist ?? null,
5775
- ...opts.bridge ? { bridge: opts.bridge } : {},
5776
5918
  ...opts.moderator ? { moderator: opts.moderator } : {}
5777
5919
  };
5778
5920
  let inner;
@@ -5984,7 +6126,7 @@ function isObj4(v) {
5984
6126
  }
5985
6127
 
5986
6128
  // src/tools/config-pin.ts
5987
- var import_node_crypto3 = require("crypto");
6129
+ var import_node_crypto4 = require("crypto");
5988
6130
  var import_node_fs6 = require("fs");
5989
6131
  var import_node_path6 = __toESM(require("path"), 1);
5990
6132
  var DEFAULT_PIN_PATH = ".crosscheck/config_pins.json";
@@ -6139,7 +6281,7 @@ function hashFile(abs) {
6139
6281
  return "";
6140
6282
  }
6141
6283
  const normalized = stripCrBeforeLf(raw);
6142
- return "sha256:" + (0, import_node_crypto3.createHash)("sha256").update(normalized).digest("hex");
6284
+ return "sha256:" + (0, import_node_crypto4.createHash)("sha256").update(normalized).digest("hex");
6143
6285
  }
6144
6286
  function stripCrBeforeLf(buf) {
6145
6287
  const out = [];
@@ -6216,7 +6358,7 @@ function pyRepr2(v) {
6216
6358
  }
6217
6359
 
6218
6360
  // src/tools/create.ts
6219
- var import_node_crypto6 = require("crypto");
6361
+ var import_node_crypto7 = require("crypto");
6220
6362
  var import_node_fs9 = require("fs");
6221
6363
  var import_node_path9 = __toESM(require("path"), 1);
6222
6364
 
@@ -6302,7 +6444,7 @@ function isDeadModelError(err) {
6302
6444
  }
6303
6445
 
6304
6446
  // src/core/node-cache.ts
6305
- var import_node_crypto4 = require("crypto");
6447
+ var import_node_crypto5 = require("crypto");
6306
6448
  var import_node_fs7 = require("fs");
6307
6449
  var import_node_path7 = require("path");
6308
6450
  var NODE_CACHE_KEY_VERSION = "v2";
@@ -6329,7 +6471,7 @@ function canonicalizeNodeText(s) {
6329
6471
  return out;
6330
6472
  }
6331
6473
  function sha256Hex(s) {
6332
- return (0, import_node_crypto4.createHash)("sha256").update(s, "utf8").digest("hex");
6474
+ return (0, import_node_crypto5.createHash)("sha256").update(s, "utf8").digest("hex");
6333
6475
  }
6334
6476
  function nodeCacheKey(node, upstreamOutputs, provider, model) {
6335
6477
  const canonUpstream = {};
@@ -6387,11 +6529,11 @@ function getNodeCache(cfg, repoRoot, key, nowMs) {
6387
6529
  return null;
6388
6530
  }
6389
6531
  }
6390
- function atomicWriteJson(path12, payload) {
6391
- (0, import_node_fs7.mkdirSync)((0, import_node_path7.dirname)(path12), { recursive: true });
6392
- const tmp = `${path12}.${process.pid}.${Date.now()}.tmp`;
6532
+ function atomicWriteJson(path13, payload) {
6533
+ (0, import_node_fs7.mkdirSync)((0, import_node_path7.dirname)(path13), { recursive: true });
6534
+ const tmp = `${path13}.${process.pid}.${Date.now()}.tmp`;
6393
6535
  (0, import_node_fs7.writeFileSync)(tmp, JSON.stringify(payload), "utf8");
6394
- (0, import_node_fs7.renameSync)(tmp, path12);
6536
+ (0, import_node_fs7.renameSync)(tmp, path13);
6395
6537
  }
6396
6538
  function putNodeCache(cfg, repoRoot, key, value) {
6397
6539
  if (!cfg || cfg.enabled === false) return;
@@ -6449,7 +6591,6 @@ var EST_TOKENS = {
6449
6591
  med: [1500, 800],
6450
6592
  high: [2500, 1500]
6451
6593
  };
6452
- var DEFERRED_OPTS2 = [];
6453
6594
  var REACTIVE_SIGNAL_RE = /<signals>\s*(\{[\s\S]*?\})\s*<\/signals>/g;
6454
6595
  function parseReactiveSignals(output) {
6455
6596
  if (typeof output !== "string" || !output.includes("<signals>")) return [];
@@ -6489,17 +6630,6 @@ async function runOrchestrate(args, opts) {
6489
6630
  );
6490
6631
  if (breakerEnv) return breakerEnv;
6491
6632
  }
6492
- const needsBridge = DEFERRED_OPTS2.some((k) => Boolean(args[k]));
6493
- if (needsBridge) {
6494
- if (opts.bridge && opts.bridge.toolNames.has("orchestrate")) {
6495
- return await deferOrchestrate(args, opts.bridge);
6496
- }
6497
- return errorEnvelope5(
6498
- "ORCHESTRATE_OPT_NOT_NATIVE",
6499
- "this orchestrate opt-in requires the Python bridge in v1",
6500
- "v1 native covers the plain DAG flow + cheap_mode. reactive (mid-flight DAG updates) still defers. Set CROSSCHECK_BRIDGE_PYTHON=1 to enable."
6501
- );
6502
- }
6503
6633
  const goal = typeof args["goal"] === "string" ? args["goal"] : null;
6504
6634
  const dagIn = isObj5(args["dag"]) ? args["dag"] : null;
6505
6635
  if (goal === null === (dagIn === null)) {
@@ -7042,8 +7172,9 @@ ${recombineSys}` : recombineSys },
7042
7172
  provider: synthProvider.name
7043
7173
  } }
7044
7174
  );
7175
+ const coProvider = pickCoReasoner(opts.providers, upgradeRequested);
7045
7176
  const coReason = await coReasonThenInject({
7046
- provider: pickCoReasoner(opts.providers, upgradeRequested),
7177
+ provider: coProvider,
7047
7178
  messages: recMsgs,
7048
7179
  maxTokens,
7049
7180
  purpose: "orchestrate-coreason"
@@ -7102,7 +7233,7 @@ ${recombineSys}` : recombineSys },
7102
7233
  model: UPGRADE_MODEL,
7103
7234
  label: UPGRADE_LABEL,
7104
7235
  seat: "recombine/synthesis",
7105
- ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
7236
+ ...coReasoned ? { co_reasoner: { model: coProvider.model, label: coReasonLabel(coProvider.model) } } : {}
7106
7237
  };
7107
7238
  } else if (upgradeRequested) {
7108
7239
  result["reasoning_upgrade"] = {
@@ -7440,21 +7571,6 @@ function resolveProviders3(names, available, allowlist) {
7440
7571
  }
7441
7572
  return out;
7442
7573
  }
7443
- async function deferOrchestrate(args, bridge) {
7444
- const r = await bridge.callTool("orchestrate", args);
7445
- const text = r.content[0]?.text;
7446
- if (typeof text === "string") {
7447
- try {
7448
- return JSON.parse(text);
7449
- } catch {
7450
- }
7451
- }
7452
- return errorEnvelope5(
7453
- "ORCHESTRATE_BRIDGE_BAD_ENVELOPE",
7454
- "bridge returned an unparseable envelope for orchestrate",
7455
- "Check that the Python child is healthy."
7456
- );
7457
- }
7458
7574
  function errorEnvelope5(code, message, hint, kind = "client") {
7459
7575
  return {
7460
7576
  tool: "orchestrate",
@@ -7502,7 +7618,7 @@ function pyRound6(x) {
7502
7618
  }
7503
7619
 
7504
7620
  // src/tools/fetch.ts
7505
- var import_node_crypto5 = require("crypto");
7621
+ var import_node_crypto6 = require("crypto");
7506
7622
  var import_node_fs8 = require("fs");
7507
7623
  var import_node_path8 = __toESM(require("path"), 1);
7508
7624
  var DEFAULT_CONFIG = {
@@ -7716,10 +7832,10 @@ function extractHost(url) {
7716
7832
  }
7717
7833
  }
7718
7834
  function sha256Hex2(s) {
7719
- return (0, import_node_crypto5.createHash)("sha256").update(s, "utf8").digest("hex");
7835
+ return (0, import_node_crypto6.createHash)("sha256").update(s, "utf8").digest("hex");
7720
7836
  }
7721
7837
  function sha256HexBytes(bytes) {
7722
- return (0, import_node_crypto5.createHash)("sha256").update(bytes).digest("hex");
7838
+ return (0, import_node_crypto6.createHash)("sha256").update(bytes).digest("hex");
7723
7839
  }
7724
7840
  function resolveEvidenceDir(configured, repoRoot) {
7725
7841
  if (import_node_path8.default.isAbsolute(configured)) return configured;
@@ -7817,7 +7933,6 @@ ${documentsPayload}`;
7817
7933
  }, {
7818
7934
  providers: opts.providers,
7819
7935
  allowlist: opts.allowlist ?? null,
7820
- ...opts.bridge ? { bridge: opts.bridge } : {},
7821
7936
  ctx
7822
7937
  });
7823
7938
  const scopeAnswer = Array.isArray(scope["answers"]) ? scope["answers"].filter((a) => typeof a["response"] === "string" && a["response"]).map((a) => `[${a["provider"]}]
@@ -7840,7 +7955,6 @@ ${scopeAnswer || "(none)"}
7840
7955
  providers: opts.providers,
7841
7956
  allowlist: opts.allowlist ?? null,
7842
7957
  moderator,
7843
- ...opts.bridge ? { bridge: opts.bridge } : {},
7844
7958
  ctx
7845
7959
  });
7846
7960
  let attempts = 1;
@@ -7875,7 +7989,6 @@ ${scopeAnswer || "(none)"}
7875
7989
  }, {
7876
7990
  providers: opts.providers,
7877
7991
  allowlist: opts.allowlist ?? null,
7878
- ...opts.bridge ? { bridge: opts.bridge } : {},
7879
7992
  ctx
7880
7993
  });
7881
7994
  }
@@ -7898,7 +8011,6 @@ ${scopeAnswer || "(none)"}
7898
8011
  }, {
7899
8012
  providers: opts.providers,
7900
8013
  allowlist: opts.allowlist ?? null,
7901
- ...opts.bridge ? { bridge: opts.bridge } : {},
7902
8014
  ctx
7903
8015
  });
7904
8016
  let overallF = toNumberOrNull(auditEnvelope["overall_score"]);
@@ -7923,7 +8035,6 @@ ${documentsPayload}`
7923
8035
  providers: opts.providers,
7924
8036
  allowlist: opts.allowlist ?? null,
7925
8037
  moderator,
7926
- ...opts.bridge ? { bridge: opts.bridge } : {},
7927
8038
  ctx
7928
8039
  }
7929
8040
  );
@@ -7943,7 +8054,6 @@ ${documentsPayload}`
7943
8054
  }, {
7944
8055
  providers: opts.providers,
7945
8056
  allowlist: opts.allowlist ?? null,
7946
- ...opts.bridge ? { bridge: opts.bridge } : {},
7947
8057
  ctx
7948
8058
  });
7949
8059
  overallF = toNumberOrNull(auditEnvelope["overall_score"]);
@@ -8080,7 +8190,7 @@ async function ingestDocuments(documents, sessionId, opts) {
8080
8190
  source: ref,
8081
8191
  type: "file",
8082
8192
  status: "ok",
8083
- hash: (0, import_node_crypto6.createHash)("sha256").update(text, "utf8").digest("hex"),
8193
+ hash: (0, import_node_crypto7.createHash)("sha256").update(text, "utf8").digest("hex"),
8084
8194
  content: ""
8085
8195
  }, text));
8086
8196
  }
@@ -8117,7 +8227,7 @@ ${d.content}
8117
8227
  function makeSessionId(opts, supplied) {
8118
8228
  if (typeof supplied === "string" && supplied) return supplied;
8119
8229
  const stamp = opts.nowEpochSeconds ? opts.nowEpochSeconds() : Math.floor(Date.now() / 1e3);
8120
- const rnd = opts.randomBytes ? opts.randomBytes() : (0, import_node_crypto6.createHash)("sha256").update(`${stamp}-${process.pid}-${Math.random()}`).digest("hex");
8230
+ const rnd = opts.randomBytes ? opts.randomBytes() : (0, import_node_crypto7.createHash)("sha256").update(`${stamp}-${process.pid}-${Math.random()}`).digest("hex");
8121
8231
  const suffix = rnd.slice(0, 8);
8122
8232
  return `${opts.toolName}-${stamp}-${suffix}`;
8123
8233
  }
@@ -8181,11 +8291,6 @@ function errorEnvelope6(toolName, code, message, hint) {
8181
8291
 
8182
8292
  // src/tools/coordinate.ts
8183
8293
  var import_node_perf_hooks7 = require("perf_hooks");
8184
- var DEFERRED_OPTS3 = [
8185
- // empty — every coordinate opt runs natively when its deps
8186
- // (storage / innerCallers) are wired. Without them the
8187
- // worker_tools gate still triggers a bridge defer.
8188
- ];
8189
8294
  var COORDINATE_DEFAULT_TEMP = 0.4;
8190
8295
  var ROLE_TURN_SCHEMA = {
8191
8296
  type: "object",
@@ -8240,23 +8345,18 @@ async function runCoordinate(args, opts) {
8240
8345
  rejectedWorkerTools.push(t);
8241
8346
  }
8242
8347
  }
8243
- const workerToolsNeedsBridge = acceptedWorkerTools.length > 0 && !opts.innerCallers;
8244
- const needsBridge = DEFERRED_OPTS3.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
8245
- if (needsBridge) {
8348
+ if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
8246
8349
  if (superRequested) {
8247
8350
  return errorEnvelope7(
8248
8351
  "COORDINATE_SUPER_NOT_NATIVE",
8249
- "super mode requested but worker_tools needs the Python bridge",
8250
- "worker_tools without innerCallers wired defers to the Python bridge, which doesn't support super mode. Drop worker_tools, or wire innerCallers, to use super."
8352
+ "super mode requested with worker_tools, but innerCallers are not wired",
8353
+ "worker_tools needs innerCallers wired by the host. Drop worker_tools, or wire innerCallers, to use super."
8251
8354
  );
8252
8355
  }
8253
- if (opts.bridge && opts.bridge.toolNames.has("coordinate")) {
8254
- return await deferCoordinate(args, opts.bridge);
8255
- }
8256
8356
  return errorEnvelope7(
8257
8357
  "COORDINATE_OPT_NOT_NATIVE",
8258
8358
  "worker_tools requested but innerCallers are not wired",
8259
- "Native coordinate covers the three-role flow + untrusted_input + inject_session_memory. worker_tools needs innerCallers wired by the host (or CROSSCHECK_BRIDGE_PYTHON=1 as a backstop)."
8359
+ "Native coordinate covers the three-role flow + untrusted_input + inject_session_memory. worker_tools needs innerCallers wired by the host."
8260
8360
  );
8261
8361
  }
8262
8362
  const untrusted = Boolean(args["untrusted_input"]);
@@ -8448,8 +8548,9 @@ CRITIQUES:
8448
8548
  ${critiqueBlock}`
8449
8549
  }
8450
8550
  ];
8551
+ const coProvider = pickCoReasoner(opts.providers, upgradeRequested);
8451
8552
  const coReason = await coReasonThenInject({
8452
- provider: pickCoReasoner(opts.providers, upgradeRequested),
8553
+ provider: coProvider,
8453
8554
  messages: synthMessages,
8454
8555
  maxTokens,
8455
8556
  purpose: "coordinate-coreason"
@@ -8513,7 +8614,7 @@ ${critiqueBlock}`
8513
8614
  model: superRequested ? superPrimary("anthropic") ?? UPGRADE_MODEL : UPGRADE_MODEL,
8514
8615
  label: UPGRADE_LABEL,
8515
8616
  seat: "synthesizer",
8516
- ...coReasonAns ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
8617
+ ...coReasonAns ? { co_reasoner: { model: coProvider.model, label: coReasonLabel(coProvider.model) } } : {}
8517
8618
  };
8518
8619
  } else if (upgradeRequested) {
8519
8620
  result["reasoning_upgrade"] = {
@@ -8655,21 +8756,6 @@ function unknownProviderError3(unknownNames, available) {
8655
8756
  available_now: Object.keys(available).sort()
8656
8757
  };
8657
8758
  }
8658
- async function deferCoordinate(args, bridge) {
8659
- const r = await bridge.callTool("coordinate", args);
8660
- const text = r.content[0]?.text;
8661
- if (typeof text === "string") {
8662
- try {
8663
- return JSON.parse(text);
8664
- } catch {
8665
- }
8666
- }
8667
- return errorEnvelope7(
8668
- "COORDINATE_BRIDGE_BAD_ENVELOPE",
8669
- "bridge returned an unparseable envelope for coordinate",
8670
- "Check that the Python child is healthy."
8671
- );
8672
- }
8673
8759
  function errorEnvelope7(code, message, hint) {
8674
8760
  return {
8675
8761
  tool: "coordinate",
@@ -8997,10 +9083,6 @@ function buildModeratorTranscript(transcript) {
8997
9083
 
8998
9084
  // src/tools/debate.ts
8999
9085
  var import_node_perf_hooks9 = require("perf_hooks");
9000
- var DEFERRED_OPTS4 = [
9001
- // empty — every debate opt runs natively when its deps
9002
- // (storage / innerCallers) are wired.
9003
- ];
9004
9086
  async function runDebate(args, opts) {
9005
9087
  const callStartedWall = import_node_perf_hooks9.performance.now();
9006
9088
  const callStartedCpu = process.cpuUsage();
@@ -9018,23 +9100,18 @@ async function runDebate(args, opts) {
9018
9100
  rejectedWorkerTools.push(t);
9019
9101
  }
9020
9102
  }
9021
- const workerToolsNeedsBridge = acceptedWorkerTools.length > 0 && !opts.innerCallers;
9022
- const needsBridge = DEFERRED_OPTS4.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
9023
- if (needsBridge) {
9103
+ if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
9024
9104
  if (superRequested) {
9025
9105
  return errorEnvelope9(
9026
9106
  "DEBATE_SUPER_NOT_NATIVE",
9027
- "super mode requested but worker_tools needs the Python bridge",
9028
- "worker_tools without innerCallers wired defers to the Python bridge, which doesn't support super mode. Drop worker_tools, or wire innerCallers, to use super."
9107
+ "super mode requested with worker_tools, but innerCallers are not wired",
9108
+ "worker_tools needs innerCallers wired by the host. Drop worker_tools, or wire innerCallers, to use super."
9029
9109
  );
9030
9110
  }
9031
- if (opts.bridge && opts.bridge.toolNames.has("debate")) {
9032
- return await deferDebate(args, opts.bridge);
9033
- }
9034
9111
  return errorEnvelope9(
9035
9112
  "DEBATE_OPT_NOT_NATIVE",
9036
9113
  "worker_tools requested but innerCallers are not wired",
9037
- "Native debate covers N-round + plain/structured moderator synthesis + inject_session_memory + auto_panel + extract_claims + early_stop. worker_tools needs innerCallers wired by the host (or CROSSCHECK_BRIDGE_PYTHON=1 as a backstop)."
9114
+ "Native debate covers N-round + plain/structured moderator synthesis + inject_session_memory + auto_panel + extract_claims + early_stop. worker_tools needs innerCallers wired by the host."
9038
9115
  );
9039
9116
  }
9040
9117
  const topic = typeof args["topic"] === "string" ? args["topic"] : String(args["topic"] ?? "");
@@ -9235,6 +9312,7 @@ ${prior.body}` });
9235
9312
  let synthesisErrors = [];
9236
9313
  let personaMeta = null;
9237
9314
  let coReasoned = false;
9315
+ let coReasonerModel = null;
9238
9316
  if (moderator) {
9239
9317
  const synthProvider = superRequested && opts.providers["anthropic"] ? retargetForSuper(opts.providers["anthropic"]) : upgraded ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : moderator;
9240
9318
  const condensed = buildModeratorTranscript(transcript);
@@ -9262,13 +9340,16 @@ TRANSCRIPT:
9262
9340
  ${condensed}`
9263
9341
  }
9264
9342
  ];
9343
+ const openAiSeat = selected.find((p) => p.name === "openai")?.model;
9344
+ const coProvider = pickCoReasoner(opts.providers, upgradeRequested, openAiSeat);
9265
9345
  const coReason = await coReasonThenInject({
9266
- provider: pickCoReasoner(opts.providers, upgradeRequested),
9346
+ provider: coProvider,
9267
9347
  messages: synthMessages,
9268
9348
  maxTokens,
9269
9349
  purpose: "debate-coreason"
9270
9350
  });
9271
9351
  synthMessages = coReason.messages;
9352
+ coReasonerModel = coProvider?.model ?? null;
9272
9353
  if (coReason.answer) extraAnswers.push(coReason.answer);
9273
9354
  coReasoned = coReason.answer !== null;
9274
9355
  if (structuredOpt) {
@@ -9327,7 +9408,7 @@ ${condensed}`
9327
9408
  model: superRequested ? superPrimary("anthropic") ?? UPGRADE_MODEL : UPGRADE_MODEL,
9328
9409
  label: UPGRADE_LABEL,
9329
9410
  seat: "moderator synthesis",
9330
- ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
9411
+ ...coReasoned && coReasonerModel ? { co_reasoner: { model: coReasonerModel, label: coReasonLabel(coReasonerModel) } } : {}
9331
9412
  };
9332
9413
  } else if (upgradeRequested) {
9333
9414
  result["reasoning_upgrade"] = {
@@ -9467,21 +9548,6 @@ function unknownProviderError5(unknownNames, available) {
9467
9548
  available_now: Object.keys(available).sort()
9468
9549
  };
9469
9550
  }
9470
- async function deferDebate(args, bridge) {
9471
- const r = await bridge.callTool("debate", args);
9472
- const text = r.content[0]?.text;
9473
- if (typeof text === "string") {
9474
- try {
9475
- return JSON.parse(text);
9476
- } catch {
9477
- }
9478
- }
9479
- return errorEnvelope9(
9480
- "DEBATE_BRIDGE_BAD_ENVELOPE",
9481
- "bridge returned an unparseable envelope for debate",
9482
- "Check that the Python child is healthy."
9483
- );
9484
- }
9485
9551
  function errorEnvelope9(code, message, hint) {
9486
9552
  return {
9487
9553
  tool: "debate",
@@ -9501,9 +9567,6 @@ var DEFAULT_DELEGATION_LIMITS = {
9501
9567
  };
9502
9568
  async function runDelegate(args, opts) {
9503
9569
  if (!opts.storage) {
9504
- if (opts.bridge && opts.bridge.toolNames.has("delegate")) {
9505
- return await deferDelegate(args, opts.bridge);
9506
- }
9507
9570
  return errorEnvelope10(
9508
9571
  "DELEGATE_STORAGE_UNAVAILABLE",
9509
9572
  "delegate needs the local database (for quota tracking), which isn't available",
@@ -9575,7 +9638,6 @@ async function runDelegate(args, opts) {
9575
9638
  const innerOpts = {
9576
9639
  providers: opts.providers,
9577
9640
  allowlist: opts.allowlist ?? null,
9578
- ...opts.bridge ? { bridge: opts.bridge } : {},
9579
9641
  ...opts.moderator ? { moderator: opts.moderator } : {}
9580
9642
  };
9581
9643
  let result;
@@ -9614,21 +9676,6 @@ async function record(storage, sessionId, requester, toolCall, via, accepted, no
9614
9676
  created_at: nowEpochSeconds
9615
9677
  });
9616
9678
  }
9617
- async function deferDelegate(args, bridge) {
9618
- const r = await bridge.callTool("delegate", args);
9619
- const text = r.content[0]?.text;
9620
- if (typeof text === "string") {
9621
- try {
9622
- return JSON.parse(text);
9623
- } catch {
9624
- }
9625
- }
9626
- return errorEnvelope10(
9627
- "DELEGATE_BRIDGE_BAD_ENVELOPE",
9628
- "bridge returned an unparseable envelope for delegate",
9629
- "Check that the Python child is healthy."
9630
- );
9631
- }
9632
9679
  function errorEnvelope10(code, message, hint) {
9633
9680
  return {
9634
9681
  tool: "delegate",
@@ -9671,9 +9718,6 @@ async function runExplain(args, opts) {
9671
9718
  );
9672
9719
  }
9673
9720
  if (!opts.storage) {
9674
- if (opts.bridge && opts.bridge.toolNames.has("explain")) {
9675
- return await deferExplain(args, opts.bridge);
9676
- }
9677
9721
  return errorEnvelope11(
9678
9722
  "EXPLAIN_STORAGE_UNAVAILABLE",
9679
9723
  "explain needs the local transcript/stats database, which isn't available",
@@ -9955,21 +9999,6 @@ function pyRepr5(v) {
9955
9999
  }
9956
10000
  return String(v);
9957
10001
  }
9958
- async function deferExplain(args, bridge) {
9959
- const r = await bridge.callTool("explain", args);
9960
- const text = r.content[0]?.text;
9961
- if (typeof text === "string") {
9962
- try {
9963
- return JSON.parse(text);
9964
- } catch {
9965
- }
9966
- }
9967
- return errorEnvelope11(
9968
- "EXPLAIN_BRIDGE_BAD_ENVELOPE",
9969
- "bridge returned an unparseable envelope for explain",
9970
- "Check that the Python child is healthy."
9971
- );
9972
- }
9973
10002
  function errorEnvelope11(code, message, hint, kind = "client", extra = {}) {
9974
10003
  return {
9975
10004
  tool: "explain",
@@ -10522,9 +10551,6 @@ async function runRecall(args, opts) {
10522
10551
  if (k < 1) k = 1;
10523
10552
  if (k > 50) k = 50;
10524
10553
  if (!opts.storage) {
10525
- if (opts.bridge && opts.bridge.toolNames.has("recall")) {
10526
- return await deferRecall(args, opts.bridge);
10527
- }
10528
10554
  return errorEnvelope12(
10529
10555
  "RECALL_STORAGE_UNAVAILABLE",
10530
10556
  "recall needs the local database, which isn't available",
@@ -10577,21 +10603,6 @@ async function runRecall(args, opts) {
10577
10603
  applied_filters: applied
10578
10604
  };
10579
10605
  }
10580
- async function deferRecall(args, bridge) {
10581
- const r = await bridge.callTool("recall", args);
10582
- const text = r.content[0]?.text;
10583
- if (typeof text === "string") {
10584
- try {
10585
- return JSON.parse(text);
10586
- } catch {
10587
- }
10588
- }
10589
- return errorEnvelope12(
10590
- "RECALL_BRIDGE_BAD_ENVELOPE",
10591
- "bridge returned an unparseable envelope for recall",
10592
- "Check that the Python child is healthy."
10593
- );
10594
- }
10595
10606
  function errorEnvelope12(code, message, hint) {
10596
10607
  return {
10597
10608
  tool: "recall",
@@ -10614,9 +10625,6 @@ async function runRecommendPanel(args, opts) {
10614
10625
  );
10615
10626
  }
10616
10627
  if (!opts.storage) {
10617
- if (opts.bridge && opts.bridge.toolNames.has("recommend_panel")) {
10618
- return await deferRecommendPanel(args, opts.bridge);
10619
- }
10620
10628
  return errorEnvelope13(
10621
10629
  "RECOMMEND_PANEL_STORAGE_UNAVAILABLE",
10622
10630
  "recommend_panel needs the local stats database, which isn't available",
@@ -10679,21 +10687,6 @@ async function runRecommendPanel(args, opts) {
10679
10687
  meta: result.meta
10680
10688
  };
10681
10689
  }
10682
- async function deferRecommendPanel(args, bridge) {
10683
- const r = await bridge.callTool("recommend_panel", args);
10684
- const text = r.content[0]?.text;
10685
- if (typeof text === "string") {
10686
- try {
10687
- return JSON.parse(text);
10688
- } catch {
10689
- }
10690
- }
10691
- return errorEnvelope13(
10692
- "RECOMMEND_PANEL_BRIDGE_BAD_ENVELOPE",
10693
- "bridge returned an unparseable envelope for recommend_panel",
10694
- "Check that the Python child is healthy."
10695
- );
10696
- }
10697
10690
  function errorEnvelope13(code, message, hint) {
10698
10691
  return {
10699
10692
  tool: "recommend_panel",
@@ -10723,9 +10716,6 @@ function toStringArray3(v) {
10723
10716
  var import_node_fs11 = require("fs");
10724
10717
  async function runScoreboard(args, opts) {
10725
10718
  if (!opts.storage) {
10726
- if (opts.bridge && opts.bridge.toolNames.has("scoreboard")) {
10727
- return await deferScoreboard(args, opts.bridge);
10728
- }
10729
10719
  return errorEnvelope14(
10730
10720
  "SCOREBOARD_STORAGE_UNAVAILABLE",
10731
10721
  "scoreboard needs the local stats database, which isn't available",
@@ -10848,21 +10838,6 @@ function clampInt3(raw, min, max, fallback) {
10848
10838
  if (!Number.isFinite(n)) return fallback;
10849
10839
  return Math.min(max, Math.max(min, Math.trunc(n)));
10850
10840
  }
10851
- async function deferScoreboard(args, bridge) {
10852
- const r = await bridge.callTool("scoreboard", args);
10853
- const text = r.content[0]?.text;
10854
- if (typeof text === "string") {
10855
- try {
10856
- return JSON.parse(text);
10857
- } catch {
10858
- }
10859
- }
10860
- return errorEnvelope14(
10861
- "SCOREBOARD_BRIDGE_BAD_ENVELOPE",
10862
- "bridge returned an unparseable envelope for scoreboard",
10863
- "Check that the Python child is healthy."
10864
- );
10865
- }
10866
10841
  function errorEnvelope14(code, message, hint) {
10867
10842
  return {
10868
10843
  tool: "scoreboard",
@@ -10899,9 +10874,6 @@ async function runSessionMemory(args, opts) {
10899
10874
  );
10900
10875
  }
10901
10876
  if (!opts.storage) {
10902
- if (opts.bridge && opts.bridge.toolNames.has("session_memory")) {
10903
- return await deferSessionMemory(args, opts.bridge);
10904
- }
10905
10877
  return errorEnvelope15(
10906
10878
  "SESSION_MEMORY_STORAGE_UNAVAILABLE",
10907
10879
  "session_memory needs the local database, which isn't available",
@@ -11006,21 +10978,6 @@ function clampInt4(raw, min, max, fallback) {
11006
10978
  if (!Number.isFinite(n)) return fallback;
11007
10979
  return Math.min(max, Math.max(min, Math.trunc(n)));
11008
10980
  }
11009
- async function deferSessionMemory(args, bridge) {
11010
- const r = await bridge.callTool("session_memory", args);
11011
- const text = r.content[0]?.text;
11012
- if (typeof text === "string") {
11013
- try {
11014
- return JSON.parse(text);
11015
- } catch {
11016
- }
11017
- }
11018
- return errorEnvelope15(
11019
- "SESSION_MEMORY_BRIDGE_BAD_ENVELOPE",
11020
- "bridge returned an unparseable envelope for session_memory",
11021
- "Check that the Python child is healthy."
11022
- );
11023
- }
11024
10981
  function errorEnvelope15(code, message, hint) {
11025
10982
  return {
11026
10983
  tool: "session_memory",
@@ -11351,7 +11308,7 @@ Re-emit the FULL solution. No commentary.`
11351
11308
  model: UPGRADE_MODEL,
11352
11309
  label: UPGRADE_LABEL,
11353
11310
  seat: "solver",
11354
- ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
11311
+ ...coReasoned ? { co_reasoner: { model: coProvider.model, label: coReasonLabel(coProvider.model) } } : {}
11355
11312
  };
11356
11313
  } else if (upgradeRequested) {
11357
11314
  result["reasoning_upgrade"] = {
@@ -11640,7 +11597,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
11640
11597
  var DEFAULT_PACKAGE = "crosscheck-cli";
11641
11598
  var FETCH_TIMEOUT_MS = 3e3;
11642
11599
  function engineVersion() {
11643
- return true ? "0.2.26" : "0.0.0-dev";
11600
+ return true ? "0.2.28" : "0.0.0-dev";
11644
11601
  }
11645
11602
  function defaultUpdateCachePath() {
11646
11603
  const base = process.env["CROSSCHECK_DATA_DIR"] || import_node_path12.default.join(import_node_os2.default.homedir() || import_node_os2.default.tmpdir(), ".crosscheck");
@@ -12412,12 +12369,11 @@ function helpTool() {
12412
12369
  }
12413
12370
  });
12414
12371
  }
12415
- function registerCoreTools(opts = {}) {
12416
- const o = opts && typeof opts === "object" && "toolNames" in opts ? { bridge: opts } : opts;
12372
+ function registerCoreTools(o = {}) {
12417
12373
  const tools = /* @__PURE__ */ new Map();
12418
12374
  const list = [
12419
12375
  pingTool(),
12420
- verifyTool(o.bridge, o.fetchConfig),
12376
+ verifyTool(o.fetchConfig),
12421
12377
  pickTool(
12422
12378
  o.providers ?? {},
12423
12379
  o.providerAllowlist ?? null,
@@ -12429,7 +12385,6 @@ function registerCoreTools(opts = {}) {
12429
12385
  auditTool(
12430
12386
  o.providers ?? {},
12431
12387
  o.providerAllowlist ?? null,
12432
- o.bridge,
12433
12388
  o.transcriptsDir,
12434
12389
  o.pricing,
12435
12390
  o.storage,
@@ -12439,7 +12394,6 @@ function registerCoreTools(opts = {}) {
12439
12394
  conferTool(
12440
12395
  o.providers ?? {},
12441
12396
  o.providerAllowlist ?? null,
12442
- o.bridge,
12443
12397
  o.moderatorDefault ?? "anthropic",
12444
12398
  o.pricing,
12445
12399
  o.storage,
@@ -12452,7 +12406,6 @@ function registerCoreTools(opts = {}) {
12452
12406
  debateTool(
12453
12407
  o.providers ?? {},
12454
12408
  o.providerAllowlist ?? null,
12455
- o.bridge,
12456
12409
  buildInnerCallers(o),
12457
12410
  o.storage,
12458
12411
  o.pricing,
@@ -12464,7 +12417,6 @@ function registerCoreTools(opts = {}) {
12464
12417
  coordinateTool(
12465
12418
  o.providers ?? {},
12466
12419
  o.providerAllowlist ?? null,
12467
- o.bridge,
12468
12420
  buildInnerCallers(o),
12469
12421
  o.storage,
12470
12422
  o.circuitBreakers,
@@ -12475,7 +12427,6 @@ function registerCoreTools(opts = {}) {
12475
12427
  triangulateTool(
12476
12428
  o.providers ?? {},
12477
12429
  o.providerAllowlist ?? null,
12478
- o.bridge,
12479
12430
  o.storage,
12480
12431
  o.circuitBreakers,
12481
12432
  o.transcriptsDir,
@@ -12484,7 +12435,6 @@ function registerCoreTools(opts = {}) {
12484
12435
  planTool(
12485
12436
  o.providers ?? {},
12486
12437
  o.providerAllowlist ?? null,
12487
- o.bridge,
12488
12438
  o.storage,
12489
12439
  o.circuitBreakers,
12490
12440
  o.transcriptsDir,
@@ -12493,7 +12443,6 @@ function registerCoreTools(opts = {}) {
12493
12443
  critiqueTool(
12494
12444
  o.providers ?? {},
12495
12445
  o.providerAllowlist ?? null,
12496
- o.bridge,
12497
12446
  o.storage,
12498
12447
  o.circuitBreakers,
12499
12448
  o.transcriptsDir,
@@ -12502,7 +12451,6 @@ function registerCoreTools(opts = {}) {
12502
12451
  reviewTool(
12503
12452
  o.providers ?? {},
12504
12453
  o.providerAllowlist ?? null,
12505
- o.bridge,
12506
12454
  o.storage,
12507
12455
  o.circuitBreakers,
12508
12456
  o.transcriptsDir,
@@ -12510,25 +12458,23 @@ function registerCoreTools(opts = {}) {
12510
12458
  ),
12511
12459
  listProvidersTool(o.providers ?? {}, o.activeProviders ?? null, o.moderatorDefault ?? "anthropic"),
12512
12460
  modelsTool(o.providers ?? {}, o.activeProviders ?? null),
12513
- recallTool(o.storage, o.bridge),
12514
- sessionMemoryTool(o.storage, o.bridge),
12515
- scoreboardTool(o.storage, o.bridge, o.eventsPath),
12516
- explainTool(o.storage, o.bridge, o.transcriptsDir),
12461
+ recallTool(o.storage),
12462
+ sessionMemoryTool(o.storage),
12463
+ scoreboardTool(o.storage, o.eventsPath),
12464
+ explainTool(o.storage, o.transcriptsDir),
12517
12465
  delegateTool(
12518
12466
  o.providers ?? {},
12519
12467
  o.providerAllowlist ?? null,
12520
12468
  o.storage,
12521
- o.bridge,
12522
12469
  o.moderatorDefault ?? "anthropic"
12523
12470
  ),
12524
12471
  fetchTool(o.storage, o.fetchConfig, o.repoRoot),
12525
- recommendPanelTool(o.providers ?? {}, o.storage, o.bridge),
12472
+ recommendPanelTool(o.providers ?? {}, o.storage),
12526
12473
  updateCrosscheckTool(o.repoRoot ?? null),
12527
12474
  benchTool(
12528
12475
  o.providers ?? {},
12529
12476
  o.providerAllowlist ?? null,
12530
12477
  o.storage,
12531
- o.bridge,
12532
12478
  o.moderatorDefault ?? "anthropic",
12533
12479
  o.benchGoldensDir,
12534
12480
  o.circuitBreakers,
@@ -12539,7 +12485,6 @@ function registerCoreTools(opts = {}) {
12539
12485
  solveTool(
12540
12486
  o.providers ?? {},
12541
12487
  o.providerAllowlist ?? null,
12542
- o.bridge,
12543
12488
  o.storage,
12544
12489
  o.circuitBreakers,
12545
12490
  o.transcriptsDir,
@@ -12548,7 +12493,6 @@ function registerCoreTools(opts = {}) {
12548
12493
  orchestrateTool(
12549
12494
  o.providers ?? {},
12550
12495
  o.providerAllowlist ?? null,
12551
- o.bridge,
12552
12496
  o.moderatorDefault ?? "anthropic",
12553
12497
  o.storage,
12554
12498
  o.pricing,
@@ -12595,7 +12539,6 @@ function createTool(o, toolName, cheapDefault) {
12595
12539
  providers: o.providers ?? {},
12596
12540
  allowlist: o.providerAllowlist ?? null,
12597
12541
  ...o.storage ? { storage: o.storage } : {},
12598
- ...o.bridge ? { bridge: o.bridge } : {},
12599
12542
  ...o.moderatorDefault ? { moderator: o.moderatorDefault } : {},
12600
12543
  ...o.fetchConfig ? { fetchConfig: o.fetchConfig } : {},
12601
12544
  ...o.repoRoot ? { repoRoot: o.repoRoot } : {},
@@ -12604,7 +12547,7 @@ function createTool(o, toolName, cheapDefault) {
12604
12547
  })
12605
12548
  };
12606
12549
  }
12607
- function orchestrateTool(providers, allowlist, bridge, moderator, storage, pricing, breakers, transcriptsDir, repoRoot, nodeCache) {
12550
+ function orchestrateTool(providers, allowlist, moderator, storage, pricing, breakers, transcriptsDir, repoRoot, nodeCache) {
12608
12551
  return {
12609
12552
  name: "orchestrate",
12610
12553
  description: "Plan and execute a DAG of LLM subtasks. Either supply a `goal` (planner will draft the DAG) OR a hand-authored `dag`. Workers run topologically; recombine produces a single `final`. Covers the sequential flow, cheap_mode (per-node tier picking), and reactive (mid-flight DAG updates) \u2014 all native.",
@@ -12629,7 +12572,6 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
12629
12572
  providers,
12630
12573
  allowlist,
12631
12574
  moderator,
12632
- ...bridge ? { bridge } : {},
12633
12575
  ...storage ? { storage } : {},
12634
12576
  ...pricing ? { pricing } : {},
12635
12577
  ...breakers ? { breakers } : {},
@@ -12639,7 +12581,7 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
12639
12581
  })
12640
12582
  };
12641
12583
  }
12642
- function solveTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
12584
+ function solveTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
12643
12585
  return {
12644
12586
  name: "solve",
12645
12587
  description: "Iterative LLM solver. Generates a proposal, verifies it against the supplied verifier, and retries with feedback up to max_attempts. Verifier kinds: regex_response and shell (run in a native sandbox with wall-clock + optional memory/CPU limits). With target_path, returns a unified-diff patch.",
@@ -12661,7 +12603,6 @@ function solveTool(providers, allowlist, bridge, storage, breakers, transcriptsD
12661
12603
  handler: (args) => runSolve(args, {
12662
12604
  providers,
12663
12605
  allowlist,
12664
- ...bridge ? { bridge } : {},
12665
12606
  ...storage ? { storage } : {},
12666
12607
  ...breakers ? { breakers } : {},
12667
12608
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -12700,7 +12641,7 @@ function configPinTool(repoRoot, config2, rejectDriftEnv) {
12700
12641
  }
12701
12642
  };
12702
12643
  }
12703
- function benchTool(providers, allowlist, storage, bridge, moderator, defaultGoldensDir, breakers, transcriptsDir, repoRoot) {
12644
+ function benchTool(providers, allowlist, storage, moderator, defaultGoldensDir, breakers, transcriptsDir, repoRoot) {
12704
12645
  return {
12705
12646
  name: "bench",
12706
12647
  description: "Run benchmark goldens against each provider's confer/review output. Each golden: {name, tool_call: confer|review, args, verifiers[]}. Returns per-provider pass/fail/error + a ranking sorted by score. Records ballots into provider_stats when storage is wired (used by triangulate's win-rate weights).",
@@ -12719,7 +12660,6 @@ function benchTool(providers, allowlist, storage, bridge, moderator, defaultGold
12719
12660
  allowlist,
12720
12661
  moderator,
12721
12662
  ...storage ? { storage } : {},
12722
- ...bridge ? { bridge } : {},
12723
12663
  ...defaultGoldensDir ? { defaultGoldensDir } : {},
12724
12664
  ...breakers ? { breakers } : {},
12725
12665
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -12746,7 +12686,7 @@ function updateCrosscheckTool(repoRoot) {
12746
12686
  }
12747
12687
  };
12748
12688
  }
12749
- function recommendPanelTool(providers, storage, bridge) {
12689
+ function recommendPanelTool(providers, storage) {
12750
12690
  return {
12751
12691
  name: "recommend_panel",
12752
12692
  description: "Recommend a minimal effective panel for a given purpose, based on historical usage_log + provider_stats. Cold-start falls back to the configured panel ordered by win-rate.",
@@ -12764,8 +12704,7 @@ function recommendPanelTool(providers, storage, bridge) {
12764
12704
  },
12765
12705
  handler: (args) => runRecommendPanel(args, {
12766
12706
  providers,
12767
- ...storage ? { storage } : {},
12768
- ...bridge ? { bridge } : {}
12707
+ ...storage ? { storage } : {}
12769
12708
  })
12770
12709
  };
12771
12710
  }
@@ -12790,7 +12729,7 @@ function fetchTool(storage, fetchConfig, repoRoot) {
12790
12729
  })
12791
12730
  };
12792
12731
  }
12793
- function delegateTool(providers, allowlist, storage, bridge, moderator) {
12732
+ function delegateTool(providers, allowlist, storage, moderator) {
12794
12733
  return {
12795
12734
  name: "delegate",
12796
12735
  description: "Run a delegable tool (confer | review) restricted to a single named provider, with explicit quota check. Records every attempt (accepted or refused) to the delegations table; quota in the response reflects counts AFTER the current call.",
@@ -12810,12 +12749,11 @@ function delegateTool(providers, allowlist, storage, bridge, moderator) {
12810
12749
  providers,
12811
12750
  allowlist,
12812
12751
  moderator,
12813
- ...storage ? { storage } : {},
12814
- ...bridge ? { bridge } : {}
12752
+ ...storage ? { storage } : {}
12815
12753
  })
12816
12754
  };
12817
12755
  }
12818
- function explainTool(storage, bridge, transcriptsDir) {
12756
+ function explainTool(storage, transcriptsDir) {
12819
12757
  return {
12820
12758
  name: "explain",
12821
12759
  description: "Replay a session as a navigable tree with cost/latency annotations. Reads usage_log + optionally walks the transcripts directory for per-tool summaries.",
@@ -12833,12 +12771,11 @@ function explainTool(storage, bridge, transcriptsDir) {
12833
12771
  },
12834
12772
  handler: (args) => runExplain(args, {
12835
12773
  ...storage ? { storage } : {},
12836
- ...bridge ? { bridge } : {},
12837
12774
  ...transcriptsDir ? { transcriptsDir } : {}
12838
12775
  })
12839
12776
  };
12840
12777
  }
12841
- function scoreboardTool(storage, bridge, eventsPath) {
12778
+ function scoreboardTool(storage, eventsPath) {
12842
12779
  return {
12843
12780
  name: "scoreboard",
12844
12781
  description: "Aggregate provider ballot stats + delegation counts + table totals. Supports top_k (rank limit) and recent_limit (tail of events.jsonl when configured). Reads the engine's local stats database (auto-created at <data dir>/db.sqlite).",
@@ -12852,12 +12789,11 @@ function scoreboardTool(storage, bridge, eventsPath) {
12852
12789
  },
12853
12790
  handler: (args) => runScoreboard(args, {
12854
12791
  ...storage ? { storage } : {},
12855
- ...bridge ? { bridge } : {},
12856
12792
  ...eventsPath ? { eventsPath } : {}
12857
12793
  })
12858
12794
  };
12859
12795
  }
12860
- function sessionMemoryTool(storage, bridge) {
12796
+ function sessionMemoryTool(storage) {
12861
12797
  return {
12862
12798
  name: "session_memory",
12863
12799
  description: "CRUD over the per-session working memory ledger. Actions: list, add, mark_stale, clear. Uses the engine's local database (auto-created at <data dir>/db.sqlite).",
@@ -12880,15 +12816,14 @@ function sessionMemoryTool(storage, bridge) {
12880
12816
  required: ["action", "session_id"]
12881
12817
  },
12882
12818
  handler: (args) => runSessionMemory(args, {
12883
- ...storage ? { storage } : {},
12884
- ...bridge ? { bridge } : {}
12819
+ ...storage ? { storage } : {}
12885
12820
  })
12886
12821
  };
12887
12822
  }
12888
- function recallTool(storage, bridge) {
12823
+ function recallTool(storage) {
12889
12824
  return {
12890
12825
  name: "recall",
12891
- description: "Full-text search across persisted transcripts via SQLite FTS5. Returns rows ordered by relevance with a windowed snippet. Requires a wired Storage adapter; falls back to the Python bridge when not available.",
12826
+ description: "Full-text search across persisted transcripts via SQLite FTS5. Returns rows ordered by relevance with a windowed snippet. Requires a wired Storage adapter.",
12892
12827
  inputSchema: {
12893
12828
  type: "object",
12894
12829
  additionalProperties: true,
@@ -12902,8 +12837,7 @@ function recallTool(storage, bridge) {
12902
12837
  required: ["query"]
12903
12838
  },
12904
12839
  handler: (args) => runRecall(args, {
12905
- ...storage ? { storage } : {},
12906
- ...bridge ? { bridge } : {}
12840
+ ...storage ? { storage } : {}
12907
12841
  })
12908
12842
  };
12909
12843
  }
@@ -12939,7 +12873,7 @@ function modelsTool(providers, activeProviders) {
12939
12873
  handler: async (args) => runModels(args, { providers, activeProviders })
12940
12874
  };
12941
12875
  }
12942
- function reviewTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
12876
+ function reviewTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
12943
12877
  return {
12944
12878
  name: "review",
12945
12879
  description: "Have an LLM panel peer-review a code or proposal snippet. Returns the confer envelope (one answer per provider).",
@@ -12958,7 +12892,6 @@ function reviewTool(providers, allowlist, bridge, storage, breakers, transcripts
12958
12892
  handler: (args) => runReview(args, {
12959
12893
  providers,
12960
12894
  allowlist,
12961
- ...bridge ? { bridge } : {},
12962
12895
  ...storage ? { storage } : {},
12963
12896
  ...breakers ? { breakers } : {},
12964
12897
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -12966,7 +12899,7 @@ function reviewTool(providers, allowlist, bridge, storage, breakers, transcripts
12966
12899
  })
12967
12900
  };
12968
12901
  }
12969
- function critiqueTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
12902
+ function critiqueTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
12970
12903
  return {
12971
12904
  name: "critique",
12972
12905
  description: "Have each LLM panelist list the top weaknesses of a proposed answer or approach (severity-rated). Returns per-provider weakness lists + a merged list ordered by severity.",
@@ -12986,7 +12919,6 @@ function critiqueTool(providers, allowlist, bridge, storage, breakers, transcrip
12986
12919
  handler: (args) => runCritique(args, {
12987
12920
  providers,
12988
12921
  allowlist,
12989
- ...bridge ? { bridge } : {},
12990
12922
  ...storage ? { storage } : {},
12991
12923
  ...breakers ? { breakers } : {},
12992
12924
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -12994,7 +12926,7 @@ function critiqueTool(providers, allowlist, bridge, storage, breakers, transcrip
12994
12926
  })
12995
12927
  };
12996
12928
  }
12997
- function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
12929
+ function planTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
12998
12930
  return {
12999
12931
  name: "plan",
13000
12932
  description: 'Have an LLM panel debate a step-by-step plan for the stated goal under the given constraints. Returns the debate envelope with a moderator-synthesised plan. Defaults to `mode: "fast"` (2 rounds + early_stop) \u2014 set `mode: "thorough"` for 5 rounds without early_stop. Explicit `max_rounds` / `early_stop` / `early_stop_threshold` always override the mode preset. Use `structured: true` for schema-validated synthesis.',
@@ -13021,7 +12953,6 @@ function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDi
13021
12953
  handler: (args) => runPlan(args, {
13022
12954
  providers,
13023
12955
  allowlist,
13024
- ...bridge ? { bridge } : {},
13025
12956
  ...storage ? { storage } : {},
13026
12957
  ...breakers ? { breakers } : {},
13027
12958
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -13029,7 +12960,7 @@ function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDi
13029
12960
  })
13030
12961
  };
13031
12962
  }
13032
- function triangulateTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
12963
+ function triangulateTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
13033
12964
  return {
13034
12965
  name: "triangulate",
13035
12966
  description: "Run a coordinate flow and reshape the output as a consensus + minority report with per-provider weights. v1 uses 1.0 weights (matches a fresh provider_stats DB); future versions thread real win-rate weights when the DB layer ports.",
@@ -13050,7 +12981,6 @@ function triangulateTool(providers, allowlist, bridge, storage, breakers, transc
13050
12981
  handler: (args) => runTriangulate(args, {
13051
12982
  providers,
13052
12983
  allowlist,
13053
- ...bridge ? { bridge } : {},
13054
12984
  ...storage ? { storage } : {},
13055
12985
  ...breakers ? { breakers } : {},
13056
12986
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -13058,7 +12988,7 @@ function triangulateTool(providers, allowlist, bridge, storage, breakers, transc
13058
12988
  })
13059
12989
  };
13060
12990
  }
13061
- function coordinateTool(providers, allowlist, bridge, innerCallers, storage, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
12991
+ function coordinateTool(providers, allowlist, innerCallers, storage, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13062
12992
  return {
13063
12993
  name: "coordinate",
13064
12994
  description: "Run a three-role coordination flow (proposer \u2192 critics \u2192 synthesizer) with structured output at every step. Native opts: untrusted_input (canary + neutralize), worker_tools (bounded ReAct on proposer + critic roles; synth never sees inner tools), inject_session_memory (storage-backed working-memory block prepended to the topic).",
@@ -13083,7 +13013,6 @@ function coordinateTool(providers, allowlist, bridge, innerCallers, storage, bre
13083
13013
  handler: (args) => runCoordinate(args, {
13084
13014
  providers,
13085
13015
  allowlist,
13086
- ...bridge ? { bridge } : {},
13087
13016
  innerCallers,
13088
13017
  ...storage ? { storage } : {},
13089
13018
  ...breakers ? { breakers } : {},
@@ -13093,7 +13022,7 @@ function coordinateTool(providers, allowlist, bridge, innerCallers, storage, bre
13093
13022
  })
13094
13023
  };
13095
13024
  }
13096
- function debateTool(providers, allowlist, bridge, innerCallers, storage, pricing, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13025
+ function debateTool(providers, allowlist, innerCallers, storage, pricing, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13097
13026
  return {
13098
13027
  name: "debate",
13099
13028
  description: "Run a multi-round debate between LLM providers and synthesise the result via a moderator. Native opts: inject_session_memory, auto_panel, worker_tools, structured synthesis (schema-validated), extract_claims (final-round distillation), early_stop (post-round agreement check).",
@@ -13123,7 +13052,6 @@ function debateTool(providers, allowlist, bridge, innerCallers, storage, pricing
13123
13052
  handler: (args) => runDebate(args, {
13124
13053
  providers,
13125
13054
  allowlist,
13126
- ...bridge ? { bridge } : {},
13127
13055
  innerCallers,
13128
13056
  ...storage ? { storage } : {},
13129
13057
  ...pricing ? { pricing } : {},
@@ -13143,10 +13071,10 @@ function buildInnerCallers(o) {
13143
13071
  ...o.repoRoot ? { repoRoot: o.repoRoot } : {}
13144
13072
  });
13145
13073
  }
13146
- out.verify = (args) => runVerify(args, o.bridge, o.fetchConfig);
13074
+ out.verify = (args) => runVerify(args, o.fetchConfig);
13147
13075
  return out;
13148
13076
  }
13149
- function conferTool(providers, allowlist, bridge, moderator, pricing, storage, innerCallers, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13077
+ function conferTool(providers, allowlist, moderator, pricing, storage, innerCallers, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13150
13078
  return {
13151
13079
  name: "confer",
13152
13080
  description: "Ask a panel of LLM providers the same question; return one answer per provider. Native opts: untrusted_input (canary + neutralization), early_stop (cheap-tier agreement check after first 2 panelists when N>=3), extract_claims (cheap-tier extractor with per-provider support maps), inject_session_memory (storage-backed working-memory block prepended to the first user message), auto_panel (router-driven top-N panel pick), worker_tools (bounded ReAct loop per panelist when innerCallers are wired by the host).",
@@ -13173,7 +13101,6 @@ function conferTool(providers, allowlist, bridge, moderator, pricing, storage, i
13173
13101
  handler: (args) => runConfer(args, {
13174
13102
  providers,
13175
13103
  allowlist,
13176
- ...bridge ? { bridge } : {},
13177
13104
  moderator,
13178
13105
  ...pricing ? { pricing } : {},
13179
13106
  ...storage ? { storage } : {},
@@ -13185,7 +13112,7 @@ function conferTool(providers, allowlist, bridge, moderator, pricing, storage, i
13185
13112
  })
13186
13113
  };
13187
13114
  }
13188
- function auditTool(providers, allowlist, bridge, transcriptsDir, pricing, storage, breakers, repoRoot) {
13115
+ function auditTool(providers, allowlist, transcriptsDir, pricing, storage, breakers, repoRoot) {
13189
13116
  return {
13190
13117
  name: "audit",
13191
13118
  description: "Score a piece of output against an audit rubric. Single-judge by default; coalesce-mode (multi-judge consensus) and panel-exhausted self-audit run natively. cheap_mode picks the cheapest 'med'-tier model as auditor when a pricing.json is wired. session_id-only inputs load the latest transcript automatically when a transcripts directory is wired.",
@@ -13211,7 +13138,6 @@ function auditTool(providers, allowlist, bridge, transcriptsDir, pricing, storag
13211
13138
  handler: (args) => runAudit(args, {
13212
13139
  providers,
13213
13140
  allowlist,
13214
- ...bridge ? { bridge } : {},
13215
13141
  ...transcriptsDir ? { transcriptsDir } : {},
13216
13142
  ...pricing ? { pricing } : {},
13217
13143
  ...storage ? { storage } : {},
@@ -13275,7 +13201,7 @@ function pickTool(providers, allowlist, storage, breakers, transcriptsDir, repoR
13275
13201
  })
13276
13202
  };
13277
13203
  }
13278
- function verifyTool(bridge, fetchConfig) {
13204
+ function verifyTool(fetchConfig) {
13279
13205
  return {
13280
13206
  name: "verify",
13281
13207
  description: "Run a list of deterministic property checks against caller-supplied data. No LLM calls; everything is local. Returns per-check {passed, reason} plus all_passed / summary / timing fields. Supports the text kinds (contains, not_contains, regex_match, contains_any, contains_all, min_length), shell (sandboxed subprocess with timeout + Unix pgid isolation), and url_head (HEAD request gated by fetch.url_allowlist). All kinds run natively.",
@@ -13293,7 +13219,7 @@ function verifyTool(bridge, fetchConfig) {
13293
13219
  },
13294
13220
  required: ["checks"]
13295
13221
  },
13296
- handler: (args) => runVerify(args, bridge, fetchConfig)
13222
+ handler: (args) => runVerify(args, fetchConfig)
13297
13223
  };
13298
13224
  }
13299
13225
  function pingTool() {
@@ -13313,7 +13239,7 @@ function pingTool() {
13313
13239
  }
13314
13240
 
13315
13241
  // src/core/telemetry.ts
13316
- var import_node_crypto7 = __toESM(require("crypto"), 1);
13242
+ var import_node_crypto8 = __toESM(require("crypto"), 1);
13317
13243
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13318
13244
  var BATCH_MAX = 100;
13319
13245
  var MAX_QUEUE = 500;
@@ -13377,6 +13303,64 @@ async function flush() {
13377
13303
  }
13378
13304
  }
13379
13305
 
13306
+ // src/core/process-registry.ts
13307
+ var import_node_fs15 = require("fs");
13308
+ var import_node_os3 = __toESM(require("os"), 1);
13309
+ var import_node_path14 = __toESM(require("path"), 1);
13310
+ function registryDir(env = process.env) {
13311
+ const base = env["CROSSCHECK_DATA_DIR"] || import_node_path14.default.join(env["HOME"] ?? env["USERPROFILE"] ?? import_node_os3.default.homedir(), ".crosscheck");
13312
+ return import_node_path14.default.join(base, "procs");
13313
+ }
13314
+ function isAlive(pid) {
13315
+ try {
13316
+ process.kill(pid, 0);
13317
+ return true;
13318
+ } catch (err) {
13319
+ return err.code === "EPERM";
13320
+ }
13321
+ }
13322
+ function listProcesses(installedVersion, env = process.env, now = Date.now()) {
13323
+ const dir = registryDir(env);
13324
+ let files;
13325
+ try {
13326
+ files = (0, import_node_fs15.readdirSync)(dir).filter((f) => f.endsWith(".json"));
13327
+ } catch {
13328
+ return [];
13329
+ }
13330
+ const out = [];
13331
+ for (const f of files) {
13332
+ let rec;
13333
+ try {
13334
+ rec = JSON.parse((0, import_node_fs15.readFileSync)(import_node_path14.default.join(dir, f), "utf8"));
13335
+ } catch {
13336
+ try {
13337
+ (0, import_node_fs15.rmSync)(import_node_path14.default.join(dir, f), { force: true });
13338
+ } catch {
13339
+ }
13340
+ continue;
13341
+ }
13342
+ if (typeof rec.pid !== "number") continue;
13343
+ const alive = isAlive(rec.pid);
13344
+ if (!alive) {
13345
+ try {
13346
+ (0, import_node_fs15.rmSync)(import_node_path14.default.join(dir, f), { force: true });
13347
+ } catch {
13348
+ }
13349
+ continue;
13350
+ }
13351
+ out.push({
13352
+ ...rec,
13353
+ alive,
13354
+ outdated: Boolean(rec.version) && rec.version !== installedVersion,
13355
+ ageMs: Math.max(0, now - (rec.startedAt ?? now))
13356
+ });
13357
+ }
13358
+ return out.sort((a, b) => a.startedAt - b.startedAt);
13359
+ }
13360
+ function processRegistryPath(env = process.env) {
13361
+ return registryDir(env);
13362
+ }
13363
+
13380
13364
  // src/entrypoints/embed.ts
13381
13365
  var KEY_ENV = {
13382
13366
  anthropic: "ANTHROPIC_API_KEY",
@@ -13433,7 +13417,7 @@ function errorOf(answer) {
13433
13417
  }
13434
13418
  function bundledPricingPath() {
13435
13419
  try {
13436
- return import_node_path14.default.join(import_node_path14.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl)), "pricing.json");
13420
+ return import_node_path15.default.join(import_node_path15.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl)), "pricing.json");
13437
13421
  } catch {
13438
13422
  return void 0;
13439
13423
  }
@@ -13454,7 +13438,7 @@ function createEmbeddedEngine(opts) {
13454
13438
  if (varName && model) env[varName] = model;
13455
13439
  }
13456
13440
  const pricingPath = [opts.pricingPath, bundledPricingPath()].find(
13457
- (p) => Boolean(p) && (0, import_node_fs15.existsSync)(p)
13441
+ (p) => Boolean(p) && (0, import_node_fs16.existsSync)(p)
13458
13442
  );
13459
13443
  const pricing = pricingPath ? loadPricing(pricingPath) : {};
13460
13444
  const built = buildProviders({ env, pricing });
@@ -13577,6 +13561,9 @@ var __test_internals = { usageOf, textOf, errorOf, vaultId };
13577
13561
  __KEY_ENV,
13578
13562
  __MODEL_ENV,
13579
13563
  __test_internals,
13580
- createEmbeddedEngine
13564
+ createEmbeddedEngine,
13565
+ isAlive,
13566
+ listProcesses,
13567
+ processRegistryPath
13581
13568
  });
13582
13569
  //# sourceMappingURL=embed.cjs.map