crosscheck-mcp 0.2.27 → 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) {
@@ -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.27" : "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) {
@@ -4710,10 +4861,6 @@ If you need supporting evidence, you may emit ONE \`<tool_call>...</tool_call>\`
4710
4861
  }
4711
4862
 
4712
4863
  // src/tools/confer.ts
4713
- var DEFERRED_OPTS = [
4714
- // empty — every confer opt runs natively except worker_tools, which
4715
- // is gated below (non-empty list → defer).
4716
- ];
4717
4864
  async function runConfer(args, opts) {
4718
4865
  const callStartedWall = import_node_perf_hooks2.performance.now();
4719
4866
  const callStartedCpu = process.cpuUsage();
@@ -4729,16 +4876,11 @@ async function runConfer(args, opts) {
4729
4876
  rejectedWorkerTools.push(t);
4730
4877
  }
4731
4878
  }
4732
- const workerToolsNeedsBridge = acceptedWorkerTools.length > 0 && !opts.innerCallers;
4733
- const needsBridge = DEFERRED_OPTS.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
4734
- if (needsBridge) {
4735
- if (opts.bridge && opts.bridge.toolNames.has("confer")) {
4736
- return await deferConfer(args, opts.bridge);
4737
- }
4879
+ if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
4738
4880
  return errorEnvelope2(
4739
4881
  "CONFER_OPT_NOT_NATIVE",
4740
4882
  "worker_tools requested but innerCallers are not wired",
4741
- "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."
4742
4884
  );
4743
4885
  }
4744
4886
  const question = typeof args["question"] === "string" ? args["question"] : String(args["question"] ?? "");
@@ -5089,21 +5231,6 @@ function unknownProviderError(unknownNames, available) {
5089
5231
  available_now: Object.keys(available).sort()
5090
5232
  };
5091
5233
  }
5092
- async function deferConfer(args, bridge) {
5093
- const r = await bridge.callTool("confer", args);
5094
- const text = r.content[0]?.text;
5095
- if (typeof text === "string") {
5096
- try {
5097
- return JSON.parse(text);
5098
- } catch {
5099
- }
5100
- }
5101
- return errorEnvelope2(
5102
- "CONFER_BRIDGE_BAD_ENVELOPE",
5103
- "bridge returned an unparseable envelope for confer",
5104
- "Check that the Python child is healthy."
5105
- );
5106
- }
5107
5234
  function errorEnvelope2(code, message, hint) {
5108
5235
  return {
5109
5236
  tool: "confer",
@@ -5475,7 +5602,7 @@ function errorEnvelope3(code, message, hint) {
5475
5602
  transient: false
5476
5603
  };
5477
5604
  }
5478
- async function runVerify(args, bridge, fetchConfig) {
5605
+ async function runVerify(args, fetchConfig) {
5479
5606
  const checks = args["checks"];
5480
5607
  if (!Array.isArray(checks) || checks.length === 0) {
5481
5608
  return {
@@ -5487,7 +5614,6 @@ async function runVerify(args, bridge, fetchConfig) {
5487
5614
  )
5488
5615
  };
5489
5616
  }
5490
- void bridge;
5491
5617
  const allowShell = Boolean(args["allow_shell"] ?? false);
5492
5618
  const wallStart = import_node_perf_hooks3.performance.now();
5493
5619
  const cpuStart = process.cpuUsage();
@@ -5789,7 +5915,6 @@ async function runBench(args, opts) {
5789
5915
  const innerOpts = {
5790
5916
  providers: opts.providers,
5791
5917
  allowlist: opts.allowlist ?? null,
5792
- ...opts.bridge ? { bridge: opts.bridge } : {},
5793
5918
  ...opts.moderator ? { moderator: opts.moderator } : {}
5794
5919
  };
5795
5920
  let inner;
@@ -6001,7 +6126,7 @@ function isObj4(v) {
6001
6126
  }
6002
6127
 
6003
6128
  // src/tools/config-pin.ts
6004
- var import_node_crypto3 = require("crypto");
6129
+ var import_node_crypto4 = require("crypto");
6005
6130
  var import_node_fs6 = require("fs");
6006
6131
  var import_node_path6 = __toESM(require("path"), 1);
6007
6132
  var DEFAULT_PIN_PATH = ".crosscheck/config_pins.json";
@@ -6156,7 +6281,7 @@ function hashFile(abs) {
6156
6281
  return "";
6157
6282
  }
6158
6283
  const normalized = stripCrBeforeLf(raw);
6159
- 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");
6160
6285
  }
6161
6286
  function stripCrBeforeLf(buf) {
6162
6287
  const out = [];
@@ -6233,7 +6358,7 @@ function pyRepr2(v) {
6233
6358
  }
6234
6359
 
6235
6360
  // src/tools/create.ts
6236
- var import_node_crypto6 = require("crypto");
6361
+ var import_node_crypto7 = require("crypto");
6237
6362
  var import_node_fs9 = require("fs");
6238
6363
  var import_node_path9 = __toESM(require("path"), 1);
6239
6364
 
@@ -6319,7 +6444,7 @@ function isDeadModelError(err) {
6319
6444
  }
6320
6445
 
6321
6446
  // src/core/node-cache.ts
6322
- var import_node_crypto4 = require("crypto");
6447
+ var import_node_crypto5 = require("crypto");
6323
6448
  var import_node_fs7 = require("fs");
6324
6449
  var import_node_path7 = require("path");
6325
6450
  var NODE_CACHE_KEY_VERSION = "v2";
@@ -6346,7 +6471,7 @@ function canonicalizeNodeText(s) {
6346
6471
  return out;
6347
6472
  }
6348
6473
  function sha256Hex(s) {
6349
- 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");
6350
6475
  }
6351
6476
  function nodeCacheKey(node, upstreamOutputs, provider, model) {
6352
6477
  const canonUpstream = {};
@@ -6404,11 +6529,11 @@ function getNodeCache(cfg, repoRoot, key, nowMs) {
6404
6529
  return null;
6405
6530
  }
6406
6531
  }
6407
- function atomicWriteJson(path12, payload) {
6408
- (0, import_node_fs7.mkdirSync)((0, import_node_path7.dirname)(path12), { recursive: true });
6409
- 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`;
6410
6535
  (0, import_node_fs7.writeFileSync)(tmp, JSON.stringify(payload), "utf8");
6411
- (0, import_node_fs7.renameSync)(tmp, path12);
6536
+ (0, import_node_fs7.renameSync)(tmp, path13);
6412
6537
  }
