@konneal/engine 0.2.157 → 0.2.159

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.
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  handleAsk
3
- } from "./chunk-S3O7QZQ7.js";
3
+ } from "./chunk-CBSVUTFM.js";
4
4
  import "./chunk-ECOYO7EX.js";
5
- import "./chunk-VYEMFSU5.js";
5
+ import "./chunk-PBHMQZKA.js";
6
6
  import "./chunk-G2RE4XRV.js";
7
7
  import "./chunk-NI4CIK6W.js";
8
8
  import "./chunk-W7J5SFXJ.js";
@@ -32,7 +32,7 @@ import {
32
32
  tableRetyped,
33
33
  toolNote,
34
34
  verdictNote
35
- } from "./chunk-VYEMFSU5.js";
35
+ } from "./chunk-PBHMQZKA.js";
36
36
  import {
37
37
  NO_CONTEXT,
38
38
  STAGE_NAMES,
@@ -2749,6 +2749,15 @@ Answer account questions from these records ONLY: name the record when you use i
2749
2749
  const streamed = { total: streamedAnchors.total, violations: streamedRetyped ? ["table-retyped"] : streamedAnchors.violations };
2750
2750
  if (streamed.violations.length > 0) {
2751
2751
  console.log("anchors:", streamed.violations.length, "of", streamed.total, "unverified \u2014 not caching");
2752
+ try {
2753
+ live2.send({
2754
+ type: "contract",
2755
+ verified: streamed.total - streamed.violations.length,
2756
+ violations: streamed.violations.slice(0, 5),
2757
+ note: "the streamed answer carried unverified quote anchors \u2014 the json lane enforces this contract by regeneration; treat the quoted spans as unverified"
2758
+ });
2759
+ } catch {
2760
+ }
2752
2761
  }
2753
2762
  if (streamed.violations.length === 0 && canonical.length > 0 && !contextual && !declaredCtx && cacheableAnswer(canonical, refusalScope(answerCites(canonical))) && !ablate) {
2754
2763
  ctx.waitUntil(
@@ -271,7 +271,7 @@ function parseNumber(raw) {
271
271
  return Number(s.replace(/,(?=\d{3}\b)/g, ""));
272
272
  }
273
273
  var TOL_SEP_SRC = "\\u00b1|\\bpm\\b|\\+/-";
274
- var NUM_SRC = "[0-9][0-9 ,.]*[0-9]";
274
+ var NUM_SRC = "[0-9]+(?:[0-9 ,.]*[0-9])?";
275
275
  var UNIT_SRC = "%|\\u00b0?[A-Za-z\\u00b5\\u03a9]{0,6}";
276
276
  function statedUncertainty(value, tolRaw, tolUnitRaw, valueUnit) {
277
277
  const tolNum = parseNumber(tolRaw);
@@ -404,6 +404,42 @@ function evaluate(content, query, opts) {
404
404
  const decided = corners.filter((c2) => c2 !== null);
405
405
  if (decided.length && decided.some((c2) => c2 !== result)) {
406
406
  voidReason = voidReason ?? `the stated uncertainty (${un.stated}) on ${first.split(".").pop()} crosses the decision boundary \u2014 the check evaluates ${result ? "true" : "false"} at the stated value but ${decided.find((c2) => c2 !== result) ? "true" : "false"} at the band edge; the question cannot be decided as stated`;
407
+ } else if (decided.length === corners.length && un.tol > 0) {
408
+ const flipsAt = (scale) => {
409
+ for (const dir of [1, -1]) {
410
+ const corner = { ...params, [first]: params[first] + dir * scale * un.tol };
411
+ try {
412
+ if (!!parseAndEval(expression, corner) !== result) return true;
413
+ } catch {
414
+ return true;
415
+ }
416
+ }
417
+ return false;
418
+ };
419
+ if (flipsAt(20)) {
420
+ let lo = 1, hi = 20;
421
+ for (let i = 0; i < 12; i++) {
422
+ const mid = (lo + hi) / 2;
423
+ if (flipsAt(mid)) hi = mid;
424
+ else lo = mid;
425
+ }
426
+ const marginTol = hi * un.tol;
427
+ uncertainty = {
428
+ ...uncertainty,
429
+ margin_tol: marginTol,
430
+ margin_bounded: true,
431
+ coverage: "k=2",
432
+ safety_factor: marginTol / (2 * un.tol)
433
+ };
434
+ } else {
435
+ uncertainty = {
436
+ ...uncertainty,
437
+ margin_tol: 20 * un.tol,
438
+ margin_bounded: false,
439
+ coverage: "k=2",
440
+ safety_factor: 20 * un.tol / (2 * un.tol)
441
+ };
442
+ }
407
443
  }
408
444
  }
409
445
  }
@@ -4,7 +4,7 @@ import {
4
4
  parseToolCall,
5
5
  runTool,
6
6
  toolNote
7
- } from "./chunk-VYEMFSU5.js";
7
+ } from "./chunk-PBHMQZKA.js";
8
8
  import "./chunk-NI4CIK6W.js";
9
9
  import "./chunk-4NXH5ZI6.js";
10
10
  import "./chunk-VT7DR6NQ.js";
package/dist/verdict.d.ts CHANGED
@@ -4,7 +4,13 @@ export interface MachineCheck {
4
4
  values: Record<string, number>;
5
5
  result: boolean | null;
6
6
  /** present when the question states a tolerance on a symbol this
7
- * check reads: the band's corner evaluations beside the nominal */
7
+ * check reads: the band's corner evaluations beside the nominal,
8
+ * and — when the band is robust (every corner agrees with the
9
+ * nominal) — the GUM-style budget: the tolerance magnitude that
10
+ * would flip the decision (bisected up to 20× the stated band;
11
+ * margin_bounded false when even 20× does not flip), and the safety
12
+ * factor of that margin over the k=2 expanded uncertainty
13
+ * (U = 2u, the ≈95% coverage a metrologist reports). */
8
14
  uncertainty?: {
9
15
  symbol: string;
10
16
  stated: string;
@@ -12,6 +18,10 @@ export interface MachineCheck {
12
18
  unit?: string;
13
19
  nominal: boolean;
14
20
  corners: (boolean | null)[];
21
+ margin_tol?: number;
22
+ margin_bounded?: boolean;
23
+ coverage?: "k=2";
24
+ safety_factor?: number;
15
25
  };
16
26
  }
17
27
  export interface Verdict {
@@ -4,13 +4,13 @@ import {
4
4
  handleMemories,
5
5
  scoreFaithfulness,
6
6
  scoreJudge
7
- } from "../../chunk-S3O7QZQ7.js";
7
+ } from "../../chunk-CBSVUTFM.js";
8
8
  import "../../chunk-ECOYO7EX.js";
9
9
  import {
10
10
  TOOLS_REGISTRY,
11
11
  bindModelNode,
12
12
  modelGroundingBlock
13
- } from "../../chunk-VYEMFSU5.js";
13
+ } from "../../chunk-PBHMQZKA.js";
14
14
  import {
15
15
  handleSearch
16
16
  } from "../../chunk-OL7KKGEO.js";
@@ -1118,13 +1118,13 @@ async function callToolOnce(env, ctx, _req, tier, key, name, args, t0) {
1118
1118
  // stream:false forces the JSON lane (anon defaults to SSE)
1119
1119
  body: JSON.stringify({ ...args, stream: false })
1120
1120
  });
1121
- const { runTool, TOOLS_REGISTRY: TOOLS_REGISTRY2 } = await import("../../tools-CWPQQTBQ.js");
1121
+ const { runTool, TOOLS_REGISTRY: TOOLS_REGISTRY2 } = await import("../../tools-W5HGME7W.js");
1122
1122
  let payload;
1123
1123
  if (TOOLS_REGISTRY2.some((t) => t.name === name && t.audiences.includes("mcp"))) {
1124
1124
  const r = await runTool({ ...env, DB: env.DB }, { name, args }, "mcp");
1125
1125
  payload = r ? { tool: r.name, query: r.query, result: r.output } : { error: { message: `tool ${name} returned nothing for the given arguments` } };
1126
1126
  } else {
1127
- const res = name === "ask" ? await (await import("../../ask-IC5A5LIN.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-GAU5SEZI.js")).handleSearch(env, ctx, inner, tier, key);
1127
+ const res = name === "ask" ? await (await import("../../ask-FUNBGZKM.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-GAU5SEZI.js")).handleSearch(env, ctx, inner, tier, key);
1128
1128
  payload = await res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
1129
1129
  }
1130
1130
  telemetry(env, ctx, tier, `mcp:${name}`, null, !payload?.error, JSON.stringify(payload).length, await sha256Hex(`${name}:${JSON.stringify(args ?? {})}`), void 0, void 0, { durationMs: Date.now() - t0 });
package/package.json CHANGED
@@ -27,7 +27,7 @@
27
27
  "playwright": "^1.62.1",
28
28
  "yaml": "^2.9.1"
29
29
  },
