@remnic/core 9.3.596 → 9.3.598

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 (89) hide show
  1. package/dist/access-cli.js +17 -17
  2. package/dist/access-http.js +6 -6
  3. package/dist/access-mcp.js +5 -5
  4. package/dist/access-service.js +4 -4
  5. package/dist/behavior-learner.js +2 -1
  6. package/dist/behavior-learner.js.map +1 -1
  7. package/dist/causal-behavior.js +3 -3
  8. package/dist/causal-chain.js +3 -3
  9. package/dist/causal-consolidation.js +4 -4
  10. package/dist/causal-retrieval.js +3 -3
  11. package/dist/causal-trajectory.js +2 -2
  12. package/dist/{chunk-A2Z6UCWT.js → chunk-33JBK2XP.js} +2 -2
  13. package/dist/{chunk-D2MMMTDV.js → chunk-5SQ5CQJP.js} +2 -2
  14. package/dist/{chunk-F4LM4ULA.js → chunk-65JSA4MP.js} +12 -12
  15. package/dist/{chunk-SKGV326D.js → chunk-6GDHLVJC.js} +2 -2
  16. package/dist/chunk-6HEM6HTQ.js +359 -0
  17. package/dist/chunk-6HEM6HTQ.js.map +1 -0
  18. package/dist/{chunk-WXACKLKP.js → chunk-75O6YQ63.js} +22 -7
  19. package/dist/chunk-75O6YQ63.js.map +1 -0
  20. package/dist/{chunk-D65TSG24.js → chunk-7DZRO2DC.js} +2 -2
  21. package/dist/{chunk-TYICDVQW.js → chunk-BDCCWRHR.js} +4 -4
  22. package/dist/{chunk-LYPDMKUT.js → chunk-CL3MWNNQ.js} +2 -2
  23. package/dist/{chunk-YQMZ7IH2.js → chunk-D4KJ74JJ.js} +65 -27
  24. package/dist/chunk-D4KJ74JJ.js.map +1 -0
  25. package/dist/{chunk-W5O2FQTZ.js → chunk-GUPISBV2.js} +2 -2
  26. package/dist/{chunk-472U7RDF.js → chunk-JGSKJHF7.js} +2 -2
  27. package/dist/{chunk-IEFHBIU2.js → chunk-KDUVQU6Y.js} +14 -14
  28. package/dist/{chunk-6HZ6AO2P.js → chunk-LBJBNWS2.js} +37 -10
  29. package/dist/chunk-LBJBNWS2.js.map +1 -0
  30. package/dist/{chunk-Z4R6RI2N.js → chunk-NSKYFGDL.js} +2 -2
  31. package/dist/{chunk-OD5LFAPZ.js → chunk-V67GWXM2.js} +1 -1
  32. package/dist/{chunk-5NXIJZFX.js → chunk-WR64DQFE.js} +3 -3
  33. package/dist/{chunk-5BUGGPBR.js → chunk-WZA5Y6AC.js} +3 -3
  34. package/dist/chunk-ZBJMUXZH.js +121 -0
  35. package/dist/chunk-ZBJMUXZH.js.map +1 -0
  36. package/dist/{chunk-XPXEJRUB.js → chunk-ZRWB5D4H.js} +2 -2
  37. package/dist/{chunk-MA5MWGKP.js → chunk-ZT3EGNLR.js} +2 -2
  38. package/dist/{chunk-LMPHTYJC.js → chunk-ZZYF3BUL.js} +2 -2
  39. package/dist/cli.js +14 -14
  40. package/dist/compounding/engine.js +1 -1
  41. package/dist/direct-answer-wiring.js +3 -3
  42. package/dist/direct-answer.d.ts +1 -1
  43. package/dist/direct-answer.js +2 -2
  44. package/dist/harmonic-retrieval.js +2 -2
  45. package/dist/index.js +21 -21
  46. package/dist/orchestrator.js +16 -16
  47. package/dist/policy-runtime.js +3 -2
  48. package/dist/recall-query-policy.js +2 -1
  49. package/dist/recall-tokenization.d.ts +5 -1
  50. package/dist/recall-tokenization.js +3 -1
  51. package/dist/resume-bundles.js +3 -3
  52. package/dist/retrieval-agents.js +2 -2
  53. package/dist/semantic-consolidation.js +2 -2
  54. package/dist/semantic-rule-verifier.js +2 -2
  55. package/dist/temporal-index.js +1 -1
  56. package/dist/trust-zones.js +2 -2
  57. package/dist/verified-recall.js +2 -2
  58. package/dist/work-product-ledger.js +2 -2
  59. package/package.json +1 -1
  60. package/src/causal-chain.ts +80 -42
  61. package/src/direct-answer.test.ts +618 -15
  62. package/src/direct-answer.ts +259 -20
  63. package/src/recall-query-policy.ts +49 -27
  64. package/src/recall-tokenization.ts +131 -21
  65. package/src/temporal-index.ts +23 -6
  66. package/dist/chunk-6HZ6AO2P.js.map +0 -1
  67. package/dist/chunk-DT5TVLJE.js +0 -32
  68. package/dist/chunk-DT5TVLJE.js.map +0 -1
  69. package/dist/chunk-WXACKLKP.js.map +0 -1
  70. package/dist/chunk-Y4FHOFJ2.js +0 -140
  71. package/dist/chunk-Y4FHOFJ2.js.map +0 -1
  72. package/dist/chunk-YQMZ7IH2.js.map +0 -1
  73. /package/dist/{chunk-A2Z6UCWT.js.map → chunk-33JBK2XP.js.map} +0 -0
  74. /package/dist/{chunk-D2MMMTDV.js.map → chunk-5SQ5CQJP.js.map} +0 -0
  75. /package/dist/{chunk-F4LM4ULA.js.map → chunk-65JSA4MP.js.map} +0 -0
  76. /package/dist/{chunk-SKGV326D.js.map → chunk-6GDHLVJC.js.map} +0 -0
  77. /package/dist/{chunk-D65TSG24.js.map → chunk-7DZRO2DC.js.map} +0 -0
  78. /package/dist/{chunk-TYICDVQW.js.map → chunk-BDCCWRHR.js.map} +0 -0
  79. /package/dist/{chunk-LYPDMKUT.js.map → chunk-CL3MWNNQ.js.map} +0 -0
  80. /package/dist/{chunk-W5O2FQTZ.js.map → chunk-GUPISBV2.js.map} +0 -0
  81. /package/dist/{chunk-472U7RDF.js.map → chunk-JGSKJHF7.js.map} +0 -0
  82. /package/dist/{chunk-IEFHBIU2.js.map → chunk-KDUVQU6Y.js.map} +0 -0
  83. /package/dist/{chunk-Z4R6RI2N.js.map → chunk-NSKYFGDL.js.map} +0 -0
  84. /package/dist/{chunk-OD5LFAPZ.js.map → chunk-V67GWXM2.js.map} +0 -0
  85. /package/dist/{chunk-5NXIJZFX.js.map → chunk-WR64DQFE.js.map} +0 -0
  86. /package/dist/{chunk-5BUGGPBR.js.map → chunk-WZA5Y6AC.js.map} +0 -0
  87. /package/dist/{chunk-XPXEJRUB.js.map → chunk-ZRWB5D4H.js.map} +0 -0
  88. /package/dist/{chunk-MA5MWGKP.js.map → chunk-ZT3EGNLR.js.map} +0 -0
  89. /package/dist/{chunk-LMPHTYJC.js.map → chunk-ZZYF3BUL.js.map} +0 -0
