@konneal/engine 0.2.168 → 0.2.170

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.
Files changed (31) hide show
  1. package/dist/ablate.d.ts +3 -0
  2. package/dist/ask-BKWQEMSY.js +16 -0
  3. package/dist/{chunk-4FZNJR5Q.js → chunk-5UIMQAJZ.js} +10 -0
  4. package/dist/{chunk-BFOCWZ7U.js → chunk-6KEWBP7O.js} +5 -5
  5. package/dist/{chunk-LSZTJI7V.js → chunk-KINFFYQH.js} +6 -2
  6. package/dist/{chunk-QY556RJM.js → chunk-O2XMNKCK.js} +1 -1
  7. package/dist/{chunk-AGL4NGXY.js → chunk-PO3UBDNZ.js} +224 -12
  8. package/dist/{chunk-Y7LWT24U.js → chunk-PQDAL4MX.js} +1 -1
  9. package/dist/{chunk-PTY2OSC4.js → chunk-QS6V53RO.js} +5 -5
  10. package/dist/{chunk-LIZJLRXZ.js → chunk-RZLEHCIA.js} +4 -4
  11. package/dist/{chunk-LU7VIMD7.js → chunk-XWSZWFYP.js} +1 -1
  12. package/dist/config.d.ts +6 -0
  13. package/dist/decisionWire.d.ts +25 -0
  14. package/dist/decisions.d.ts +39 -0
  15. package/dist/{env-LMHGNJTN.js → env-CNO44VN2.js} +1 -1
  16. package/dist/search-RNCRT5BR.js +14 -0
  17. package/dist/{tools-3RP7DHGI.js → tools-HK5RXHBQ.js} +5 -5
  18. package/dist/worker_mcp/src/index.js +2 -2
  19. package/dist/worker_public/src/config.js +1 -1
  20. package/dist/worker_public/src/index.js +11 -11
  21. package/dist/worker_public/src/requestScope.js +2 -2
  22. package/package.json +1 -1
  23. package/workers/worker_public/src/ablate.ts +6 -2
  24. package/workers/worker_public/src/ask.ts +56 -3
  25. package/workers/worker_public/src/config.ts +10 -0
  26. package/workers/worker_public/src/decisionWire.ts +124 -0
  27. package/workers/worker_public/src/decisions.ts +148 -0
  28. package/workers/worker_public/src/ports/cloudflare/adapters.ts +10 -2
  29. package/workers/worker_public/src/ports/model.ts +8 -1
  30. package/dist/ask-RUMLIO35.js +0 -16
  31. package/dist/search-Y4Y46Y57.js +0 -14
package/dist/ablate.d.ts CHANGED
@@ -18,6 +18,9 @@ export interface AblateConfig {
18
18
  * budget before the answer model reads it. Off in serving; the grid
19
19
  * arms it per ask (the row's accuracy-at-token-budget gate). */
20
20
  compress: boolean;
21
+ /** The decision pass (TODO.decisions/01): per-request stand-down for
22
+ * the measurement — the serving switch is DECISIONS_ENABLED. */
23
+ noDecisions: boolean;
21
24
  }
22
25
  export type AblateParse = {
23
26
  ok: true;
@@ -0,0 +1,16 @@
1
+ import {
2
+ handleAsk
3
+ } from "./chunk-PO3UBDNZ.js";
4
+ import "./chunk-ECOYO7EX.js";
5
+ import "./chunk-QS6V53RO.js";
6
+ import "./chunk-RZLEHCIA.js";
7
+ import "./chunk-XWSZWFYP.js";
8
+ import "./chunk-O2XMNKCK.js";
9
+ import "./chunk-ETLSWSZ7.js";
10
+ import "./chunk-PQDAL4MX.js";
11
+ import "./chunk-5UIMQAJZ.js";
12
+ import "./chunk-3FYJM7LH.js";
13
+ import "./chunk-KINFFYQH.js";
14
+ export {
15
+ handleAsk
16
+ };
@@ -15,6 +15,10 @@ var MODELS = {
15
15
  // vision-capable MoE scores figure IMAGES against figure-seeking
16
16
  // questions — one bounded call per figure question, ablatable stage
17
17
  vlmFigure: "@cf/deepseek-ai/deepseek-v4.1-flash-1017",
18
+ // the decision pass (TODO.decisions/01): clef-flash gates the
19
+ // requirement-shaped questions, clef decides the derived checklist
20
+ decisionsGate: "@cf/cloudflare/clef-flash",
21
+ decisionsModel: "@cf/cloudflare/clef",
18
22
  // hot-path understanding/summarize stays on the cheap Qwen (cost-first lane)
19
23
  understand: "@cf/qwen/qwen3-30b-a3b-fp8",
20
24
  // the api_call act's intent-to-act mapping (TODO.ai-platform/09) — the
@@ -93,6 +97,12 @@ var THRESHOLDS = {
93
97
  // re-query runs at this depth and scopes in code (the native filter is
94
98
  // dead — measured 2026-10-05)
95
99
  denseStarveK: 100,
100
+ // the decision pass (TODO.decisions): the gate fires at decisionsGateMin
101
+ // noul; the bands assemble met / not clearly stated / not met
102
+ decisionsGateMin: 0.5,
103
+ decisionsMetBand: 0.8,
104
+ decisionsRefuteBand: 0.2,
105
+ decisionsRequirementsMax: 12,
96
106
  entailmentGate: true,
97
107
  entailmentBudgetMs: 6e3,
98
108
  entailmentSupportedFloor: 0.9,
@@ -6,27 +6,27 @@ import {
6
6
  sessionFrom,
7
7
  telemetry,
8
8
  understandQuery
9
- } from "./chunk-LIZJLRXZ.js";
9
+ } from "./chunk-RZLEHCIA.js";
10
10
  import {
11
11
  corsHeaders,
12
12
  err,
13
13
  json,
14
14
  readJson,
15
15
  validateQuery
16
- } from "./chunk-QY556RJM.js";
16
+ } from "./chunk-O2XMNKCK.js";
17
17
  import {
18
18
  entitlementScope,
19
19
  standardKeysFrom
20
- } from "./chunk-Y7LWT24U.js";
20
+ } from "./chunk-PQDAL4MX.js";
21
21
  import {
22
22
  LIMITS,
23
23
  MODELS,
24
24
  num,
25
25
  sha256Hex
26
- } from "./chunk-4FZNJR5Q.js";
26
+ } from "./chunk-5UIMQAJZ.js";
27
27
  import {
28
28
  portModelRunner
29
- } from "./chunk-LSZTJI7V.js";
29
+ } from "./chunk-KINFFYQH.js";
30
30
 