6413
6538
  function putNodeCache(cfg, repoRoot, key, value) {
6414
6539
  if (!cfg || cfg.enabled === false) return;
@@ -6466,7 +6591,6 @@ var EST_TOKENS = {
6466
6591
  med: [1500, 800],
6467
6592
  high: [2500, 1500]
6468
6593
  };
6469
- var DEFERRED_OPTS2 = [];
6470
6594
  var REACTIVE_SIGNAL_RE = /<signals>\s*(\{[\s\S]*?\})\s*<\/signals>/g;
6471
6595
  function parseReactiveSignals(output) {
6472
6596
  if (typeof output !== "string" || !output.includes("<signals>")) return [];
@@ -6506,17 +6630,6 @@ async function runOrchestrate(args, opts) {
6506
6630
  );
6507
6631
  if (breakerEnv) return breakerEnv;
6508
6632
  }
6509
- const needsBridge = DEFERRED_OPTS2.some((k) => Boolean(args[k]));
6510
- if (needsBridge) {
6511
- if (opts.bridge && opts.bridge.toolNames.has("orchestrate")) {
6512
- return await deferOrchestrate(args, opts.bridge);
6513
- }
6514
- return errorEnvelope5(
6515
- "ORCHESTRATE_OPT_NOT_NATIVE",
6516
- "this orchestrate opt-in requires the Python bridge in v1",
6517
- "v1 native covers the plain DAG flow + cheap_mode. reactive (mid-flight DAG updates) still defers. Set CROSSCHECK_BRIDGE_PYTHON=1 to enable."
6518
- );
6519
- }
6520
6633
  const goal = typeof args["goal"] === "string" ? args["goal"] : null;
6521
6634
  const dagIn = isObj5(args["dag"]) ? args["dag"] : null;
6522
6635
  if (goal === null === (dagIn === null)) {
@@ -7458,21 +7571,6 @@ function resolveProviders3(names, available, allowlist) {
7458
7571
  }
7459
7572
  return out;
7460
7573
  }
7461
- async function deferOrchestrate(args, bridge) {
7462
- const r = await bridge.callTool("orchestrate", args);
7463
- const text = r.content[0]?.text;
7464
- if (typeof text === "string") {
7465
- try {
7466
- return JSON.parse(text);
7467
- } catch {
7468
- }
7469
- }
7470
- return errorEnvelope5(
7471
- "ORCHESTRATE_BRIDGE_BAD_ENVELOPE",
7472
- "bridge returned an unparseable envelope for orchestrate",
7473
- "Check that the Python child is healthy."
7474
- );
7475
- }
7476
7574
  function errorEnvelope5(code, message, hint, kind = "client") {
7477
7575
  return {
7478
7576
  tool: "orchestrate",
@@ -7520,7 +7618,7 @@ function pyRound6(x) {
7520
7618
  }
7521
7619
 
7522
7620
  // src/tools/fetch.ts
7523
- var import_node_crypto5 = require("crypto");
7621
+ var import_node_crypto6 = require("crypto");
7524
7622
  var import_node_fs8 = require("fs");
7525
7623
  var import_node_path8 = __toESM(require("path"), 1);
7526
7624
  var DEFAULT_CONFIG = {
@@ -7734,10 +7832,10 @@ function extractHost(url) {
7734
7832
  }
7735
7833
  }
7736
7834
  function sha256Hex2(s) {
7737
- 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");
7738
7836
  }
7739
7837
  function sha256HexBytes(bytes) {
7740
- return (0, import_node_crypto5.createHash)("sha256").update(bytes).digest("hex");
7838
+ return (0, import_node_crypto6.createHash)("sha256").update(bytes).digest("hex");
7741
7839
  }
7742
7840
  function resolveEvidenceDir(configured, repoRoot) {
7743
7841
  if (import_node_path8.default.isAbsolute(configured)) return configured;
@@ -7835,7 +7933,6 @@ ${documentsPayload}`;
7835
7933
  }, {
7836
7934
  providers: opts.providers,
7837
7935
  allowlist: opts.allowlist ?? null,
7838
- ...opts.bridge ? { bridge: opts.bridge } : {},
7839
7936
  ctx
7840
7937
  });
7841
7938
  const scopeAnswer = Array.isArray(scope["answers"]) ? scope["answers"].filter((a) => typeof a["response"] === "string" && a["response"]).map((a) => `[${a["provider"]}]
@@ -7858,7 +7955,6 @@ ${scopeAnswer || "(none)"}
7858
7955
  providers: opts.providers,
7859
7956
  allowlist: opts.allowlist ?? null,
7860
7957
  moderator,
7861
- ...opts.bridge ? { bridge: opts.bridge } : {},
7862
7958
  ctx
7863
7959
  });
7864
7960
  let attempts = 1;
@@ -7893,7 +7989,6 @@ ${scopeAnswer || "(none)"}
7893
7989
  }, {
7894
7990
  providers: opts.providers,
7895
7991
  allowlist: opts.allowlist ?? null,
7896
- ...opts.bridge ? { bridge: opts.bridge } : {},
7897
7992
  ctx
7898
7993
  });
7899
7994
  }
@@ -7916,7 +8011,6 @@ ${scopeAnswer || "(none)"}
7916
8011
  }, {
7917
8012
  providers: opts.providers,
7918
8013
  allowlist: opts.allowlist ?? null,
7919
- ...opts.bridge ? { bridge: opts.bridge } : {},
7920
8014
  ctx
7921
8015
  });
7922
8016
  let overallF = toNumberOrNull(auditEnvelope["overall_score"]);
@@ -7941,7 +8035,6 @@ ${documentsPayload}`
7941
8035
  providers: opts.providers,
7942
8036
  allowlist: opts.allowlist ?? null,
7943
8037
  moderator,
7944
- ...opts.bridge ? { bridge: opts.bridge } : {},
7945
8038
  ctx
7946
8039
  }
7947
8040
  );
@@ -7961,7 +8054,6 @@ ${documentsPayload}`
7961
8054
  }, {
7962
8055
  providers: opts.providers,
7963
8056
  allowlist: opts.allowlist ?? null,
7964
- ...opts.bridge ? { bridge: opts.bridge } : {},
7965
8057
  ctx
7966
8058
  });
7967
8059
  overallF = toNumberOrNull(auditEnvelope["overall_score"]);
@@ -8098,7 +8190,7 @@ async function ingestDocuments(documents, sessionId, opts) {
8098
8190
  source: ref,
8099
8191
  type: "file",
8100
8192
  status: "ok",
8101
- 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"),
8102
8194
  content: ""
8103
8195
  }, text));
