@konneal/engine 0.2.157 → 0.2.158

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-STDXSVLX.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";
@@ -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
  }
@@ -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,
@@ -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-STDXSVLX.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-7GRQQEBN.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.158",
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",
@@ -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
  }