30
- "version": "0.2.157",
30
+ "version": "0.2.159",
31
31
  "description": "The Konneal engine: the publisher-agnostic build pipeline and API plane for standards intelligence (retrieval, answer contract, verdicts, evaluation).",
32
32
  "license": "BSD-3-Clause",
33
33
  "type": "module",
@@ -1702,6 +1702,20 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
1702
1702
  const streamed = { total: streamedAnchors.total, violations: streamedRetyped ? ["table-retyped"] : streamedAnchors.violations };
1703
1703
  if (streamed.violations.length > 0) {
1704
1704
  console.log("anchors:", streamed.violations.length, "of", streamed.total, "unverified — not caching");
1705
+ // the streaming-contract event (TODO.sota/14.5, v1 — the
1706
+ // detection half): a mid-stream answer cannot regenerate, so
1707
+ // the violations are reported to the client as they are —
1708
+ // measured, never hidden — and the unverified answer never
1709
+ // enters the cache. The bounded restart still covers the
1710
+ // head class (narration, preamble).
1711
+ try {
1712
+ live!.send({
1713
+ type: "contract",
1714
+ verified: streamed.total - streamed.violations.length,
1715
+ violations: streamed.violations.slice(0, 5),
1716
+ note: "the streamed answer carried unverified quote anchors — the json lane enforces this contract by regeneration; treat the quoted spans as unverified",
1717
+ });
1718
+ } catch { /* the client may have closed; never block the close */ }
1705
1719
  }
