@konneal/engine 0.2.92 → 0.2.93

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,7 +1,7 @@
1
1
  import {
2
2
  handleAsk
3
- } from "./chunk-EHABW23I.js";
4
- import "./chunk-QBWZ6HVP.js";
3
+ } from "./chunk-WZKLWK7E.js";
4
+ import "./chunk-PE2D5MFD.js";
5
5
  import "./chunk-3BL223VD.js";
6
6
  import "./chunk-LOBYXEVD.js";
7
7
  import "./chunk-SPKPH54J.js";
@@ -851,6 +851,63 @@ var conditionsCheck = {
851
851
  }
852
852
  }
853
853
  };
854
+ var bibEntry = {
855
+ name: "bib.entry",
856
+ description: "Fetch the bibliographic registry record for a citation label: every edition document under it with derived status (in-force/superseded, the ACTIVE flag), the relation edges (successor, amends, variant), and its outgoing citations. Use after graph.cites to resolve a cited label to its own record.",
857
+ params: [
858
+ { key: "label", required: true, description: "the citation label exactly as graph.cites returns it, e.g. ISO 8601" }
859
+ ],
860
+ audiences: ["mcp"],
861
+ handler: async (env, args) => {
862
+ const label = String(args?.label ?? "").trim();
863
+ if (label.length < 2) return null;
864
+ try {
865
+ const rows = await env.DB.prepare(
866
+ "SELECT id, kind, label FROM graph_nodes WHERE label = ?1 COLLATE NOCASE LIMIT 5"
867
+ ).bind(label).all();
868
+ const nodes = rows.results ?? [];
869
+ if (!nodes.length) {
870
+ return { name: "bib.entry", query: label, output: `No registry node carries the label "${label}". State this plainly.` };
871
+ }
872
+ const out = [];
873
+ for (const n of nodes) {
874
+ const entry = { label: n.label, kind: n.kind };
875
+ if (n.kind === "doc") {
876
+ const d = await env.DB.prepare(
877
+ "SELECT docidentifier, family, part, edition, derived_status, active, superseded_by, title FROM documents WHERE canonical_id = ?1"
878
+ ).bind(n.id).all();
879
+ const doc = (d.results ?? [])[0];
880
+ if (doc) {
881
+ entry.document = {
882
+ docidentifier: doc.docidentifier,
883
+ family: doc.family,
884
+ part: doc.part,
885
+ edition: doc.edition,
886
+ status: doc.derived_status,
887
+ active: !!doc.active,
888
+ superseded_by: doc.superseded_by,
889
+ title: doc.title
890
+ };
891
+ }
892
+ }
893
+ const rel = await env.DB.prepare(
894
+ "SELECT e.kind, n.label AS target FROM graph_edges e JOIN graph_nodes n ON e.dst = n.id WHERE e.src = ?1 LIMIT 25"
895
+ ).bind(n.id).all();
896
+ const relations = rel.results ?? [];
897
+ if (relations.length) entry.relations = relations;
898
+ const cites = await env.DB.prepare(
899
+ "SELECT n.label AS cited FROM graph_edges e JOIN graph_nodes n ON e.dst = n.id WHERE e.src = ?1 AND e.kind = 'cites' LIMIT 40"
900
+ ).bind(n.id).all();
901
+ const cited = (cites.results ?? []).map((r) => r.cited).filter(Boolean);
902
+ if (cited.length) entry.cites = cited;
903
+ out.push(entry);
904
+ }
905
+ return { name: "bib.entry", query: label, output: JSON.stringify(out) };
906
+ } catch {
907
+ return null;
908
+ }
909
+ }
910
+ };
854
911
  var glossaryLookup = {
855
912
  name: "glossary.lookup",
856
913
  description: "Look up a defined term in the terminology datasets \u2014 the concept's definition and its defining publication. Bind everyday words to the defined term before interpreting a question.",
@@ -919,7 +976,7 @@ var certificatesSearch = {
919
976
  return { name: "certificates.search", query, output };
920
977
  }
921
978
  };
