@konneal/engine 0.2.178 → 0.2.180

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,6 +1,6 @@
1
1
  import {
2
2
  handleAsk
3
- } from "./chunk-V2QW6EZB.js";
3
+ } from "./chunk-UMF7Y6JH.js";
4
4
  import "./chunk-IRCDOFP4.js";
5
5
  import "./chunk-ROXOL4GF.js";
6
6
  import "./chunk-CLDMP5YH.js";
@@ -2435,6 +2435,8 @@ Certificates are issued per recommendation family \u2014 the register carries no
2435
2435
  }
2436
2436
  const regNote = aggregateNoteText ?? (register ? [registerNote(register.rows), certificateLinks(register.rows)].filter(Boolean).join("\n") : void 0);
2437
2437
  const ops = await operationsLane(env.DB, q2.query);
2438
+ const registerOwns = !!register?.rows?.length;
2439
+ const registerCitation = registerOwns ? [{ docidentifier: `${P().publisher.name}-CS certificate register`, corpus: "register" }] : [];
2438
2440
  if (understanding?.intent === "conversational") {
2439
2441
  const queryHash2 = await sha256Hex(q2.query);
2440
2442
  const messages2 = [
@@ -2831,9 +2833,10 @@ Answer account questions from these records ONLY: name the record when you use i
2831
2833
  },
2832
2834
  text: `${m.anchor} \u2014 ${m.text}`
2833
2835
  }));
2836
+ const passagePool = registerOwns ? [...opsHits, ...hits].filter((h) => !!h.metadata.cert_holder) : [...opsHits, ...hits];
2834
2837
  const { messages, usedHits } = buildMessages(
2835
2838
  q2.query,
2836
- [...opsHits, ...hits],
2839
+ passagePool,
2837
2840
  q2.lang,
2838
2841
  keptHistory,
2839
2842
  // stage-extracted graph facts (GraphRAG) ride the same note channel
@@ -2902,7 +2905,7 @@ Answer account questions from these records ONLY: name the record when you use i
2902
2905
  console.log("user image attached to generation");
2903
2906
  }
2904
2907
  const queryHash = await sha256Hex(q2.query);
