@konneal/engine 0.2.93 → 0.2.95

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-WZKLWK7E.js";
4
- import "./chunk-PE2D5MFD.js";
5
- import "./chunk-3BL223VD.js";
3
+ } from "./chunk-CX3OVN3V.js";
4
+ import "./chunk-AJU6LMY3.js";
5
+ import "./chunk-PTCDEFI3.js";
6
6
  import "./chunk-LOBYXEVD.js";
7
7
  import "./chunk-SPKPH54J.js";
8
8
  import "./chunk-A3QHHUN5.js";
@@ -148,9 +148,11 @@ async function bindModelNode(env, opts) {
148
148
  };
149
149
  if (opts.standard) return gate(await fetchNode(env, opts.standard, nodeId));
150
150
  try {
151
- const rows = await env.DB.prepare("SELECT standard FROM model_nodes WHERE node_id = ?1 LIMIT 2").bind(nodeId).all();
152
- const standards = (rows?.results ?? []).map((r) => String(r.standard));
153
- if (standards.length === 1) return gate(await fetchNode(env, standards[0], nodeId));
151
+ const rows = await env.DB.prepare(
152
+ "SELECT n.standard AS standard FROM model_nodes n LEFT JOIN model_plane_meta m ON m.standard = n.standard WHERE n.node_id = ?1 ORDER BY m.indexed_at DESC, n.standard DESC LIMIT 1"
153
+ ).bind(nodeId).all();
154
+ const standard = (rows?.results ?? []).map((r) => String(r.standard))[0];
155
+ if (standard) return gate(await fetchNode(env, standard, nodeId));
154
156
  return null;
155
157
  } catch {
156
158
  return null;
@@ -754,17 +756,17 @@ var verdictEvaluate = {
754
756
  description: "Deterministically evaluate a model-plane node's machine checks (OCL boolean expressions, threshold limits) against the quantities a question states. Returns pass/fail with every check's expression and values, or void with the missing parameter names when the question does not state enough. The machine computes; cite the node's clause.",
755
757
  params: [
756
758
  { key: "node_id", required: true, description: "the model-plane node id, e.g. /req/metrological/repeatability (node ids appear in answers' verdict blocks)" },
757
- { key: "question", required: true, description: "the statement carrying the quantities, e.g. 'is mpe 0.02 with n_lc 3000 within the limit?'" }
759
+ { key: "question", required: true, description: "the statement carrying the quantities, e.g. 'is mpe 0.02 with n_lc 3000 within the limit?'" },
760
+ { key: "standard", required: false, description: "the package id when the node id indexes under several standards, as the ambiguity message names it" }
758
761
  ],
759
762
  audiences: ["mcp"],
760
763
  handler: async (env, args) => {
761
764
  const node_id = String(args?.node_id ?? "").trim();
762
765
  const question = String(args?.question ?? "").trim();
766
+ const standard = args?.standard ? String(args.standard).trim() : null;
763
767
  if (!node_id.startsWith("/") || question.length < 4) return null;
764
768
  try {
765
- const rows = await env.DB.prepare(
766
- "SELECT standard, kind, name, content FROM model_nodes WHERE node_id = ?1 LIMIT 2"
767
- ).bind(node_id).all();
769
+ const rows = standard ? await env.DB.prepare("SELECT standard, kind, name, content FROM model_nodes WHERE node_id = ?1 AND standard = ?2 LIMIT 2").bind(node_id, standard).all() : await env.DB.prepare("SELECT standard, kind, name, content FROM model_nodes WHERE node_id = ?1 LIMIT 2").bind(node_id).all();
768
770
  const found = rows.results ?? [];
769
771
  if (found.length !== 1) {
770
772
  return {
@@ -865,7 +867,17 @@ var bibEntry = {
865
867
  const rows = await env.DB.prepare(
866
868
  "SELECT id, kind, label FROM graph_nodes WHERE label = ?1 COLLATE NOCASE LIMIT 5"
867
869
  ).bind(label).all();
868
- const nodes = rows.results ?? [];
870
+ let nodes = rows.results ?? [];
871
+ if (!nodes.length) {
872
+ const d = await env.DB.prepare(
873
+ "SELECT canonical_id, docidentifier FROM documents WHERE docidentifier = ?1 COLLATE NOCASE LIMIT 5"
874
+ ).bind(label).all();
875
+ nodes = (d.results ?? []).map((r) => ({
876
+ id: r.canonical_id,
877
+ kind: "doc",
878
+ label: r.docidentifier
879
+ }));
880
+ }
869
881
  if (!nodes.length) {
870
882
  return { name: "bib.entry", query: label, output: `No registry node carries the label "${label}". State this plainly.` };
871
883
  }
@@ -18,7 +18,7 @@ import {
18
18
  tableRetyped,
19
19
  toolNote,
20
20
  verdictNote
21
- } from "./chunk-PE2D5MFD.js";
21
+ } from "./chunk-AJU6LMY3.js";
22
22
  import {
23
23
  NO_CONTEXT,
24
24
  answerQuality,
@@ -56,7 +56,7 @@ import {
56
56
  tokenBudget,
57
57
  understandQuery,
58
58
  usageTotal
59
- } from "./chunk-3BL223VD.js";
59
+ } from "./chunk-PTCDEFI3.js";
60
60
  import {
61
61
  embed,
62
62
  generateOnce,
@@ -2166,6 +2166,7 @@ ${summary}` }] : [],
2166
2166
  if (aggregationVerdict) console.log("aggregation engine:", aggregationVerdict.operation, aggregationVerdict.table, "\u2192", aggregationVerdict.value);
2167
2167
  let boundaryNote = null;
2168
2168
  let boundaryBoost;
2169
+ let licensedDocNumbers;
2169
2170
  let editionBoost;
2170
2171
  try {
2171
2172
  const fam = understanding?.doc ? refCodec().familyOf(understanding.doc) : null;
@@ -2178,7 +2179,9 @@ ${summary}` }] : [],
2178
2179
  const lexicalBoost = [boundaryBoost, editionBoost].filter(Boolean).join(" ") || void 0;
2179
2180
  if (P().sources?.licensed?.length) {
2180
2181
  const match = matchLicensedTopic(q.query, P().sources.licensed);
2181
- if (match && !(standardKeys?.has(match.entry.key) ?? false)) {
2182
+ if (match && (standardKeys?.has(match.entry.key) ?? false)) {
2183
+ licensedDocNumbers = match.entry.package ? [match.entry.package] : void 0;
2184
+ } else if (match && !(standardKeys?.has(match.entry.key) ?? false)) {
2182
2185
  const docNum = match.entry.doc_number ?? "";
2183
2186
  boundaryBoost = docNum || void 0;
2184
2187
  let citing = [];
@@ -2227,7 +2230,8 @@ Answer account questions from these records ONLY: name the record when you use i
2227
2230
  optimisticVec,
2228
2231
  datasetScope: narrowed ? corpora : null,
2229
2232
  standardKeys,
2230
- lexicalBoost
2233
+ lexicalBoost,
2234
+ licensedDocNumbers
2231
2235
  });
2232
2236
  stageTiming["retrieve-core"] = Date.now() - tR;
2233
2237
  console.log("stage: retrieve", Date.now() - tR, "ms");
@@ -22522,6 +22522,33 @@ var graphLane = {
22522
22522
  }
22523
22523
  };
22524
22524
 
22525
+ // workers/worker_public/src/stages/licensedLane.ts
22526
+ var licensedLane = {
22527
+ name: "licensed-lane",
22528
+ failure: "additive",
22529
+ when: (c) => !!c.opts.licensedDocNumbers?.length && c.vector.length > 0,
22530
+ prefetch: (c) => {
22531
+ c.lane["licensed-lane"] = portIndex(c.env, "public").query({
22532
+ vector: c.vector,
22533
+ topK: 12,
22534
+ filter: { standard: { $in: c.opts.licensedDocNumbers } }
22535
+ });
22536
+ },
22537
+ run: async (c) => {
22538
+ const g = await c.lane["licensed-lane"];
22539
+ const seenIds = new Set(c.matches.map((m) => m.id));
22540
+ let merged = 0;
22541
+ for (const m of (g ?? []).slice(0, 10)) {
22542
+ if (!seenIds.has(m.id)) {
22543
+ c.matches.push({ id: m.id, score: m.score * THRESHOLDS.graphLaneDiscount, metadata: m.metadata });
22544
+ seenIds.add(m.id);
22545
+ merged++;
22546
+ }
22547
+ }
22548
+ console.log("licensed lane:", g?.length ?? 0, "hits,", merged, "merged");
22549
+ }
22550
+ };
22551
+
22525
22552
  // workers/worker_public/src/stages/multiQuery.ts
22526
22553
  var RRF_K = 60;
22527
22554
  var multiQuery = {
@@ -23133,6 +23160,7 @@ var STAGES = [
23133
23160
  glossary,
23134
23161
  conceptGraph,
23135
23162
  graphLane,
23163
+ licensedLane,
23136
23164
  multiQuery,
23137
23165
  subQuery,
23138
23166
  poolOpen,
@@ -6,7 +6,7 @@ import {
6
6
  sessionFrom,
7
7
  telemetry,
8
8
  understandQuery
9
- } from "./chunk-3BL223VD.js";
9
+ } from "./chunk-PTCDEFI3.js";
10
10
  import {
11
11
  portModelRunner
12
12
  } from "./chunk-LOBYXEVD.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  handleSearch
3
- } from "./chunk-TJTEBS4S.js";
4
- import "./chunk-3BL223VD.js";
3
+ } from "./chunk-ZLQMRQOV.js";
4
+ import "./chunk-PTCDEFI3.js";
5
5
  import "./chunk-LOBYXEVD.js";
6
6
  import "./chunk-SPKPH54J.js";
7
7
  import "./chunk-A3QHHUN5.js";
@@ -4,7 +4,7 @@ import {
4
4
  parseToolCall,
5
5
  runTool,
6
6
  toolNote
7
- } from "./chunk-PE2D5MFD.js";
7
+ } from "./chunk-AJU6LMY3.js";
8
8
  import "./chunk-LOBYXEVD.js";
9
9
  import "./chunk-LVZTWUVJ.js";
10
10
  import "./chunk-2PCUAJJO.js";
@@ -4,15 +4,15 @@ import {
4
4
  handleMemories,
5
5
  scoreFaithfulness,
6
6
  scoreJudge
7
- } from "../../chunk-WZKLWK7E.js";
7
+ } from "../../chunk-CX3OVN3V.js";
8
8
  import {
9
9
  TOOLS_REGISTRY,
10
10
  bindModelNode,
11
11
  modelGroundingBlock
12
- } from "../../chunk-PE2D5MFD.js";
12
+ } from "../../chunk-AJU6LMY3.js";
13
13
  import {
14
14
  handleSearch
15
- } from "../../chunk-TJTEBS4S.js";
15
+ } from "../../chunk-ZLQMRQOV.js";
16
16
  import {
17
17
  buildMessages,
18
18
  citations,
@@ -34,7 +34,7 @@ import {
34
34
  sessionFrom,
35
35
  telemetry,
36
36
  understandQuery
37
- } from "../../chunk-3BL223VD.js";
37
+ } from "../../chunk-PTCDEFI3.js";
38
38
  import {
39
39
  cfBlobs,
40
40
  embed,
@@ -967,26 +967,39 @@ async function handleMcp(env, ctx, req, tier, key) {
967
967
  const method = typeof body?.method === "string" ? body.method : null;
968
968
  const id = body?.id ?? null;
969
969
  const out = await dispatch(method, body?.params, async (name, args) => {
970
+ const t0 = Date.now();
971
+ try {
972
+ return await callToolOnce(env, ctx, req, tier, key, name, args, t0);
973
+ } catch (e) {
974
+ telemetry(env, ctx, tier, `mcp:${name}`, null, false, 0, await sha256Hex(`${name}:${JSON.stringify(args ?? {})}`), void 0, void 0, { durationMs: Date.now() - t0 });
975
+ throw e;
976
+ }
977
+ });
978
+ if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
979
+ if (out.ok) {
980
+ if (out.result?.serverInfo) out.result.serverInfo.name = `${P().publisher.id}-rag`;
981
+ return json({ jsonrpc: "2.0", id, result: out.result });
982
+ }
983
+ return json({ jsonrpc: "2.0", id, error: { code: out.code, message: out.message } });
984
+ }
985
+ async function callToolOnce(env, ctx, _req, tier, key, name, args, t0) {
986
+ {
970
987
  const inner = new Request("https://internal/mcp", {
971
988
  method: "POST",
972
989
  headers: { "content-type": "application/json" },
973
990
  // stream:false forces the JSON lane (anon defaults to SSE)
974
991
  body: JSON.stringify({ ...args, stream: false })
975
992
  });
976
- const { runTool, TOOLS_REGISTRY: TOOLS_REGISTRY2 } = await import("../../tools-SVP6MKBR.js");
993
+ const { runTool, TOOLS_REGISTRY: TOOLS_REGISTRY2 } = await import("../../tools-Z4HQH3QU.js");
977
994
  if (TOOLS_REGISTRY2.some((t) => t.name === name && t.audiences.includes("mcp"))) {
978
995
  const r = await runTool({ ...env, DB: env.DB }, { name, args }, "mcp");
979
996
  return r ? { tool: r.name, query: r.query, result: r.output } : { error: { message: `tool ${name} returned nothing for the given arguments` } };
980
997
  }
981
- const res = name === "ask" ? await (await import("../../ask-RP2Z7CIV.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-G76DK4AF.js")).handleSearch(env, ctx, inner, tier, key);
982
- return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
983
- });
984
- if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
985
- if (out.ok) {
986
- if (out.result?.serverInfo) out.result.serverInfo.name = `${P().publisher.id}-rag`;
987
- return json({ jsonrpc: "2.0", id, result: out.result });
998
+ const res = name === "ask" ? await (await import("../../ask-KKOQH7HK.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-CGQFGYTR.js")).handleSearch(env, ctx, inner, tier, key);
999
+ const payload = await res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
1000
+ 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 });
1001
+ return payload;
988
1002
  }