8104
8196
  }
@@ -8135,7 +8227,7 @@ ${d.content}
8135
8227
  function makeSessionId(opts, supplied) {
8136
8228
  if (typeof supplied === "string" && supplied) return supplied;
8137
8229
  const stamp = opts.nowEpochSeconds ? opts.nowEpochSeconds() : Math.floor(Date.now() / 1e3);
8138
- 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");
8139
8231
  const suffix = rnd.slice(0, 8);
8140
8232
  return `${opts.toolName}-${stamp}-${suffix}`;
8141
8233
  }
@@ -8199,11 +8291,6 @@ function errorEnvelope6(toolName, code, message, hint) {
8199
8291
 
8200
8292
  // src/tools/coordinate.ts
8201
8293
  var import_node_perf_hooks7 = require("perf_hooks");
8202
- var DEFERRED_OPTS3 = [
8203
- // empty — every coordinate opt runs natively when its deps
8204
- // (storage / innerCallers) are wired. Without them the
8205
- // worker_tools gate still triggers a bridge defer.
8206
- ];
8207
8294
  var COORDINATE_DEFAULT_TEMP = 0.4;
8208
8295
  var ROLE_TURN_SCHEMA = {
8209
8296
  type: "object",
@@ -8258,23 +8345,18 @@ async function runCoordinate(args, opts) {
8258
8345
  rejectedWorkerTools.push(t);
8259
8346
  }
8260
8347
  }
8261
- const workerToolsNeedsBridge = acceptedWorkerTools.length > 0 && !opts.innerCallers;
8262
- const needsBridge = DEFERRED_OPTS3.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
8263
- if (needsBridge) {
8348
+ if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
8264
8349
  if (superRequested) {
8265
8350
  return errorEnvelope7(
8266
8351
  "COORDINATE_SUPER_NOT_NATIVE",
8267
- "super mode requested but worker_tools needs the Python bridge",
8268
- "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."
8269
8354
  );
8270
8355
  }
8271
- if (opts.bridge && opts.bridge.toolNames.has("coordinate")) {
8272
- return await deferCoordinate(args, opts.bridge);
8273
- }
8274
8356
  return errorEnvelope7(
8275
8357
  "COORDINATE_OPT_NOT_NATIVE",
8276
8358
  "worker_tools requested but innerCallers are not wired",
8277
- "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."
8278
8360
  );
8279
8361
  }
8280
8362
  const untrusted = Boolean(args["untrusted_input"]);
@@ -8674,21 +8756,6 @@ function unknownProviderError3(unknownNames, available) {
8674
8756
  available_now: Object.keys(available).sort()
8675
8757
  };
8676
8758
  }
