@konneal/engine 0.2.10 → 0.2.11
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/{ask-PKHGS2DZ.js → ask-AAEPGPJI.js} +1 -1
- package/dist/{chunk-ZAEUQFC2.js → chunk-KMSUJI75.js} +22 -21
- package/dist/conditions.d.ts +9 -5
- package/dist/worker_public/src/index.js +2 -2
- package/docs/ADOPTION.md +9 -0
- package/package.json +1 -1
- package/workers/worker_public/src/conditions.ts +43 -34
|
@@ -764,39 +764,40 @@ var NUM = String.raw`-?\d+(?:[.,]\d+)?`;
|
|
|
764
764
|
function quantitiesIn(query) {
|
|
765
765
|
const out = {};
|
|
766
766
|
const num2 = (s) => Number(s.replace(",", "."));
|
|
767
|
-
const
|
|
768
|
-
|
|
767
|
+
const put = (kind, stated, stated_unit, si) => {
|
|
768
|
+
if (Number.isFinite(si)) out[kind] = { stated, stated_unit, si };
|
|
769
|
+
};
|
|
770
|
+
const tempC = query.match(new RegExp(`(${NUM})\\s*(?:\xB0\\s*)?C\\b`));
|
|
771
|
+
if (tempC) put("temperature", num2(tempC[1]), "degC", num2(tempC[1]) + 273.15);
|
|
772
|
+
const tempK = query.match(new RegExp(`(${NUM})\\s*K\\b`));
|
|
773
|
+
if (tempK && out.temperature === void 0) put("temperature", num2(tempK[1]), "K", num2(tempK[1]));
|
|
769
774
|
const rh = query.match(new RegExp(`(${NUM})\\s*%\\s*(?:RH\\b|relative\\s+humidity)?`, "i"));
|
|
770
|
-
if (rh)
|
|
775
|
+
if (rh) put("relative_humidity", num2(rh[1]), "%", num2(rh[1]) / 100);
|
|
771
776
|
const hours = query.match(new RegExp(`(${NUM})\\s*h\\b`, "i"));
|
|
772
|
-
if (hours)
|
|
777
|
+
if (hours) put("duration", num2(hours[1]), "h", num2(hours[1]) * 3600);
|
|
773
778
|
const days = query.match(new RegExp(`(${NUM})\\s*days?\\b`, "i"));
|
|
774
|
-
if (days && out.duration === void 0)
|
|
779
|
+
if (days && out.duration === void 0) put("duration", num2(days[1]), "d", num2(days[1]) * 86400);
|
|
775
780
|
return out;
|
|
776
781
|
}
|
|
777
|
-
function entryBand(e) {
|
|
778
|
-
const value = Number(String(e.value).replace(",", "."));
|
|
779
|
-
const tolerance = Number(String(e.tolerance ?? "0").replace(",", "."));
|
|
780
|
-
if (!Number.isFinite(value)) return null;
|
|
781
|
-
return { value, tolerance: Number.isFinite(tolerance) ? tolerance : 0, lo: value - tolerance, hi: value + tolerance };
|
|
782
|
-
}
|
|
783
782
|
function scoreSet(entries, q) {
|
|
784
783
|
const checks = [];
|
|
785
784
|
let distance = 0;
|
|
786
785
|
let stated = 0;
|
|
787
786
|
for (const e of entries) {
|
|
788
|
-
const
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
const
|
|
793
|
-
const
|
|
794
|
-
|
|
787
|
+
const siEntry = e;
|
|
788
|
+
const statedQ = q[e.quantity_kind];
|
|
789
|
+
if (!statedQ || !siEntry?.si) continue;
|
|
790
|
+
const tol = Number(String(siEntry.tolerance ?? "0").replace(",", "."));
|
|
791
|
+
const tolSi = (Number.isFinite(tol) ? tol : 0) * (siEntry.si.unit === "K" ? 1 : siEntry.si.unit === "1" ? 0.01 : 1);
|
|
792
|
+
const in_band = statedQ.si >= siEntry.si.value - tolSi && statedQ.si <= siEntry.si.value + tolSi;
|
|
793
|
+
const gap = Math.max(0, statedQ.si - (siEntry.si.value + tolSi), siEntry.si.value - tolSi - statedQ.si);
|
|
794
|
+
distance += gap / Math.max(tolSi, 1);
|
|
795
795
|
stated += 1;
|
|
796
796
|
checks.push({
|
|
797
797
|
quantity_kind: e.quantity_kind,
|
|
798
|
-
band: `${
|
|
799
|
-
stated:
|
|
798
|
+
band: `${siEntry.si.value} ${siEntry.si.unit} \xB1${tolSi}`,
|
|
799
|
+
stated: statedQ.stated,
|
|
800
|
+
stated_unit: statedQ.stated_unit,
|
|
800
801
|
in_band
|
|
801
802
|
});
|
|
802
803
|
}
|
|
@@ -831,7 +832,7 @@ function evaluateConditionSets(nodes, query) {
|
|
|
831
832
|
verdict: "fail",
|
|
832
833
|
matched: [],
|
|
833
834
|
nearest: { node_id: nearest.node_id, distance: Number(nearest.distance.toFixed(2)), bands: nearest.checks.map((c) => c.band) },
|
|
834
|
-
checks:
|
|
835
|
+
checks: nearest.checks,
|
|
835
836
|
note: `VERDICT: FAIL \u2014 no severity set admits the stated combination. The nearest set is ${nearest.node_id} (bands: ${nearest.checks.map((c) => c.band).join("; ")}). Say the combination is outside the menu and name the nearest set; never soften it.`
|
|
836
837
|
};
|
|
837
838
|
}
|
package/dist/conditions.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export interface ConditionCheck {
|
|
|
2
2
|
quantity_kind: string;
|
|
3
3
|
band: string;
|
|
4
4
|
stated: number;
|
|
5
|
+
stated_unit: string;
|
|
5
6
|
in_band: boolean;
|
|
6
7
|
}
|
|
7
8
|
export interface ConditionVerdict {
|
|
@@ -15,11 +16,14 @@ export interface ConditionVerdict {
|
|
|
15
16
|
checks: ConditionCheck[];
|
|
16
17
|
note: string;
|
|
17
18
|
}
|
|
18
|
-
/** The question's stated quantities
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
/** The question's stated quantities with their SI normalization
|
|
20
|
+
* (temperature → K, relative_humidity → the ratio unit, duration → s).
|
|
21
|
+
* Units, never words: "12 months" is not a 12 h duration. */
|
|
22
|
+
export declare function quantitiesIn(query: string): Record<string, {
|
|
23
|
+
stated: number;
|
|
24
|
+
stated_unit: string;
|
|
25
|
+
si: number;
|
|
26
|
+
}>;
|
|
23
27
|
/** Evaluate the candidate condition_set nodes against the question's
|
|
24
28
|
* stated quantities. PASS when at least one set admits every stated
|
|
25
29
|
* quantity within its band (the set is named); FAIL names the nearest
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
handleMemories,
|
|
8
8
|
scoreJudge,
|
|
9
9
|
standardForDocNumber
|
|
10
|
-
} from "../../chunk-
|
|
10
|
+
} from "../../chunk-KMSUJI75.js";
|
|
11
11
|
import {
|
|
12
12
|
buildMessages,
|
|
13
13
|
citations,
|
|
@@ -979,7 +979,7 @@ async function handleMcp(env, ctx, req, tier, key) {
|
|
|
979
979
|
// stream:false forces the JSON lane (anon defaults to SSE)
|
|
980
980
|
body: JSON.stringify({ ...args, stream: false })
|
|
981
981
|
});
|
|
982
|
-
const res = name === "ask" ? await (await import("../../ask-
|
|
982
|
+
const res = name === "ask" ? await (await import("../../ask-AAEPGPJI.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-RFKT7ZZY.js")).handleSearch(env, ctx, inner, tier, key);
|
|
983
983
|
return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
|
|
984
984
|
});
|
|
985
985
|
if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
|
package/docs/ADOPTION.md
CHANGED
|
@@ -42,6 +42,15 @@ request cannot reach internal indexes at all: the public surface holds
|
|
|
42
42
|
no binding to them, and the internal worker re-verifies every session
|
|
43
43
|
itself.
|
|
44
44
|
|
|
45
|
+
## Grounded in the literature
|
|
46
|
+
|
|
47
|
+
The execution pattern (a deterministic evaluator computes; the model
|
|
48
|
+
narrates) adopts the program-aided line — PAL (arXiv:2211.10435) and
|
|
49
|
+
Program of Thoughts (arXiv:2211.12588) — and the structured-numeric
|
|
50
|
+
retrieval lessons of TableRAG (arXiv:2410.04739, arXiv:2506.10380).
|
|
51
|
+
The deployment's research notes map every technique to its source and
|
|
52
|
+
to the code path that implements it.
|
|
53
|
+
|
|
45
54
|
## The proof
|
|
46
55
|
|
|
47
56
|
Your golden suite gates every promotion: content witnesses, refusal
|
package/package.json
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@oimlsmart/oiml-pubid": "^1.2.1"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {},
|
|
37
|
-
"version": "0.2.
|
|
37
|
+
"version": "0.2.11",
|
|
38
38
|
"description": "The Konneal engine: the publisher-agnostic build pipeline and API plane for standards intelligence (retrieval, answer contract, verdicts, evaluation).",
|
|
39
39
|
"license": "BSD-3-Clause",
|
|
40
40
|
"type": "module",
|
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
// the test-method packages as machine-verifiable membership. A
|
|
3
3
|
// condition_set node's payload.entries carry the kernel's quantity
|
|
4
4
|
// doctrine — value + unit inseparable, tolerance the SPECIFIED band —
|
|
5
|
-
//
|
|
6
|
-
// the
|
|
7
|
-
//
|
|
5
|
+
// and each entry resolves to SI through the package's own quantity
|
|
6
|
+
// register (the export ships si { value, unit }). The stated quantities
|
|
7
|
+
// normalize through the same SI targets, so 313 K and 40 °C are the
|
|
8
|
+
// same stated temperature.
|
|
8
9
|
|
|
9
10
|
export interface ConditionCheck {
|
|
10
11
|
quantity_kind: string;
|
|
11
12
|
band: string;
|
|
12
13
|
stated: number;
|
|
14
|
+
stated_unit: string;
|
|
13
15
|
in_band: boolean;
|
|
14
16
|
}
|
|
15
17
|
|
|
@@ -26,55 +28,62 @@ interface Entry {
|
|
|
26
28
|
value: string | number;
|
|
27
29
|
unit: string;
|
|
28
30
|
tolerance: string | number;
|
|
31
|
+
si?: { value: number; unit: string };
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
const NUM = String.raw`-?\d+(?:[.,]\d+)?`;
|
|
32
35
|
|
|
33
|
-
/** The question's stated quantities
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const out: Record<string, number> = {};
|
|
36
|
+
/** The question's stated quantities with their SI normalization
|
|
37
|
+
* (temperature → K, relative_humidity → the ratio unit, duration → s).
|
|
38
|
+
* Units, never words: "12 months" is not a 12 h duration. */
|
|
39
|
+
export function quantitiesIn(query: string): Record<string, { stated: number; stated_unit: string; si: number }> {
|
|
40
|
+
const out: Record<string, { stated: number; stated_unit: string; si: number }> = {};
|
|
39
41
|
const num = (s: string) => Number(s.replace(",", "."));
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
+
const put = (kind: string, stated: number, stated_unit: string, si: number) => {
|
|
43
|
+
if (Number.isFinite(si)) out[kind] = { stated, stated_unit, si };
|
|
44
|
+
};
|
|
45
|
+
const tempC = query.match(new RegExp(`(${NUM})\\s*(?:°\\s*)?C\\b`));
|
|
46
|
+
if (tempC) put("temperature", num(tempC[1]!), "degC", num(tempC[1]!) + 273.15);
|
|
47
|
+
const tempK = query.match(new RegExp(`(${NUM})\\s*K\\b`));
|
|
48
|
+
if (tempK && out.temperature === undefined) put("temperature", num(tempK[1]!), "K", num(tempK[1]!));
|
|
42
49
|
const rh = query.match(new RegExp(`(${NUM})\\s*%\\s*(?:RH\\b|relative\\s+humidity)?`, "i"));
|
|
43
|
-
if (rh)
|
|
50
|
+
if (rh) put("relative_humidity", num(rh[1]!), "%", num(rh[1]!) / 100);
|
|
44
51
|
const hours = query.match(new RegExp(`(${NUM})\\s*h\\b`, "i"));
|
|
45
|
-
if (hours)
|
|
52
|
+
if (hours) put("duration", num(hours[1]!), "h", num(hours[1]!) * 3600);
|
|
46
53
|
const days = query.match(new RegExp(`(${NUM})\\s*days?\\b`, "i"));
|
|
47
|
-
if (days && out.duration === undefined)
|
|
54
|
+
if (days && out.duration === undefined) put("duration", num(days[1]!), "d", num(days[1]!) * 86400);
|
|
48
55
|
return out;
|
|
49
56
|
}
|
|
50
57
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
interface SiEntry {
|
|
59
|
+
quantity_kind: string;
|
|
60
|
+
unit: string;
|
|
61
|
+
tolerance: string | number;
|
|
62
|
+
si: { value: number; unit: string };
|
|
56
63
|
}
|
|
57
64
|
|
|
58
|
-
/** Evaluate ONE set: every stated quantity
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
function scoreSet(entries: Entry[], q: Record<string, number>): { checks: ConditionCheck[]; distance: number; stated: number } | null {
|
|
65
|
+
/** Evaluate ONE set: every stated quantity's SI value inside the
|
|
66
|
+
* entry's SI band (the tolerance converts with the factor, never the
|
|
67
|
+
* offset — a difference has no affine part). */
|
|
68
|
+
function scoreSet(entries: (Entry | SiEntry)[], q: Record<string, { stated: number; stated_unit: string; si: number }>): { checks: ConditionCheck[]; distance: number; stated: number } | null {
|
|
62
69
|
const checks: ConditionCheck[] = [];
|
|
63
70
|
let distance = 0;
|
|
64
71
|
let stated = 0;
|
|
65
72
|
for (const e of entries) {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
+
const siEntry = e as SiEntry;
|
|
74
|
+
const statedQ = q[e.quantity_kind];
|
|
75
|
+
if (!statedQ || !siEntry?.si) continue;
|
|
76
|
+
const tol = Number(String(siEntry.tolerance ?? "0").replace(",", "."));
|
|
77
|
+
const tolSi = (Number.isFinite(tol) ? tol : 0) * (siEntry.si.unit === "K" ? 1 : siEntry.si.unit === "1" ? 0.01 : 1);
|
|
78
|
+
const in_band = statedQ.si >= siEntry.si.value - tolSi && statedQ.si <= siEntry.si.value + tolSi;
|
|
79
|
+
const gap = Math.max(0, statedQ.si - (siEntry.si.value + tolSi), siEntry.si.value - tolSi - statedQ.si);
|
|
80
|
+
distance += gap / Math.max(tolSi, 1);
|
|
73
81
|
stated += 1;
|
|
74
82
|
checks.push({
|
|
75
83
|
quantity_kind: e.quantity_kind,
|
|
76
|
-
band: `${
|
|
77
|
-
stated:
|
|
84
|
+
band: `${siEntry.si.value} ${siEntry.si.unit} ±${tolSi}`,
|
|
85
|
+
stated: statedQ.stated,
|
|
86
|
+
stated_unit: statedQ.stated_unit,
|
|
78
87
|
in_band,
|
|
79
88
|
});
|
|
80
89
|
}
|
|
@@ -95,7 +104,7 @@ export function evaluateConditionSets(
|
|
|
95
104
|
const scored: { node_id: string; checks: ConditionCheck[]; distance: number }[] = [];
|
|
96
105
|
for (const n of nodes) {
|
|
97
106
|
const c = (n.content && typeof n.content === "object" ? n.content : {}) as Record<string, any>;
|
|
98
|
-
const payload = (c.payload ?? {}) as {
|
|
107
|
+
const payload = (c.payload ?? {}) as { entries?: (Entry | SiEntry)[] };
|
|
99
108
|
const entries = Array.isArray(payload.entries) ? payload.entries : [];
|
|
100
109
|
if (!entries.length) continue;
|
|
101
110
|
const s = scoreSet(entries, q);
|
|
@@ -117,7 +126,7 @@ export function evaluateConditionSets(
|
|
|
117
126
|
verdict: "fail",
|
|
118
127
|
matched: [],
|
|
119
128
|
nearest: { node_id: nearest.node_id, distance: Number(nearest.distance.toFixed(2)), bands: nearest.checks.map((c) => c.band) },
|
|
120
|
-
checks:
|
|
129
|
+
checks: nearest.checks,
|
|
121
130
|
note: `VERDICT: FAIL — no severity set admits the stated combination. The nearest set is ${nearest.node_id} (bands: ${nearest.checks.map((c) => c.band).join("; ")}). Say the combination is outside the menu and name the nearest set; never soften it.`,
|
|
122
131
|
};
|
|
123
132
|
}
|