@@ -3,16 +3,16 @@ import {
3
3
  } from "./chunk-AU7Q3LSC.js";
4
4
  import {
5
5
  EngramMcpServer
6
- } from "./chunk-LYPDMKUT.js";
6
+ } from "./chunk-CL3MWNNQ.js";
7
7
  import {
8
8
  EngramAccessInputError
9
- } from "./chunk-5BUGGPBR.js";
9
+ } from "./chunk-WZA5Y6AC.js";
10
10
  import {
11
11
  projectTagProjectId
12
12
  } from "./chunk-EDQVAMQI.js";
13
13
  import {
14
14
  isTrustZoneName
15
- } from "./chunk-472U7RDF.js";
15
+ } from "./chunk-JGSKJHF7.js";
16
16
  import {
17
17
  subscribeGraphEvents
18
18
  } from "./chunk-DEUNUKTD.js";
@@ -1846,4 +1846,4 @@ var EngramAccessHttpServer = class {
1846
1846
  export {
1847
1847
  EngramAccessHttpServer
1848
1848
  };
1849
- //# sourceMappingURL=chunk-TYICDVQW.js.map
1849
+ //# sourceMappingURL=chunk-BDCCWRHR.js.map
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-D24OXEPB.js";
12
12
  import {
13
13
  EngramAccessInputError
14
- } from "./chunk-5BUGGPBR.js";
14
+ } from "./chunk-WZA5Y6AC.js";
15
15
  import {
16
16
  projectTagProjectId
17
17
  } from "./chunk-EDQVAMQI.js";