922
- var TOOLS_REGISTRY = [certificatesSearch, unitsGet, graphCites, docsSection, glossaryLookup, documentsFamily, licensedSection, verdictEvaluate, conditionsCheck];
979
+ var TOOLS_REGISTRY = [certificatesSearch, unitsGet, graphCites, docsSection, glossaryLookup, documentsFamily, licensedSection, verdictEvaluate, conditionsCheck, bibEntry];
923
980
  var TOOL_DECLARATION = [
924
981
  "You may use one tool before answering, by writing a single line:",
925
982
  ...TOOLS_REGISTRY.filter((t) => t.audiences.includes("agent")).map((t) => {
@@ -18,7 +18,7 @@ import {
18
18
  tableRetyped,
19
19
  toolNote,
20
20
  verdictNote
21
- } from "./chunk-QBWZ6HVP.js";
21
+ } from "./chunk-PE2D5MFD.js";
22
22
  import {
23
23
  NO_CONTEXT,
24
24
  answerQuality,
@@ -4,7 +4,7 @@ import {
4
4
  parseToolCall,
5
5
  runTool,
6
6
  toolNote
7
- } from "./chunk-QBWZ6HVP.js";
7
+ } from "./chunk-PE2D5MFD.js";
8
8
  import "./chunk-LOBYXEVD.js";
9
9
  import "./chunk-LVZTWUVJ.js";
10
10
  import "./chunk-2PCUAJJO.js";
@@ -6,4 +6,5 @@ export declare const documentsFamily: ToolSpec;
6
6
  export declare const licensedSection: ToolSpec;
7
7
  export declare const verdictEvaluate: ToolSpec;
8
8
  export declare const conditionsCheck: ToolSpec;
9
+ export declare const bibEntry: ToolSpec;
9
10
  export declare const glossaryLookup: ToolSpec;
@@ -4,12 +4,12 @@ import {
4
4
  handleMemories,
5
5
  scoreFaithfulness,
6
6
  scoreJudge
7
- } from "../../chunk-EHABW23I.js";
7
+ } from "../../chunk-WZKLWK7E.js";
8
8
  import {
9
9
  TOOLS_REGISTRY,
10
10
  bindModelNode,
11
11
  modelGroundingBlock
12
- } from "../../chunk-QBWZ6HVP.js";
12
+ } from "../../chunk-PE2D5MFD.js";
13
13
  import {
14
14
  handleSearch
15
15
  } from "../../chunk-TJTEBS4S.js";
@@ -973,12 +973,12 @@ async function handleMcp(env, ctx, req, tier, key) {
973
973
  // stream:false forces the JSON lane (anon defaults to SSE)
974
974
  body: JSON.stringify({ ...args, stream: false })
975
975
  });
976
- const { runTool, TOOLS_REGISTRY: TOOLS_REGISTRY2 } = await import("../../tools-PI7IXAL4.js");
976
+ const { runTool, TOOLS_REGISTRY: TOOLS_REGISTRY2 } = await import("../../tools-SVP6MKBR.js");
977
977
  if (TOOLS_REGISTRY2.some((t) => t.name === name && t.audiences.includes("mcp"))) {
978
978
  const r = await runTool({ ...env, DB: env.DB }, { name, args }, "mcp");
979
979
  return r ? { tool: r.name, query: r.query, result: r.output } : { error: { message: `tool ${name} returned nothing for the given arguments` } };
980
980
  }
981
- const res = name === "ask" ? await (await import("../../ask-UG5UYRJV.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-G76DK4AF.js")).handleSearch(env, ctx, inner, tier, key);
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
982
  return res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
983
983
  });
984
984
  if (out.ok && "accepted" in out) return new Response(null, { status: 202 });
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.92",
30
+ "version": "0.2.93",
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",
@@ -339,6 +339,79 @@ export const conditionsCheck: ToolSpec = {
339
339
  },
340
340
  };
341
341
 