8677
- async function deferCoordinate(args, bridge) {
8678
- const r = await bridge.callTool("coordinate", args);
8679
- const text = r.content[0]?.text;
8680
- if (typeof text === "string") {
8681
- try {
8682
- return JSON.parse(text);
8683
- } catch {
8684
- }
8685
- }
8686
- return errorEnvelope7(
8687
- "COORDINATE_BRIDGE_BAD_ENVELOPE",
8688
- "bridge returned an unparseable envelope for coordinate",
8689
- "Check that the Python child is healthy."
8690
- );
8691
- }
8692
8759
  function errorEnvelope7(code, message, hint) {
8693
8760
  return {
8694
8761
  tool: "coordinate",
@@ -9016,10 +9083,6 @@ function buildModeratorTranscript(transcript) {
9016
9083
 
9017
9084
  // src/tools/debate.ts
9018
9085
  var import_node_perf_hooks9 = require("perf_hooks");
9019
- var DEFERRED_OPTS4 = [
9020
- // empty — every debate opt runs natively when its deps
9021
- // (storage / innerCallers) are wired.
9022
- ];
9023
9086
  async function runDebate(args, opts) {
9024
9087
  const callStartedWall = import_node_perf_hooks9.performance.now();
9025
9088
  const callStartedCpu = process.cpuUsage();
@@ -9037,23 +9100,18 @@ async function runDebate(args, opts) {
9037
9100
  rejectedWorkerTools.push(t);
9038
9101
  }
9039
9102
  }
9040
- const workerToolsNeedsBridge = acceptedWorkerTools.length > 0 && !opts.innerCallers;
9041
- const needsBridge = DEFERRED_OPTS4.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
9042
- if (needsBridge) {
9103
+ if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
9043
9104
  if (superRequested) {
9044
9105
  return errorEnvelope9(
9045
9106
  "DEBATE_SUPER_NOT_NATIVE",
9046
- "super mode requested but worker_tools needs the Python bridge",
9047
- "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."
9048
9109
  );
9049
9110
  }
9050
- if (opts.bridge && opts.bridge.toolNames.has("debate")) {
9051
- return await deferDebate(args, opts.bridge);
9052
- }
9053
9111
  return errorEnvelope9(
9054
9112
  "DEBATE_OPT_NOT_NATIVE",
9055
9113
  "worker_tools requested but innerCallers are not wired",
9056
- "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."
9057
9115
  );
9058
9116
  }
9059
9117
  const topic = typeof args["topic"] === "string" ? args["topic"] : String(args["topic"] ?? "");
@@ -9490,21 +9548,6 @@ function unknownProviderError5(unknownNames, available) {
9490
9548
  available_now: Object.keys(available).sort()
9491
9549
  };
9492
9550
  }
9493
- async function deferDebate(args, bridge) {
9494
- const r = await bridge.callTool("debate", args);
9495
- const text = r.content[0]?.text;
9496
- if (typeof text === "string") {
9497
- try {
9498
- return JSON.parse(text);
9499
- } catch {
9500
- }
9501
- }
9502
- return errorEnvelope9(
9503
- "DEBATE_BRIDGE_BAD_ENVELOPE",
9504
- "bridge returned an unparseable envelope for debate",
9505
- "Check that the Python child is healthy."
9506
- );
9507
- }
9508
9551
  function errorEnvelope9(code, message, hint) {
9509
9552
  return {
9510
9553
  tool: "debate",
@@ -9524,9 +9567,6 @@ var DEFAULT_DELEGATION_LIMITS = {
9524
9567
  };
9525
9568
  async function runDelegate(args, opts) {
9526
9569
  if (!opts.storage) {
9527
- if (opts.bridge && opts.bridge.toolNames.has("delegate")) {
9528
- return await deferDelegate(args, opts.bridge);
9529
- }
9530
9570
  return errorEnvelope10(
9531
9571
  "DELEGATE_STORAGE_UNAVAILABLE",
9532
9572
  "delegate needs the local database (for quota tracking), which isn't available",
@@ -9598,7 +9638,6 @@ async function runDelegate(args, opts) {
9598
9638
  const innerOpts = {
9599
9639
  providers: opts.providers,
9600
9640
  allowlist: opts.allowlist ?? null,
9601
- ...opts.bridge ? { bridge: opts.bridge } : {},
9602
9641
  ...opts.moderator ? { moderator: opts.moderator } : {}
9603
9642
  };
9604
9643
  let result;
@@ -9637,21 +9676,6 @@ async function record(storage, sessionId, requester, toolCall, via, accepted, no
9637
9676
  created_at: nowEpochSeconds
9638
9677
  });
9639
9678
  }
9640
- async function deferDelegate(args, bridge) {
9641
- const r = await bridge.callTool("delegate", args);
9642
- const text = r.content[0]?.text;
9643
- if (typeof text === "string") {
9644
- try {
9645
- return JSON.parse(text);
9646
- } catch {
9647
- }
9648
- }
9649
- return errorEnvelope10(
9650
- "DELEGATE_BRIDGE_BAD_ENVELOPE",
9651
- "bridge returned an unparseable envelope for delegate",
9652
- "Check that the Python child is healthy."
9653
- );
9654
- }
9655
9679
  function errorEnvelope10(code, message, hint) {
9656
9680
  return {
9657
9681
  tool: "delegate",
@@ -9694,9 +9718,6 @@ async function runExplain(args, opts) {
9694
9718
  );
9695
9719
  }
9696
9720
  if (!opts.storage) {
9697
- if (opts.bridge && opts.bridge.toolNames.has("explain")) {
9698
- return await deferExplain(args, opts.bridge);
9699
- }
9700
9721
  return errorEnvelope11(
9701
9722
  "EXPLAIN_STORAGE_UNAVAILABLE",
9702
9723
  "explain needs the local transcript/stats database, which isn't available",
@@ -9978,21 +9999,6 @@ function pyRepr5(v) {
9978
9999
  }
9979
10000
  return String(v);
9980
10001
  }
9981
- async function deferExplain(args, bridge) {
9982
- const r = await bridge.callTool("explain", args);
9983
- const text = r.content[0]?.text;
9984
- if (typeof text === "string") {
9985
- try {
9986
- return JSON.parse(text);
9987
- } catch {
9988
- }
9989
- }
9990
- return errorEnvelope11(
9991
- "EXPLAIN_BRIDGE_BAD_ENVELOPE",
9992
- "bridge returned an unparseable envelope for explain",
9993
- "Check that the Python child is healthy."
9994
- );
9995
- }
9996
10002
  function errorEnvelope11(code, message, hint, kind = "client", extra = {}) {
9997
10003
  return {
9998
10004
  tool: "explain",
@@ -10545,9 +10551,6 @@ async function runRecall(args, opts) {
10545
10551
  if (k < 1) k = 1;
10546
10552
  if (k > 50) k = 50;
10547
10553
  if (!opts.storage) {
10548
- if (opts.bridge && opts.bridge.toolNames.has("recall")) {
10549
- return await deferRecall(args, opts.bridge);
10550
- }
10551
10554
  return errorEnvelope12(
10552
10555
  "RECALL_STORAGE_UNAVAILABLE",
10553
10556
  "recall needs the local database, which isn't available",
@@ -10600,21 +10603,6 @@ async function runRecall(args, opts) {
10600
10603
  applied_filters: applied
10601
10604
  };
10602
10605
  }
10603
- async function deferRecall(args, bridge) {
10604
- const r = await bridge.callTool("recall", args);
10605
- const text = r.content[0]?.text;
10606
- if (typeof text === "string") {
10607
- try {
10608
- return JSON.parse(text);
10609
- } catch {
10610
- }
10611
- }
10612
- return errorEnvelope12(
10613
- "RECALL_BRIDGE_BAD_ENVELOPE",
10614
- "bridge returned an unparseable envelope for recall",
10615
- "Check that the Python child is healthy."
10616
- );
10617
- }
10618
10606
  function errorEnvelope12(code, message, hint) {
10619
10607
  return {
10620
10608
  tool: "recall",
@@ -10637,9 +10625,6 @@ async function runRecommendPanel(args, opts) {
10637
10625
  );
10638
10626
  }
10639
10627
  if (!opts.storage) {
10640
- if (opts.bridge && opts.bridge.toolNames.has("recommend_panel")) {
10641
- return await deferRecommendPanel(args, opts.bridge);
10642
- }
10643
10628
  return errorEnvelope13(
10644
10629
  "RECOMMEND_PANEL_STORAGE_UNAVAILABLE",
10645
10630
  "recommend_panel needs the local stats database, which isn't available",
@@ -10702,21 +10687,6 @@ async function runRecommendPanel(args, opts) {
10702
10687
  meta: result.meta
10703
10688
  };
10704
10689
  }
10705
- async function deferRecommendPanel(args, bridge) {
10706
- const r = await bridge.callTool("recommend_panel", args);
10707
- const text = r.content[0]?.text;
10708
- if (typeof text === "string") {
10709
- try {
10710
- return JSON.parse(text);
10711
- } catch {
10712
- }
10713
- }
10714
- return errorEnvelope13(
10715
- "RECOMMEND_PANEL_BRIDGE_BAD_ENVELOPE",
10716
- "bridge returned an unparseable envelope for recommend_panel",
10717
- "Check that the Python child is healthy."
10718
- );
10719
- }
10720
10690
  function errorEnvelope13(code, message, hint) {
10721
10691
  return {
10722
10692
  tool: "recommend_panel",
@@ -10746,9 +10716,6 @@ function toStringArray3(v) {
10746
10716
  var import_node_fs11 = require("fs");
10747
10717
  async function runScoreboard(args, opts) {
10748
10718
  if (!opts.storage) {
10749
- if (opts.bridge && opts.bridge.toolNames.has("scoreboard")) {
10750
- return await deferScoreboard(args, opts.bridge);
10751
- }
10752
10719
  return errorEnvelope14(
10753
10720
  "SCOREBOARD_STORAGE_UNAVAILABLE",
10754
10721
  "scoreboard needs the local stats database, which isn't available",
@@ -10871,21 +10838,6 @@ function clampInt3(raw, min, max, fallback) {
10871
10838
  if (!Number.isFinite(n)) return fallback;
10872
10839
  return Math.min(max, Math.max(min, Math.trunc(n)));
10873
10840
  }
10874
- async function deferScoreboard(args, bridge) {
10875
- const r = await bridge.callTool("scoreboard", args);
10876
- const text = r.content[0]?.text;
10877
- if (typeof text === "string") {
10878
- try {
10879
- return JSON.parse(text);
10880
- } catch {
10881
- }
10882
- }
10883
- return errorEnvelope14(
10884
- "SCOREBOARD_BRIDGE_BAD_ENVELOPE",
10885
- "bridge returned an unparseable envelope for scoreboard",
10886
- "Check that the Python child is healthy."
10887
- );
10888
- }
10889
10841
  function errorEnvelope14(code, message, hint) {
10890
10842
  return {
10891
10843
  tool: "scoreboard",
@@ -10922,9 +10874,6 @@ async function runSessionMemory(args, opts) {
10922
10874
  );
10923
10875
  }
10924
10876
  if (!opts.storage) {
10925
- if (opts.bridge && opts.bridge.toolNames.has("session_memory")) {
10926
- return await deferSessionMemory(args, opts.bridge);
10927
- }
10928
10877
  return errorEnvelope15(
10929
10878
  "SESSION_MEMORY_STORAGE_UNAVAILABLE",
10930
10879
  "session_memory needs the local database, which isn't available",
@@ -11029,21 +10978,6 @@ function clampInt4(raw, min, max, fallback) {
11029
10978
  if (!Number.isFinite(n)) return fallback;
11030
10979
  return Math.min(max, Math.max(min, Math.trunc(n)));
11031
10980
  }
11032
- async function deferSessionMemory(args, bridge) {
11033
- const r = await bridge.callTool("session_memory", args);
11034
- const text = r.content[0]?.text;
11035
- if (typeof text === "string") {
11036
- try {
11037
- return JSON.parse(text);
11038
- } catch {
11039
- }
11040
- }
11041
- return errorEnvelope15(
11042
- "SESSION_MEMORY_BRIDGE_BAD_ENVELOPE",
11043
- "bridge returned an unparseable envelope for session_memory",
11044
- "Check that the Python child is healthy."
11045
- );
11046
- }
11047
10981
  function errorEnvelope15(code, message, hint) {
11048
10982
  return {
11049
10983
  tool: "session_memory",
@@ -11663,7 +11597,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
11663
11597
  var DEFAULT_PACKAGE = "crosscheck-cli";
11664
11598
  var FETCH_TIMEOUT_MS = 3e3;
11665
11599
  function engineVersion() {
11666
- return true ? "0.2.27" : "0.0.0-dev";
11600
+ return true ? "0.2.28" : "0.0.0-dev";
11667
11601
  }
11668
11602
  function defaultUpdateCachePath() {
11669
11603
  const base = process.env["CROSSCHECK_DATA_DIR"] || import_node_path12.default.join(import_node_os2.default.homedir() || import_node_os2.default.tmpdir(), ".crosscheck");
@@ -12435,12 +12369,11 @@ function helpTool() {
12435
12369
  }
12436
12370
  });
12437
12371
  }
12438
- function registerCoreTools(opts = {}) {
12439
- const o = opts && typeof opts === "object" && "toolNames" in opts ? { bridge: opts } : opts;
12372
+ function registerCoreTools(o = {}) {
12440
12373
  const tools = /* @__PURE__ */ new Map();
12441
12374
  const list = [
12442
12375
  pingTool(),
12443
- verifyTool(o.bridge, o.fetchConfig),
12376
+ verifyTool(o.fetchConfig),
12444
12377
  pickTool(
12445
12378
  o.providers ?? {},
12446
12379
  o.providerAllowlist ?? null,
@@ -12452,7 +12385,6 @@ function registerCoreTools(opts = {}) {
12452
12385
  auditTool(
12453
12386
  o.providers ?? {},
12454
12387
  o.providerAllowlist ?? null,
12455
- o.bridge,
12456
12388
  o.transcriptsDir,
12457
12389
  o.pricing,
12458
12390
  o.storage,
@@ -12462,7 +12394,6 @@ function registerCoreTools(opts = {}) {
12462
12394
  conferTool(
12463
12395
  o.providers ?? {},
12464
12396
  o.providerAllowlist ?? null,
12465
- o.bridge,
12466
12397
  o.moderatorDefault ?? "anthropic",
12467
12398
  o.pricing,
12468
12399
  o.storage,
@@ -12475,7 +12406,6 @@ function registerCoreTools(opts = {}) {
12475
12406
  debateTool(
12476
12407
  o.providers ?? {},
12477
12408
  o.providerAllowlist ?? null,
12478
- o.bridge,
12479
12409
  buildInnerCallers(o),
12480
12410
  o.storage,
12481
12411
  o.pricing,
@@ -12487,7 +12417,6 @@ function registerCoreTools(opts = {}) {
12487
12417
  coordinateTool(
12488
12418
  o.providers ?? {},
12489
12419
  o.providerAllowlist ?? null,
12490
- o.bridge,
12491
12420
  buildInnerCallers(o),
12492
12421
  o.storage,
12493
12422
  o.circuitBreakers,
@@ -12498,7 +12427,6 @@ function registerCoreTools(opts = {}) {
12498
12427
  triangulateTool(
12499
12428
  o.providers ?? {},
12500
12429
  o.providerAllowlist ?? null,
12501
- o.bridge,
12502
12430
  o.storage,
12503
12431
  o.circuitBreakers,
12504
12432
  o.transcriptsDir,
@@ -12507,7 +12435,6 @@ function registerCoreTools(opts = {}) {
12507
12435
  planTool(
12508
12436
  o.providers ?? {},
12509
12437
  o.providerAllowlist ?? null,
12510
- o.bridge,
12511
12438
  o.storage,
12512
12439
  o.circuitBreakers,
12513
12440
  o.transcriptsDir,
@@ -12516,7 +12443,6 @@ function registerCoreTools(opts = {}) {
12516
12443
  critiqueTool(
12517
12444
  o.providers ?? {},
12518
12445
  o.providerAllowlist ?? null,
12519
- o.bridge,
12520
12446
  o.storage,
12521
12447
  o.circuitBreakers,
12522
12448
  o.transcriptsDir,
@@ -12525,7 +12451,6 @@ function registerCoreTools(opts = {}) {
12525
12451
  reviewTool(
12526
12452
  o.providers ?? {},
12527
12453
  o.providerAllowlist ?? null,
12528
- o.bridge,
12529
12454
  o.storage,
12530
12455
  o.circuitBreakers,
12531
12456
  o.transcriptsDir,
@@ -12533,25 +12458,23 @@ function registerCoreTools(opts = {}) {
12533
12458
  ),
12534
12459
  listProvidersTool(o.providers ?? {}, o.activeProviders ?? null, o.moderatorDefault ?? "anthropic"),
12535
12460
  modelsTool(o.providers ?? {}, o.activeProviders ?? null),
12536
- recallTool(o.storage, o.bridge),
12537
- sessionMemoryTool(o.storage, o.bridge),
12538
- scoreboardTool(o.storage, o.bridge, o.eventsPath),
12539
- 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),
12540
12465
  delegateTool(
12541
12466
  o.providers ?? {},
12542
12467
  o.providerAllowlist ?? null,
12543
12468
  o.storage,
12544
- o.bridge,
12545
12469
  o.moderatorDefault ?? "anthropic"
12546
12470
  ),
12547
12471
  fetchTool(o.storage, o.fetchConfig, o.repoRoot),
12548
- recommendPanelTool(o.providers ?? {}, o.storage, o.bridge),
12472
+ recommendPanelTool(o.providers ?? {}, o.storage),
12549
12473
  updateCrosscheckTool(o.repoRoot ?? null),
12550
12474
  benchTool(
12551
12475
  o.providers ?? {},
12552
12476
  o.providerAllowlist ?? null,
12553
12477
  o.storage,
12554
- o.bridge,
12555
12478
  o.moderatorDefault ?? "anthropic",
12556
12479
  o.benchGoldensDir,
12557
12480
  o.circuitBreakers,
@@ -12562,7 +12485,6 @@ function registerCoreTools(opts = {}) {
12562
12485
  solveTool(
12563
12486
  o.providers ?? {},
12564
12487
  o.providerAllowlist ?? null,
12565
- o.bridge,
12566
12488
  o.storage,
12567
12489
  o.circuitBreakers,
12568
12490
  o.transcriptsDir,
@@ -12571,7 +12493,6 @@ function registerCoreTools(opts = {}) {
12571
12493
  orchestrateTool(
12572
12494
  o.providers ?? {},
12573
12495
  o.providerAllowlist ?? null,
12574
- o.bridge,
12575
12496
  o.moderatorDefault ?? "anthropic",
12576
12497
  o.storage,
12577
12498
  o.pricing,
@@ -12618,7 +12539,6 @@ function createTool(o, toolName, cheapDefault) {
12618
12539
  providers: o.providers ?? {},
12619
12540
  allowlist: o.providerAllowlist ?? null,
12620
12541
  ...o.storage ? { storage: o.storage } : {},
12621
- ...o.bridge ? { bridge: o.bridge } : {},
12622
12542
  ...o.moderatorDefault ? { moderator: o.moderatorDefault } : {},
12623
12543
  ...o.fetchConfig ? { fetchConfig: o.fetchConfig } : {},
12624
12544
  ...o.repoRoot ? { repoRoot: o.repoRoot } : {},
@@ -12627,7 +12547,7 @@ function createTool(o, toolName, cheapDefault) {
12627
12547
  })
12628
12548
  };
12629
12549
  }
12630
- function orchestrateTool(providers, allowlist, bridge, moderator, storage, pricing, breakers, transcriptsDir, repoRoot, nodeCache) {
12550
+ function orchestrateTool(providers, allowlist, moderator, storage, pricing, breakers, transcriptsDir, repoRoot, nodeCache) {
12631
12551
  return {
12632
12552
  name: "orchestrate",
12633
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.",
@@ -12652,7 +12572,6 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
12652
12572
  providers,
12653
12573
  allowlist,
12654
12574
  moderator,
12655
- ...bridge ? { bridge } : {},
12656
12575
  ...storage ? { storage } : {},
12657
12576
  ...pricing ? { pricing } : {},
12658
12577
  ...breakers ? { breakers } : {},
@@ -12662,7 +12581,7 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
12662
12581
  })
12663
12582
  };
12664
12583
  }
12665
- function solveTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
12584
+ function solveTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
12666
12585
  return {
12667
12586
  name: "solve",
12668
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.",
@@ -12684,7 +12603,6 @@ function solveTool(providers, allowlist, bridge, storage, breakers, transcriptsD
12684
12603
  handler: (args) => runSolve(args, {
12685
12604
  providers,
12686
12605
  allowlist,
12687
- ...bridge ? { bridge } : {},
12688
12606
  ...storage ? { storage } : {},
12689
12607
  ...breakers ? { breakers } : {},
12690
12608
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -12723,7 +12641,7 @@ function configPinTool(repoRoot, config2, rejectDriftEnv) {
12723
12641
  }
12724
12642
  };
12725
12643
  }
12726
- function benchTool(providers, allowlist, storage, bridge, moderator, defaultGoldensDir, breakers, transcriptsDir, repoRoot) {
12644
+ function benchTool(providers, allowlist, storage, moderator, defaultGoldensDir, breakers, transcriptsDir, repoRoot) {
12727
12645
  return {
12728
12646
  name: "bench",
12729
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).",
@@ -12742,7 +12660,6 @@ function benchTool(providers, allowlist, storage, bridge, moderator, defaultGold
12742
12660
  allowlist,
12743
12661
  moderator,
12744
12662
  ...storage ? { storage } : {},
12745
- ...bridge ? { bridge } : {},
12746
12663
  ...defaultGoldensDir ? { defaultGoldensDir } : {},
12747
12664
  ...breakers ? { breakers } : {},
12748
12665
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -12769,7 +12686,7 @@ function updateCrosscheckTool(repoRoot) {
12769
12686
  }
12770
12687
  };
12771
12688
  }
12772
- function recommendPanelTool(providers, storage, bridge) {
12689
+ function recommendPanelTool(providers, storage) {
12773
12690
  return {
12774
12691
  name: "recommend_panel",
12775
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.",
@@ -12787,8 +12704,7 @@ function recommendPanelTool(providers, storage, bridge) {
12787
12704
  },
12788
12705
  handler: (args) => runRecommendPanel(args, {
12789
12706
  providers,
12790
- ...storage ? { storage } : {},
12791
- ...bridge ? { bridge } : {}
12707
+ ...storage ? { storage } : {}
12792
12708
  })
12793
12709
  };
12794
12710
  }
@@ -12813,7 +12729,7 @@ function fetchTool(storage, fetchConfig, repoRoot) {
12813
12729
  })
12814
12730
  };
12815
12731
  }
12816
- function delegateTool(providers, allowlist, storage, bridge, moderator) {
12732
+ function delegateTool(providers, allowlist, storage, moderator) {
12817
12733
  return {
12818
12734
  name: "delegate",
12819
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.",
@@ -12833,12 +12749,11 @@ function delegateTool(providers, allowlist, storage, bridge, moderator) {
12833
12749
  providers,
12834
12750
  allowlist,
12835
12751
  moderator,
12836
- ...storage ? { storage } : {},
12837
- ...bridge ? { bridge } : {}
12752
+ ...storage ? { storage } : {}
12838
12753
  })
12839
12754
  };
12840
12755
  }
12841
- function explainTool(storage, bridge, transcriptsDir) {
12756
+ function explainTool(storage, transcriptsDir) {
12842
12757
  return {
12843
12758
  name: "explain",
12844
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.",
@@ -12856,12 +12771,11 @@ function explainTool(storage, bridge, transcriptsDir) {
12856
12771
  },
12857
12772
  handler: (args) => runExplain(args, {
12858
12773
  ...storage ? { storage } : {},
12859
- ...bridge ? { bridge } : {},
12860
12774
  ...transcriptsDir ? { transcriptsDir } : {}
12861
12775
  })
12862
12776
  };
12863
12777
  }
12864
- function scoreboardTool(storage, bridge, eventsPath) {
12778
+ function scoreboardTool(storage, eventsPath) {
12865
12779
  return {
12866
12780
  name: "scoreboard",
12867
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).",
@@ -12875,12 +12789,11 @@ function scoreboardTool(storage, bridge, eventsPath) {
12875
12789
  },
12876
12790
  handler: (args) => runScoreboard(args, {
12877
12791
  ...storage ? { storage } : {},
12878
- ...bridge ? { bridge } : {},
12879
12792
  ...eventsPath ? { eventsPath } : {}
12880
12793
  })
12881
12794
  };
12882
12795
  }
12883
- function sessionMemoryTool(storage, bridge) {
12796
+ function sessionMemoryTool(storage) {
12884
12797
  return {
12885
12798
  name: "session_memory",
12886
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).",
@@ -12903,15 +12816,14 @@ function sessionMemoryTool(storage, bridge) {
12903
12816
  required: ["action", "session_id"]
12904
12817
  },
12905
12818
  handler: (args) => runSessionMemory(args, {
12906
- ...storage ? { storage } : {},
12907
- ...bridge ? { bridge } : {}
12819
+ ...storage ? { storage } : {}
12908
12820
  })
12909
12821
  };
12910
12822
  }
12911
- function recallTool(storage, bridge) {
12823
+ function recallTool(storage) {
12912
12824
  return {
12913
12825
  name: "recall",
12914
- 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.",
12915
12827
  inputSchema: {
12916
12828
  type: "object",
12917
12829
  additionalProperties: true,
@@ -12925,8 +12837,7 @@ function recallTool(storage, bridge) {
12925
12837
  required: ["query"]
12926
12838
  },
12927
12839
  handler: (args) => runRecall(args, {
12928
- ...storage ? { storage } : {},
12929
- ...bridge ? { bridge } : {}
12840
+ ...storage ? { storage } : {}
12930
12841
  })
12931
12842
  };
12932
12843
  }
@@ -12962,7 +12873,7 @@ function modelsTool(providers, activeProviders) {
12962
12873
  handler: async (args) => runModels(args, { providers, activeProviders })
12963
12874
  };
12964
12875
  }
12965
- function reviewTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
12876
+ function reviewTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
12966
12877
  return {
12967
12878
  name: "review",
12968
12879
  description: "Have an LLM panel peer-review a code or proposal snippet. Returns the confer envelope (one answer per provider).",
@@ -12981,7 +12892,6 @@ function reviewTool(providers, allowlist, bridge, storage, breakers, transcripts
12981
12892
  handler: (args) => runReview(args, {
12982
12893
  providers,
12983
12894
  allowlist,
12984
- ...bridge ? { bridge } : {},
12985
12895
  ...storage ? { storage } : {},
12986
12896
  ...breakers ? { breakers } : {},
12987
12897
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -12989,7 +12899,7 @@ function reviewTool(providers, allowlist, bridge, storage, breakers, transcripts
12989
12899
  })
12990
12900
  };
12991
12901
  }
12992
- function critiqueTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
12902
+ function critiqueTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
12993
12903
  return {
12994
12904
  name: "critique",
12995
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.",
@@ -13009,7 +12919,6 @@ function critiqueTool(providers, allowlist, bridge, storage, breakers, transcrip
13009
12919
  handler: (args) => runCritique(args, {
13010
12920
  providers,
13011
12921
  allowlist,
13012
- ...bridge ? { bridge } : {},
13013
12922
  ...storage ? { storage } : {},
13014
12923
  ...breakers ? { breakers } : {},
13015
12924
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -13017,7 +12926,7 @@ function critiqueTool(providers, allowlist, bridge, storage, breakers, transcrip
13017
12926
  })
13018
12927
  };
13019
12928
  }
13020
- function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
12929
+ function planTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
13021
12930
  return {
13022
12931
  name: "plan",
13023
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.',
@@ -13044,7 +12953,6 @@ function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDi
13044
12953
  handler: (args) => runPlan(args, {
13045
12954
  providers,
13046
12955
  allowlist,
13047
- ...bridge ? { bridge } : {},
13048
12956
  ...storage ? { storage } : {},
13049
12957
  ...breakers ? { breakers } : {},
13050
12958
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -13052,7 +12960,7 @@ function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDi
13052
12960
  })
13053
12961
  };
13054
12962
  }
13055
- function triangulateTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
12963
+ function triangulateTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
13056
12964
  return {
13057
12965
  name: "triangulate",
13058
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.",
@@ -13073,7 +12981,6 @@ function triangulateTool(providers, allowlist, bridge, storage, breakers, transc
13073
12981
  handler: (args) => runTriangulate(args, {
13074
12982
  providers,
13075
12983
  allowlist,
13076
- ...bridge ? { bridge } : {},
13077
12984
  ...storage ? { storage } : {},
13078
12985
  ...breakers ? { breakers } : {},
13079
12986
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -13081,7 +12988,7 @@ function triangulateTool(providers, allowlist, bridge, storage, breakers, transc
13081
12988
  })
13082
12989
  };
13083
12990
  }
13084
- function coordinateTool(providers, allowlist, bridge, innerCallers, storage, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
12991
+ function coordinateTool(providers, allowlist, innerCallers, storage, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13085
12992
  return {
13086
12993
  name: "coordinate",
13087
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).",
@@ -13106,7 +13013,6 @@ function coordinateTool(providers, allowlist, bridge, innerCallers, storage, bre
13106
13013
  handler: (args) => runCoordinate(args, {
13107
13014
  providers,
13108
13015
  allowlist,
13109
- ...bridge ? { bridge } : {},
13110
13016
  innerCallers,
13111
13017
  ...storage ? { storage } : {},
13112
13018
  ...breakers ? { breakers } : {},
@@ -13116,7 +13022,7 @@ function coordinateTool(providers, allowlist, bridge, innerCallers, storage, bre
13116
13022
  })
13117
13023
  };
13118
13024
  }
13119
- function debateTool(providers, allowlist, bridge, innerCallers, storage, pricing, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13025
+ function debateTool(providers, allowlist, innerCallers, storage, pricing, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13120
13026
  return {
13121
13027
  name: "debate",
13122
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).",
@@ -13146,7 +13052,6 @@ function debateTool(providers, allowlist, bridge, innerCallers, storage, pricing
13146
13052
  handler: (args) => runDebate(args, {
13147
13053
  providers,
13148
13054
  allowlist,
13149
- ...bridge ? { bridge } : {},
13150
13055
  innerCallers,
13151
13056
  ...storage ? { storage } : {},
13152
13057
  ...pricing ? { pricing } : {},
@@ -13166,10 +13071,10 @@ function buildInnerCallers(o) {
13166
13071
  ...o.repoRoot ? { repoRoot: o.repoRoot } : {}
13167
13072
  });
13168
13073
  }
13169
- out.verify = (args) => runVerify(args, o.bridge, o.fetchConfig);
13074
+ out.verify = (args) => runVerify(args, o.fetchConfig);
13170
13075
  return out;
13171
13076
  }
13172
- 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) {
13173
13078
  return {
13174
13079
  name: "confer",
13175
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).",
@@ -13196,7 +13101,6 @@ function conferTool(providers, allowlist, bridge, moderator, pricing, storage, i
13196
13101
  handler: (args) => runConfer(args, {
13197
13102
  providers,
13198
13103
  allowlist,
13199
- ...bridge ? { bridge } : {},
13200
13104
  moderator,
13201
13105
  ...pricing ? { pricing } : {},
13202
13106
  ...storage ? { storage } : {},
@@ -13208,7 +13112,7 @@ function conferTool(providers, allowlist, bridge, moderator, pricing, storage, i
13208
13112
  })
13209
13113
  };
13210
13114
  }
13211
- function auditTool(providers, allowlist, bridge, transcriptsDir, pricing, storage, breakers, repoRoot) {
13115
+ function auditTool(providers, allowlist, transcriptsDir, pricing, storage, breakers, repoRoot) {
13212
13116
  return {
13213
13117
  name: "audit",
13214
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.",
@@ -13234,7 +13138,6 @@ function auditTool(providers, allowlist, bridge, transcriptsDir, pricing, storag
13234
13138
  handler: (args) => runAudit(args, {
13235
13139
  providers,
13236
13140
  allowlist,
13237
- ...bridge ? { bridge } : {},
13238
13141
  ...transcriptsDir ? { transcriptsDir } : {},
13239
13142
  ...pricing ? { pricing } : {},
13240
13143
  ...storage ? { storage } : {},
@@ -13298,7 +13201,7 @@ function pickTool(providers, allowlist, storage, breakers, transcriptsDir, repoR
13298
13201
  })
13299
13202
  };
13300
13203
  }
13301
- function verifyTool(bridge, fetchConfig) {
13204
+ function verifyTool(fetchConfig) {
13302
13205
  return {
13303
13206
  name: "verify",
13304
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.",
@@ -13316,7 +13219,7 @@ function verifyTool(bridge, fetchConfig) {
13316
13219
  },
13317
13220
  required: ["checks"]
13318
13221
  },
13319
- handler: (args) => runVerify(args, bridge, fetchConfig)
13222
+ handler: (args) => runVerify(args, fetchConfig)
13320
13223
  };
13321
13224
  }
13322
13225
  function pingTool() {
@@ -13336,7 +13239,7 @@ function pingTool() {
13336
13239
  }
13337
13240
 
13338
13241
  // src/core/telemetry.ts
13339
- var import_node_crypto7 = __toESM(require("crypto"), 1);
13242
+ var import_node_crypto8 = __toESM(require("crypto"), 1);
13340
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;
13341
13244
  var BATCH_MAX = 100;
13342
13245
  var MAX_QUEUE = 500;
@@ -13400,6 +13303,64 @@ async function flush() {
13400
13303
  }
13401
13304
  }
13402
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
+
13403
13364
  // src/entrypoints/embed.ts
13404
13365
  var KEY_ENV = {
13405
13366
  anthropic: "ANTHROPIC_API_KEY",
@@ -13456,7 +13417,7 @@ function errorOf(answer) {
13456
13417
  }
13457
13418
  function bundledPricingPath() {
13458
13419
  try {
13459
- 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");
13460
13421
  } catch {
13461
13422
  return void 0;
13462
13423
  }
@@ -13477,7 +13438,7 @@ function createEmbeddedEngine(opts) {
13477
13438
  if (varName && model) env[varName] = model;
13478
13439
  }
13479
13440
  const pricingPath = [opts.pricingPath, bundledPricingPath()].find(
13480
- (p) => Boolean(p) && (0, import_node_fs15.existsSync)(p)
13441
+ (p) => Boolean(p) && (0, import_node_fs16.existsSync)(p)
13481
13442
  );
13482
13443
  const pricing = pricingPath ? loadPricing(pricingPath) : {};
13483
13444
  const built = buildProviders({ env, pricing });
@@ -13600,6 +13561,9 @@ var __test_internals = { usageOf, textOf, errorOf, vaultId };
13600
13561
  __KEY_ENV,
13601
13562
  __MODEL_ENV,
13602
13563
  __test_internals,
13603
- createEmbeddedEngine
13564
+ createEmbeddedEngine,
13565
+ isAlive,
13566
+ listProcesses,
13567
+ processRegistryPath
13604
13568
  });
13605
13569
  //# sourceMappingURL=embed.cjs.map