@@ -2860,4 +2860,4 @@ ${body}`;
2860
2860
  export {
2861
2861
  EngramMcpServer
2862
2862
  };
2863
- //# sourceMappingURL=chunk-LYPDMKUT.js.map
2863
+ //# sourceMappingURL=chunk-CL3MWNNQ.js.map
@@ -3,11 +3,10 @@ import {
3
3
  } from "./chunk-HQ6NIBL6.js";
4
4
  import {
5
5
  resolveCausalTrajectoryStoreDir
6
- } from "./chunk-LMPHTYJC.js";
6
+ } from "./chunk-ZZYF3BUL.js";
7
7
  import {
8
- countRecallTokenOverlap,
9
8
  normalizeRecallTokens
10
- } from "./chunk-DT5TVLJE.js";
9
+ } from "./chunk-ZBJMUXZH.js";
11
10
  import {
12
11
  log
13
12
  } from "./chunk-2ODBA7MQ.js";
@@ -23,9 +22,9 @@ import {
23
22
  } from "./chunk-LPSF4OQH.js";
24
23
 
25
24
  // src/causal-chain.ts
26
- import path from "path";
27
- import { mkdir, readFile, writeFile } from "fs/promises";
28
25
  import { createHash } from "crypto";
26
+ import { mkdir, readFile, writeFile } from "fs/promises";
27
+ import path from "path";
29
28
  var STITCH_WEIGHTS = {
30
29
  followUpToGoal: 4,
31
30
  outcomeToGoal: 2,
@@ -33,6 +32,52 @@ var STITCH_WEIGHTS = {
33
32
  tagOverlap: 1.5,
34
33
  temporalProximity: 1
35
34
  };
35
+ function hasUnsegmentableRecallChar(token) {
36
+ if (token.includes("\u30FC") || token.includes("\uFF70")) return true;
37
+ return /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}]/u.test(token);
38
+ }
39
+ function extractUnsegmentableStitchPhrases(value) {
40
+ const phrases = /* @__PURE__ */ new Set();
41
+ let segment = "";
42
+ const flushSegment = () => {
43
+ if ([...segment].length >= 4) {
44
+ phrases.add(segment);
45
+ }
46
+ segment = "";
47
+ };
48
+ for (const ch of value.toLowerCase().normalize("NFC")) {
49
+ if (hasUnsegmentableRecallChar(ch)) {
50
+ segment += ch;
51
+ continue;
52
+ }
53
+ if (/\p{M}/u.test(ch) && segment.length > 0) {
54
+ segment += ch;
55
+ continue;
56
+ }
57
+ if (/\s/u.test(ch) && segment.length > 0) {
58
+ continue;
59
+ }
60
+ flushSegment();
61
+ }
62
+ flushSegment();
63
+ return [...phrases];
64
+ }
65
+ function normalizeStitchLexicalTokens(value, extraStopWords = []) {
66
+ const tokens = new Set(
67
+ normalizeRecallTokens(value, extraStopWords).filter((token) => !hasUnsegmentableRecallChar(token))
68
+ );
69
+ for (const phrase of extractUnsegmentableStitchPhrases(value)) {
70
+ tokens.add(phrase);
71
+ }
72
+ return [...tokens];
73
+ }
74
+ function countTokenSetOverlap(queryTokens, valueTokens) {
75
+ let matches = 0;
76
+ for (const token of queryTokens) {
77
+ if (valueTokens.has(token)) matches += 1;
78
+ }
79
+ return matches;
80
+ }
36
81
  function validateCausalEdge(raw) {
37
82
  if (!isRecord(raw)) throw new Error("CausalEdge must be an object");
38
83
  if (raw.schemaVersion !== 1) throw new Error("CausalEdge.schemaVersion must be 1");
@@ -58,9 +103,7 @@ function validateCausalEdge(raw) {
58
103
  stitchMethod,
59
104
  createdAt: assertIsoRecordedAt(assertString(raw.createdAt, "createdAt")),
60
105
  metadata: isRecord(raw.metadata) ? Object.fromEntries(
61
- Object.entries(raw.metadata).filter(
62
- (entry) => typeof entry[1] === "string"
63
- )
106
+ Object.entries(raw.metadata).filter((entry) => typeof entry[1] === "string")
64
107
  ) : void 0
65
108
  };
66
109
  }
@@ -138,12 +181,11 @@ function scoreStitchCandidate(newTrajectory, candidate) {
138
181
  let score = 0;
139
182
  let dominantMethod = "lexical";
140
183
  let maxComponent = 0;
141
- const newFollowUpTokens = new Set(
142
- normalizeRecallTokens(newTrajectory.followUpSummary ?? "", [])
143
- );
144
- const candidateGoalTokens = normalizeRecallTokens(candidate.goal, []);
184
+ const newFollowUpTokens = new Set(normalizeStitchLexicalTokens(newTrajectory.followUpSummary ?? "", []));
185
+ const candidateGoalTokens = normalizeStitchLexicalTokens(candidate.goal, []);
186
+ const candidateGoalTokenSet = new Set(candidateGoalTokens);
145
187
  if (newFollowUpTokens.size > 0 && candidateGoalTokens.length > 0) {
146
- const overlap = countRecallTokenOverlap(newFollowUpTokens, candidate.goal, []);
188
+ const overlap = countTokenSetOverlap(newFollowUpTokens, candidateGoalTokenSet);
147
189
  const normalized = overlap / Math.max(newFollowUpTokens.size, candidateGoalTokens.length);
148
190
  const component = normalized * STITCH_WEIGHTS.followUpToGoal;
149
191
  score += component;
@@ -152,12 +194,11 @@ function scoreStitchCandidate(newTrajectory, candidate) {
152
194
  dominantMethod = "lexical";
153
195
  }
154
196
  }
155
- const candidateFollowUpTokens = new Set(
156
- normalizeRecallTokens(candidate.followUpSummary ?? "", [])
157
- );
158
- const newGoalTokens = normalizeRecallTokens(newTrajectory.goal, []);
197
+ const candidateFollowUpTokens = new Set(normalizeStitchLexicalTokens(candidate.followUpSummary ?? "", []));
198
+ const newGoalTokens = normalizeStitchLexicalTokens(newTrajectory.goal, []);
199
+ const newGoalTokenSet = new Set(newGoalTokens);
159
200
  if (candidateFollowUpTokens.size > 0 && newGoalTokens.length > 0) {
160
- const overlap = countRecallTokenOverlap(candidateFollowUpTokens, newTrajectory.goal, []);
201
+ const overlap = countTokenSetOverlap(candidateFollowUpTokens, newGoalTokenSet);
161
202
  const normalized = overlap / Math.max(candidateFollowUpTokens.size, newGoalTokens.length);
162
203
  const component = normalized * 3;
163
204
  score += component;
@@ -166,11 +207,9 @@ function scoreStitchCandidate(newTrajectory, candidate) {
166
207
  dominantMethod = "lexical";
167
208
  }
168
209
  }
169
- const newOutcomeTokens = new Set(
170
- normalizeRecallTokens(newTrajectory.outcomeSummary, [])
171
- );
210
+ const newOutcomeTokens = new Set(normalizeStitchLexicalTokens(newTrajectory.outcomeSummary, []));
172
211
  if (newOutcomeTokens.size > 0) {
173
- const overlap = countRecallTokenOverlap(newOutcomeTokens, candidate.goal, []);
212
+ const overlap = countTokenSetOverlap(newOutcomeTokens, candidateGoalTokenSet);
174
213
  const normalized = overlap / Math.max(newOutcomeTokens.size, candidateGoalTokens.length || 1);
175
214
  const component = normalized * STITCH_WEIGHTS.outcomeToGoal;
176
215
  score += component;
@@ -214,16 +253,15 @@ function scoreStitchCandidate(newTrajectory, candidate) {
214
253
  }
215
254
  }
216
255
  let edgeType = "continuation";
217
- const goalTokens = new Set(normalizeRecallTokens(newTrajectory.goal, []));
218
- const candidateGoalSet = new Set(candidateGoalTokens);
219
- const goalOverlap = [...goalTokens].filter((t) => candidateGoalSet.has(t)).length;
256
+ const goalTokens = new Set(newGoalTokens);
257
+ const goalOverlap = countTokenSetOverlap(goalTokens, candidateGoalTokenSet);
220
258
  const goalSimilarity = goalTokens.size > 0 ? goalOverlap / goalTokens.size : 0;
221
259
  if (goalSimilarity > 0.7 && candidate.outcomeKind === "failure") {
222
260
  edgeType = "retry";
223
261
  } else if (goalSimilarity > 0.7 && newTrajectory.outcomeKind !== candidate.outcomeKind) {
224
262
  edgeType = "correction";
225
263
  } else if (newFollowUpTokens.size > 0 && candidateGoalTokens.length > 0) {
226
- const followUpGoalOverlap = countRecallTokenOverlap(newFollowUpTokens, candidate.goal, []);
264
+ const followUpGoalOverlap = countTokenSetOverlap(newFollowUpTokens, candidateGoalTokenSet);
227
265
  if (followUpGoalOverlap > 0) {
228
266
  edgeType = "follow_up_to_goal";
229
267
  }
@@ -301,4 +339,4 @@ export {
301
339
  scoreStitchCandidate,
302
340
  stitchCausalChain
303
341
  };
304
- //# sourceMappingURL=chunk-YQMZ7IH2.js.map
342
+ //# sourceMappingURL=chunk-D4KJ74JJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/causal-chain.ts"],"sourcesContent":["/**\n * causal-chain.ts — Cross-session causal chain persistence for CMC.\n *\n * Stitches causal trajectories across session boundaries by detecting\n * when a trajectory in one session follows up on a trajectory from\n * another session. Persists edges in a graph index for later retrieval.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { topicOverlapScore } from \"./boxes.js\";\nimport { type CausalTrajectoryRecord, resolveCausalTrajectoryStoreDir } from \"./causal-trajectory.js\";\nimport { listJsonFiles, readJsonFile } from \"./json-store.js\";\nimport { log } from \"./logger.js\";\nimport { normalizeRecallTokens } from \"./recall-tokenization.js\";\nimport { assertIsoRecordedAt, assertString, isRecord, recordStoreDay } from \"./store-contract.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface CausalEdge {\n schemaVersion: 1;\n edgeId: string;\n fromTrajectoryId: string;\n toTrajectoryId: string;\n edgeType: \"follow_up_to_goal\" | \"retry\" | \"continuation\" | \"correction\";\n confidence: number;\n stitchMethod: \"lexical\" | \"entity\" | \"temporal\" | \"explicit\";\n createdAt: string;\n metadata?: Record<string, string>;\n}\n\nexport interface CausalChainIndex {\n outgoing: Record<string, string[]>;\n incoming: Record<string, string[]>;\n edges: Record<string, CausalEdge>;\n updatedAt: string;\n}\n\nexport interface StitchConfig {\n lookbackDays: number;\n minScore: number;\n maxEdgesPerTrajectory: number;\n}\n\nexport interface StitchCandidate {\n trajectory: CausalTrajectoryRecord;\n score: number;\n edgeType: CausalEdge[\"edgeType\"];\n stitchMethod: CausalEdge[\"stitchMethod\"];\n}\n\n// ─── Scoring Weights ─────────────────────────────────────────────────────────\n\nconst STITCH_WEIGHTS = {\n followUpToGoal: 4.0,\n outcomeToGoal: 2.0,\n entityOverlap: 3.0,\n tagOverlap: 1.5,\n temporalProximity: 1.0,\n} as const;\n\nfunction hasUnsegmentableRecallChar(token: string): boolean {\n if (token.includes(\"ー\") || token.includes(\"ー\")) return true;\n return /[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}]/u.test(token);\n}\n\nfunction extractUnsegmentableStitchPhrases(value: string): string[] {\n const phrases = new Set<string>();\n let segment = \"\";\n\n const flushSegment = () => {\n if ([...segment].length >= 4) {\n phrases.add(segment);\n }\n segment = \"\";\n };\n\n for (const ch of value.toLowerCase().normalize(\"NFC\")) {\n if (hasUnsegmentableRecallChar(ch)) {\n segment += ch;\n continue;\n }\n if (/\\p{M}/u.test(ch) && segment.length > 0) {\n segment += ch;\n continue;\n }\n if (/\\s/u.test(ch) && segment.length > 0) {\n continue;\n }\n flushSegment();\n }\n flushSegment();\n\n return [...phrases];\n}\n\nfunction normalizeStitchLexicalTokens(value: string, extraStopWords: string[] = []): string[] {\n const tokens = new Set(\n normalizeRecallTokens(value, extraStopWords).filter((token) => !hasUnsegmentableRecallChar(token))\n );\n for (const phrase of extractUnsegmentableStitchPhrases(value)) {\n tokens.add(phrase);\n }\n return [...tokens];\n}\n\nfunction countTokenSetOverlap(queryTokens: Set<string>, valueTokens: Set<string>): number {\n let matches = 0;\n for (const token of queryTokens) {\n if (valueTokens.has(token)) matches += 1;\n }\n return matches;\n}\n\n// ─── Validation ──────────────────────────────────────────────────────────────\n\nexport function validateCausalEdge(raw: unknown): CausalEdge {\n if (!isRecord(raw)) throw new Error(\"CausalEdge must be an object\");\n if (raw.schemaVersion !== 1) throw new Error(\"CausalEdge.schemaVersion must be 1\");\n\n const edgeType = assertString(raw.edgeType, \"edgeType\");\n const validEdgeTypes = [\"follow_up_to_goal\", \"retry\", \"continuation\", \"correction\"];\n if (!validEdgeTypes.includes(edgeType)) {\n throw new Error(`CausalEdge.edgeType must be one of ${validEdgeTypes.join(\", \")}`);\n }\n\n const stitchMethod = assertString(raw.stitchMethod, \"stitchMethod\");\n const validMethods = [\"lexical\", \"entity\", \"temporal\", \"explicit\"];\n if (!validMethods.includes(stitchMethod)) {\n throw new Error(`CausalEdge.stitchMethod must be one of ${validMethods.join(\", \")}`);\n }\n\n const confidence = typeof raw.confidence === \"number\" ? raw.confidence : 0;\n if (confidence < 0 || confidence > 1) throw new Error(\"CausalEdge.confidence must be in [0, 1]\");\n\n return {\n schemaVersion: 1,\n edgeId: assertString(raw.edgeId, \"edgeId\"),\n fromTrajectoryId: assertString(raw.fromTrajectoryId, \"fromTrajectoryId\"),\n toTrajectoryId: assertString(raw.toTrajectoryId, \"toTrajectoryId\"),\n edgeType: edgeType as CausalEdge[\"edgeType\"],\n confidence: confidence,\n stitchMethod: stitchMethod as CausalEdge[\"stitchMethod\"],\n createdAt: assertIsoRecordedAt(assertString(raw.createdAt, \"createdAt\")),\n metadata: isRecord(raw.metadata)\n ? Object.fromEntries(\n Object.entries(raw.metadata).filter((entry): entry is [string, string] => typeof entry[1] === \"string\")\n )\n : undefined,\n };\n}\n\n// ─── Stable Edge ID ──────────────────────────────────────────────────────────\n\nexport function makeEdgeId(fromId: string, toId: string): string {\n const digest = createHash(\"sha256\").update(`${fromId}\\0${toId}`).digest(\"hex\").slice(0, 12);\n return `edge-${digest}`;\n}\n\n// ─── Storage Paths ───────────────────────────────────────────────────────────\n\nexport function resolveChainsDir(memoryDir: string, causalTrajectoryStoreDir?: string): string {\n const root = resolveCausalTrajectoryStoreDir(memoryDir, causalTrajectoryStoreDir);\n return path.join(root, \"chains\");\n}\n\nfunction chainIndexPath(chainsDir: string): string {\n return path.join(chainsDir, \"chain-index.json\");\n}\n\nfunction edgeFilePath(chainsDir: string, edge: CausalEdge): string {\n const day = recordStoreDay(edge.createdAt);\n return path.join(chainsDir, \"edges\", day, `${edge.edgeId}.json`);\n}\n\n// ─── Chain Index CRUD ────────────────────────────────────────────────────────\n\nconst chainMutationQueues = new Map<string, Promise<unknown>>();\n\nfunction enqueueChainMutation<T>(chainsDir: string, op: () => Promise<T>): Promise<T> {\n const key = path.resolve(chainsDir);\n const previous = chainMutationQueues.get(key) ?? Promise.resolve();\n const run = previous.catch(() => {}).then(op);\n const settled = run.catch(() => {});\n chainMutationQueues.set(key, settled);\n void settled.finally(() => {\n if (chainMutationQueues.get(key) === settled) {\n chainMutationQueues.delete(key);\n }\n });\n return run;\n}\n\nexport async function readChainIndex(chainsDir: string): Promise<CausalChainIndex> {\n try {\n const raw = JSON.parse(await readFile(chainIndexPath(chainsDir), \"utf8\"));\n return {\n outgoing: isRecord(raw.outgoing) ? (raw.outgoing as Record<string, string[]>) : {},\n incoming: isRecord(raw.incoming) ? (raw.incoming as Record<string, string[]>) : {},\n edges: isRecord(raw.edges) ? (raw.edges as Record<string, CausalEdge>) : {},\n updatedAt: typeof raw.updatedAt === \"string\" ? raw.updatedAt : new Date().toISOString(),\n };\n } catch {\n return { outgoing: {}, incoming: {}, edges: {}, updatedAt: new Date().toISOString() };\n }\n}\n\nexport async function writeChainIndex(chainsDir: string, index: CausalChainIndex): Promise<void> {\n await mkdir(chainsDir, { recursive: true });\n index.updatedAt = new Date().toISOString();\n await writeFile(chainIndexPath(chainsDir), JSON.stringify(index, null, 2), \"utf8\");\n}\n\nasync function persistEdge(chainsDir: string, edge: CausalEdge): Promise<string> {\n const filePath = edgeFilePath(chainsDir, edge);\n await mkdir(path.dirname(filePath), { recursive: true });\n await writeFile(filePath, JSON.stringify(edge, null, 2), \"utf8\");\n return filePath;\n}\n\nfunction addEdgeToIndex(index: CausalChainIndex, edge: CausalEdge): void {\n if (!index.outgoing[edge.fromTrajectoryId]) {\n index.outgoing[edge.fromTrajectoryId] = [];\n }\n if (!index.outgoing[edge.fromTrajectoryId].includes(edge.edgeId)) {\n index.outgoing[edge.fromTrajectoryId].push(edge.edgeId);\n }\n\n if (!index.incoming[edge.toTrajectoryId]) {\n index.incoming[edge.toTrajectoryId] = [];\n }\n if (!index.incoming[edge.toTrajectoryId].includes(edge.edgeId)) {\n index.incoming[edge.toTrajectoryId].push(edge.edgeId);\n }\n\n index.edges[edge.edgeId] = edge;\n}\n\n// ─── Stitching Algorithm ─────────────────────────────────────────────────────\n\n/**\n * Score how strongly a candidate trajectory from another session\n * relates to the new trajectory being recorded.\n */\nexport function scoreStitchCandidate(\n newTrajectory: CausalTrajectoryRecord,\n candidate: CausalTrajectoryRecord\n): StitchCandidate {\n let score = 0;\n let dominantMethod: CausalEdge[\"stitchMethod\"] = \"lexical\";\n let maxComponent = 0;\n\n // 1. Follow-up → Goal match (token overlap)\n const newFollowUpTokens = new Set(normalizeStitchLexicalTokens(newTrajectory.followUpSummary ?? \"\", []));\n const candidateGoalTokens = normalizeStitchLexicalTokens(candidate.goal, []);\n const candidateGoalTokenSet = new Set(candidateGoalTokens);\n if (newFollowUpTokens.size > 0 && candidateGoalTokens.length > 0) {\n const overlap = countTokenSetOverlap(newFollowUpTokens, candidateGoalTokenSet);\n const normalized = overlap / Math.max(newFollowUpTokens.size, candidateGoalTokens.length);\n const component = normalized * STITCH_WEIGHTS.followUpToGoal;\n score += component;\n if (component > maxComponent) {\n maxComponent = component;\n dominantMethod = \"lexical\";\n }\n }\n\n // 1b. Candidate follow-up → New goal match (reverse direction)\n const candidateFollowUpTokens = new Set(normalizeStitchLexicalTokens(candidate.followUpSummary ?? \"\", []));\n const newGoalTokens = normalizeStitchLexicalTokens(newTrajectory.goal, []);\n const newGoalTokenSet = new Set(newGoalTokens);\n if (candidateFollowUpTokens.size > 0 && newGoalTokens.length > 0) {\n const overlap = countTokenSetOverlap(candidateFollowUpTokens, newGoalTokenSet);\n const normalized = overlap / Math.max(candidateFollowUpTokens.size, newGoalTokens.length);\n const component = normalized * 3.0;\n score += component;\n if (component > maxComponent) {\n maxComponent = component;\n dominantMethod = \"lexical\";\n }\n }\n\n // 2. Outcome → Goal match\n const newOutcomeTokens = new Set(normalizeStitchLexicalTokens(newTrajectory.outcomeSummary, []));\n if (newOutcomeTokens.size > 0) {\n const overlap = countTokenSetOverlap(newOutcomeTokens, candidateGoalTokenSet);\n const normalized = overlap / Math.max(newOutcomeTokens.size, candidateGoalTokens.length || 1);\n const component = normalized * STITCH_WEIGHTS.outcomeToGoal;\n score += component;\n if (component > maxComponent) {\n maxComponent = component;\n dominantMethod = \"lexical\";\n }\n }\n\n // 3. Entity overlap (Jaccard)\n const newEntities = newTrajectory.entityRefs ?? [];\n const candidateEntities = candidate.entityRefs ?? [];\n if (newEntities.length > 0 && candidateEntities.length > 0) {\n const entityJaccard = topicOverlapScore(newEntities, candidateEntities);\n const component = entityJaccard * STITCH_WEIGHTS.entityOverlap;\n score += component;\n if (component > maxComponent) {\n maxComponent = component;\n dominantMethod = \"entity\";\n }\n }\n\n // 4. Tag overlap (Jaccard)\n const newTags = newTrajectory.tags ?? [];\n const candidateTags = candidate.tags ?? [];\n if (newTags.length > 0 && candidateTags.length > 0) {\n const tagJaccard = topicOverlapScore(newTags, candidateTags);\n const component = tagJaccard * STITCH_WEIGHTS.tagOverlap;\n score += component;\n if (component > maxComponent) {\n maxComponent = component;\n dominantMethod = \"lexical\";\n }\n }\n\n // 5. Temporal proximity: 1/(1 + gapHours/24)\n const newMs = Date.parse(newTrajectory.recordedAt);\n const candidateMs = Date.parse(candidate.recordedAt);\n if (Number.isFinite(newMs) && Number.isFinite(candidateMs)) {\n const gapHours = Math.abs(newMs - candidateMs) / 3_600_000;\n const proximity = 1 / (1 + gapHours / 24);\n const component = proximity * STITCH_WEIGHTS.temporalProximity;\n score += component;\n if (component > maxComponent) {\n maxComponent = component;\n dominantMethod = \"temporal\";\n }\n }\n\n // Determine edge type by heuristic\n let edgeType: CausalEdge[\"edgeType\"] = \"continuation\";\n const goalTokens = new Set(newGoalTokens);\n const goalOverlap = countTokenSetOverlap(goalTokens, candidateGoalTokenSet);\n const goalSimilarity = goalTokens.size > 0 ? goalOverlap / goalTokens.size : 0;\n\n if (goalSimilarity > 0.7 && candidate.outcomeKind === \"failure\") {\n edgeType = \"retry\";\n } else if (goalSimilarity > 0.7 && newTrajectory.outcomeKind !== candidate.outcomeKind) {\n edgeType = \"correction\";\n } else if (newFollowUpTokens.size > 0 && candidateGoalTokens.length > 0) {\n const followUpGoalOverlap = countTokenSetOverlap(newFollowUpTokens, candidateGoalTokenSet);\n if (followUpGoalOverlap > 0) {\n edgeType = \"follow_up_to_goal\";\n }\n }\n\n return { trajectory: candidate, score, edgeType, stitchMethod: dominantMethod };\n}\n\n/**\n * Read trajectory records from the causal-trajectories store within\n * the lookback window, excluding the current session.\n */\nasync function readRecentTrajectories(\n memoryDir: string,\n causalTrajectoryStoreDir: string | undefined,\n currentSessionKey: string,\n lookbackDays: number\n): Promise<CausalTrajectoryRecord[]> {\n const root = resolveCausalTrajectoryStoreDir(memoryDir, causalTrajectoryStoreDir);\n const trajectoriesDir = path.join(root, \"trajectories\");\n\n const files = await listJsonFiles(trajectoriesDir).catch(() => [] as string[]);\n if (files.length === 0) return [];\n\n const cutoff = Date.now() - lookbackDays * 86_400_000;\n const results: CausalTrajectoryRecord[] = [];\n\n for (const filePath of files) {\n try {\n const raw = await readJsonFile(filePath);\n if (!isRecord(raw)) continue;\n const sessionKey = typeof raw.sessionKey === \"string\" ? raw.sessionKey : \"\";\n if (sessionKey === currentSessionKey) continue;\n const recordedAt = typeof raw.recordedAt === \"string\" ? raw.recordedAt : \"\";\n const ms = Date.parse(recordedAt);\n if (!Number.isFinite(ms) || ms < cutoff) continue;\n results.push(raw as unknown as CausalTrajectoryRecord);\n } catch {\n // skip invalid files\n }\n }\n\n return results;\n}\n\n/**\n * After a new trajectory is recorded, attempt to stitch it to\n * existing trajectories from other sessions.\n */\nexport async function stitchCausalChain(options: {\n memoryDir: string;\n causalTrajectoryStoreDir?: string;\n newTrajectory: CausalTrajectoryRecord;\n config: StitchConfig;\n}): Promise<CausalEdge[]> {\n const { memoryDir, causalTrajectoryStoreDir, newTrajectory, config: stitchConfig } = options;\n const chainsDir = resolveChainsDir(memoryDir, causalTrajectoryStoreDir);\n\n const candidates = await readRecentTrajectories(\n memoryDir,\n causalTrajectoryStoreDir,\n newTrajectory.sessionKey,\n stitchConfig.lookbackDays\n );\n\n if (candidates.length === 0) return [];\n\n const scored = candidates\n .map((c) => scoreStitchCandidate(newTrajectory, c))\n .filter((s) => s.score >= stitchConfig.minScore)\n .sort((a, b) => b.score - a.score)\n .slice(0, stitchConfig.maxEdgesPerTrajectory);\n\n if (scored.length === 0) return [];\n\n return enqueueChainMutation(chainsDir, async () => {\n const index = await readChainIndex(chainsDir);\n const newEdges: CausalEdge[] = [];\n\n for (const candidate of scored) {\n const edgeId = makeEdgeId(candidate.trajectory.trajectoryId, newTrajectory.trajectoryId);\n\n // Skip if edge already exists\n if (index.edges[edgeId]) continue;\n\n const edge: CausalEdge = {\n schemaVersion: 1,\n edgeId,\n fromTrajectoryId: candidate.trajectory.trajectoryId,\n toTrajectoryId: newTrajectory.trajectoryId,\n edgeType: candidate.edgeType,\n confidence: Math.min(1, candidate.score / 10),\n stitchMethod: candidate.stitchMethod,\n createdAt: new Date().toISOString(),\n };\n\n addEdgeToIndex(index, edge);\n await persistEdge(chainsDir, edge);\n newEdges.push(edge);\n }\n\n if (newEdges.length > 0) {\n await writeChainIndex(chainsDir, index);\n log.debug(`[cmc] stitched ${newEdges.length} causal edge(s) for trajectory ${newTrajectory.trajectoryId}`);\n }\n\n return newEdges;\n });\n}\n"],"mappings":"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","names":[]}
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  countRecallTokenOverlap,
10
10
  normalizeRecallTokens