31
31
  // workers/worker_public/src/search.ts
32
32
  async function handleSearch(env, ctx, req, tier, key) {
@@ -74,7 +74,7 @@ function cfModelRunner(ai) {
74
74
  return null;
75
75
  },
76
76
  async run(req) {
77
- const res = await ai.run(req.model, {
77
+ const payload = req.input !== void 0 ? req.input : {
78
78
  messages: req.messages,
79
79
  max_tokens: req.maxTokens,
80
80
  ...req.effort ? { reasoning_effort: req.effort } : {},
@@ -82,9 +82,13 @@ function cfModelRunner(ai) {
82
82
  ...req.topP != null ? { top_p: req.topP } : {},
83
83
  ...req.topK != null ? { top_k: req.topK } : {},
84
84
  ...req.stream ? { stream: true } : {}
85
- });
85
+ };
86
+ const res = await ai.run(req.model, payload);
86
87
  if (req.stream && res && typeof res.getReader === "function") return { text: null, stream: res };
87
88
  if (req.stream && res?.body && typeof res.body.getReader === "function") return { text: null, stream: res.body };
89
+ if (res && typeof res === "object" && res.answers && typeof res.answers === "object") {
90
+ return { text: JSON.stringify(res.answers) };
91
+ }
88
92
  const text = typeof res?.response === "string" ? res.response : res?.choices?.[0]?.message?.content;
89
93
  return { text: typeof text === "string" ? text : null };
90
94
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  LIMITS,
3
3
  sha256Hex
4
- } from "./chunk-4FZNJR5Q.js";
4
+ } from "./chunk-5UIMQAJZ.js";
5
5
  import {
6
6
  P
7
7
  } from "./chunk-3FYJM7LH.js";
@@ -32,7 +32,7 @@ import {
32
32
  tableRetyped,
33
33
  toolNote,
34
34
  verdictNote
35
- } from "./chunk-PTY2OSC4.js";
35
+ } from "./chunk-QS6V53RO.js";
36
36
  import {
37
37
  NO_CONTEXT,
38
38
  STAGE_NAMES,
@@ -75,18 +75,18 @@ import {
75
75
  tokenBudget,
76
76
  understandQuery,
77
77
  usageTotal
78
- } from "./chunk-LIZJLRXZ.js";
78
+ } from "./chunk-RZLEHCIA.js";
79
79
  import {
80
80
  embed,
81
81
  generateOnce
82
- } from "./chunk-LU7VIMD7.js";
82
+ } from "./chunk-XWSZWFYP.js";
83
83
  import {
84
84
  corsHeaders,
85
85
  err,
86
86
  json,
87
87
  readJson,
88
88
  validateQuery
89
- } from "./chunk-QY556RJM.js";
89
+ } from "./chunk-O2XMNKCK.js";
90
90
  import {
91
91
  cacheableAnswer,
92
92
  canonicalRefusal,
@@ -99,7 +99,7 @@ import {
99
99
  requestSalt,
100
100
  resolveRequestScope,
101
101
  standardKeysFrom
102
- } from "./chunk-Y7LWT24U.js";
102
+ } from "./chunk-PQDAL4MX.js";
103
103
  import {
104
104
  LIMITS,
105
105
  MODELS,
@@ -110,14 +110,14 @@ import {
110
110
  requestEffort,
111
111
  roleModel,
112
112
  sha256Hex
113
- } from "./chunk-4FZNJR5Q.js";
113
+ } from "./chunk-5UIMQAJZ.js";
114
114
  import {
115
115
  P
116
116
  } from "./chunk-3FYJM7LH.js";