1706
1720
  if (streamed.violations.length === 0 && canonical.length > 0 && !contextual && !declaredCtx && cacheableAnswer(canonical, refusalScope(answerCites(canonical))) && !ablate) {
1707
1721
  ctx.waitUntil(
@@ -20,7 +20,13 @@ export interface MachineCheck {
20
20
  values: Record<string, number>;
21
21
  result: boolean | null; // null: could not evaluate (missing params)
22
22
  /** present when the question states a tolerance on a symbol this
23
- * check reads: the band's corner evaluations beside the nominal */
23
+ * check reads: the band's corner evaluations beside the nominal,
24
+ * and — when the band is robust (every corner agrees with the
25
+ * nominal) — the GUM-style budget: the tolerance magnitude that
26
+ * would flip the decision (bisected up to 20× the stated band;
27
+ * margin_bounded false when even 20× does not flip), and the safety
28
+ * factor of that margin over the k=2 expanded uncertainty
29
+ * (U = 2u, the ≈95% coverage a metrologist reports). */
24
30
  uncertainty?: {
25
31
  symbol: string;
26
32
  stated: string;
@@ -28,6 +34,10 @@ export interface MachineCheck {
28
34
  unit?: string;
29
35
  nominal: boolean;
30
36
  corners: (boolean | null)[];
37
+ margin_tol?: number;
38
+ margin_bounded?: boolean;
39
+ coverage?: "k=2";
40
+ safety_factor?: number;
31
41
  };
32
42
  }
33
43
 
@@ -223,7 +233,10 @@ export interface StatedUncertainty {
223
233
  }
224
234
 
225
235
  const TOL_SEP_SRC = "\\u00b1|\\bpm\\b|\\+/-";
226
- const NUM_SRC = "[0-9][0-9 ,.]*[0-9]";
236
+ // single digits bind too — a metrologist's "± 5 v" is a first-class
237
+ // tolerance (the two-digit minimum silently dropped every one-digit
238
+ // value and tolerance; found by the GUM-budget tests, 2026-10-20)
239
+ const NUM_SRC = "[0-9]+(?:[0-9 ,.]*[0-9])?";
227
240
  const UNIT_SRC = "%|\\u00b0?[A-Za-z\\u00b5\\u03a9]{0,6}";
228
241
 
229
242
  function statedUncertainty(
@@ -392,6 +405,43 @@ export function evaluate(content: unknown, query: string, opts?: { dimensions?:
392
405
  `the check evaluates ${result ? "true" : "false"} at the stated value but ` +
393
406
  `${decided.find((c) => c !== result) ? "true" : "false"} at the band edge; the question cannot be decided as stated`
394
407
  );
408
+ } else if (decided.length === corners.length && un.tol > 0) {
409
+ // the band is robust: report the GUM-style budget — bisect
410
+ // the tolerance scaling for the flip point (both directions,
411
+ // up to 20× the stated band), then state the safety factor
412
+ // over the k=2 expanded uncertainty (U = 2u)
413
+ const flipsAt = (scale: number): boolean => {
414
+ for (const dir of [1, -1]) {
415
+ const corner = { ...params, [first]: params[first]! + dir * scale * un.tol };
416
+ try {
417
+ if (!!parseAndEval(expression, corner) !== result) return true;
418
+ } catch { return true; }
419
+ }
420
+ return false;
421
+ };
422
+ if (flipsAt(20)) {
423
+ let lo = 1, hi = 20;
424
+ for (let i = 0; i < 12; i++) {
425
+ const mid = (lo + hi) / 2;
426
+ if (flipsAt(mid)) hi = mid; else lo = mid;
427
+ }
428
+ const marginTol = hi * un.tol;
429
+ uncertainty = {
430
+ ...uncertainty!,
431
+ margin_tol: marginTol,
432
+ margin_bounded: true,
433
+ coverage: "k=2",
434
+ safety_factor: marginTol / (2 * un.tol),
435
+ };
436
+ } else {
437
+ uncertainty = {
438
+ ...uncertainty!,
439
+ margin_tol: 20 * un.tol,
440
+ margin_bounded: false,
441
+ coverage: "k=2",
442
+ safety_factor: (20 * un.tol) / (2 * un.tol),
443
+ };
444
+ }
395
445
  }
396
446
  }
397
447
  }