11
- } from "./chunk-DT5TVLJE.js";
11
+ } from "./chunk-ZBJMUXZH.js";
12
12
 
13
13
  // src/semantic-rule-verifier.ts
14
14
  var DEFAULT_MIN_EFFECTIVE_CONFIDENCE = 0.45;
@@ -115,4 +115,4 @@ async function searchVerifiedSemanticRules(options) {
115
115
  export {
116
116
  searchVerifiedSemanticRules
117
117
  };
118
- //# sourceMappingURL=chunk-W5O2FQTZ.js.map
118
+ //# sourceMappingURL=chunk-GUPISBV2.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  countRecallTokenOverlap,
3
3
  normalizeRecallTokens
4
- } from "./chunk-DT5TVLJE.js";
4
+ } from "./chunk-ZBJMUXZH.js";
5
5
  import {
6
6
  assertIsoRecordedAt,
7
7
  assertSafePathSegment,
@@ -905,4 +905,4 @@ export {
905
905
  seedTrustZoneDemoDataset,
906
906
  getTrustZoneStoreStatus
907
907
  };
908
- //# sourceMappingURL=chunk-472U7RDF.js.map
908
+ //# sourceMappingURL=chunk-JGSKJHF7.js.map
@@ -19,7 +19,7 @@ import {
19
19
  import {
20
20
  CompoundingEngine,
21
21
  defaultTierMigrationCycleBudget
22
- } from "./chunk-OD5LFAPZ.js";
22
+ } from "./chunk-V67GWXM2.js";
23
23
  import {
24
24
  SharedContextManager
25
25
  } from "./chunk-DRD2Q7HQ.js";
@@ -70,7 +70,7 @@ import {
70
70
  runDirectAgent,
71
71
  runTemporalAgent,
72
72
  shouldRunAgent
73
- } from "./chunk-D2MMMTDV.js";
73
+ } from "./chunk-5SQ5CQJP.js";
74
74
  import {
75
75
  clearIndexes,
76
76
  deindexMemory,
@@ -82,7 +82,7 @@ import {
82
82
  queryByTagsAsync,
83
83
  recencyWindowFromPrompt,
84
84
  resolvePromptTagPrefilterAsync
85
- } from "./chunk-WXACKLKP.js";
85
+ } from "./chunk-75O6YQ63.js";
86
86
  import {
87
87
  applyRuntimeRetrievalPolicy
88
88
  } from "./chunk-5IZL4DCV.js";