989
- return json({ jsonrpc: "2.0", id, error: { code: out.code, message: out.message } });
990
1003
  }
991
1004
 
992
1005
  // workers/shared/router.ts
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.93",
30
+ "version": "0.2.95",
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",
@@ -1017,6 +1017,7 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
1017
1017
  // publication's own clause — surface for a question the document's
1018
1018
  // vocabulary alone would miss
1019
1019
  let boundaryBoost: string | undefined;
1020
+ let licensedDocNumbers: string[] | undefined;
1020
1021
  // the EDITION boost: the grounding pool tilts to the publication's
1021
1022
  // ACTIVE edition (the graph's own registry) — the dirty corpus's
1022
1023
  // superseded editions otherwise outrank the current ones on shared
@@ -1037,7 +1038,11 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
1037
1038
  const lexicalBoost = [boundaryBoost, editionBoost].filter(Boolean).join(" ") || undefined;
1038
1039
  if (P().sources?.licensed?.length) {
1039
1040
  const match = matchLicensedTopic(q.query, P().sources.licensed);
1040
- if (match && !(standardKeys?.has(match.entry.key) ?? false)) {
1041
+ if (match && (standardKeys?.has(match.entry.key) ?? false)) {
1042
+ // the entitled caller: the licensed lane pulls the package's own
1043
+ // units so they compete with (and outrank) the public restatements
1044
+ licensedDocNumbers = match.entry.package ? [match.entry.package] : undefined;
1045
+ } else if (match && !(standardKeys?.has(match.entry.key) ?? false)) {
1041
1046
  const docNum = match.entry.doc_number ?? "";
1042
1047
  boundaryBoost = docNum || undefined;
1043
1048
  let citing: string[] = [];
@@ -1106,7 +1111,7 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
1106
1111
  // publications there).
1107
1112
  retrieved = await retrieve(env, q.query, { prev, understanding, federate, warmEmbed, graphDocNumbers,
1108
1113
  sealScope: declaredScoped ? docScope : null, optimisticHits, optimisticVec,
1109
- datasetScope: narrowed ? corpora : null, standardKeys, lexicalBoost });
1114
+ datasetScope: narrowed ? corpora : null, standardKeys, lexicalBoost, licensedDocNumbers });
1110
1115
  stageTiming["retrieve-core"] = Date.now() - tR;
1111
1116
  console.log("stage: retrieve", Date.now() - tR, "ms");
1112
1117
  // ── TTFT surgery: the two post-retrieval LLM calls run IN PARALLEL —
@@ -6,6 +6,8 @@
6
6
  // mcp-proto.ts (dependency-free, unit-tested). The internal-audience
7
7
  // server federates both indexes and lives in its own worker, never here.
8
8
  import { json, readJson, type ApiKey } from "./lib/http";
9
+ import { sha256Hex } from "./config.ts";
10
+ import { telemetry } from "./quota.ts";
9
11
  import { P } from "./profile.ts";
10
12
  import { dispatch } from "./mcp-proto.ts";
11
13
  import type { Env } from "./env.ts";
@@ -24,6 +26,37 @@ export async function handleMcp(
24
26
  const id = body?.id ?? null;
25
27
 
26
28
  const out = await dispatch(method, body?.params, async (name, args) => {
29
+ const t0 = Date.now();
30
+ try {
31
+ return await callToolOnce(env, ctx, req, tier, key, name, args, t0);
32
+ } catch (e) {
33
+ telemetry(env, ctx, tier, `mcp:${name}`, null, false, 0, await sha256Hex(`${name}:${JSON.stringify(args ?? {})}`), undefined, undefined, { durationMs: Date.now() - t0 });
34
+ throw e;
35
+ }
36
+ });
37
+
38
+ if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
39
+ if (out.ok) {
40
+ if ((out.result as any)?.serverInfo) (out.result as any).serverInfo.name = `${P().publisher.id}-rag`;
41
+ return json({ jsonrpc: "2.0", id, result: out.result });
42
+ }
43
+ return json({ jsonrpc: "2.0", id, error: { code: out.code, message: out.message } });
44
+ }
45
+
46
+ /** One tools/call dispatch, measured: every MCP surface's tool usage
47
+ * lands in the queries table under the mcp:<tool> route — which tools
48
+ * agents actually call becomes countable, per tier, per key. */
49
+ async function callToolOnce(
50
+ env: Env,
51
+ ctx: Background,
52
+ _req: Request,
53
+ tier: "anon" | "key" | "member",
54
+ key: ApiKey | null,
55
+ name: string,
56
+ args: Record<string, unknown>,
57
+ t0: number,
58
+ ) {
59
+ {
27
60
  const inner = new Request("https://internal/mcp", {
28
61
  method: "POST",
29
62
  headers: { "content-type": "application/json" },
@@ -42,13 +75,8 @@ export async function handleMcp(
42
75
  const res = name === "ask"
43
76
  ? await (await import("./ask")).handleAsk(env, ctx as any, inner, tier, key)
44
77
  : await (await import("./search")).handleSearch(env, ctx as any, inner, tier, key);
45
- return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
46
- });
47
-
48
- if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
49
- if (out.ok) {
50
- if ((out.result as any)?.serverInfo) (out.result as any).serverInfo.name = `${P().publisher.id}-rag`;
51
- return json({ jsonrpc: "2.0", id, result: out.result });
78
+ const payload: any = await res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
79
+ telemetry(env, ctx, tier, `mcp:${name}`, null, !payload?.error, JSON.stringify(payload).length, await sha256Hex(`${name}:${JSON.stringify(args ?? {})}`), undefined, undefined, { durationMs: Date.now() - t0 });
80
+ return payload;
52
81
  }
53
- return json({ jsonrpc: "2.0", id, error: { code: out.code, message: out.message } });
54
82
  }
@@ -196,10 +196,22 @@ export async function bindModelNode(
196
196
  };
197
197
  if (opts.standard) return gate(await fetchNode(env, opts.standard, nodeId));
198
198
  try {
199
- const rows = await env.DB.prepare("SELECT standard FROM model_nodes WHERE node_id = ?1 LIMIT 2").bind(nodeId).all();
200
- const standards = (rows?.results ?? []).map((r: any) => String(r.standard));
201
- if (standards.length === 1) return gate(await fetchNode(env, standards[0]!, nodeId));
202
- return null; // zero (not indexed) or ambiguous (several standards) — no silent pick
199
+ // The MECE flip left the retired standards' nodes beside their
200
+ // successors' (the same node id under oiml-r60 and oiml-r60-lml),
201
+ // so ambiguity is the COMMON case now. The plane's own registry
202
+ // breaks the tie: the standard loaded most recently is the
203
+ // canonical layer for that id (the flip's law — the layer owns its
204
+ // units), standard name descending as the deterministic second key;
205
+ // a standard with no meta row (orphaned) sorts last. An id under
206
+ // zero standards still binds to nothing.
207
+ const rows = await env.DB.prepare(
208
+ "SELECT n.standard AS standard FROM model_nodes n LEFT JOIN model_plane_meta m ON m.standard = n.standard WHERE n.node_id = ?1 ORDER BY m.indexed_at DESC, n.standard DESC LIMIT 1",
209
+ )
210
+ .bind(nodeId)
211
+ .all();
212
+ const standard = (rows?.results ?? []).map((r: any) => String(r.standard))[0];
213
+ if (standard) return gate(await fetchNode(env, standard, nodeId));
214
+ return null; // not indexed
203
215
  } catch {
204
216
  return null;
205
217
  }
@@ -17,6 +17,7 @@ import { hyde } from "./hyde.ts";
17
17
  import { glossary } from "./glossary.ts";
18
18
  import { conceptGraph } from "./conceptGraph.ts";
19
19
  import { graphLane } from "./graphLane.ts";
20
+ import { licensedLane } from "./licensedLane.ts";
20
21
  import { multiQuery } from "./multiQuery.ts";
21
22
  import { subQuery } from "./subQuery.ts";
22
23
  import { poolOpen } from "./poolOpen.ts";
@@ -46,6 +47,7 @@ export const STAGES: Stage[] = [
46
47
  glossary,
47
48
  conceptGraph,
48
49
  graphLane,
50
+ licensedLane,
49
51
  multiQuery,
50
52
  subQuery,
51
53
  poolOpen,
@@ -0,0 +1,38 @@
1
+ // Licensed lane (additive): an entitled caller whose question is
2
+ // topically about a licensed standard gets that standard's typed units
3
+ // merged into the pool at the graph lane's discount — the public
4
+ // restatements (the Recommendations' own annexes citing the standard)
5
+ // stop out-ranking the licensed package's own units, the rank-order
6
+ // gap the quality ledger has documented on every damp-heat run since
7
+ // the eleven-standard wave. Unentitled callers never see this lane
8
+ // (license-scope would strip the units anyway — the lane simply does
9
+ // not fire).
10
+ import { THRESHOLDS } from "../config.ts";
11
+ import { portIndex } from "../env.ts";
12
+ import type { Stage } from "./types.ts";
13
+
14
+ export const licensedLane: Stage = {
15
+ name: "licensed-lane",
16
+ failure: "additive",
17
+ when: (c) => !!c.opts.licensedDocNumbers?.length && c.vector.length > 0,
18
+ prefetch: (c) => {
19
+ c.lane["licensed-lane"] = portIndex(c.env, "public").query({
20
+ vector: c.vector,
21
+ topK: 12,
22
+ filter: { standard: { $in: c.opts.licensedDocNumbers } },
23
+ });
24
+ },
25
+ run: async (c) => {
26
+ const g = (await c.lane["licensed-lane"]!) as any;
27
+ const seenIds = new Set(c.matches.map((m: any) => m.id));
28
+ let merged = 0;
29
+ for (const m of (g ?? []).slice(0, 10)) {
30
+ if (!seenIds.has(m.id)) {
31
+ c.matches.push({ id: m.id, score: m.score * THRESHOLDS.graphLaneDiscount, metadata: m.metadata });
32
+ seenIds.add(m.id);
33
+ merged++;
34
+ }
35
+ }
36
+ console.log("licensed lane:", g?.length ?? 0, "hits,", merged, "merged");
37
+ },
38
+ };
@@ -20,6 +20,10 @@ export interface RetrieveOptions {
20
20
  federate?: (query: string) => Promise<Hit[]>;
21
21
  warmEmbed?: Promise<number[] | null>;
22
22
  graphDocNumbers?: string[];
23
+ /** The licensed standards the entitled, topically-matched question
24
+ * pulls (the licensed lane's metadata filter — the package ids, e.g.
25
+ * iec-60068-2-30). Empty/absent for everyone else. */
26
+ licensedDocNumbers?: string[];
23
27
  /** The declared context's HARD seal (TODO.ai-platform/02): when the
24
28
  * panel's chip declares a document scope, the CANDIDATE POOL is cut
25
29
  * to the publication family before rerank + the top-N cut — the
@@ -236,21 +236,22 @@ export const verdictEvaluate: ToolSpec = {
236
236
  params: [
237
237
  { key: "node_id", required: true, description: "the model-plane node id, e.g. /req/metrological/repeatability (node ids appear in answers' verdict blocks)" },
238
238
  { key: "question", required: true, description: "the statement carrying the quantities, e.g. 'is mpe 0.02 with n_lc 3000 within the limit?'" },
239
+ { key: "standard", required: false, description: "the package id when the node id indexes under several standards, as the ambiguity message names it" },
239
240
  ],
240
241
  audiences: ["mcp"],
241
242
  handler: async (env, args) => {
242
243
  const node_id = String(args?.node_id ?? "").trim();
243
244
  const question = String(args?.question ?? "").trim();
245
+ const standard = args?.standard ? String(args.standard).trim() : null;
244
246
  if (!node_id.startsWith("/") || question.length < 4) return null;
245
247
  try {
246
248
  // the same zero-or-ambiguous rule bindModelNode applies: a node
247
249
  // id that indexes under exactly one standard resolves; several
248
- // or none resolve to nothing — no silent pick
249
- const rows = await env.DB.prepare(
250
- "SELECT standard, kind, name, content FROM model_nodes WHERE node_id = ?1 LIMIT 2",
251
- )
252
- .bind(node_id)
253
- .all();
250
+ // or none resolve to nothing — no silent pick (the standard
251
+ // param is the caller's disambiguator)
252
+ const rows = standard
253
+ ? await env.DB.prepare("SELECT standard, kind, name, content FROM model_nodes WHERE node_id = ?1 AND standard = ?2 LIMIT 2").bind(node_id, standard).all()
254
+ : await env.DB.prepare("SELECT standard, kind, name, content FROM model_nodes WHERE node_id = ?1 LIMIT 2").bind(node_id).all();
254
255
  const found = (rows.results ?? []) as { standard: string; kind: string; name: string | null; content: string }[];
255
256
  if (found.length !== 1) {
256
257
  return {
@@ -362,7 +363,22 @@ export const bibEntry: ToolSpec = {
362
363
  )
363
364
  .bind(label)
364
365
  .all();
365
- const nodes = ((rows.results ?? []) as { id: string; kind: string; label: string }[]);
366
+ let nodes = ((rows.results ?? []) as { id: string; kind: string; label: string }[]);
367
+ if (!nodes.length) {
368
+ // the docidentifier form ("OIML R 60:2017") is a documents-
369
+ // registry key, not a graph label (labels are titles) — resolve
370
+ // it through the registry and synthesize the node rows
371
+ const d = await env.DB.prepare(
372
+ "SELECT canonical_id, docidentifier FROM documents WHERE docidentifier = ?1 COLLATE NOCASE LIMIT 5",
373
+ )
374
+ .bind(label)
375
+ .all();
376
+ nodes = ((d.results ?? []) as { canonical_id: string; docidentifier: string }[]).map((r) => ({
377
+ id: r.canonical_id,
378
+ kind: "doc",
379
+ label: r.docidentifier,
380
+ }));
381
+ }
366
382
  if (!nodes.length) {
367
383
  return { name: "bib.entry", query: label, output: `No registry node carries the label "${label}". State this plainly.` };
368
384
  }