117
117
  import {
118
118
  portModelRunner,
119
119
  portStore
120
- } from "./chunk-LSZTJI7V.js";
120
+ } from "./chunk-KINFFYQH.js";
121
121
 
122
122
  // workers/worker_public/src/internal_gateway.ts
123
123
  async function retrieveInternal(service, auth, query) {
@@ -1404,9 +1404,10 @@ function parseAblate(body, adminToken, presentedToken, knownStages) {
1404
1404
  const rawRoute = body?.ablate_route;
1405
1405
  const speculative = body?.ablate_speculative === true;
1406
1406
  const compress = body?.ablate_compress === true;
1407
+ const noDecisions = body?.ablate_no_decisions === true;
1407
1408
  const namesAblation = rawStages !== void 0 && rawStages !== null;
1408
1409
  const routeAblation = rawRoute !== void 0 && rawRoute !== null && rawRoute !== "adaptive";
1409
- if (!namesAblation && !noVerdict && !routeAblation && !speculative && !compress) return { ok: true, config: null };
1410
+ if (!namesAblation && !noVerdict && !routeAblation && !speculative && !compress && !noDecisions) return { ok: true, config: null };
1410
1411
  if (!adminToken || presentedToken !== adminToken) {
1411
1412
  return {
1412
1413
  ok: false,
@@ -1437,7 +1438,184 @@ function parseAblate(body, adminToken, presentedToken, knownStages) {
1437
1438
  }
1438
1439
  stages = [...new Set(rawStages)];
1439
1440
  }
1440
- return { ok: true, config: { stages, noVerdict, route, speculative, compress } };
1441
+ return { ok: true, config: { stages, noVerdict, route, speculative, compress, noDecisions } };
1442
+ }
1443
+
1444
+ // workers/worker_public/src/decisions.ts
1445
+ function parseDerivation(text, cap) {
1446
+ const fallback = { mode: "list", requirements: [] };
1447
+ if (!text) return fallback;
1448
+ const cleaned = text.replace(/```json|```/g, "").trim();
1449
+ const start = cleaned.indexOf("{");
1450
+ const end = cleaned.lastIndexOf("}");
1451
+ if (start === -1 || end <= start) return fallback;
1452
+ let parsed;
1453
+ try {
1454
+ parsed = JSON.parse(cleaned.slice(start, end + 1));
1455
+ } catch {
1456
+ return fallback;
1457
+ }
1458
+ const reqs = Array.isArray(parsed?.requirements) ? parsed.requirements : [];
1459
+ const requirements = [];
1460
+ for (const r of reqs) {
1461
+ const t = typeof r?.text === "string" ? r.text.trim() : "";
1462
+ if (t.length < 8) continue;
1463
+ requirements.push({ text: t.slice(0, 300), clause: typeof r?.clause === "string" ? r.clause.trim().slice(0, 40) : "" });
1464
+ if (requirements.length >= cap) break;
1465
+ }
1466
+ if (!requirements.length) return fallback;
1467
+ const mode = parsed?.mode === "check" ? "check" : "list";
1468
+ return { mode, requirements };
1469
+ }
1470
+ function buildDecisionQuestions(mode, requirements, userQuestion, statedValues) {
1471
+ const questions = {};
1472
+ requirements.forEach((r, i) => {
1473
+ const id = `r${i + 1}`;
1474
+ if (mode === "check") {
1475
+ questions[id] = {
1476
+ type: "noul",
1477
+ instructions: `Requirement: "${r.text}" (clause ${r.clause || "n/a"}). The user asks: "${userQuestion}". Stated values: ${statedValues || "(none stated \u2014 judge whether the state text answers it)"}. Is this requirement met, based only on what the state contains?`,
1478
+ criteria: {
1479
+ true: "the state shows the requirement is satisfied",
1480
+ false: "the state shows it is not satisfied, or the state says nothing about it"
1481
+ }
1482
+ };
1483
+ } else {
1484
+ questions[id] = {
1485
+ type: "noul",
1486
+ instructions: `Is this a genuine, self-contained requirement statement: "${r.text}"?`,
1487
+ criteria: {
1488
+ true: "a real requirement a reader could check",
1489
+ false: "a fragment, duplicate, or not a requirement"
1490
+ }
1491
+ };
1492
+ }
1493
+ });
1494
+ return questions;
1495
+ }
1496
+ function bandFor(p, metBand, refuteBand) {
1497
+ if (p >= metBand) return "met";
1498
+ if (p <= refuteBand) return "not-met";
1499
+ return "unclear";
1500
+ }
1501
+ function matchAnswers(mode, requirements, answers, metBand, refuteBand) {
1502
+ const items = [];
1503
+ requirements.forEach((r, i) => {
1504
+ const a = answers[`r${i + 1}`];
1505
+ let probability;
1506
+ if (a && a.type === "noul" && typeof a.noul === "number") {
1507
+ probability = a.noul;
1508
+ } else if (a && typeof a === "number") {
1509
+ probability = a;
1510
+ } else {
1511
+ return;
1512
+ }
1513
+ if (probability < 0 || probability > 1) return;
1514
+ items.push({
1515
+ text: r.text,
1516
+ clause: r.clause,
1517
+ band: mode === "check" ? bandFor(probability, metBand, refuteBand) : "met",
1518
+ probability: Math.round(probability * 100) / 100
1519
+ });
1520
+ });
1521
+ return items;
1522
+ }
1523
+ var MARK = { met: "\u2713", "not-met": "\u2717", unclear: "?" };
1524
+ var WORD = { met: "met", "not-met": "not met", unclear: "not clearly stated" };
1525
+ function assembleSection(mode, items) {
1526
+ if (!items.length) return "";
1527
+ const title = mode === "check" ? "Requirements check (automated)" : "Requirements (from the cited clauses)";
1528
+ const lines = items.map((it) => {
1529
+ const mark = mode === "check" ? MARK[it.band] : "\u2022";
1530
+ const clause = it.clause ? ` \u2014 ${it.clause}` : "";
1531
+ const prob = mode === "check" ? ` (${Math.round(it.probability * 100)}%)` : "";
1532
+ return `- ${mark} ${it.text}${clause}${prob}${mode === "check" ? ` \u2014 ${WORD[it.band]}` : ""}`;
1533
+ });
1534
+ return `
1535
+
1536
+ ${title}:
1537
+ ${lines.join("\n")}`;
1538
+ }
1539
+
1540
+ // workers/worker_public/src/decisionWire.ts
1541
+ function decisionsEnabled(env) {
1542
+ return String(env.DECISIONS_ENABLED ?? "true") !== "false";
1543
+ }
1544
+ async function gateQuestion(env, question) {
1545
+ try {
1546
+ const res = await portModelRunner(env).run({
1547
+ model: env.DECISIONS_GATE_MODEL || MODELS.decisionsGate,
1548
+ input: {
1549
+ state: question.slice(0, 500),
1550
+ questions: {
1551
+ requirements: {
1552
+ type: "noul",
1553
+ instructions: "Is this question asking whether requirements are met, or asking what requirements apply to something?",
1554
+ criteria: {
1555
+ true: "the asker wants requirements listed or their own values/products checked against requirements",
1556
+ false: "a definitional, lookup, how-to, or conversational question"
1557
+ }
1558
+ }
1559
+ }
1560
+ },
1561
+ maxTokens: 512
1562
+ });
1563
+ const parsed = JSON.parse(res.text ?? "{}");
1564
+ const p = parsed?.requirements?.noul;
1565
+ return typeof p === "number" ? p : null;
1566
+ } catch {
1567
+ return null;
1568
+ }
1569
+ }
1570
+ async function runDecisionPass(env, opts) {
1571
+ const gateMin = THRESHOLDS.decisionsGateMin;
1572
+ if (opts.gate == null || opts.gate < gateMin) return null;
1573
+ const passages = opts.passages.filter(Boolean).slice(0, 8).map((p) => p.slice(0, 1600));
1574
+ if (!passages.length) return null;
1575
+ try {
1576
+ const deriveModel = env.DECISIONS_EXTRACT_MODEL || MODELS.member;
1577
+ const derived = await portModelRunner(env).run({
1578
+ model: deriveModel,
1579
+ messages: [
1580
+ { role: "system", content: "You extract requirement checklists from legal-metrology text. Reply with ONLY JSON, no prose." },
1581
+ {
1582
+ role: "user",
1583
+ content: `User question: ${opts.question}
1584
+
1585
+ ` + (opts.statedValues ? `The user's stated values: ${opts.statedValues}
1586
+
1587
+ ` : "") + `Passages:
1588
+ ${passages.map((p, i) => `[${i + 1}] ${p}`).join("\n")}
1589
+
1590
+ List the DISTINCT requirements relevant to the question as JSON: {"mode":"check"|"list","requirements":[{"text":"...","clause":"..."}]} \u2014 "check" when the user's question or values ask whether requirements are MET; "list" when the user asks what the requirements ARE. Max ${THRESHOLDS.decisionsRequirementsMax}. Each requirement's clause = the clause anchor it comes from. If nothing qualifies, return {"mode":"list","requirements":[]}.`
1591
+ }
1592
+ ],
1593
+ maxTokens: 1536,
1594
+ temperature: 0
1595
+ });
1596
+ const { mode, requirements } = parseDerivation(derived.text, THRESHOLDS.decisionsRequirementsMax);
1597
+ if (!requirements.length) return null;
1598
+ const decideModel = env.DECISIONS_MODEL || MODELS.decisionsModel;
1599
+ const decided = await portModelRunner(env).run({
1600
+ model: decideModel,
1601
+ input: {
1602
+ state: `User question: ${opts.question}
1603
+ ` + (opts.statedValues ? `Stated values: ${opts.statedValues}
1604
+ ` : "") + `Corpus passages:
1605
+ ${passages.join("\n")}`.slice(0, 12e3),
1606
+ questions: buildDecisionQuestions(mode, requirements, opts.question, opts.statedValues ?? "")
1607
+ },
1608
+ maxTokens: 4096
1609
+ });
1610
+ const answers = JSON.parse(decided.text ?? "{}");
1611
+ const items = matchAnswers(mode, requirements, answers, THRESHOLDS.decisionsMetBand, THRESHOLDS.decisionsRefuteBand);
1612
+ if (!items.length) return null;
1613
+ const section = assembleSection(mode, items);
1614
+ if (!section) return null;
1615
+ return { mode, gate: opts.gate, items, section };
1616
+ } catch {
1617
+ return null;
1618
+ }
1441
1619
  }
1442
1620
 
1443
1621
  // workers/worker_public/src/route.ts
@@ -2507,6 +2685,8 @@ ${summary}` }] : [],
2507
2685
  const routeSubset = ablate?.stages ?? (routed.route === "fast" ? fastRouteStages(STAGE_NAMES) : null);
2508
2686
  if (routeSubset) console.log("route:", routed.route, routed.features.join("+"), "\u2014", STAGE_NAMES.length - routeSubset.length, "lanes dropped");
2509
2687
  const crag = { grade: null, corrective: null };
2688
+ const decisionsArmed = decisionsEnabled(env) && !ablate?.noDecisions;
2689
+ const decisionsGatePromise = decisionsArmed ? gateQuestion(env, q2.query) : Promise.resolve(null);
2510
2690
  try {
2511
2691
  const tR = Date.now();
2512
2692
  if (declaredCtx?.kind === "account") {
@@ -2646,6 +2826,12 @@ Answer account questions from these records ONLY: name the record when you use i
2646
2826
  budget,
2647
2827
  ablate?.compress === true
2648
2828
  );
2829
+ const decisionPromise = decisionsArmed && decisionsGatePromise ? decisionsGatePromise.then((g) => g != null && g >= THRESHOLDS.decisionsGateMin ? runDecisionPass(env, {
2830
+ question: q2.query,
2831
+ gate: g,
2832
+ passages: usedHits.map((h) => h.text),
2833
+ docidentifier: understanding?.docidentifier ?? null
2834
+ }) : null) : Promise.resolve(null);
2649
2835
  await attachFigureImages(env, messages, usedHits, q2.query);
2650
2836
  const pendingTools = [];
2651
2837
  if (multiTurn && env.DB && !nameplate?.manufacturer) {
@@ -2783,14 +2969,32 @@ Answer account questions from these records ONLY: name the record when you use i
2783
2969
  }
2784
2970
  }
2785
2971
  }
2786
- const canonical0 = exciseMisplacedPin(canonicalRefusal(full.replace(/^TOOL [a-z_.]+.*$\n?/gm, "").replace(/^\n+/, ""), refusalScope(answerCites(full))), answerCites(full));
2972
+ let canonical0 = exciseMisplacedPin(canonicalRefusal(full.replace(/^TOOL [a-z_.]+.*$\n?/gm, "").replace(/^\n+/, ""), refusalScope(answerCites(full))), answerCites(full));
2787
2973
  const c2 = canonical0.includes(refusalAnswer()) ? { text: canonical0, blocks: [], dropped: [] } : await contractV2(env.DB, canonical0, usedHits);
2974
+ let streamedCompletionBlocks = [];
2975
+ if (decisionPromise && !canonical0.includes(refusalAnswer())) {
2976
+ const dp = await decisionPromise;
2977
+ if (dp) {
2978
+ canonical0 += dp.section;
2979
+ send({ type: "token", v: dp.section });
2980
+ full += dp.section;
2981
+ console.log("decisions: streamed the checklist section (" + dp.items.length + " items, mode " + dp.mode + ")");
2982
+ }
2983
+ }
2984
+ if (!canonical0.includes(refusalAnswer())) {
2985
+ try {
2986
+ streamedCompletionBlocks = await completeTables(env.DB, canonical0, usedHits);
2987
+ streamedCompletionBlocks.push(...await completeFigures(env.DB, canonical0, [...c2.blocks, ...streamedCompletionBlocks], usedHits, q2.query));
2988
+ if (streamedCompletionBlocks.length) console.log("streamed completion:", streamedCompletionBlocks.length, "block(s) attached");
2989
+ } catch {
2990
+ }
2991
+ }
2788
2992
  send({
2789
2993
  type: "done",
2790
2994
  model,
2791
2995
  query_hash: queryHash,
2792
2996
  follow_ups: refusalShaped(canonical0, refusalScope(answerCites(full))) ? [] : understanding?.follow_ups ?? [],
2793
- blocks: [...c2.blocks, ...verdictBlock ? [verdictBlock] : [], ...conditionBlock ? [conditionBlock] : [], ...aggregationBlock ? [aggregationBlock] : []],
2997
+ blocks: [...c2.blocks, ...verdictBlock ? [verdictBlock] : [], ...conditionBlock ? [conditionBlock] : [], ...aggregationBlock ? [aggregationBlock] : [], ...streamedCompletionBlocks],
2794
2998
  context_applied: ctxApplied,
2795
2999
  read: readAs(),
2796
3000
  // the evidence view's ground truth: the exact passages this
@@ -3008,7 +3212,15 @@ Answer account questions from these records ONLY: name the record when you use i
3008
3212
  if (v.support !== "supported") console.log("entailment:", v.support, raced.score, raced.ungrounded_claims?.slice(0, 2));
3009
3213
  }
3010
3214
  }
3011
- const out = { answer, citations: finalCites, ...jsonQuality ? { source_quality: jsonQuality, confidence_note: entailmentNote || qualityNote(jsonQuality), ...entailment ? { entailment } : {}, ...jsonQuality === "ocr" ? { experimental_sources: experimentalSourceLabels(finalCites) } : {} } : {}, model: MODELS.member, query_hash: queryHash, follow_ups: refusalShaped(answer, refusalScope(answerCites(answer))) ? [] : understanding?.follow_ups ?? [], blocks: [...c2ns.blocks, ...verdictBlock ? [verdictBlock] : [], ...conditionBlock ? [conditionBlock] : [], ...aggregationBlock ? [aggregationBlock] : [], ...registerBlock ? [registerBlock] : [], ...completionBlocks], context_applied: ctxApplied, ...liveRecords ? { records: liveRecords } : {}, ...ablate ? { ablate } : {}, route: { route: routed.route, features: routed.features } };
3215
+ let decisionsOut;
3216
+ if (decisionPromise) {
3217
+ const dp = await decisionPromise;
3218
+ if (dp && answer && !answer.includes(refusalAnswer())) {
3219
+ answer = answer + dp.section;
3220
+ decisionsOut = { mode: dp.mode, gate: dp.gate, items: dp.items };
3221
+ }
3222
+ }
3223
+ const out = { answer, citations: finalCites, ...jsonQuality ? { source_quality: jsonQuality, confidence_note: entailmentNote || qualityNote(jsonQuality), ...entailment ? { entailment } : {}, ...jsonQuality === "ocr" ? { experimental_sources: experimentalSourceLabels(finalCites) } : {} } : {}, model: MODELS.member, query_hash: queryHash, follow_ups: refusalShaped(answer, refusalScope(answerCites(answer))) ? [] : understanding?.follow_ups ?? [], blocks: [...c2ns.blocks, ...verdictBlock ? [verdictBlock] : [], ...conditionBlock ? [conditionBlock] : [], ...aggregationBlock ? [aggregationBlock] : [], ...registerBlock ? [registerBlock] : [], ...completionBlocks], context_applied: ctxApplied, ...liveRecords ? { records: liveRecords } : {}, ...decisionsOut ? { decisions: decisionsOut } : {}, ...ablate ? { ablate } : {}, route: { route: routed.route, features: routed.features } };
3012
3224
  const cacheable = !contextual && !declaredCtx && !ablate && cacheableAnswer(answer, refusalScope(answerCites(answer))) && finalAnchors.violations.length === 0;
3013
3225
  if (cacheable) {
3014
3226
  const ck = exactCacheKey(env.INDEX_VERSION, gen, ns, await sha256Hex(cacheKeyMaterial(q2.query, q2.lang, salt)));
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DATASETS,
3
3
  datasetAllowed
4
- } from "./chunk-4FZNJR5Q.js";
4
+ } from "./chunk-5UIMQAJZ.js";
5
5
  import {
6
6
  P
7
7
  } from "./chunk-3FYJM7LH.js";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  embed
3
- } from "./chunk-LU7VIMD7.js";
3
+ } from "./chunk-XWSZWFYP.js";
4
4
  import {
5
5
  standardKeysFrom
6
- } from "./chunk-Y7LWT24U.js";
6
+ } from "./chunk-PQDAL4MX.js";
7
7
  import {
8
8
  THRESHOLDS
9
- } from "./chunk-4FZNJR5Q.js";
9
+ } from "./chunk-5UIMQAJZ.js";
10
10
  import {
11
11
  P
12
12
  } from "./chunk-3FYJM7LH.js";
@@ -15,7 +15,7 @@ import {
15
15
  portIndex,
16
16
  portModelRunner,
17
17
  portStore
18
- } from "./chunk-LSZTJI7V.js";
18
+ } from "./chunk-KINFFYQH.js";
19
19
 
20
20
  // workers/worker_public/src/refs.ts
21
21
  var REF = /\[\[(u:(?:u:)?[A-Za-z0-9_-]+)\]\]/g;
@@ -1509,7 +1509,7 @@ async function runFind(env, args) {
1509
1509
  };
1510
1510
  }
1511
1511
  try {
1512
- const { portStore: portStore2 } = await import("./env-LMHGNJTN.js");
1512
+ const { portStore: portStore2 } = await import("./env-CNO44VN2.js");
1513
1513
  const res = await portStore2(env).prepare(compiled.sql).bind(...compiled.params).all();
1514
1514
  const rows = res?.results ?? [];
1515
1515
  const body = rows.length ? rows.map((r) => JSON.stringify(r)).join("\n") : "No rows matched. Either the predicates are too narrow or the data is absent \u2014 state which, and consider widening.";
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  embed,
3
3
  rerank
4
- } from "./chunk-LU7VIMD7.js";
4
+ } from "./chunk-XWSZWFYP.js";
5
5
  import {
6
6
  bubbleConfirmPage,
7
7
  isAllowedBubbleOrigin
8
- } from "./chunk-QY556RJM.js";
8
+ } from "./chunk-O2XMNKCK.js";
9
9
  import {
10
10
  DATASETS,
11
11
  LIMITS,
@@ -15,7 +15,7 @@ import {
15
15
  processExpansion,
16
16
  sha256Hex,
17
17
  today
18
- } from "./chunk-4FZNJR5Q.js";
18
+ } from "./chunk-5UIMQAJZ.js";
19
19
  import {
20
20
  P
21
21
  } from "./chunk-3FYJM7LH.js";
@@ -25,7 +25,7 @@ import {
25
25
  portIndex,
26
26
  portModelRunner,
27
27
  portStore
28
- } from "./chunk-LSZTJI7V.js";
28
+ } from "./chunk-KINFFYQH.js";
29
29
 
30
30
  // node_modules/@pubid/pubid/dist/grammar/engine.js
31
31
  var ParseFailed = class extends Error {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  answerEffort,
3
3
  effortBudget
4
- } from "./chunk-4FZNJR5Q.js";
4
+ } from "./chunk-5UIMQAJZ.js";
5
5
 
6
6
  // workers/worker_public/src/ai.ts
7
7
  var delay = (ms) => new Promise((r) => setTimeout(r, ms));
package/dist/config.d.ts CHANGED
@@ -4,6 +4,8 @@ export declare const MODELS: {
4
4
  readonly anon: "@cf/zai-org/glm-5.3-flash";
5
5
  readonly member: "@cf/zai-org/glm-5.3-flash";
6
6
  readonly vlmFigure: "@cf/deepseek-ai/deepseek-v4.1-flash-1017";
7
+ readonly decisionsGate: "@cf/cloudflare/clef-flash";
8
+ readonly decisionsModel: "@cf/cloudflare/clef";
7
9
  readonly understand: "@cf/qwen/qwen3-30b-a3b-fp8";
8
10
  readonly acts: "@cf/qwen/qwen3-30b-a3b-fp8";
9
11
  readonly fallback: "@cf/qwen/qwen3-30b-a3b-fp8";
@@ -52,6 +54,10 @@ export declare const THRESHOLDS: {
52
54
  * leaves the source-rung note unchanged). */
53
55
  readonly compressShare: 0.6;
54
56
  readonly denseStarveK: 100;
57
+ readonly decisionsGateMin: 0.5;
58
+ readonly decisionsMetBand: 0.8;
59
+ readonly decisionsRefuteBand: 0.2;
60
+ readonly decisionsRequirementsMax: 12;
55
61
  readonly entailmentGate: true;
56
62
  readonly entailmentBudgetMs: 6000;
57
63
  readonly entailmentSupportedFloor: 0.9;
@@ -0,0 +1,25 @@
1
+ import { type DecisionItem, type DecisionMode } from "./decisions.ts";
2
+ import type { Env } from "./env";
3
+ export interface DecisionPassResult {
4
+ mode: DecisionMode;
5
+ gate: number;
6
+ items: DecisionItem[];
7
+ section: string;
8
+ }
9
+ export declare function decisionsEnabled(env: Env): boolean;
10
+ /** The gate: one clef-flash noul over the question — "is this a
11
+ * requirement-shaped question?" Cheap; prefetched in parallel with
12
+ * retrieval by the caller. Returns the probability, or null on any
13
+ * failure (fail-open: the pass just doesn't fire). */
14
+ export declare function gateQuestion(env: Env, question: string): Promise<number | null>;
15
+ /** The full pass: derive the checklist candidates from the used
16
+ * passages, decide them in one batched Clef call, assemble the
17
+ * deterministic section. Returns null when the pass stands down. */
18
+ export declare function runDecisionPass(env: Env, opts: {
19
+ question: string;
20
+ gate: number;
21
+ passages: string[];
22
+ docidentifier: string | null;
23
+ statedValues?: string;
24
+ userDocs?: boolean;
25
+ }): Promise<DecisionPassResult | null>;
@@ -0,0 +1,39 @@
1
+ export interface DerivedRequirement {
2
+ text: string;
3
+ clause: string;
4
+ }
5
+ export interface DecisionItem {
6
+ text: string;
7
+ clause: string;
8
+ band: "met" | "not-met" | "unclear";
9
+ probability: number;
10
+ }
11
+ export type DecisionMode = "check" | "list";
12
+ /** Parse the derivation model's reply: JSON with
13
+ * {mode: "check"|"list", requirements: [{text, clause}]}.
14
+ * Tolerant of prose around the JSON, of trailing commas-free objects,
15
+ * and of missing clauses (empty string). Returns [] when nothing
16
+ * sane survives — the pass then stands down. */
17
+ export declare function parseDerivation(text: string | null | undefined, cap: number): {
18
+ mode: DecisionMode;
19
+ requirements: DerivedRequirement[];
20
+ };
21
+ /** Build the Clef questions map from the derived requirements. In
22
+ * "check" mode each requirement becomes a noul (met-or-not given the
23
+ * user's stated values); in "list" mode a noul on whether the
24
+ * requirement is genuinely stated in the corpus text. */
25
+ export declare function buildDecisionQuestions(mode: DecisionMode, requirements: DerivedRequirement[], userQuestion: string, statedValues: string): Record<string, {
26
+ type: "noul";
27
+ instructions: string;
28
+ criteria?: {
29
+ true: string;
30
+ false: string;
31
+ };
32
+ }>;
33
+ export declare function bandFor(p: number, metBand: number, refuteBand: number): DecisionItem["band"];
34
+ /** Match the Clef answers (keyed r1..rN) back onto the requirements and
35
+ * band them. Unmatched/missing answers drop (absence is honest). */
36
+ export declare function matchAnswers(mode: DecisionMode, requirements: DerivedRequirement[], answers: Record<string, any>, metBand: number, refuteBand: number): DecisionItem[];
37
+ /** The deterministic checklist section appended to the answer. The
38
+ * model never writes this — the server composes it from the decisions. */
39
+ export declare function assembleSection(mode: DecisionMode, items: DecisionItem[]): string;
@@ -6,7 +6,7 @@ import {
6
6
  portModelRunner,
7
7
  portRuntime,
8
8
  portStore
9
- } from "./chunk-LSZTJI7V.js";
9
+ } from "./chunk-KINFFYQH.js";
10
10
  export {
11
11
  hasLane,
12
12
  portBlobs,
@@ -0,0 +1,14 @@
1
+ import {
2
+ handleSearch
3
+ } from "./chunk-6KEWBP7O.js";
4
+ import "./chunk-RZLEHCIA.js";
5
+ import "./chunk-XWSZWFYP.js";
6
+ import "./chunk-O2XMNKCK.js";
7
+ import "./chunk-ETLSWSZ7.js";
8
+ import "./chunk-PQDAL4MX.js";
9
+ import "./chunk-5UIMQAJZ.js";
10
+ import "./chunk-3FYJM7LH.js";
11
+ import "./chunk-KINFFYQH.js";
12
+ export {
13
+ handleSearch
14
+ };
@@ -4,12 +4,12 @@ import {
4
4
  parseToolCall,
5
5
  runTool,
6
6
  toolNote
7
- } from "./chunk-PTY2OSC4.js";
8
- import "./chunk-LU7VIMD7.js";
9
- import "./chunk-Y7LWT24U.js";
10
- import "./chunk-4FZNJR5Q.js";
7
+ } from "./chunk-QS6V53RO.js";
8
+ import "./chunk-XWSZWFYP.js";
9
+ import "./chunk-PQDAL4MX.js";
10
+ import "./chunk-5UIMQAJZ.js";
11
11
  import "./chunk-3FYJM7LH.js";
12
- import "./chunk-LSZTJI7V.js";
12
+ import "./chunk-KINFFYQH.js";
13
13
  export {
14
14
  TOOLS_REGISTRY,
15
15
  TOOL_DECLARATION,