2905
- const cites = boundModel ? [modelCitation(boundModel), ...citations(usedHits)] : citations(usedHits);
2908
+ const cites = [...registerCitation, ...boundModel ? [modelCitation(boundModel), ...citations(usedHits)] : citations(usedHits)];
2906
2909
  if (live2) {
2907
2910
  const stream = await generateStream(env, model, messages, routeEffort(routed.route));
2908
2911
  if (stream) {
@@ -2964,14 +2967,14 @@ Answer account questions from these records ONLY: name the record when you use i
2964
2967
  }
2965
2968
  const tq2 = await chargeAnswerTokens(env, bucketId, stats, messageChars(messages), full.length, probeTokensUsed);
2966
2969
  send({ type: "quota", quota: { ...quota, ...tq2, credits: await creditBudget(env, bucketId), credit_estimate: creditPreview } });
2967
- if (withImage && register?.rows?.length && full.includes(refusalAnswer())) {
2970
+ if (register?.rows?.length && full.includes(refusalAnswer())) {
2968
2971
  console.log("blind-answer(stream): regenerating once");
2969
2972
  streamRestarts += 1;
2970
2973
  mark("Re-answering from the register results");
2971
2974
  send({ type: "retry" });
2972
2975
  const regen = await generateStream(env, model, [
2973
2976
  ...messages.slice(0, -1),
2974
- { role: "user", content: "The photograph was attached and the register note lists actual matching certificate rows. Present those rows \u2014 number, holder, model, status, and every document link \u2014 as the answer. Do not claim that nothing was provided." },
2977
+ { role: "user", content: "The certificate register note above lists actual matching certificate rows. Present those rows \u2014 number, holder, model, status, and every document link \u2014 as the answer. Do not claim that nothing was provided." },
2975
2978
  messages[messages.length - 1]
2976
2979
  ], routeEffort(routed.route));
2977
2980
  if (regen) {
@@ -3191,7 +3194,7 @@ Answer account questions from these records ONLY: name the record when you use i
3191
3194
  telemetry(env, ctx, tier, "ask", model, false, 0, queryHash, q2.lang, void 0, telemetryMeta());
3192
3195
  return err(502, "generation_failed", "The generation model is unavailable; please retry.");
3193
3196
  }
3194
- const finalCites = boundModel ? [modelCitation(boundModel), ...citations(used)] : citations(used);
3197
+ const finalCites = [...registerCitation, ...boundModel ? [modelCitation(boundModel), ...citations(used)] : citations(used)];
3195
3198
  const c2ns = answer.includes(refusalAnswer()) ? { text: answer, blocks: [], dropped: [] } : await contractV2(env.DB, answer, used);
3196
3199
  answer = c2ns.text;
3197
3200
  const finalAnchors = answer.includes(refusalAnswer()) ? { total: 0, violations: [] } : checkQuoteAnchors(answer, used.map((h) => h.text));
@@ -3204,12 +3207,12 @@ Answer account questions from these records ONLY: name the record when you use i
3204
3207
  if (completionBlocks.length) console.log("contract completion:", completionBlocks.length, "table block(s) attached server-side");
3205
3208
  }
3206
3209
  completionBlocks.push(...await completeFigures(env.DB, answer, [...c2ns.blocks, ...completionBlocks], used, q2.query));
3207
- if (withImage && register?.rows?.length && answer.includes(refusalAnswer())) {
3210
+ if (register?.rows?.length && answer.includes(refusalAnswer())) {
3208
3211
  console.log("blind-answer: the register note carried rows but the answer refused \u2014 regenerating once");
3209
3212
  mark("Re-answering from the register results");
3210
3213
  const regen = await generateOnce(env, model, [
3211
3214
  ...messages.slice(0, -1),
3212
- { role: "user", content: "The photograph was attached and the register note lists actual matching certificate rows. Present those rows \u2014 number, holder, model, status, and every document link \u2014 as the answer. Do not claim that nothing was provided." },
3215
+ { role: "user", content: "The certificate register note above lists actual matching certificate rows. Present those rows \u2014 number, holder, model, status, and every document link \u2014 as the answer. Do not claim that nothing was provided." },
3213
3216
  messages[messages.length - 1]
3214
3217
  ], effort);
3215
3218
  if (regen && !regen.includes(refusalAnswer())) {
@@ -4,7 +4,7 @@ import {
4
4
  handleMemories,
5
5
  scoreFaithfulness,
6
6
  scoreJudge
7
- } from "../../chunk-V2QW6EZB.js";
7
+ } from "../../chunk-UMF7Y6JH.js";
8
8
  import "../../chunk-IRCDOFP4.js";
9
9
  import {
10
10
  TOOLS_REGISTRY,
@@ -1181,7 +1181,7 @@ async function callToolOnce(env, ctx, _req, tier, key, name, args, t0) {
1181
1181
  const r = await runTool({ ...env, DB: env.DB }, { name, args }, "mcp");
1182
1182
  payload = r ? { tool: r.name, query: r.query, result: r.output } : { error: { message: `tool ${name} returned nothing for the given arguments` } };
1183
1183
  } else {
1184
- const res = name === "ask" ? await (await import("../../ask-64HJTVPS.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-KNPPTHMG.js")).handleSearch(env, ctx, inner, tier, key);
1184
+ const res = name === "ask" ? await (await import("../../ask-TOJKDMU7.js")).handleAsk(env, ctx, inner, tier, key) : await (await import("../../search-KNPPTHMG.js")).handleSearch(env, ctx, inner, tier, key);
1185
1185
  payload = await res.json().catch(() => ({ error: { message: "tool transport failed", status: res.status } }));
1186
1186
  }
1187
1187
  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.178",
30
+ "version": "0.2.180",
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",
@@ -914,6 +914,21 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
914
914
  const regNote = aggregateNoteText
915
915
  ?? (register ? [registerNote(register.rows), certificateLinks(register.rows)].filter(Boolean).join("\n") : undefined);
916
916
  const ops = await operationsLane(env.DB, q.query);
917
+ // The register lane owns the answer surface when it holds rows — the
918
+ // aggregate path's philosophy (the note answers the structure, the
919
+ // model narrates) extended to the standing lane. Measured 2026-10-28:
920
+ // one note among fifteen system notes loses to the retrieval volume —
921
+ // 11/14 standing probes answered the corpus-refusal template WITH the
922
+ // note in the prompt (the photo path already knew this: its
923
+ // refusal-rescue at the answer gates exists for exactly this shape).
924
+ // The passage pool narrows to the certificate plane's own chunks (the
925
+ // register's digitalized documents, metadata cert_holder); when the
926
+ // dense lane missed them the note alone carries the answer — it says
927
+ // so itself.
928
+ const registerOwns = !!register?.rows?.length;
929
+ const registerCitation = registerOwns
930
+ ? [{ docidentifier: `${P().publisher.name}-CS certificate register`, corpus: "register" }]
931
+ : [];
917
932
 
918
933
  // Conversational route, decided by query UNDERSTANDING (any language, any
919
934
  // phrasing) — not string matching. No retrieval: nothing in the corpus
@@ -1499,9 +1514,23 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
1499
1514
  },
1500
1515
  text: `${m.anchor} — ${m.text}`,
1501
1516
  }));
1517
+ // The register lane owns the answer surface when it holds rows — the
1518
+ // aggregate path's philosophy (the note answers the structure, the
1519
+ // model narrates) extended to the standing lane. Measured 2026-10-28:
1520
+ // one note among fifteen system notes loses to the retrieval volume —
1521
+ // 11/14 standing probes answered the corpus-refusal template WITH the
1522
+ // note in the prompt (the photo path already knew this: its
1523
+ // refusal-rescue at the answer gates exists for exactly this shape).
1524
+ // The passage pool narrows to the certificate plane's own chunks (the
1525
+ // register's digitalized documents, metadata cert_holder); when the
1526
+ // dense lane missed them the note alone carries the answer — it says
1527
+ // so itself.
1528
+ const passagePool = registerOwns
1529
+ ? [...opsHits, ...hits].filter((h) => !!(h.metadata as any).cert_holder)
1530
+ : [...opsHits, ...hits];
1502
1531
  const { messages, usedHits } = buildMessages(
1503
1532
  q.query,
1504
- [...opsHits, ...hits],
1533
+ passagePool,
1505
1534
  q.lang,
1506
1535
  keptHistory,
1507
1536
  // stage-extracted graph facts (GraphRAG) ride the same note channel
@@ -1623,8 +1652,10 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
1623
1652
  const queryHash = await sha256Hex(q.query);
1624
1653
  // The bound model node leads the citations (TODO.ai-platform/05): the
1625
1654
  // panel's first citation card IS the model node — its constraint, its
1626
- // provenance — ahead of the prose passages.
1627
- const cites = boundModel ? [modelCitation(boundModel), ...citations(usedHits)] : citations(usedHits);
1655
+ // provenance — ahead of the prose passages. The register rides first
1656
+ // when it owns the answer (the standing citation the aggregate path
1657
+ // has always attached).
1658
+ const cites = [...registerCitation, ...(boundModel ? [modelCitation(boundModel), ...citations(usedHits)] : citations(usedHits))];
1628
1659
 
1629
1660
  if (live) {
1630
1661
  const stream = await generateStream(env, model, messages, routeEffort(routed.route));
@@ -1691,20 +1722,23 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
1691
1722
  const tq = await chargeAnswerTokens(env, bucketId, stats, messageChars(messages!), full.length, probeTokensUsed);
1692
1723
  send({ type: "quota", quota: { ...quota, ...tq, credits: await creditBudget(env, bucketId), credit_estimate: creditPreview } });
1693
1724
  // the blind-answer guard ON THE STREAM PATH (the JSON path has
1694
- // had it since 0.2.80): an image rode the turn, the register
1695
- // note carries rows, and the streamed text is the no-information
1696
- // refusal — the multimodal call answered around the photograph.
1697
- // One bounded regeneration: the retry sentinel tells the client
1698
- // to clear the buffer, the agent step says why, and the fresh
1699
- // tokens stream as the answer.
1700
- if (withImage && register?.rows?.length && full.includes(refusalAnswer())) {
1725
+ // had it since 0.2.80): the register note carries rows and the
1726
+ // streamed text is the no-information refusal — the model
1727
+ // answered around the register (originally the photograph's
1728
+ // shape; since 0.2.179 the note rides every register-owned
1729
+ // question, and the text-only lane refuses just the same —
1730
+ // measured 2026-10-29: 11/14 standing probes with the note in
1731
+ // the prompt). One bounded regeneration: the retry sentinel
1732
+ // tells the client to clear the buffer, the agent step says
1733
+ // why, and the fresh tokens stream as the answer.
1734
+ if (register?.rows?.length && full.includes(refusalAnswer())) {
1701
1735
  console.log("blind-answer(stream): regenerating once");
1702
1736
  streamRestarts += 1;
1703
1737
  mark("Re-answering from the register results");
1704
1738
  send({ type: "retry" });
1705
1739
  const regen = await generateStream(env, model, [
1706
1740
  ...messages.slice(0, -1),
1707
- { role: "user", content: "The photograph was attached and the register note lists actual matching certificate rows. Present those rows — number, holder, model, status, and every document link — as the answer. Do not claim that nothing was provided." },
1741
+ { role: "user", content: "The certificate register note above lists actual matching certificate rows. Present those rows — number, holder, model, status, and every document link — as the answer. Do not claim that nothing was provided." },
1708
1742
  messages[messages.length - 1],
1709
1743
  ], routeEffort(routed.route));
1710
1744
  if (regen) {
@@ -2021,7 +2055,7 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
2021
2055
  telemetry(env, ctx, tier, "ask", model, false, 0, queryHash, q.lang, undefined, telemetryMeta());
2022
2056
  return err(502, "generation_failed", "The generation model is unavailable; please retry.");
2023
2057
  }
2024
- const finalCites = boundModel ? [modelCitation(boundModel!), ...citations(used)] : citations(used);
2058
+ const finalCites = [...registerCitation, ...(boundModel ? [modelCitation(boundModel!), ...citations(used)] : citations(used))];
2025
2059
  const c2ns = answer!.includes(refusalAnswer())
2026
2060
  ? { text: answer, blocks: [] as Awaited<ReturnType<typeof contractV2>>["blocks"], dropped: [] as string[] }
2027
2061
  : await contractV2(env.DB, answer!, used);
@@ -2053,12 +2087,12 @@ let convEntities: Array<{ entity: string; kind: string }> = [];
2053
2087
  // text claims nothing was provided — while the bridge succeeded and the
2054
2088
  // register note carries actual rows. One bounded regeneration, decided on
2055
2089
  // that exact signature; the retry carries a sterner ground instruction.
2056
- if (withImage && register?.rows?.length && answer!.includes(refusalAnswer())) {
2090
+ if (register?.rows?.length && answer!.includes(refusalAnswer())) {
2057
2091
  console.log("blind-answer: the register note carried rows but the answer refused — regenerating once");
2058
2092
  mark("Re-answering from the register results");
2059
2093
  const regen = await generateOnce(env, model, [
2060
2094
  ...messages.slice(0, -1),
2061
- { role: "user", content: "The photograph was attached and the register note lists actual matching certificate rows. Present those rows — number, holder, model, status, and every document link — as the answer. Do not claim that nothing was provided." },
2095
+ { role: "user", content: "The certificate register note above lists actual matching certificate rows. Present those rows — number, holder, model, status, and every document link — as the answer. Do not claim that nothing was provided." },
2062
2096
  messages[messages.length - 1],
2063
2097
  ], effort);
2064
2098
  if (regen && !regen!.includes(refusalAnswer())) {