@@ -181,7 +181,7 @@ import {
181
181
  } from "./chunk-WLEB7WCG.js";
182
182
  import {
183
183
  tryDirectAnswer
184
- } from "./chunk-5NXIJZFX.js";
184
+ } from "./chunk-WR64DQFE.js";
185
185
  import {
186
186
  EmbeddingFallback
187
187
  } from "./chunk-XCAZF7KQ.js";
@@ -203,7 +203,7 @@ import {
203
203
  materializeAfterSemanticConsolidation,
204
204
  parseConsolidationResponse,
205
205
  parseOperatorAwareConsolidationResponse
206
- } from "./chunk-D65TSG24.js";
206
+ } from "./chunk-7DZRO2DC.js";
207
207
  import {
208
208
  normalizeReplaySessionKey
209
209
  } from "./chunk-2PRQG7PV.js";
@@ -212,16 +212,16 @@ import {
212
212
  } from "./chunk-HPWVAEET.js";
213
213
  import {
214
214
  searchVerifiedEpisodes
215
- } from "./chunk-MA5MWGKP.js";
215
+ } from "./chunk-ZT3EGNLR.js";
216
216
  import {
217
217
  ThreadingManager
218
218
  } from "./chunk-W4RVMTHR.js";
219
219
  import {
220
220
  searchVerifiedSemanticRules
221
- } from "./chunk-W5O2FQTZ.js";
221
+ } from "./chunk-GUPISBV2.js";
222
222
  import {
223
223
  searchWorkProductLedgerEntries
224
- } from "./chunk-XPXEJRUB.js";
224
+ } from "./chunk-ZRWB5D4H.js";
225
225
  import {
226
226
  TranscriptManager
227
227
  } from "./chunk-A6D7A2FW.js";