342
+
343
+ // The bibliography record (the owner's 2026-10-04 direction): the full
344
+ // registry entry for one citation label — what documents exist under
345
+ // it, their derived status, the successor/amends/variant edges, and
346
+ // what it cites and is cited by. graph.cites names the labels; this is
347
+ // the record behind the label, for agents that cite properly.
348
+ export const bibEntry: ToolSpec = {
349
+ name: "bib.entry",
350
+ description:
351
+ "Fetch the bibliographic registry record for a citation label: every edition document under it with derived status (in-force/superseded, the ACTIVE flag), the relation edges (successor, amends, variant), and its outgoing citations. Use after graph.cites to resolve a cited label to its own record.",
352
+ params: [
353
+ { key: "label", required: true, description: "the citation label exactly as graph.cites returns it, e.g. ISO 8601" },
354
+ ],
355
+ audiences: ["mcp"],
356
+ handler: async (env, args) => {
357
+ const label = String(args?.label ?? "").trim();
358
+ if (label.length < 2) return null;
359
+ try {
360
+ const rows = await env.DB.prepare(
361
+ "SELECT id, kind, label FROM graph_nodes WHERE label = ?1 COLLATE NOCASE LIMIT 5",
362
+ )
363
+ .bind(label)
364
+ .all();
365
+ const nodes = ((rows.results ?? []) as { id: string; kind: string; label: string }[]);
366
+ if (!nodes.length) {
367
+ return { name: "bib.entry", query: label, output: `No registry node carries the label "${label}". State this plainly.` };
368
+ }
369
+ const out: unknown[] = [];
370
+ for (const n of nodes) {
371
+ const entry: Record<string, unknown> = { label: n.label, kind: n.kind };
372
+ if (n.kind === "doc") {
373
+ const d = await env.DB.prepare(
374
+ "SELECT docidentifier, family, part, edition, derived_status, active, superseded_by, title FROM documents WHERE canonical_id = ?1",
375
+ )
376
+ .bind(n.id)
377
+ .all();
378
+ const doc = (d.results ?? [])[0] as Record<string, unknown> | undefined;
379
+ if (doc) {
380
+ entry.document = {
381
+ docidentifier: doc.docidentifier,
382
+ family: doc.family,
383
+ part: doc.part,
384
+ edition: doc.edition,
385
+ status: doc.derived_status,
386
+ active: !!doc.active,
387
+ superseded_by: doc.superseded_by,
388
+ title: doc.title,
389
+ };
390
+ }
391
+ }
392
+ const rel = await env.DB.prepare(
393
+ "SELECT e.kind, n.label AS target FROM graph_edges e JOIN graph_nodes n ON e.dst = n.id WHERE e.src = ?1 LIMIT 25",
394
+ )
395
+ .bind(n.id)
396
+ .all();
397
+ const relations = ((rel.results ?? []) as { kind: string; target: string }[]);
398
+ if (relations.length) entry.relations = relations;
399
+ const cites = await env.DB.prepare(
400
+ "SELECT n.label AS cited FROM graph_edges e JOIN graph_nodes n ON e.dst = n.id WHERE e.src = ?1 AND e.kind = 'cites' LIMIT 40",
401
+ )
402
+ .bind(n.id)
403
+ .all();
404
+ const cited = ((cites.results ?? []) as { cited: string }[]).map((r) => r.cited).filter(Boolean);
405
+ if (cited.length) entry.cites = cited;
406
+ out.push(entry);
407
+ }
408
+ return { name: "bib.entry", query: label, output: JSON.stringify(out) };
409
+ } catch {
410
+ return null;
411
+ }
412
+ },
413
+ };
414
+
342
415
  export const glossaryLookup: ToolSpec = {
343
416
  name: "glossary.lookup",
344
417
  description:
@@ -64,9 +64,9 @@ const certificatesSearch: ToolSpec = {
64
64
  },
65
65
  };
66
66
 
67
- import { unitsGet, graphCites, docsSection, glossaryLookup, documentsFamily, licensedSection, verdictEvaluate, conditionsCheck } from "./tools-content.ts";
67
+ import { unitsGet, graphCites, docsSection, glossaryLookup, documentsFamily, licensedSection, verdictEvaluate, conditionsCheck, bibEntry } from "./tools-content.ts";
68
68
 
69
- export const TOOLS_REGISTRY: ToolSpec[] = [certificatesSearch, unitsGet, graphCites, docsSection, glossaryLookup, documentsFamily, licensedSection, verdictEvaluate, conditionsCheck];
69
+ export const TOOLS_REGISTRY: ToolSpec[] = [certificatesSearch, unitsGet, graphCites, docsSection, glossaryLookup, documentsFamily, licensedSection, verdictEvaluate, conditionsCheck, bibEntry];
70
70
 
71
71
  /** The agent loop's protocol declaration, GENERATED from the registry —
72
72
  * the model's tool vocabulary is always the registry's, never a