@@ -249,14 +249,14 @@ import {
249
249
  } from "./chunk-PCI747N2.js";
250
250
  import {
251
251
  PolicyRuntimeManager
252
- } from "./chunk-A2Z6UCWT.js";
252
+ } from "./chunk-33JBK2XP.js";
253
253
  import {
254
254
  isAboveImportanceThreshold,
255
255
  scoreImportance
256
256
  } from "./chunk-JXS5PDQ7.js";
257
257
  import {
258
258
  searchHarmonicRetrieval
259
- } from "./chunk-SKGV326D.js";
259
+ } from "./chunk-6GDHLVJC.js";
260
260
  import {
261
261
  collectNativeKnowledgeChunks,
262
262
  formatNativeKnowledgeSection,
@@ -287,7 +287,7 @@ import {
287
287
  } from "./chunk-CSKLPDN6.js";
288
288
  import {
289
289
  buildRecallQueryPolicy
290
- } from "./chunk-6HZ6AO2P.js";
290
+ } from "./chunk-LBJBNWS2.js";
291
291
  import {
292
292
  buildBehaviorSignalsForMemory,
293
293
  dedupeBehaviorSignalsByMemoryAndHash
@@ -314,7 +314,7 @@ import {
314
314
  import {
315
315
  listTrustZoneRecords,
316
316
  searchTrustZoneRecords
317
- } from "./chunk-472U7RDF.js";
317
+ } from "./chunk-JGSKJHF7.js";
318
318
  import {
319
319
  buildXraySnapshot
320
320
  } from "./chunk-FXKPZ3H6.js";
@@ -363,7 +363,7 @@ import {
363
363
  } from "./chunk-FVQJYWH7.js";
364
364
  import {
365
365
  searchCausalTrajectories
366
- } from "./chunk-LMPHTYJC.js";
366
+ } from "./chunk-ZZYF3BUL.js";
367
367
  import {
368
368
  canReadNamespace,
369
369
  defaultNamespaceForPrincipal,
@@ -12405,4 +12405,4 @@ export {
12405
12405
  resolvePersistedMemoryRelativePath,
12406
12406
  Orchestrator
12407
12407
  };
12408
- //# sourceMappingURL=chunk-IEFHBIU2.js.map
12408
+ //# sourceMappingURL=chunk-KDUVQU6Y.js.map
@@ -1,5 +1,9 @@
1
+ import {
2
+ normalizeRecallTokens
3
+ } from "./chunk-ZBJMUXZH.js";
4
+
1
5
  // src/recall-query-policy.ts
2
- var DEFAULT_STOPWORDS = /* @__PURE__ */ new Set([
6
+ var DEFAULT_STOPWORDS = [
3
7
  "the",
4
8
  "and",
5
9
  "for",
@@ -55,13 +59,27 @@ var DEFAULT_STOPWORDS = /* @__PURE__ */ new Set([
55
59
  "data",
56
60
  "gathering",
57
61
  "context"
58
- ]);
62
+ ];
63
+ var MAX_COMPACT_TOKENS_PER_SOURCE_TERM = 8;
64
+ var COMPACT_IDENTIFIER_RE = /^[a-z0-9]+(?:[:_-][a-z0-9]+)+$/i;
59
65
  function collapseWhitespace(text) {
60
66
  return text.replace(/\s+/g, " ").trim();
61
67
  }
62
68
  function stripFilesystemLikePaths(text) {
63
69
  return text.replace(/(?:^|\s)(~\/[^\s)]+)(?=\s|$)/g, " ").replace(/(?:^|\s)(\/[A-Za-z0-9._\-\/]+)(?=\s|$)/g, " ").replace(/(?:^|\s)([A-Za-z]:\\[^\s)]+)(?=\s|$)/g, " ");
64
70
  }
71
+ function trimCompactSourceTerm(term) {
72
+ return term.replace(/^[^\p{L}\p{N}\p{M}]+|[^\p{L}\p{N}\p{M}]+$/gu, "");
73
+ }
74
+ function splitCompactSourceTerm(term) {
75
+ return term.split(/[^\p{L}\p{N}\p{M}:_-]+/gu).map((part) => trimCompactSourceTerm(part)).filter((part) => part.length > 0);
76
+ }
77
+ function capCompactSourceTermTokens(tokens) {
78
+ if (tokens.length <= MAX_COMPACT_TOKENS_PER_SOURCE_TERM) return tokens;
79
+ const last = tokens.at(-1);
80
+ if (!last) return tokens.slice(0, MAX_COMPACT_TOKENS_PER_SOURCE_TERM);
81
+ return [...tokens.slice(0, MAX_COMPACT_TOKENS_PER_SOURCE_TERM - 1), last];
82
+ }
65
83
  function isBulletOrNumberedLine(line) {
66
84
  if (line.startsWith("-") || line.startsWith("*")) {
67
85
  return true;
@@ -103,16 +121,25 @@ function classifyRecallPromptShape(prompt) {
103
121
  return score >= 5 ? "instruction_heavy" : "standard";
104
122
  }
105
123
  function tokenizeForCompactQuery(text) {
106
- const raw = text.toLowerCase().replace(/[^a-z0-9\s:_-]+/g, " ").split(/\s+/).filter((token) => token.length >= 3);
107
- const deduped = [];
124
+ const tokens = [];
108
125
  const seen = /* @__PURE__ */ new Set();
109
- for (const token of raw) {
110
- if (DEFAULT_STOPWORDS.has(token)) continue;
111
- if (seen.has(token)) continue;
126
+ const addToken = (token) => {
127
+ if (token.length === 0 || seen.has(token)) return;
112
128
  seen.add(token);
113
- deduped.push(token);
129
+ tokens.push(token);
130
+ };
131
+ for (const rawTerm of text.split(/\s+/)) {
132
+ for (const sourceTerm of splitCompactSourceTerm(trimCompactSourceTerm(rawTerm))) {
133
+ if (COMPACT_IDENTIFIER_RE.test(sourceTerm)) {
134
+ addToken(sourceTerm.toLowerCase());
135
+ continue;
136
+ }
137
+ for (const token of capCompactSourceTermTokens(normalizeRecallTokens(sourceTerm, DEFAULT_STOPWORDS))) {
138
+ addToken(token);
139
+ }
140
+ }
114
141
  }
115
- return deduped;
142
+ return tokens;
116
143
  }
117
144
  function buildInstructionHeavyQuery(prompt, tokenCap, maxChars) {
118
145
  const cleaned = stripFilesystemLikePaths(prompt);
@@ -161,4 +188,4 @@ export {
161
188
  clampInstructionHeavyTokenCap,
162
189
  buildRecallQueryPolicy
163
190
  };
164
- //# sourceMappingURL=chunk-6HZ6AO2P.js.map
191
+ //# sourceMappingURL=chunk-LBJBNWS2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/recall-query-policy.ts"],"sourcesContent":["import { normalizeRecallTokens } from \"./recall-tokenization.js\";\n\nexport type RecallPromptShape = \"standard\" | \"instruction_heavy\";\nexport type CronConversationRecallMode = \"auto\" | \"always\" | \"never\";\nexport type RecallBudgetMode = \"full\" | \"minimal\";\n\nexport interface RecallQueryPolicyConfig {\n cronRecallPolicyEnabled: boolean;\n cronRecallNormalizedQueryMaxChars: number;\n cronRecallInstructionHeavyTokenCap: number;\n cronConversationRecallMode: CronConversationRecallMode;\n}\n\nexport interface RecallQueryPolicyResult {\n promptShape: RecallPromptShape;\n retrievalQuery: string;\n skipConversationRecall: boolean;\n retrievalBudgetMode: RecallBudgetMode;\n}\n\nconst DEFAULT_STOPWORDS = [\n \"the\",\n \"and\",\n \"for\",\n \"with\",\n \"from\",\n \"that\",\n \"this\",\n \"your\",\n \"you\",\n \"are\",\n \"was\",\n \"were\",\n \"have\",\n \"has\",\n \"had\",\n \"not\",\n \"but\",\n \"its\",\n \"into\",\n \"only\",\n \"use\",\n \"run\",\n \"then\",\n \"when\",\n \"what\",\n \"where\",\n \"which\",\n \"will\",\n \"would\",\n \"should\",\n \"could\",\n \"goal\",\n \"output\",\n \"format\",\n \"rules\",\n \"section\",\n \"sections\",\n \"skip\",\n \"today\",\n \"yesterday\",\n \"return\",\n \"summary\",\n \"plain\",\n \"text\",\n \"before\",\n \"after\",\n \"time\",\n \"date\",\n \"daily\",\n \"cron\",\n \"agent\",\n \"mode\",\n \"data\",\n \"gathering\",\n \"context\",\n];\nconst MAX_COMPACT_TOKENS_PER_SOURCE_TERM = 8;\nconst COMPACT_IDENTIFIER_RE = /^[a-z0-9]+(?:[:_-][a-z0-9]+)+$/i;\n\nfunction collapseWhitespace(text: string): string {\n return text.replace(/\\s+/g, \" \").trim();\n}\n\nfunction stripFilesystemLikePaths(text: string): string {\n return text\n .replace(/(?:^|\\s)(~\\/[^\\s)]+)(?=\\s|$)/g, \" \")\n .replace(/(?:^|\\s)(\\/[A-Za-z0-9._\\-\\/]+)(?=\\s|$)/g, \" \")\n .replace(/(?:^|\\s)([A-Za-z]:\\\\[^\\s)]+)(?=\\s|$)/g, \" \");\n}\n\nfunction trimCompactSourceTerm(term: string): string {\n return term.replace(/^[^\\p{L}\\p{N}\\p{M}]+|[^\\p{L}\\p{N}\\p{M}]+$/gu, \"\");\n}\n\nfunction splitCompactSourceTerm(term: string): string[] {\n return term\n .split(/[^\\p{L}\\p{N}\\p{M}:_-]+/gu)\n .map((part) => trimCompactSourceTerm(part))\n .filter((part) => part.length > 0);\n}\n\nfunction capCompactSourceTermTokens(tokens: string[]): string[] {\n if (tokens.length <= MAX_COMPACT_TOKENS_PER_SOURCE_TERM) return tokens;\n const last = tokens.at(-1);\n if (!last) return tokens.slice(0, MAX_COMPACT_TOKENS_PER_SOURCE_TERM);\n return [...tokens.slice(0, MAX_COMPACT_TOKENS_PER_SOURCE_TERM - 1), last];\n}\n\nfunction isBulletOrNumberedLine(line: string): boolean {\n if (line.startsWith(\"-\") || line.startsWith(\"*\")) {\n return true;\n }\n\n let i = 0;\n while (i < line.length) {\n const code = line.charCodeAt(i);\n if (code < 48 || code > 57) {\n break;\n }\n i += 1;\n }\n return i > 0 && i < line.length && line.charAt(i) === \".\";\n}\n\nfunction scoreInstructionHeavyShape(prompt: string): number {\n const lines = prompt\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n const lineCount = lines.length;\n if (lineCount === 0) return 0;\n\n const headingLineCount = lines.filter(\n (line) =>\n /^(goal|output format|tone rules|grounding rules|data gathering|date computation|crm context|follow-up|social|current time|return)\\b/i.test(\n line\n ) || /^[A-Z][A-Z\\s/-]{4,}:$/.test(line)\n ).length;\n const bulletLineCount = lines.filter((line) => isBulletOrNumberedLine(line)).length;\n const longLineCount = lines.filter((line) => line.length >= 180).length;\n const hasPathDensity = (prompt.match(/(?:~\\/|\\/Users\\/|[A-Za-z]:\\\\)/g)?.length ?? 0) >= 2;\n const hasImperativeDensity =\n (prompt.match(/\\b(run|extract|read|parse|determine|include|omit|skip)\\b/gi)?.length ?? 0) >= 8;\n\n let score = 0;\n if (lineCount >= 24) score += 2;\n if (headingLineCount >= 4) score += 2;\n if (bulletLineCount >= 8) score += 1;\n if (longLineCount >= 3) score += 1;\n if (hasPathDensity) score += 1;\n if (hasImperativeDensity) score += 1;\n return score;\n}\n\nexport function classifyRecallPromptShape(prompt: string): RecallPromptShape {\n const score = scoreInstructionHeavyShape(prompt);\n return score >= 5 ? \"instruction_heavy\" : \"standard\";\n}\n\nfunction tokenizeForCompactQuery(text: string): string[] {\n const tokens: string[] = [];\n const seen = new Set<string>();\n const addToken = (token: string) => {\n if (token.length === 0 || seen.has(token)) return;\n seen.add(token);\n tokens.push(token);\n };\n\n for (const rawTerm of text.split(/\\s+/)) {\n for (const sourceTerm of splitCompactSourceTerm(trimCompactSourceTerm(rawTerm))) {\n if (COMPACT_IDENTIFIER_RE.test(sourceTerm)) {\n addToken(sourceTerm.toLowerCase());\n continue;\n }\n for (const token of capCompactSourceTermTokens(normalizeRecallTokens(sourceTerm, DEFAULT_STOPWORDS))) {\n addToken(token);\n }\n }\n }\n return tokens;\n}\n\nfunction buildInstructionHeavyQuery(prompt: string, tokenCap: number, maxChars: number): string {\n const cleaned = stripFilesystemLikePaths(prompt);\n const tokens = tokenizeForCompactQuery(cleaned).slice(0, Math.max(8, tokenCap));\n const joined = tokens.join(\" \");\n const compact = collapseWhitespace(joined);\n if (compact.length <= maxChars) return compact;\n return compact.slice(0, maxChars).trim();\n}\n\nexport function clampInstructionHeavyTokenCap(value: number): number {\n if (!Number.isFinite(value)) return 8;\n return Math.max(8, Math.round(value));\n}\n\nfunction buildStandardQuery(prompt: string, maxChars: number): string {\n const trimmed = collapseWhitespace(prompt);\n if (trimmed.length <= maxChars) return trimmed;\n return trimmed.slice(0, maxChars).trim();\n}\n\nexport function buildRecallQueryPolicy(\n prompt: string,\n sessionKey: string | undefined,\n cfg: RecallQueryPolicyConfig\n): RecallQueryPolicyResult {\n const normalizedPrompt = collapseWhitespace(prompt);\n const isCron = (sessionKey ?? \"\").includes(\":cron:\");\n if (!cfg.cronRecallPolicyEnabled || !isCron) {\n return {\n promptShape: \"standard\",\n retrievalQuery: prompt,\n skipConversationRecall: false,\n retrievalBudgetMode: \"full\",\n };\n }\n\n const promptShape = classifyRecallPromptShape(prompt);\n const maxChars = Math.max(120, cfg.cronRecallNormalizedQueryMaxChars);\n const tokenCap = clampInstructionHeavyTokenCap(cfg.cronRecallInstructionHeavyTokenCap);\n const retrievalQuery =\n promptShape === \"instruction_heavy\"\n ? buildInstructionHeavyQuery(prompt, tokenCap, maxChars)\n : buildStandardQuery(prompt, maxChars);\n\n const skipConversationRecall =\n cfg.cronConversationRecallMode === \"never\"\n ? true\n : cfg.cronConversationRecallMode === \"always\"\n ? false\n : promptShape === \"instruction_heavy\";\n\n const retrievalBudgetMode = promptShape === \"instruction_heavy\" ? \"minimal\" : \"full\";\n\n return {\n promptShape,\n retrievalQuery: retrievalQuery.length > 0 ? retrievalQuery : normalizedPrompt.slice(0, maxChars),\n skipConversationRecall,\n retrievalBudgetMode,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  resolveWorkProductLedgerDir,
3
3
  validateWorkProductLedgerEntry
4
- } from "./chunk-XPXEJRUB.js";
4
+ } from "./chunk-ZRWB5D4H.js";
5
5
  import {
6
6
  TranscriptManager
7
7
  } from "./chunk-A6D7A2FW.js";
@@ -268,4 +268,4 @@ export {
268
268
  recordResumeBundle,
269
269
  getResumeBundleStatus
270
270
  };
271
- //# sourceMappingURL=chunk-Z4R6RI2N.js.map
271
+ //# sourceMappingURL=chunk-NSKYFGDL.js.map
@@ -1259,4 +1259,4 @@ export {
1259
1259
  defaultTierMigrationCycleBudget,
1260
1260
  CompoundingEngine
1261
1261
  };
1262
- //# sourceMappingURL=chunk-OD5LFAPZ.js.map
1262
+ //# sourceMappingURL=chunk-V67GWXM2.js.map
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  isDirectAnswerEligible
3
- } from "./chunk-Y4FHOFJ2.js";
3
+ } from "./chunk-6HEM6HTQ.js";
4
4
  import {
5
5
  throwIfAborted
6
6
  } from "./chunk-PVGDJXVK.js";
7
7
  import {
8
8
  normalizeRecallTokens
9
- } from "./chunk-DT5TVLJE.js";
9
+ } from "./chunk-ZBJMUXZH.js";
10
10
 
11
11
  // src/taxonomy/resolver.ts
12
12
  var DEFAULT_CATEGORY_ID = "facts";
@@ -177,4 +177,4 @@ export {
177
177
  resolveCategory,
178
178
  tryDirectAnswer
179
179
  };
180
- //# sourceMappingURL=chunk-5NXIJZFX.js.map
180
+ //# sourceMappingURL=chunk-WR64DQFE.js.map
@@ -41,7 +41,7 @@ import {
41
41
  scoreTrustZoneProvenance,
42
42
  seedTrustZoneDemoDataset,
43
43
  summarizeTrustZonePromotionReadiness
44
- } from "./chunk-472U7RDF.js";
44
+ } from "./chunk-JGSKJHF7.js";
45
45
  import {
46
46
  estimateRecallTokens
47
47
  } from "./chunk-FXKPZ3H6.js";
@@ -105,7 +105,7 @@ import {
105
105
  import {
106
106
  filterTrajectoriesByLookbackDays,
107
107
  readCausalTrajectoryRecords
108
- } from "./chunk-LMPHTYJC.js";
108
+ } from "./chunk-ZZYF3BUL.js";
109
109
  import {
110
110
  canReadNamespace,
111
111
  canWriteNamespace,
@@ -4238,4 +4238,4 @@ export {
4238
4238
  shapeMemorySummary,
4239
4239
  EngramAccessService
4240
4240
  };
4241
- //# sourceMappingURL=chunk-5BUGGPBR.js.map
4241
+ //# sourceMappingURL=chunk-WZA5Y6AC.js.map