@lucern/sdk 1.0.11 → 1.0.13

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 (331) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +24 -27
  3. package/dist/.generated +2 -0
  4. package/dist/accessControl.d.ts +19 -26
  5. package/dist/accessControl.js +195 -1423
  6. package/dist/adminClient.d.ts +52 -59
  7. package/dist/adminClient.js +364 -1142
  8. package/dist/answersClient.d.ts +5 -14
  9. package/dist/answersClient.js +19 -737
  10. package/dist/audience/index.d.ts +18 -18
  11. package/dist/audience/index.js +87 -90
  12. package/dist/audiencesClient.d.ts +19 -27
  13. package/dist/audiencesClient.js +107 -868
  14. package/dist/auditClient.d.ts +8 -15
  15. package/dist/auditClient.js +18 -791
  16. package/dist/authContext.d.ts +11 -16
  17. package/dist/authContext.js +122 -154
  18. package/dist/authDeviceClient.d.ts +8 -17
  19. package/dist/authDeviceClient.js +113 -102
  20. package/dist/beliefs/index.d.ts +16 -67
  21. package/dist/beliefs/index.js +20 -10181
  22. package/dist/beliefs/lifecycle.d.ts +10 -11
  23. package/dist/beliefs/lifecycle.js +78 -80
  24. package/dist/beliefsClient.d.ts +30 -35
  25. package/dist/beliefsClient.js +238 -994
  26. package/dist/boundaryClientSurface.d.ts +11 -16
  27. package/dist/boundaryClientSurface.js +49 -68
  28. package/dist/client.d.ts +82 -113
  29. package/dist/client.js +232 -10155
  30. package/dist/clientAssemblyTypes.d.ts +3 -3
  31. package/dist/clientAssemblyTypes.js +1 -2
  32. package/dist/clientConfig.d.ts +45 -59
  33. package/dist/clientConfig.js +1 -2
  34. package/dist/clientEvidenceCompat.d.ts +24 -14
  35. package/dist/clientEvidenceCompat.js +56 -64
  36. package/dist/clientGraphNamespaces.d.ts +3 -5
  37. package/dist/clientGraphNamespaces.js +170 -245
  38. package/dist/clientHelpers.d.ts +20 -25
  39. package/dist/clientHelpers.js +104 -127
  40. package/dist/clientKnowledgeNamespaces.d.ts +24 -54
  41. package/dist/clientKnowledgeNamespaces.js +506 -506
  42. package/dist/clientLocalHelpers.d.ts +11 -56
  43. package/dist/clientLocalHelpers.js +503 -732
  44. package/dist/clientPlatformNamespaces.d.ts +5 -53
  45. package/dist/clientPlatformNamespaces.js +229 -323
  46. package/dist/clientRuntime.d.ts +5 -53
  47. package/dist/clientRuntime.js +26 -30
  48. package/dist/clientWorkflowNamespaces.d.ts +6 -15
  49. package/dist/clientWorkflowNamespaces.js +529 -596
  50. package/dist/contextClient.d.ts +9 -17
  51. package/dist/contextClient.js +92 -805
  52. package/dist/contextFacade.d.ts +11 -2
  53. package/dist/contextFacade.js +10 -81
  54. package/dist/contextPackCompiler.d.ts +10 -11
  55. package/dist/contextPackCompiler.js +494 -1040
  56. package/dist/contextPackPolicy.d.ts +14 -15
  57. package/dist/contextPackPolicy.js +227 -305
  58. package/dist/contextPackSchema.d.ts +3 -3
  59. package/dist/contextPackSchema.js +169 -176
  60. package/dist/contextTypes.d.ts +14 -15
  61. package/dist/contextTypes.js +1 -2
  62. package/dist/contracts/api-enums.contract.d.ts +29 -30
  63. package/dist/contracts/api-enums.contract.js +162 -88
  64. package/dist/contracts/auth-session.contract.d.ts +13 -14
  65. package/dist/contracts/auth-session.contract.js +55 -52
  66. package/dist/contracts/context-pack.contract.d.ts +54 -55
  67. package/dist/contracts/context-pack.contract.js +160 -88
  68. package/dist/contracts/contextPack.d.ts +2 -1
  69. package/dist/contracts/contextPack.js +1 -97
  70. package/dist/contracts/index.d.ts +11 -12
  71. package/dist/contracts/index.js +10 -854
  72. package/dist/contracts/lens-filter.contract.d.ts +9 -10
  73. package/dist/contracts/lens-filter.contract.js +82 -58
  74. package/dist/contracts/lens-workflow.contract.d.ts +21 -23
  75. package/dist/contracts/lens-workflow.contract.js +48 -117
  76. package/dist/contracts/lensFilter.d.ts +2 -1
  77. package/dist/contracts/lensFilter.js +1 -71
  78. package/dist/contracts/lensWorkflow.d.ts +2 -2
  79. package/dist/contracts/lensWorkflow.js +1 -123
  80. package/dist/contracts/mcpTools.d.ts +16 -18
  81. package/dist/contracts/mcpTools.js +89 -123
  82. package/dist/contracts/prompt.contract.d.ts +4 -5
  83. package/dist/contracts/prompt.contract.js +23 -10
  84. package/dist/contracts/prompt.d.ts +2 -1
  85. package/dist/contracts/prompt.js +1 -11
  86. package/dist/contracts/sdk-tools.contract.d.ts +2 -1
  87. package/dist/contracts/sdk-tools.contract.js +1 -2
  88. package/dist/contracts/sdkTools.d.ts +2 -1
  89. package/dist/contracts/sdkTools.js +1 -26
  90. package/dist/contracts/tool-contracts.d.ts +2 -1
  91. package/dist/contracts/tool-contracts.js +1 -2
  92. package/dist/contracts/workflow-runtime.contract.d.ts +45 -46
  93. package/dist/contracts/workflow-runtime.contract.js +241 -228
  94. package/dist/contracts/workflowRuntime.d.ts +2 -1
  95. package/dist/contracts/workflowRuntime.js +1 -244
  96. package/dist/contradictions/index.d.ts +8 -60
  97. package/dist/contradictions/index.js +11 -10175
  98. package/dist/control-plane.d.ts +17 -24
  99. package/dist/control-plane.js +124 -840
  100. package/dist/controlObjectOwnership.d.ts +19 -20
  101. package/dist/controlObjectOwnership.js +207 -201
  102. package/dist/coreClient.d.ts +23 -28
  103. package/dist/coreClient.js +567 -692
  104. package/dist/customTools.d.ts +17 -21
  105. package/dist/customTools.js +221 -221
  106. package/dist/decisions/index.d.ts +7 -58
  107. package/dist/decisions/index.js +14 -10177
  108. package/dist/decisionsClient.d.ts +25 -32
  109. package/dist/decisionsClient.js +113 -913
  110. package/dist/domainContext.d.ts +2 -1
  111. package/dist/domainContext.js +1 -2
  112. package/dist/edges/index.d.ts +21 -73
  113. package/dist/edges/index.js +12 -10176
  114. package/dist/embeddingsClient.d.ts +22 -30
  115. package/dist/embeddingsClient.js +73 -922
  116. package/dist/eventingClient.d.ts +23 -31
  117. package/dist/eventingClient.js +89 -918
  118. package/dist/events.d.ts +48 -49
  119. package/dist/events.js +257 -241
  120. package/dist/eventsCore.d.ts +20 -29
  121. package/dist/eventsCore.js +86 -830
  122. package/dist/evidence/index.d.ts +42 -61
  123. package/dist/evidence/index.js +13 -10176
  124. package/dist/evidenceClient.d.ts +13 -22
  125. package/dist/evidenceClient.js +34 -751
  126. package/dist/facade/context.d.ts +7 -8
  127. package/dist/facade/context.js +73 -72
  128. package/dist/functionSurface.d.ts +2 -156
  129. package/dist/functionSurface.js +1 -1460
  130. package/dist/functionSurfaceClient.d.ts +2 -9
  131. package/dist/functionSurfaceClient.js +1 -1460
  132. package/dist/gatewayFacades.d.ts +93 -296
  133. package/dist/gatewayFacades.factories.d.ts +209 -14
  134. package/dist/gatewayFacades.factories.js +545 -2228
  135. package/dist/gatewayFacades.js +284 -2627
  136. package/dist/generated/functionSurface.d.ts +149 -0
  137. package/dist/generated/functionSurface.js +749 -0
  138. package/dist/graphAnalysisClient.d.ts +41 -49
  139. package/dist/graphAnalysisClient.js +185 -974
  140. package/dist/graphClient.d.ts +53 -60
  141. package/dist/graphClient.js +219 -1090
  142. package/dist/graphIntel.d.ts +2 -4
  143. package/dist/graphIntel.js +1 -2
  144. package/dist/graphIntelligence.d.ts +4 -2
  145. package/dist/graphIntelligence.js +2 -46
  146. package/dist/graphRecommendationsClient.d.ts +15 -23
  147. package/dist/graphRecommendationsClient.js +70 -849
  148. package/dist/graphStateClassifierClient.d.ts +17 -25
  149. package/dist/graphStateClassifierClient.js +67 -908
  150. package/dist/harnessClient.d.ts +40 -47
  151. package/dist/harnessClient.js +198 -993
  152. package/dist/identityClient.d.ts +25 -33
  153. package/dist/identityClient.js +245 -1186
  154. package/dist/index.d.ts +73 -69
  155. package/dist/index.js +72 -13313
  156. package/dist/infisicalRuntime.d.ts +12 -14
  157. package/dist/infisicalRuntime.js +290 -297
  158. package/dist/jobsClient.d.ts +24 -32
  159. package/dist/jobsClient.js +101 -916
  160. package/dist/learningClient.d.ts +8 -16
  161. package/dist/learningClient.js +45 -809
  162. package/dist/lenses/index.d.ts +13 -65
  163. package/dist/lenses/index.js +11 -10175
  164. package/dist/mcpClient.d.ts +14 -23
  165. package/dist/mcpClient.js +115 -856
  166. package/dist/modelRuntimeClient.d.ts +18 -26
  167. package/dist/modelRuntimeClient.js +74 -894
  168. package/dist/nodes/index.d.ts +7 -58
  169. package/dist/nodes/index.js +14 -10177
  170. package/dist/ontologies/index.d.ts +21 -73
  171. package/dist/ontologies/index.js +14 -10178
  172. package/dist/ontologyClient.d.ts +23 -31
  173. package/dist/ontologyClient.js +138 -924
  174. package/dist/ontologyLinksClient.d.ts +16 -24
  175. package/dist/ontologyLinksClient.js +76 -886
  176. package/dist/opinion.d.ts +5 -6
  177. package/dist/opinion.js +21 -25
  178. package/dist/orgGraphSearchClient.d.ts +19 -27
  179. package/dist/orgGraphSearchClient.js +89 -857
  180. package/dist/packRuntime.d.ts +2 -2
  181. package/dist/packRuntime.js +1 -2
  182. package/dist/packsClient.d.ts +30 -37
  183. package/dist/packsClient.js +131 -906
  184. package/dist/policyClient.d.ts +21 -29
  185. package/dist/policyClient.js +267 -1026
  186. package/dist/proof-attestation.json +1 -1
  187. package/dist/questions/index.d.ts +9 -60
  188. package/dist/questions/index.js +15 -10178
  189. package/dist/realtime/index.d.ts +20 -16
  190. package/dist/realtime/index.js +30 -19
  191. package/dist/realtime/refs.d.ts +4 -6
  192. package/dist/realtime/refs.js +12 -7
  193. package/dist/realtime-refs.d.ts +1 -0
  194. package/dist/realtime-refs.js +1 -0
  195. package/dist/realtime.d.ts +1 -0
  196. package/dist/realtime.js +1 -0
  197. package/dist/reportsClient.d.ts +10 -19
  198. package/dist/reportsClient.js +48 -836
  199. package/dist/schemaClient.d.ts +16 -23
  200. package/dist/schemaClient.js +62 -832
  201. package/dist/sdkSurface.d.ts +18 -25
  202. package/dist/sdkSurface.js +135 -106
  203. package/dist/secrets.d.ts +2 -1
  204. package/dist/secrets.js +1 -2
  205. package/dist/sourcesClient.d.ts +11 -18
  206. package/dist/sourcesClient.js +18 -741
  207. package/dist/telemetryClient.d.ts +22 -30
  208. package/dist/telemetryClient.js +107 -931
  209. package/dist/toolRegistryClient.d.ts +27 -35
  210. package/dist/toolRegistryClient.js +116 -954
  211. package/dist/topics/index.d.ts +13 -64
  212. package/dist/topics/index.js +15 -10178
  213. package/dist/topicsClient.d.ts +19 -27
  214. package/dist/topicsClient.js +106 -894
  215. package/dist/types.d.ts +84 -87
  216. package/dist/types.js +1 -2
  217. package/dist/version.d.ts +2 -3
  218. package/dist/version.js +2 -5
  219. package/dist/workflowClient.d.ts +60 -65
  220. package/dist/workflowClient.js +343 -1219
  221. package/dist/worktrees/index.d.ts +16 -68
  222. package/dist/worktrees/index.js +14 -10178
  223. package/package.json +6 -6
  224. package/dist/accessControl.js.map +0 -1
  225. package/dist/adminClient.js.map +0 -1
  226. package/dist/answersClient.js.map +0 -1
  227. package/dist/audience/index.js.map +0 -1
  228. package/dist/audiencesClient.js.map +0 -1
  229. package/dist/auditClient.js.map +0 -1
  230. package/dist/authContext.js.map +0 -1
  231. package/dist/authDeviceClient.js.map +0 -1
  232. package/dist/beliefs/index.js.map +0 -1
  233. package/dist/beliefs/lifecycle.js.map +0 -1
  234. package/dist/beliefsClient.js.map +0 -1
  235. package/dist/boundaryClientSurface.js.map +0 -1
  236. package/dist/client.js.map +0 -1
  237. package/dist/clientAssemblyTypes.js.map +0 -1
  238. package/dist/clientConfig.js.map +0 -1
  239. package/dist/clientEvidenceCompat.js.map +0 -1
  240. package/dist/clientGraphNamespaces.js.map +0 -1
  241. package/dist/clientHelpers.js.map +0 -1
  242. package/dist/clientKnowledgeNamespaces.js.map +0 -1
  243. package/dist/clientLocalHelpers.js.map +0 -1
  244. package/dist/clientPlatformNamespaces.js.map +0 -1
  245. package/dist/clientRuntime.js.map +0 -1
  246. package/dist/clientWorkflowNamespaces.js.map +0 -1
  247. package/dist/contextClient.js.map +0 -1
  248. package/dist/contextFacade.js.map +0 -1
  249. package/dist/contextPackCompiler.js.map +0 -1
  250. package/dist/contextPackPolicy.js.map +0 -1
  251. package/dist/contextPackSchema.js.map +0 -1
  252. package/dist/contextTypes.js.map +0 -1
  253. package/dist/contracts/api-enums.contract.js.map +0 -1
  254. package/dist/contracts/auth-session.contract.js.map +0 -1
  255. package/dist/contracts/context-pack.contract.js.map +0 -1
  256. package/dist/contracts/contextPack.js.map +0 -1
  257. package/dist/contracts/index.js.map +0 -1
  258. package/dist/contracts/lens-filter.contract.js.map +0 -1
  259. package/dist/contracts/lens-workflow.contract.js.map +0 -1
  260. package/dist/contracts/lensFilter.js.map +0 -1
  261. package/dist/contracts/lensWorkflow.js.map +0 -1
  262. package/dist/contracts/mcpTools.js.map +0 -1
  263. package/dist/contracts/prompt.contract.js.map +0 -1
  264. package/dist/contracts/prompt.js.map +0 -1
  265. package/dist/contracts/sdk-tools.contract.js.map +0 -1
  266. package/dist/contracts/sdkTools.js.map +0 -1
  267. package/dist/contracts/tool-contracts.js.map +0 -1
  268. package/dist/contracts/workflow-runtime.contract.js.map +0 -1
  269. package/dist/contracts/workflowRuntime.js.map +0 -1
  270. package/dist/contradictions/index.js.map +0 -1
  271. package/dist/control-plane.js.map +0 -1
  272. package/dist/controlObjectOwnership.js.map +0 -1
  273. package/dist/coreClient.js.map +0 -1
  274. package/dist/customTools.js.map +0 -1
  275. package/dist/decisions/index.js.map +0 -1
  276. package/dist/decisionsClient.js.map +0 -1
  277. package/dist/domainContext.js.map +0 -1
  278. package/dist/edges/index.js.map +0 -1
  279. package/dist/embeddingsClient.js.map +0 -1
  280. package/dist/eventingClient.js.map +0 -1
  281. package/dist/events.js.map +0 -1
  282. package/dist/eventsCore.js.map +0 -1
  283. package/dist/evidence/index.js.map +0 -1
  284. package/dist/evidenceClient.js.map +0 -1
  285. package/dist/facade/context.js.map +0 -1
  286. package/dist/functionSurface.js.map +0 -1
  287. package/dist/functionSurfaceClient.js.map +0 -1
  288. package/dist/gatewayFacades.factories.js.map +0 -1
  289. package/dist/gatewayFacades.js.map +0 -1
  290. package/dist/graphAnalysisClient.js.map +0 -1
  291. package/dist/graphClient.js.map +0 -1
  292. package/dist/graphIntel.js.map +0 -1
  293. package/dist/graphIntelligence.js.map +0 -1
  294. package/dist/graphRecommendationsClient.js.map +0 -1
  295. package/dist/graphStateClassifierClient.js.map +0 -1
  296. package/dist/harnessClient.js.map +0 -1
  297. package/dist/identityClient.js.map +0 -1
  298. package/dist/index.js.map +0 -1
  299. package/dist/infisicalRuntime.js.map +0 -1
  300. package/dist/jobsClient.js.map +0 -1
  301. package/dist/learningClient.js.map +0 -1
  302. package/dist/lenses/index.js.map +0 -1
  303. package/dist/mcpClient.js.map +0 -1
  304. package/dist/modelRuntimeClient.js.map +0 -1
  305. package/dist/nodes/index.js.map +0 -1
  306. package/dist/ontologies/index.js.map +0 -1
  307. package/dist/ontologyClient.js.map +0 -1
  308. package/dist/ontologyLinksClient.js.map +0 -1
  309. package/dist/opinion.js.map +0 -1
  310. package/dist/orgGraphSearchClient.js.map +0 -1
  311. package/dist/packRuntime.js.map +0 -1
  312. package/dist/packsClient.js.map +0 -1
  313. package/dist/policyClient.js.map +0 -1
  314. package/dist/questions/index.js.map +0 -1
  315. package/dist/realtime/index.js.map +0 -1
  316. package/dist/realtime/refs.js.map +0 -1
  317. package/dist/reportsClient.js.map +0 -1
  318. package/dist/schemaClient.js.map +0 -1
  319. package/dist/sdk-tools.contract-B4c1Zr1o.d.ts +0 -22
  320. package/dist/sdkSurface.js.map +0 -1
  321. package/dist/secrets.js.map +0 -1
  322. package/dist/sourcesClient.js.map +0 -1
  323. package/dist/telemetryClient.js.map +0 -1
  324. package/dist/tool-contracts-BUiL9P6z.d.ts +0 -22
  325. package/dist/toolRegistryClient.js.map +0 -1
  326. package/dist/topics/index.js.map +0 -1
  327. package/dist/topicsClient.js.map +0 -1
  328. package/dist/types.js.map +0 -1
  329. package/dist/version.js.map +0 -1
  330. package/dist/workflowClient.js.map +0 -1
  331. package/dist/worktrees/index.js.map +0 -1
@@ -1,1080 +1,534 @@
1
- // src/contracts/context-pack.contract.ts
2
- var CONTEXT_PACK_SCHEMA_VERSION = "1.0.0";
3
- var DEFAULT_COMPILATION_MODE = "standard";
4
- var SECTION_BUDGET_RATIOS = {
5
- invariants: 0.28,
6
- activeBeliefs: 0.3,
7
- openQuestions: 0.17,
8
- recentEvidence: 0.17,
9
- contradictions: 0.08
10
- };
11
- var MIN_TOKEN_BUDGET = 400;
12
- var MAX_TOKEN_BUDGET = 8e3;
13
- var DEFAULT_TOKEN_BUDGET = 1800;
14
- var MIN_CONTRADICTION_BUDGET = 40;
15
- var RANKING_WEIGHTS = {
16
- invariants: {
17
- query: 0.35,
18
- recency: 0.1,
19
- confidence: 0.4,
20
- beliefType: 0.15
21
- },
22
- activeBeliefs: {
23
- query: 0.5,
24
- recency: 0.2,
25
- confidence: 0.2,
26
- beliefType: 0.1
27
- },
28
- openQuestions: {
29
- query: 0.55,
30
- recency: 0.2,
31
- priority: 0.25
32
- },
33
- recentEvidence: {
34
- query: 0.6,
35
- recency: 0.4
36
- },
37
- contradictions: {
38
- query: 0.4,
39
- recency: 0.2,
40
- severity: 0.4
41
- }
42
- };
43
- var RECENCY_HALF_LIFE_DAYS = 30;
44
- var ENTITY_RANKING_WEIGHTS = {
45
- query: 0.4,
46
- connectivity: 0.6
47
- };
48
- var DEFAULT_ENTITY_LIMIT = 10;
49
- var MAX_ENTITY_LIMIT = 50;
50
- var BELIEF_TYPE_BONUS = {
51
- invariant: 1,
52
- tenet: 0.8,
53
- principle: 0.6
54
- };
55
- var DEFAULT_BELIEF_TYPE_BONUS = 0.4;
56
- var PRIORITY_SCORES = {
57
- critical: 1,
58
- high: 0.85,
59
- medium: 0.55,
60
- low: 0.35
61
- };
62
- var DEFAULT_PRIORITY_SCORE = 0.5;
63
- var SEVERITY_SCORES = {
64
- critical: 1,
65
- high: 0.85,
66
- medium: 0.6,
67
- low: 0.35
68
- };
69
- var DEFAULT_SEVERITY_SCORE = 0.5;
70
- var TOKENS_PER_WORD = 1.35;
71
- var MIN_TOKEN_ESTIMATE = 8;
72
-
73
- // src/contextPackPolicy.ts
74
- function tokenHits(text, tokens) {
75
- if (tokens.length === 0) {
76
- return 1;
77
- }
78
- const haystack = text.trim().toLowerCase();
79
- let hits = 0;
80
- for (const token of tokens) {
81
- if (haystack.includes(token)) {
82
- hits += 1;
83
- }
84
- }
85
- return hits;
86
- }
87
- function clamp01(value) {
88
- if (!Number.isFinite(value)) {
89
- return 0;
90
- }
91
- return Math.max(0, Math.min(1, value));
92
- }
93
- function recencyScore(updatedAt, referenceTimeMs = Date.now()) {
94
- if (!updatedAt || !Number.isFinite(updatedAt)) {
95
- return 0.25;
96
- }
97
- const ageMs = Math.max(0, referenceTimeMs - updatedAt);
98
- const ageDays = ageMs / (1e3 * 60 * 60 * 24);
99
- const decay = 0.5 ** (ageDays / RECENCY_HALF_LIFE_DAYS);
100
- return clamp01(decay);
101
- }
102
- function confidenceScore(confidence) {
103
- if (typeof confidence !== "number" || !Number.isFinite(confidence)) {
104
- return 0.5;
105
- }
106
- return clamp01(confidence);
107
- }
108
- function priorityScore(priority) {
109
- const value = (priority || "").trim().toLowerCase();
110
- return PRIORITY_SCORES[value] ?? DEFAULT_PRIORITY_SCORE;
111
- }
112
- function severityScore(severity) {
113
- const value = (severity || "").trim().toLowerCase();
114
- return SEVERITY_SCORES[value] ?? DEFAULT_SEVERITY_SCORE;
115
- }
116
- function beliefTypeBonus(beliefType) {
117
- const value = (beliefType || "").trim().toLowerCase();
118
- return BELIEF_TYPE_BONUS[value] ?? DEFAULT_BELIEF_TYPE_BONUS;
119
- }
120
- function resolveEffectiveWeights(overrides) {
121
- if (!overrides || overrides.length === 0) {
122
- return RANKING_WEIGHTS;
123
- }
124
- const result = { ...RANKING_WEIGHTS };
125
- for (const override of overrides) {
126
- const base = RANKING_WEIGHTS[override.section];
127
- if (base) {
128
- result[override.section] = { ...base, ...override.weights };
129
- }
130
- }
131
- return result;
132
- }
133
- function generateJustification(_section, candidate, queryTokens, weights) {
134
- const parts = [];
135
- const hits = tokenHits(candidate.text, queryTokens);
136
- if (queryTokens.length > 0 && hits > 0) {
137
- parts.push(`${hits}/${queryTokens.length} query terms matched`);
138
- } else if (queryTokens.length === 0) {
139
- parts.push("no query filter");
140
- }
141
- const ts = candidate.updatedAt || candidate.createdAt || null;
142
- if (ts && Number.isFinite(ts)) {
143
- const ageDays = Math.max(0, Date.now() - ts) / (1e3 * 60 * 60 * 24);
144
- if (ageDays < 1) {
145
- parts.push("updated today");
146
- } else if (ageDays < 7) {
147
- parts.push(`updated ${Math.floor(ageDays)}d ago`);
148
- } else if (ageDays < 30) {
149
- parts.push(`updated ${Math.floor(ageDays / 7)}w ago`);
150
- } else {
151
- parts.push(`updated ${Math.floor(ageDays)}d ago (decayed)`);
152
- }
153
- }
154
- if (weights.confidence !== void 0 && candidate.confidence !== null && candidate.confidence !== void 0) {
155
- parts.push(`confidence=${candidate.confidence.toFixed(2)}`);
156
- }
157
- if (weights.beliefType !== void 0 && candidate.beliefType) {
158
- parts.push(`type=${candidate.beliefType}`);
159
- }
160
- if (weights.priority !== void 0 && candidate.priority) {
161
- parts.push(`priority=${candidate.priority}`);
162
- }
163
- if (weights.severity !== void 0 && candidate.severity) {
164
- parts.push(`severity=${candidate.severity}`);
165
- }
166
- return parts.join(", ");
167
- }
168
- function computeWeightedScore(section, candidate, queryTokens, effectiveWeights, referenceTimeMs) {
169
- const weights = (effectiveWeights ?? RANKING_WEIGHTS)[section];
170
- const queryComponent = queryTokens.length === 0 ? 0.4 : clamp01(tokenHits(candidate.text, queryTokens) / queryTokens.length);
171
- const recencyComponent = recencyScore(
172
- candidate.updatedAt || candidate.createdAt || null,
173
- referenceTimeMs
174
- );
175
- let score = queryComponent * weights.query + recencyComponent * weights.recency;
176
- if (weights.confidence !== void 0) {
177
- score += confidenceScore(candidate.confidence) * weights.confidence;
178
- }
179
- if (weights.beliefType !== void 0) {
180
- score += beliefTypeBonus(candidate.beliefType) * weights.beliefType;
181
- }
182
- if (weights.priority !== void 0) {
183
- score += priorityScore(candidate.priority) * weights.priority;
184
- }
185
- if (weights.severity !== void 0) {
186
- score += severityScore(candidate.severity) * weights.severity;
187
- }
188
- return score;
189
- }
190
- function rankContextSection(section, rows, queryTokens, limit, profile, options) {
191
- const effectiveWeights = options?.effectiveWeights;
192
- const includeJustifications = options?.includeJustifications ?? false;
193
- const referenceTimeMs = options?.referenceTimeMs;
194
- const scored = rows.map((row) => {
195
- const score = profile === "weighted_v1" ? computeWeightedScore(
196
- section,
197
- row,
198
- queryTokens,
199
- effectiveWeights,
200
- referenceTimeMs
201
- ) : queryTokens.length === 0 ? 1 : tokenHits(row.text, queryTokens);
202
- const result = { ...row, score };
203
- if (includeJustifications && profile === "weighted_v1") {
204
- const weights = (effectiveWeights ?? RANKING_WEIGHTS)[section];
205
- result.justification = generateJustification(section, row, queryTokens, weights);
206
- }
207
- return result;
208
- });
209
- const filtered = queryTokens.length === 0 ? scored : scored.filter((row) => row.score > 0);
210
- filtered.sort((left, right) => {
211
- if (right.score !== left.score) {
212
- return right.score - left.score;
213
- }
214
- const rightTs = right.updatedAt || right.createdAt || 0;
215
- const leftTs = left.updatedAt || left.createdAt || 0;
216
- return rightTs - leftTs;
217
- });
218
- return filtered.slice(0, limit);
219
- }
220
- function parseTokenBudget(value, fallback = DEFAULT_TOKEN_BUDGET) {
221
- const parsed = typeof value === "number" && Number.isFinite(value) ? Math.floor(value) : fallback;
222
- return Math.max(MIN_TOKEN_BUDGET, Math.min(MAX_TOKEN_BUDGET, parsed));
223
- }
224
- function estimateTokens(text) {
225
- const words = text.trim().split(/\s+/).filter(Boolean).length;
226
- return Math.max(MIN_TOKEN_ESTIMATE, Math.ceil(words * TOKENS_PER_WORD));
227
- }
228
- function buildInjectionPlan(args) {
229
- const tokenBudget = parseTokenBudget(args.tokenBudget);
230
- const trackExclusions = args.trackExclusions ?? false;
231
- const sectionBudgets = {
232
- invariants: Math.floor(tokenBudget * SECTION_BUDGET_RATIOS.invariants),
233
- activeBeliefs: Math.floor(
234
- tokenBudget * SECTION_BUDGET_RATIOS.activeBeliefs
235
- ),
236
- openQuestions: Math.floor(
237
- tokenBudget * SECTION_BUDGET_RATIOS.openQuestions
238
- ),
239
- recentEvidence: Math.floor(
240
- tokenBudget * SECTION_BUDGET_RATIOS.recentEvidence
241
- ),
242
- contradictions: Math.max(
243
- MIN_CONTRADICTION_BUDGET,
244
- Math.floor(tokenBudget * SECTION_BUDGET_RATIOS.contradictions)
245
- )
246
- };
247
- const selected = {
248
- invariants: [],
249
- activeBeliefs: [],
250
- openQuestions: [],
251
- recentEvidence: [],
252
- contradictions: []
253
- };
254
- const sectionUsage = {
255
- invariants: 0,
256
- activeBeliefs: 0,
257
- openQuestions: 0,
258
- recentEvidence: 0,
259
- contradictions: 0
260
- };
261
- const excludedItems = [];
262
- const pushItem = (section, id, text, score) => {
263
- const itemTokens = estimateTokens(text);
264
- const nextUsage = sectionUsage[section] + itemTokens;
265
- if (nextUsage > sectionBudgets[section]) {
266
- if (trackExclusions) {
267
- excludedItems.push({
268
- id,
269
- section,
270
- reason: "budget_exceeded",
271
- score: score ?? 0
272
- });
273
- }
274
- return;
275
- }
276
- selected[section].push(id);
277
- sectionUsage[section] = nextUsage;
278
- };
279
- for (const row of args.invariants) {
280
- pushItem("invariants", row.nodeId, row.canonicalText, row.score);
281
- }
282
- for (const row of args.activeBeliefs) {
283
- pushItem("activeBeliefs", row.nodeId, row.canonicalText, row.score);
284
- }
285
- for (const row of args.openQuestions) {
286
- pushItem("openQuestions", row.questionId, row.text, row.score);
287
- }
288
- for (const row of args.recentEvidence) {
289
- pushItem("recentEvidence", row.nodeId, row.canonicalText, row.score);
290
- }
291
- for (const row of args.contradictions) {
292
- pushItem("contradictions", row.contradictionId, row.description, row.score);
293
- }
294
- const estimatedTokens = sectionUsage.invariants + sectionUsage.activeBeliefs + sectionUsage.openQuestions + sectionUsage.recentEvidence + sectionUsage.contradictions;
295
- return {
296
- tokenBudget,
297
- estimatedTokens,
298
- sectionBudgets,
299
- sectionUsage,
300
- selected,
301
- ...trackExclusions ? { excludedItems } : {}
302
- };
303
- }
304
- function rankEntities(candidates, queryTokens, limit) {
305
- if (candidates.length === 0) {
306
- return [];
307
- }
308
- const effectiveLimit = Math.max(
309
- 1,
310
- Math.min(limit ?? DEFAULT_ENTITY_LIMIT, MAX_ENTITY_LIMIT)
311
- );
312
- const maxConnections = Math.max(
313
- 1,
314
- ...candidates.map(
315
- (candidate) => candidate.connectedBeliefCount + candidate.connectedEvidenceCount
316
- )
317
- );
318
- const scored = candidates.map((candidate) => {
319
- const searchText = `${candidate.title} ${candidate.entityType} ${candidate.canonicalText}`;
320
- const queryScore = queryTokens.length === 0 ? 0.4 : clamp01(tokenHits(searchText, queryTokens) / queryTokens.length);
321
- const totalConnections = candidate.connectedBeliefCount + candidate.connectedEvidenceCount;
322
- const connectivityScore = clamp01(totalConnections / maxConnections);
323
- const score = queryScore * ENTITY_RANKING_WEIGHTS.query + connectivityScore * ENTITY_RANKING_WEIGHTS.connectivity;
324
- return { ...candidate, score };
325
- });
326
- scored.sort((left, right) => {
327
- if (right.score !== left.score) {
328
- return right.score - left.score;
329
- }
330
- const rightConn = right.connectedBeliefCount + right.connectedEvidenceCount;
331
- const leftConn = left.connectedBeliefCount + left.connectedEvidenceCount;
332
- return rightConn - leftConn;
333
- });
334
- return scored.slice(0, effectiveLimit);
335
- }
336
-
337
- // src/contextPackSchema.ts
338
- var CONTEXT_PACK_SCHEMA_VERSION2 = "1.0.0";
339
- function isObject(value) {
340
- return typeof value === "object" && value !== null && !Array.isArray(value);
341
- }
342
- function isString(value) {
343
- return typeof value === "string";
344
- }
345
- function isNumber(value) {
346
- return typeof value === "number" && Number.isFinite(value);
347
- }
348
- function isNullableNumber(value) {
349
- return value === null || isNumber(value);
350
- }
351
- function isStringArray(value) {
352
- return Array.isArray(value) && value.every((entry) => isString(entry));
353
- }
354
- function requireObject(parent, key, errors) {
355
- const value = parent[key];
356
- if (!isObject(value)) {
357
- errors.push(`Expected '${key}' to be an object`);
358
- return null;
359
- }
360
- return value;
361
- }
362
- function validateBeliefArray(key, value, errors) {
363
- if (!Array.isArray(value)) {
364
- errors.push(`Expected '${key}' to be an array`);
365
- return;
366
- }
367
- for (let index = 0; index < value.length; index += 1) {
368
- const row = value[index];
369
- if (!isObject(row)) {
370
- errors.push(`Expected '${key}[${index}]' to be an object`);
371
- continue;
372
- }
373
- if (!isString(row.nodeId)) {
374
- errors.push(`Expected '${key}[${index}].nodeId' to be a string`);
375
- }
376
- if (!isString(row.canonicalText)) {
377
- errors.push(`Expected '${key}[${index}].canonicalText' to be a string`);
378
- }
379
- if (!isNullableNumber(row.confidence)) {
380
- errors.push(`Expected '${key}[${index}].confidence' to be number|null`);
381
- }
382
- }
383
- }
384
- function validateQuestionArray(key, value, errors) {
385
- if (!Array.isArray(value)) {
386
- errors.push(`Expected '${key}' to be an array`);
387
- return;
388
- }
389
- for (let index = 0; index < value.length; index += 1) {
390
- const row = value[index];
391
- if (!isObject(row)) {
392
- errors.push(`Expected '${key}[${index}]' to be an object`);
393
- continue;
394
- }
395
- if (!isString(row.questionId)) {
396
- errors.push(`Expected '${key}[${index}].questionId' to be a string`);
397
- }
398
- if (!isString(row.text)) {
399
- errors.push(`Expected '${key}[${index}].text' to be a string`);
400
- }
401
- if (!isString(row.status)) {
402
- errors.push(`Expected '${key}[${index}].status' to be a string`);
403
- }
404
- }
405
- }
406
- function validateEvidenceArray(key, value, errors) {
407
- if (!Array.isArray(value)) {
408
- errors.push(`Expected '${key}' to be an array`);
409
- return;
410
- }
411
- for (let index = 0; index < value.length; index += 1) {
412
- const row = value[index];
413
- if (!isObject(row)) {
414
- errors.push(`Expected '${key}[${index}]' to be an object`);
415
- continue;
416
- }
417
- if (!isString(row.nodeId)) {
418
- errors.push(`Expected '${key}[${index}].nodeId' to be a string`);
419
- }
420
- if (!isString(row.canonicalText)) {
421
- errors.push(`Expected '${key}[${index}].canonicalText' to be a string`);
422
- }
423
- }
424
- }
425
- function validateEntityArray(key, value, errors) {
426
- if (!Array.isArray(value)) {
427
- errors.push(`Expected '${key}' to be an array`);
428
- return;
429
- }
430
- for (let index = 0; index < value.length; index += 1) {
431
- const row = value[index];
432
- if (!isObject(row)) {
433
- errors.push(`Expected '${key}[${index}]' to be an object`);
434
- continue;
435
- }
436
- if (!isString(row.nodeId)) {
437
- errors.push(`Expected '${key}[${index}].nodeId' to be a string`);
438
- }
439
- if (!isString(row.entityType)) {
440
- errors.push(`Expected '${key}[${index}].entityType' to be a string`);
441
- }
442
- if (!isString(row.title)) {
443
- errors.push(`Expected '${key}[${index}].title' to be a string`);
444
- }
445
- if (!isNumber(row.connectedBeliefCount)) {
446
- errors.push(`Expected '${key}[${index}].connectedBeliefCount' to be a number`);
447
- }
448
- if (!isNumber(row.connectedEvidenceCount)) {
449
- errors.push(`Expected '${key}[${index}].connectedEvidenceCount' to be a number`);
450
- }
451
- if (!isNumber(row.score)) {
452
- errors.push(`Expected '${key}[${index}].score' to be a number`);
453
- }
454
- }
455
- }
456
- function validateContradictionArray(key, value, errors) {
457
- if (!Array.isArray(value)) {
458
- errors.push(`Expected '${key}' to be an array`);
459
- return;
460
- }
461
- for (let index = 0; index < value.length; index += 1) {
462
- const row = value[index];
463
- if (!isObject(row)) {
464
- errors.push(`Expected '${key}[${index}]' to be an object`);
465
- continue;
466
- }
467
- if (!isString(row.contradictionId)) {
468
- errors.push(`Expected '${key}[${index}].contradictionId' to be a string`);
469
- }
470
- if (!isString(row.status)) {
471
- errors.push(`Expected '${key}[${index}].status' to be a string`);
472
- }
473
- }
474
- }
475
- function validateContextPackSchema(payload) {
476
- const errors = [];
477
- if (!isObject(payload)) {
478
- return {
479
- valid: false,
480
- errors: ["Expected context pack payload to be an object"]
481
- };
482
- }
483
- if (payload.schemaVersion !== CONTEXT_PACK_SCHEMA_VERSION2) {
484
- errors.push(
485
- `Expected schemaVersion='${CONTEXT_PACK_SCHEMA_VERSION2}', received '${String(
486
- payload.schemaVersion
487
- )}'`
488
- );
489
- }
490
- if (!isString(payload.topicId)) {
491
- errors.push("Expected 'topicId' to be a string");
492
- }
493
- if (!isString(payload.topicName)) {
494
- errors.push("Expected 'topicName' to be a string");
495
- }
496
- if (!isStringArray(payload.scopedTopicIds)) {
497
- errors.push("Expected 'scopedTopicIds' to be string[]");
498
- }
499
- if (!isNumber(payload.generatedAt)) {
500
- errors.push("Expected 'generatedAt' to be a number");
501
- }
502
- if (!isString(payload.ranking)) {
503
- errors.push("Expected 'ranking' to be a string");
504
- }
505
- validateBeliefArray("invariants", payload.invariants, errors);
506
- validateBeliefArray("activeBeliefs", payload.activeBeliefs, errors);
507
- validateQuestionArray("openQuestions", payload.openQuestions, errors);
508
- validateEvidenceArray("recentEvidence", payload.recentEvidence, errors);
509
- validateContradictionArray("contradictions", payload.contradictions, errors);
510
- if (payload.relatedEntities !== void 0 && payload.relatedEntities !== null) {
511
- validateEntityArray("relatedEntities", payload.relatedEntities, errors);
512
- }
513
- if (!Array.isArray(payload.contextNarrative)) {
514
- errors.push("Expected 'contextNarrative' to be an array");
515
- }
516
- const injectionPolicy = requireObject(payload, "injectionPolicy", errors);
517
- if (injectionPolicy) {
518
- if (!isNumber(injectionPolicy.tokenBudget)) {
519
- errors.push("Expected 'injectionPolicy.tokenBudget' to be a number");
520
- }
521
- if (!isNumber(injectionPolicy.estimatedTokens)) {
522
- errors.push("Expected 'injectionPolicy.estimatedTokens' to be a number");
523
- }
524
- }
525
- if (!isObject(payload.summary)) {
526
- errors.push("Expected 'summary' to be an object");
527
- }
528
- if (!isObject(payload.diagnostics)) {
529
- errors.push("Expected 'diagnostics' to be an object");
530
- }
531
- return {
532
- valid: errors.length === 0,
533
- errors
534
- };
535
- }
536
-
537
- // src/contextPackCompiler.ts
1
+ import { CONTEXT_PACK_SCHEMA_VERSION, DEFAULT_COMPILATION_MODE, DEFAULT_ENTITY_LIMIT, MAX_ENTITY_LIMIT, } from "./contracts/context-pack.contract.js";
2
+ import { buildInjectionPlan, parseTokenBudget, rankContextSection, rankEntities, resolveEffectiveWeights, } from "./contextPackPolicy.js";
3
+ import { validateContextPackSchema } from "./contextPackSchema.js";
538
4
  function assertContextPackSchema(payload) {
539
- const result = validateContextPackSchema(payload);
540
- if (!result.valid) {
541
- throw new Error(
542
- `Invalid context pack payload: ${result.errors.join("; ")}`
543
- );
544
- }
5
+ const result = validateContextPackSchema(payload);
6
+ if (!result.valid) {
7
+ throw new Error(`Invalid context pack payload: ${result.errors.join("; ")}`);
8
+ }
545
9
  }
546
10
  function asStringArray(value) {
547
- if (!Array.isArray(value)) {
548
- return [];
549
- }
550
- return value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter((entry) => entry.length > 0);
11
+ if (!Array.isArray(value)) {
12
+ return [];
13
+ }
14
+ return value
15
+ .map((entry) => (typeof entry === "string" ? entry.trim() : ""))
16
+ .filter((entry) => entry.length > 0);
551
17
  }
552
18
  function toPositiveInt(value, fallback, max) {
553
- if (typeof value !== "number" || !Number.isFinite(value)) {
554
- return fallback;
555
- }
556
- const floored = Math.floor(value);
557
- return Math.max(1, Math.min(floored, max));
19
+ if (typeof value !== "number" || !Number.isFinite(value)) {
20
+ return fallback;
21
+ }
22
+ const floored = Math.floor(value);
23
+ return Math.max(1, Math.min(floored, max));
558
24
  }
559
25
  function normalizeQueryTokens(query) {
560
- if (!query) {
561
- return [];
562
- }
563
- return query.toLowerCase().split(/[^a-z0-9]+/).map((token) => token.trim()).filter((token) => token.length >= 2);
26
+ if (!query) {
27
+ return [];
28
+ }
29
+ return query
30
+ .toLowerCase()
31
+ .split(/[^a-z0-9]+/)
32
+ .map((token) => token.trim())
33
+ .filter((token) => token.length >= 2);
564
34
  }
565
35
  function parseRankingProfile(value) {
566
- return value === "baseline_v1" ? "baseline_v1" : "weighted_v1";
36
+ return value === "baseline_v1" ? "baseline_v1" : "weighted_v1";
567
37
  }
568
38
  function isRecord(value) {
569
- return value !== null && typeof value === "object" && !Array.isArray(value);
39
+ return value !== null && typeof value === "object" && !Array.isArray(value);
570
40
  }
571
41
  function beliefTypeOf(node) {
572
- if (typeof node.beliefType === "string") {
573
- return node.beliefType;
574
- }
575
- const metadata = isRecord(node.metadata) ? node.metadata : {};
576
- if (typeof metadata.beliefType === "string") {
577
- return metadata.beliefType;
578
- }
579
- return "";
42
+ if (typeof node.beliefType === "string") {
43
+ return node.beliefType;
44
+ }
45
+ const metadata = isRecord(node.metadata) ? node.metadata : {};
46
+ if (typeof metadata.beliefType === "string") {
47
+ return metadata.beliefType;
48
+ }
49
+ return "";
580
50
  }
581
51
  function questionStatusOf(node) {
582
- const metadata = isRecord(node.metadata) ? node.metadata : {};
583
- const direct = typeof node.status === "string" ? node.status : "";
584
- const questionStatus = typeof metadata.questionStatus === "string" ? metadata.questionStatus : "";
585
- return (questionStatus || direct || "open").toLowerCase();
52
+ const metadata = isRecord(node.metadata) ? node.metadata : {};
53
+ const direct = typeof node.status === "string" ? node.status : "";
54
+ const questionStatus = typeof metadata.questionStatus === "string" ? metadata.questionStatus : "";
55
+ return (questionStatus || direct || "open").toLowerCase();
586
56
  }
587
57
  function isOpenQuestion(status) {
588
- return ![
589
- "answered",
590
- "archived",
591
- "closed",
592
- "resolved",
593
- "resolved_support",
594
- "resolved_contra",
595
- "belief_forked"
596
- ].includes(status);
58
+ return ![
59
+ "answered",
60
+ "archived",
61
+ "closed",
62
+ "resolved",
63
+ "resolved_support",
64
+ "resolved_contra",
65
+ "belief_forked",
66
+ ].includes(status);
597
67
  }
598
68
  function collectTopicNeighborhood(topics, rootTopicId, maxDescendantDepth = 2) {
599
- const byId = /* @__PURE__ */ new Map();
600
- const children = /* @__PURE__ */ new Map();
601
- for (const topic of topics) {
602
- const id = String(topic._id);
603
- byId.set(id, topic);
604
- if (!children.has(id)) {
605
- children.set(id, []);
606
- }
607
- }
608
- for (const topic of topics) {
609
- if (!topic.parentTopicId) {
610
- continue;
611
- }
612
- const parent = String(topic.parentTopicId);
613
- const id = String(topic._id);
614
- const list = children.get(parent) || [];
615
- list.push(id);
616
- children.set(parent, list);
617
- }
618
- const selected = /* @__PURE__ */ new Set([rootTopicId]);
619
- let cursor = byId.get(rootTopicId);
620
- while (cursor?.parentTopicId) {
621
- const parentId = String(cursor.parentTopicId);
622
- if (selected.has(parentId)) {
623
- break;
624
- }
625
- selected.add(parentId);
626
- cursor = byId.get(parentId);
627
- }
628
- const queue = [
629
- { id: rootTopicId, depth: 0 }
630
- ];
631
- while (queue.length > 0) {
632
- const current = queue.shift();
633
- if (!current || current.depth >= maxDescendantDepth) {
634
- continue;
69
+ const byId = new Map();
70
+ const children = new Map();
71
+ for (const topic of topics) {
72
+ const id = String(topic._id);
73
+ byId.set(id, topic);
74
+ if (!children.has(id)) {
75
+ children.set(id, []);
76
+ }
635
77
  }
636
- for (const childId of children.get(current.id) || []) {
637
- if (!selected.has(childId)) {
638
- selected.add(childId);
639
- }
640
- queue.push({ id: childId, depth: current.depth + 1 });
78
+ for (const topic of topics) {
79
+ if (!topic.parentTopicId) {
80
+ continue;
81
+ }
82
+ const parent = String(topic.parentTopicId);
83
+ const id = String(topic._id);
84
+ const list = children.get(parent) || [];
85
+ list.push(id);
86
+ children.set(parent, list);
87
+ }
88
+ const selected = new Set([rootTopicId]);
89
+ let cursor = byId.get(rootTopicId);
90
+ while (cursor?.parentTopicId) {
91
+ const parentId = String(cursor.parentTopicId);
92
+ if (selected.has(parentId)) {
93
+ break;
94
+ }
95
+ selected.add(parentId);
96
+ cursor = byId.get(parentId);
97
+ }
98
+ const queue = [
99
+ { id: rootTopicId, depth: 0 },
100
+ ];
101
+ while (queue.length > 0) {
102
+ const current = queue.shift();
103
+ if (!current || current.depth >= maxDescendantDepth) {
104
+ continue;
105
+ }
106
+ for (const childId of children.get(current.id) || []) {
107
+ if (!selected.has(childId)) {
108
+ selected.add(childId);
109
+ }
110
+ queue.push({ id: childId, depth: current.depth + 1 });
111
+ }
641
112
  }
642
- }
643
- return Array.from(selected);
113
+ return Array.from(selected);
644
114
  }
645
115
  function dedupeById(rows) {
646
- const seen = /* @__PURE__ */ new Set();
647
- const output = [];
648
- for (const row of rows) {
649
- const id = row?._id ? String(row._id) : "";
650
- if (!id || seen.has(id)) {
651
- continue;
116
+ const seen = new Set();
117
+ const output = [];
118
+ for (const row of rows) {
119
+ const id = row?._id ? String(row._id) : "";
120
+ if (!id || seen.has(id)) {
121
+ continue;
122
+ }
123
+ seen.add(id);
124
+ output.push(row);
652
125
  }
653
- seen.add(id);
654
- output.push(row);
655
- }
656
- return output;
126
+ return output;
657
127
  }
658
128
  function candidateTimestamp(candidate) {
659
- if (!isRecord(candidate)) {
660
- return 0;
661
- }
662
- const timestamps = [candidate.updatedAt, candidate.createdAt, candidate.generatedAt].filter(
663
- (value) => typeof value === "number" && Number.isFinite(value)
664
- );
665
- return timestamps.length > 0 ? Math.max(...timestamps) : 0;
129
+ if (!isRecord(candidate)) {
130
+ return 0;
131
+ }
132
+ const timestamps = [candidate.updatedAt, candidate.createdAt, candidate.generatedAt].filter((value) => typeof value === "number" && Number.isFinite(value));
133
+ return timestamps.length > 0 ? Math.max(...timestamps) : 0;
666
134
  }
667
135
  function resolveReferenceTimeMs(...collections) {
668
- let maxTimestamp = 0;
669
- for (const collection of collections) {
670
- for (const item of collection) {
671
- const timestamp = candidateTimestamp(item);
672
- if (timestamp > maxTimestamp) {
673
- maxTimestamp = timestamp;
674
- }
136
+ let maxTimestamp = 0;
137
+ for (const collection of collections) {
138
+ for (const item of collection) {
139
+ const timestamp = candidateTimestamp(item);
140
+ if (timestamp > maxTimestamp) {
141
+ maxTimestamp = timestamp;
142
+ }
143
+ }
675
144
  }
676
- }
677
- return maxTimestamp;
678
- }
679
- function planContextPackCompilation(input) {
680
- const args = input.args ?? {};
681
- const topicId = String(input.topic._id);
682
- const queryText = typeof args.query === "string" && args.query.trim().length > 0 ? args.query.trim() : void 0;
683
- const tokens = normalizeQueryTokens(queryText);
684
- const limit = toPositiveInt(args.limit, 8, 25);
685
- const rankingProfile = parseRankingProfile(
686
- typeof args.ranking === "string" ? args.ranking : args.rankingProfile
687
- );
688
- const tokenBudget = parseTokenBudget(
689
- typeof args.budget === "number" ? args.budget : args.tokenBudget,
690
- 1800
691
- );
692
- const topicDepth = typeof input.topic.depth === "number" && Number.isFinite(input.topic.depth) ? input.topic.depth : 0;
693
- const requestedMaxDepth = typeof args.maxDepth === "number" && Number.isFinite(args.maxDepth) ? Math.max(1, Math.min(Math.floor(args.maxDepth), 6)) : void 0;
694
- const descendantDepth = requestedMaxDepth ?? (topicDepth <= 1 ? 4 : 2);
695
- const includeEntities = args.includeEntities !== false;
696
- const compilationMode = args.mode === "delta" ? "delta" : DEFAULT_COMPILATION_MODE;
697
- const includeFailures = compilationMode === "delta" || args.includeFailures === true;
698
- const worktreeId = typeof args.worktreeId === "string" && args.worktreeId.trim().length > 0 ? args.worktreeId.trim() : void 0;
699
- const sessionId = typeof args.sessionId === "string" && args.sessionId.trim().length > 0 ? args.sessionId.trim() : void 0;
700
- const packWeightOverrides = Array.isArray(args.packWeightOverrides) ? args.packWeightOverrides : void 0;
701
- const effectiveWeights = resolveEffectiveWeights(packWeightOverrides);
702
- let scopedTopicIds = collectTopicNeighborhood(
703
- input.allTopics,
704
- topicId,
705
- descendantDepth
706
- );
707
- const allowedTopicIds = asStringArray(args.allowedTopicIds);
708
- if (allowedTopicIds.length > 0) {
709
- const allowedSet = new Set(allowedTopicIds);
710
- if (!allowedSet.has(topicId)) {
711
- throw new Error(`Access denied to compile context for topic ${topicId}.`);
145
+ return maxTimestamp;
146
+ }
147
+ export function planContextPackCompilation(input) {
148
+ const args = input.args ?? {};
149
+ const topicId = String(input.topic._id);
150
+ const queryText = typeof args.query === "string" && args.query.trim().length > 0
151
+ ? args.query.trim()
152
+ : undefined;
153
+ const tokens = normalizeQueryTokens(queryText);
154
+ const limit = toPositiveInt(args.limit, 8, 25);
155
+ const rankingProfile = parseRankingProfile(typeof args.ranking === "string" ? args.ranking : args.rankingProfile);
156
+ const tokenBudget = parseTokenBudget(typeof args.budget === "number" ? args.budget : args.tokenBudget, 1800);
157
+ const topicDepth = typeof input.topic.depth === "number" && Number.isFinite(input.topic.depth)
158
+ ? input.topic.depth
159
+ : 0;
160
+ const requestedMaxDepth = typeof args.maxDepth === "number" && Number.isFinite(args.maxDepth)
161
+ ? Math.max(1, Math.min(Math.floor(args.maxDepth), 6))
162
+ : undefined;
163
+ const descendantDepth = requestedMaxDepth ?? (topicDepth <= 1 ? 4 : 2);
164
+ const includeEntities = args.includeEntities !== false;
165
+ const compilationMode = args.mode === "delta" ? "delta" : DEFAULT_COMPILATION_MODE;
166
+ const includeFailures = compilationMode === "delta" || args.includeFailures === true;
167
+ const worktreeId = typeof args.worktreeId === "string" && args.worktreeId.trim().length > 0
168
+ ? args.worktreeId.trim()
169
+ : undefined;
170
+ const sessionId = typeof args.sessionId === "string" && args.sessionId.trim().length > 0
171
+ ? args.sessionId.trim()
172
+ : undefined;
173
+ const packWeightOverrides = Array.isArray(args.packWeightOverrides)
174
+ ? args.packWeightOverrides
175
+ : undefined;
176
+ const effectiveWeights = resolveEffectiveWeights(packWeightOverrides);
177
+ let scopedTopicIds = collectTopicNeighborhood(input.allTopics, topicId, descendantDepth);
178
+ const allowedTopicIds = asStringArray(args.allowedTopicIds);
179
+ if (allowedTopicIds.length > 0) {
180
+ const allowedSet = new Set(allowedTopicIds);
181
+ if (!allowedSet.has(topicId)) {
182
+ throw new Error(`Access denied to compile context for topic ${topicId}.`);
183
+ }
184
+ scopedTopicIds = scopedTopicIds.filter((id) => allowedSet.has(id));
712
185
  }
713
- scopedTopicIds = scopedTopicIds.filter((id) => allowedSet.has(id));
714
- }
715
- return {
716
- topicId,
717
- ...queryText ? { queryText } : {},
718
- tokens,
719
- limit,
720
- rankingProfile,
721
- tokenBudget,
722
- descendantDepth,
723
- includeEntities,
724
- compilationMode,
725
- includeFailures,
726
- ...worktreeId ? { worktreeId } : {},
727
- ...sessionId ? { sessionId } : {},
728
- ...packWeightOverrides ? { packWeightOverrides } : {},
729
- effectiveWeights,
730
- scopedTopicIds
731
- };
732
- }
733
- function compileContextPackFromSnapshot(snapshot) {
734
- const uniqueBeliefs = dedupeById(snapshot.beliefs);
735
- const uniqueQuestions = dedupeById(snapshot.questions);
736
- const uniqueEvidence = dedupeById(snapshot.evidence);
737
- const uniqueContradictions = dedupeById(snapshot.contradictions);
738
- const referenceTimeMs = resolveReferenceTimeMs(
739
- [snapshot.topic],
740
- uniqueBeliefs,
741
- uniqueQuestions,
742
- uniqueEvidence,
743
- uniqueContradictions,
744
- snapshot.entities
745
- ) || 0;
746
- const rankOptions = {
747
- effectiveWeights: snapshot.plan.effectiveWeights,
748
- includeJustifications: snapshot.plan.compilationMode === "delta",
749
- referenceTimeMs
750
- };
751
- const invariantCandidates = uniqueBeliefs.filter((belief) => beliefTypeOf(belief).toLowerCase() === "invariant").map((belief) => ({
752
- nodeId: String(belief._id),
753
- canonicalText: String(belief.canonicalText || ""),
754
- confidence: typeof belief.confidence === "number" ? belief.confidence : null,
755
- beliefType: beliefTypeOf(belief) || "invariant",
756
- updatedAt: belief.updatedAt || belief.createdAt || null
757
- }));
758
- const invariants = rankContextSection(
759
- "invariants",
760
- invariantCandidates.map((candidate) => ({
761
- ...candidate,
762
- id: candidate.nodeId,
763
- text: `${candidate.canonicalText} ${candidate.beliefType}`
764
- })),
765
- snapshot.plan.tokens,
766
- snapshot.plan.limit,
767
- snapshot.plan.rankingProfile,
768
- rankOptions
769
- ).map((row) => ({
770
- nodeId: row.nodeId,
771
- canonicalText: row.canonicalText,
772
- confidence: row.confidence,
773
- beliefType: row.beliefType,
774
- score: row.score,
775
- ...row.justification ? { justification: row.justification } : {}
776
- }));
777
- const activeBeliefCandidates = uniqueBeliefs.filter((belief) => (belief.status || "active") !== "archived").map((belief) => ({
778
- nodeId: String(belief._id),
779
- canonicalText: String(belief.canonicalText || ""),
780
- confidence: typeof belief.confidence === "number" ? belief.confidence : null,
781
- beliefType: beliefTypeOf(belief) || null,
782
- status: belief.status || "active",
783
- updatedAt: belief.updatedAt || belief.createdAt || null,
784
- metadataText: belief.metadata && typeof belief.metadata === "object" ? JSON.stringify(belief.metadata).toLowerCase() : ""
785
- }));
786
- const activeBeliefs = rankContextSection(
787
- "activeBeliefs",
788
- activeBeliefCandidates.map((candidate) => ({
789
- ...candidate,
790
- id: candidate.nodeId,
791
- text: `${candidate.canonicalText} ${candidate.metadataText}`
792
- })),
793
- snapshot.plan.tokens,
794
- snapshot.plan.limit,
795
- snapshot.plan.rankingProfile,
796
- rankOptions
797
- ).map((row) => ({
798
- nodeId: row.nodeId,
799
- canonicalText: row.canonicalText,
800
- confidence: row.confidence,
801
- beliefType: row.beliefType,
802
- status: row.status,
803
- updatedAt: row.updatedAt,
804
- score: row.score,
805
- ...row.justification ? { justification: row.justification } : {}
806
- }));
807
- const openQuestionCandidates = uniqueQuestions.map((question) => {
808
- const status = questionStatusOf(question);
809
- const metadata = question.metadata && typeof question.metadata === "object" ? question.metadata : {};
810
- return {
811
- questionId: String(question._id),
812
- text: String(question.canonicalText || ""),
813
- status,
814
- priority: typeof metadata.priority === "string" ? metadata.priority : "medium",
815
- updatedAt: question.updatedAt || question.createdAt || null,
816
- metadataText: JSON.stringify(metadata).toLowerCase()
817
- };
818
- }).filter((row) => isOpenQuestion(row.status));
819
- const openQuestions = rankContextSection(
820
- "openQuestions",
821
- openQuestionCandidates.map((candidate) => ({
822
- ...candidate,
823
- id: candidate.questionId,
824
- text: `${candidate.text} ${candidate.metadataText}`
825
- })),
826
- snapshot.plan.tokens,
827
- snapshot.plan.limit,
828
- snapshot.plan.rankingProfile,
829
- rankOptions
830
- ).map((row) => ({
831
- questionId: row.questionId,
832
- text: row.text,
833
- status: row.status,
834
- priority: row.priority,
835
- updatedAt: row.updatedAt,
836
- score: row.score,
837
- ...row.justification ? { justification: row.justification } : {}
838
- }));
839
- const evidenceCandidates = uniqueEvidence.map((item) => {
840
- const metadata = item.metadata && typeof item.metadata === "object" ? item.metadata : {};
841
186
  return {
842
- nodeId: String(item._id),
843
- canonicalText: String(item.canonicalText || ""),
844
- sourceUrl: typeof metadata.sourceUrl === "string" && metadata.sourceUrl || typeof item.sourceUrl === "string" && item.sourceUrl || null,
845
- kind: typeof metadata.kind === "string" && metadata.kind || "observation",
846
- createdAt: item.createdAt || null,
847
- updatedAt: item.updatedAt || item.createdAt || null,
848
- metadataText: JSON.stringify(metadata).toLowerCase()
187
+ topicId,
188
+ ...(queryText ? { queryText } : {}),
189
+ tokens,
190
+ limit,
191
+ rankingProfile,
192
+ tokenBudget,
193
+ descendantDepth,
194
+ includeEntities,
195
+ compilationMode,
196
+ includeFailures,
197
+ ...(worktreeId ? { worktreeId } : {}),
198
+ ...(sessionId ? { sessionId } : {}),
199
+ ...(packWeightOverrides ? { packWeightOverrides } : {}),
200
+ effectiveWeights,
201
+ scopedTopicIds,
849
202
  };
850
- });
851
- const recentEvidence = rankContextSection(
852
- "recentEvidence",
853
- evidenceCandidates.map((candidate) => ({
854
- ...candidate,
855
- id: candidate.nodeId,
856
- text: `${candidate.canonicalText} ${candidate.metadataText}`
857
- })),
858
- snapshot.plan.tokens,
859
- snapshot.plan.limit,
860
- snapshot.plan.rankingProfile,
861
- rankOptions
862
- ).map((row) => ({
863
- nodeId: row.nodeId,
864
- canonicalText: row.canonicalText,
865
- sourceUrl: row.sourceUrl,
866
- kind: row.kind,
867
- createdAt: row.createdAt,
868
- score: row.score,
869
- ...row.justification ? { justification: row.justification } : {}
870
- }));
871
- const contradictionCandidates = uniqueContradictions.map((row) => {
872
- const weight = typeof row.weight === "number" ? row.weight : 0;
873
- const severity = weight <= -0.9 ? "critical" : weight <= -0.7 ? "high" : weight <= -0.5 ? "medium" : "low";
874
- return {
875
- contradictionId: String(row._id || row.globalId || ""),
876
- severity,
877
- status: "active",
878
- description: row.context || row.description || row.summary || "",
879
- updatedAt: row.updatedAt || row.createdAt || null
203
+ }
204
+ export function compileContextPackFromSnapshot(snapshot) {
205
+ const uniqueBeliefs = dedupeById(snapshot.beliefs);
206
+ const uniqueQuestions = dedupeById(snapshot.questions);
207
+ const uniqueEvidence = dedupeById(snapshot.evidence);
208
+ const uniqueContradictions = dedupeById(snapshot.contradictions);
209
+ const referenceTimeMs = resolveReferenceTimeMs([snapshot.topic], uniqueBeliefs, uniqueQuestions, uniqueEvidence, uniqueContradictions, snapshot.entities) || 0;
210
+ const rankOptions = {
211
+ effectiveWeights: snapshot.plan.effectiveWeights,
212
+ includeJustifications: snapshot.plan.compilationMode === "delta",
213
+ referenceTimeMs,
880
214
  };
881
- });
882
- const contradictions = rankContextSection(
883
- "contradictions",
884
- contradictionCandidates.map((candidate) => ({
885
- ...candidate,
886
- id: candidate.contradictionId,
887
- text: `${candidate.description} ${candidate.severity}`
888
- })),
889
- snapshot.plan.tokens,
890
- snapshot.plan.limit,
891
- snapshot.plan.rankingProfile,
892
- rankOptions
893
- ).map((row) => ({
894
- contradictionId: row.contradictionId,
895
- severity: row.severity,
896
- status: row.status,
897
- description: row.description,
898
- score: row.score,
899
- ...row.justification ? { justification: row.justification } : {}
900
- }));
901
- const entityCandidates = snapshot.entities.map((row) => ({
902
- nodeId: String(row._id),
903
- entityType: String(row.nodeType || ""),
904
- title: String(row.title || ""),
905
- canonicalText: String(row.canonicalText || ""),
906
- connectedBeliefCount: typeof row.connectedBeliefCount === "number" ? row.connectedBeliefCount : 0,
907
- connectedEvidenceCount: typeof row.connectedEvidenceCount === "number" ? row.connectedEvidenceCount : 0,
908
- metadata: row.metadata && typeof row.metadata === "object" ? row.metadata : {},
909
- updatedAt: row.updatedAt || null
910
- }));
911
- const entityLimit = toPositiveInt(
912
- snapshot.plan.limit,
913
- DEFAULT_ENTITY_LIMIT,
914
- MAX_ENTITY_LIMIT
915
- );
916
- const rankedEntities = snapshot.plan.includeEntities ? rankEntities(entityCandidates, snapshot.plan.tokens, entityLimit).map(
917
- (row) => ({
918
- nodeId: row.nodeId,
919
- entityType: row.entityType,
920
- title: row.title,
921
- connectedBeliefCount: row.connectedBeliefCount,
922
- connectedEvidenceCount: row.connectedEvidenceCount,
923
- score: row.score,
924
- ...Object.keys(row.metadata).length > 0 ? { metadata: row.metadata } : {}
215
+ const invariantCandidates = uniqueBeliefs
216
+ .filter((belief) => beliefTypeOf(belief).toLowerCase() === "invariant")
217
+ .map((belief) => ({
218
+ nodeId: String(belief._id),
219
+ canonicalText: String(belief.canonicalText || ""),
220
+ confidence: typeof belief.confidence === "number" ? belief.confidence : null,
221
+ beliefType: beliefTypeOf(belief) || "invariant",
222
+ updatedAt: belief.updatedAt || belief.createdAt || null,
223
+ }));
224
+ const invariants = rankContextSection("invariants", invariantCandidates.map((candidate) => ({
225
+ ...candidate,
226
+ id: candidate.nodeId,
227
+ text: `${candidate.canonicalText} ${candidate.beliefType}`,
228
+ })), snapshot.plan.tokens, snapshot.plan.limit, snapshot.plan.rankingProfile, rankOptions).map((row) => ({
229
+ nodeId: row.nodeId,
230
+ canonicalText: row.canonicalText,
231
+ confidence: row.confidence,
232
+ beliefType: row.beliefType,
233
+ score: row.score,
234
+ ...(row.justification ? { justification: row.justification } : {}),
235
+ }));
236
+ const activeBeliefCandidates = uniqueBeliefs
237
+ .filter((belief) => (belief.status || "active") !== "archived")
238
+ .map((belief) => ({
239
+ nodeId: String(belief._id),
240
+ canonicalText: String(belief.canonicalText || ""),
241
+ confidence: typeof belief.confidence === "number" ? belief.confidence : null,
242
+ beliefType: beliefTypeOf(belief) || null,
243
+ status: belief.status || "active",
244
+ updatedAt: belief.updatedAt || belief.createdAt || null,
245
+ metadataText: belief.metadata && typeof belief.metadata === "object"
246
+ ? JSON.stringify(belief.metadata).toLowerCase()
247
+ : "",
248
+ }));
249
+ const activeBeliefs = rankContextSection("activeBeliefs", activeBeliefCandidates.map((candidate) => ({
250
+ ...candidate,
251
+ id: candidate.nodeId,
252
+ text: `${candidate.canonicalText} ${candidate.metadataText}`,
253
+ })), snapshot.plan.tokens, snapshot.plan.limit, snapshot.plan.rankingProfile, rankOptions).map((row) => ({
254
+ nodeId: row.nodeId,
255
+ canonicalText: row.canonicalText,
256
+ confidence: row.confidence,
257
+ beliefType: row.beliefType,
258
+ status: row.status,
259
+ updatedAt: row.updatedAt,
260
+ score: row.score,
261
+ ...(row.justification ? { justification: row.justification } : {}),
262
+ }));
263
+ const openQuestionCandidates = uniqueQuestions
264
+ .map((question) => {
265
+ const status = questionStatusOf(question);
266
+ const metadata = question.metadata && typeof question.metadata === "object"
267
+ ? question.metadata
268
+ : {};
269
+ return {
270
+ questionId: String(question._id),
271
+ text: String(question.canonicalText || ""),
272
+ status,
273
+ priority: typeof metadata.priority === "string" ? metadata.priority : "medium",
274
+ updatedAt: question.updatedAt || question.createdAt || null,
275
+ metadataText: JSON.stringify(metadata).toLowerCase(),
276
+ };
925
277
  })
926
- ) : void 0;
927
- let failureContext;
928
- if (snapshot.plan.includeFailures && snapshot.failures) {
929
- const allFailures = snapshot.failures.filter((node) => {
930
- const metadata = isRecord(node.metadata) ? node.metadata : {};
931
- return metadata.failedApproach === true || metadata.isFailedAttempt === true;
278
+ .filter((row) => isOpenQuestion(row.status));
279
+ const openQuestions = rankContextSection("openQuestions", openQuestionCandidates.map((candidate) => ({
280
+ ...candidate,
281
+ id: candidate.questionId,
282
+ text: `${candidate.text} ${candidate.metadataText}`,
283
+ })), snapshot.plan.tokens, snapshot.plan.limit, snapshot.plan.rankingProfile, rankOptions).map((row) => ({
284
+ questionId: row.questionId,
285
+ text: row.text,
286
+ status: row.status,
287
+ priority: row.priority,
288
+ updatedAt: row.updatedAt,
289
+ score: row.score,
290
+ ...(row.justification ? { justification: row.justification } : {}),
291
+ }));
292
+ const evidenceCandidates = uniqueEvidence.map((item) => {
293
+ const metadata = item.metadata && typeof item.metadata === "object" ? item.metadata : {};
294
+ return {
295
+ nodeId: String(item._id),
296
+ canonicalText: String(item.canonicalText || ""),
297
+ sourceUrl: (typeof metadata.sourceUrl === "string" && metadata.sourceUrl) ||
298
+ (typeof item.sourceUrl === "string" && item.sourceUrl) ||
299
+ null,
300
+ kind: (typeof metadata.kind === "string" && metadata.kind) || "observation",
301
+ createdAt: item.createdAt || null,
302
+ updatedAt: item.updatedAt || item.createdAt || null,
303
+ metadataText: JSON.stringify(metadata).toLowerCase(),
304
+ };
932
305
  });
933
- const rankedFailures = rankContextSection(
934
- "recentEvidence",
935
- allFailures.map((node) => ({
936
- id: String(node._id),
937
- text: String(node.canonicalText || ""),
938
- createdAt: node.createdAt || null,
939
- updatedAt: node.updatedAt || node.createdAt || null
940
- })),
941
- snapshot.plan.tokens,
942
- 10,
943
- snapshot.plan.rankingProfile,
944
- rankOptions
945
- );
946
- const failures = rankedFailures.map((row) => {
947
- const original = allFailures.find((node) => String(node._id) === row.id);
948
- const metadata = isRecord(original?.metadata) ? original?.metadata : {};
949
- return {
950
- attemptId: row.id,
951
- approach: String(row.text || ""),
952
- outcome: String(metadata.errorMessage || "Failed"),
953
- recordedAt: row.createdAt || referenceTimeMs || 0,
954
- score: row.score
955
- };
306
+ const recentEvidence = rankContextSection("recentEvidence", evidenceCandidates.map((candidate) => ({
307
+ ...candidate,
308
+ id: candidate.nodeId,
309
+ text: `${candidate.canonicalText} ${candidate.metadataText}`,
310
+ })), snapshot.plan.tokens, snapshot.plan.limit, snapshot.plan.rankingProfile, rankOptions).map((row) => ({
311
+ nodeId: row.nodeId,
312
+ canonicalText: row.canonicalText,
313
+ sourceUrl: row.sourceUrl,
314
+ kind: row.kind,
315
+ createdAt: row.createdAt,
316
+ score: row.score,
317
+ ...(row.justification ? { justification: row.justification } : {}),
318
+ }));
319
+ const contradictionCandidates = uniqueContradictions.map((row) => {
320
+ const weight = typeof row.weight === "number" ? row.weight : 0;
321
+ const severity = weight <= -0.9
322
+ ? "critical"
323
+ : weight <= -0.7
324
+ ? "high"
325
+ : weight <= -0.5
326
+ ? "medium"
327
+ : "low";
328
+ return {
329
+ contradictionId: String(row._id || row.globalId || ""),
330
+ severity,
331
+ status: "active",
332
+ description: row.context || row.description || row.summary || "",
333
+ updatedAt: row.updatedAt || row.createdAt || null,
334
+ };
956
335
  });
957
- const failureTexts = new Set(
958
- failures.map((failure) => failure.approach.toLowerCase().slice(0, 100))
959
- );
960
- const suppressionIds = /* @__PURE__ */ new Set();
961
- if (snapshot.plan.sessionId && failureTexts.size > 0) {
962
- for (const evidenceRow of recentEvidence) {
963
- const evidenceText = evidenceRow.canonicalText.toLowerCase().slice(0, 100);
964
- for (const failureText of failureTexts) {
965
- if (evidenceText.includes(failureText) || failureText.includes(evidenceText)) {
966
- suppressionIds.add(evidenceRow.nodeId);
967
- break;
968
- }
336
+ const contradictions = rankContextSection("contradictions", contradictionCandidates.map((candidate) => ({
337
+ ...candidate,
338
+ id: candidate.contradictionId,
339
+ text: `${candidate.description} ${candidate.severity}`,
340
+ })), snapshot.plan.tokens, snapshot.plan.limit, snapshot.plan.rankingProfile, rankOptions).map((row) => ({
341
+ contradictionId: row.contradictionId,
342
+ severity: row.severity,
343
+ status: row.status,
344
+ description: row.description,
345
+ score: row.score,
346
+ ...(row.justification ? { justification: row.justification } : {}),
347
+ }));
348
+ const entityCandidates = snapshot.entities.map((row) => ({
349
+ nodeId: String(row._id),
350
+ entityType: String(row.nodeType || ""),
351
+ title: String(row.title || ""),
352
+ canonicalText: String(row.canonicalText || ""),
353
+ connectedBeliefCount: typeof row.connectedBeliefCount === "number" ? row.connectedBeliefCount : 0,
354
+ connectedEvidenceCount: typeof row.connectedEvidenceCount === "number"
355
+ ? row.connectedEvidenceCount
356
+ : 0,
357
+ metadata: row.metadata && typeof row.metadata === "object" ? row.metadata : {},
358
+ updatedAt: row.updatedAt || null,
359
+ }));
360
+ const entityLimit = toPositiveInt(snapshot.plan.limit, DEFAULT_ENTITY_LIMIT, MAX_ENTITY_LIMIT);
361
+ const rankedEntities = snapshot.plan.includeEntities
362
+ ? rankEntities(entityCandidates, snapshot.plan.tokens, entityLimit).map((row) => ({
363
+ nodeId: row.nodeId,
364
+ entityType: row.entityType,
365
+ title: row.title,
366
+ connectedBeliefCount: row.connectedBeliefCount,
367
+ connectedEvidenceCount: row.connectedEvidenceCount,
368
+ score: row.score,
369
+ ...(Object.keys(row.metadata).length > 0
370
+ ? { metadata: row.metadata }
371
+ : {}),
372
+ }))
373
+ : undefined;
374
+ let failureContext;
375
+ if (snapshot.plan.includeFailures && snapshot.failures) {
376
+ const allFailures = snapshot.failures.filter((node) => {
377
+ const metadata = isRecord(node.metadata) ? node.metadata : {};
378
+ return metadata.failedApproach === true || metadata.isFailedAttempt === true;
379
+ });
380
+ const rankedFailures = rankContextSection("recentEvidence", allFailures.map((node) => ({
381
+ id: String(node._id),
382
+ text: String(node.canonicalText || ""),
383
+ createdAt: node.createdAt || null,
384
+ updatedAt: node.updatedAt || node.createdAt || null,
385
+ })), snapshot.plan.tokens, 10, snapshot.plan.rankingProfile, rankOptions);
386
+ const failures = rankedFailures.map((row) => {
387
+ const original = allFailures.find((node) => String(node._id) === row.id);
388
+ const metadata = isRecord(original?.metadata) ? original?.metadata : {};
389
+ return {
390
+ attemptId: row.id,
391
+ approach: String(row.text || ""),
392
+ outcome: String(metadata.errorMessage || "Failed"),
393
+ recordedAt: row.createdAt || referenceTimeMs || 0,
394
+ score: row.score,
395
+ };
396
+ });
397
+ const failureTexts = new Set(failures.map((failure) => failure.approach.toLowerCase().slice(0, 100)));
398
+ const suppressionIds = new Set();
399
+ if (snapshot.plan.sessionId && failureTexts.size > 0) {
400
+ for (const evidenceRow of recentEvidence) {
401
+ const evidenceText = evidenceRow.canonicalText.toLowerCase().slice(0, 100);
402
+ for (const failureText of failureTexts) {
403
+ if (evidenceText.includes(failureText) ||
404
+ failureText.includes(evidenceText)) {
405
+ suppressionIds.add(evidenceRow.nodeId);
406
+ break;
407
+ }
408
+ }
409
+ }
410
+ }
411
+ if (failures.length > 0) {
412
+ failureContext = {
413
+ failures,
414
+ suppressedIds: Array.from(suppressionIds),
415
+ };
969
416
  }
970
- }
971
- }
972
- if (failures.length > 0) {
973
- failureContext = {
974
- failures,
975
- suppressedIds: Array.from(suppressionIds)
976
- };
977
417
  }
978
- }
979
- const suppressionSet = new Set(failureContext?.suppressedIds || []);
980
- const effectiveEvidence = suppressionSet.size > 0 ? recentEvidence.filter((row) => !suppressionSet.has(row.nodeId)) : recentEvidence;
981
- const suppressedEvidenceIds = suppressionSet.size > 0 ? recentEvidence.filter((row) => suppressionSet.has(row.nodeId)).map((row) => row.nodeId) : [];
982
- const summary = {
983
- totalBeliefs: uniqueBeliefs.length,
984
- invariants: invariants.length,
985
- openQuestions: openQuestions.length,
986
- evidenceItems: uniqueEvidence.length,
987
- contradictions: contradictions.length,
988
- ...rankedEntities ? { relatedEntities: rankedEntities.length } : {},
989
- scopedTopics: snapshot.plan.scopedTopicIds.length,
990
- descendantDepth: snapshot.plan.descendantDepth,
991
- query: snapshot.plan.queryText || null
992
- };
993
- const injectionPolicy = buildInjectionPlan({
994
- tokenBudget: snapshot.plan.tokenBudget,
995
- invariants: invariants.map((row) => ({
996
- nodeId: row.nodeId,
997
- canonicalText: row.canonicalText,
998
- score: row.score
999
- })),
1000
- activeBeliefs: activeBeliefs.map((row) => ({
1001
- nodeId: row.nodeId,
1002
- canonicalText: row.canonicalText,
1003
- score: row.score
1004
- })),
1005
- openQuestions: openQuestions.map((row) => ({
1006
- questionId: row.questionId,
1007
- text: row.text,
1008
- score: row.score
1009
- })),
1010
- recentEvidence: effectiveEvidence.map((row) => ({
1011
- nodeId: row.nodeId,
1012
- canonicalText: row.canonicalText,
1013
- score: row.score
1014
- })),
1015
- contradictions: contradictions.map((row) => ({
1016
- contradictionId: row.contradictionId,
1017
- description: row.description,
1018
- score: row.score
1019
- })),
1020
- trackExclusions: snapshot.plan.compilationMode === "delta"
1021
- });
1022
- const contextNarrative = [
1023
- "Prefer invariant beliefs as hard constraints while reasoning over this scope.",
1024
- "Treat open questions as unresolved work items and avoid claiming closure without evidence.",
1025
- "Use recent evidence for implementation context before creating new beliefs.",
1026
- "When contradictions exist, resolve explicitly (fork, lower confidence, or gather counter-evidence).",
1027
- `Apply injection token budget of ${injectionPolicy.tokenBudget} with section quotas before prompt assembly.`
1028
- ];
1029
- const deltaReport = snapshot.plan.compilationMode === "delta" && snapshot.plan.worktreeId ? {
1030
- changedItems: [],
1031
- verificationObligations: [],
1032
- referencePoint: snapshot.plan.worktreeId
1033
- } : void 0;
1034
- const excludedItems = [
1035
- ...injectionPolicy.excludedItems || [],
1036
- ...suppressedEvidenceIds.map((id) => ({
1037
- id,
1038
- section: "recentEvidence",
1039
- reason: "anti_repetition",
1040
- score: recentEvidence.find((row) => row.nodeId === id)?.score ?? 0
1041
- }))
1042
- ];
1043
- const result = {
1044
- schemaVersion: CONTEXT_PACK_SCHEMA_VERSION,
1045
- topicId: snapshot.plan.topicId,
1046
- topicName: snapshot.topic.name || "Untitled Topic",
1047
- scopedTopicIds: snapshot.plan.scopedTopicIds,
1048
- generatedAt: referenceTimeMs,
1049
- rankingProfile: snapshot.plan.rankingProfile,
1050
- summary,
1051
- invariants,
1052
- activeBeliefs,
1053
- openQuestions,
1054
- recentEvidence: effectiveEvidence,
1055
- contradictions,
1056
- ...rankedEntities ? { relatedEntities: rankedEntities } : {},
1057
- contextNarrative,
1058
- injectionPolicy: {
1059
- ...injectionPolicy,
1060
- ...excludedItems.length > 0 ? { excludedItems } : {}
1061
- },
1062
- diagnostics: {
1063
- itemsScored: invariantCandidates.length + activeBeliefCandidates.length + openQuestionCandidates.length + evidenceCandidates.length + contradictionCandidates.length + entityCandidates.length,
1064
- tokenBudgetUtilization: injectionPolicy.tokenBudget === 0 ? 0 : Number(
1065
- (injectionPolicy.estimatedTokens / injectionPolicy.tokenBudget).toFixed(4)
1066
- ),
1067
- referenceTimeMs
1068
- },
1069
- ...snapshot.plan.compilationMode !== "standard" ? { compilationMode: snapshot.plan.compilationMode } : {},
1070
- ...failureContext ? { failureContext } : {},
1071
- ...deltaReport ? { deltaReport } : {},
1072
- ...snapshot.plan.packWeightOverrides && snapshot.plan.packWeightOverrides.length > 0 ? { appliedWeightOverrides: snapshot.plan.packWeightOverrides } : {}
1073
- };
1074
- assertContextPackSchema(result);
1075
- return result;
418
+ const suppressionSet = new Set(failureContext?.suppressedIds || []);
419
+ const effectiveEvidence = suppressionSet.size > 0
420
+ ? recentEvidence.filter((row) => !suppressionSet.has(row.nodeId))
421
+ : recentEvidence;
422
+ const suppressedEvidenceIds = suppressionSet.size > 0
423
+ ? recentEvidence
424
+ .filter((row) => suppressionSet.has(row.nodeId))
425
+ .map((row) => row.nodeId)
426
+ : [];
427
+ const summary = {
428
+ totalBeliefs: uniqueBeliefs.length,
429
+ invariants: invariants.length,
430
+ openQuestions: openQuestions.length,
431
+ evidenceItems: uniqueEvidence.length,
432
+ contradictions: contradictions.length,
433
+ ...(rankedEntities ? { relatedEntities: rankedEntities.length } : {}),
434
+ scopedTopics: snapshot.plan.scopedTopicIds.length,
435
+ descendantDepth: snapshot.plan.descendantDepth,
436
+ query: snapshot.plan.queryText || null,
437
+ };
438
+ const injectionPolicy = buildInjectionPlan({
439
+ tokenBudget: snapshot.plan.tokenBudget,
440
+ invariants: invariants.map((row) => ({
441
+ nodeId: row.nodeId,
442
+ canonicalText: row.canonicalText,
443
+ score: row.score,
444
+ })),
445
+ activeBeliefs: activeBeliefs.map((row) => ({
446
+ nodeId: row.nodeId,
447
+ canonicalText: row.canonicalText,
448
+ score: row.score,
449
+ })),
450
+ openQuestions: openQuestions.map((row) => ({
451
+ questionId: row.questionId,
452
+ text: row.text,
453
+ score: row.score,
454
+ })),
455
+ recentEvidence: effectiveEvidence.map((row) => ({
456
+ nodeId: row.nodeId,
457
+ canonicalText: row.canonicalText,
458
+ score: row.score,
459
+ })),
460
+ contradictions: contradictions.map((row) => ({
461
+ contradictionId: row.contradictionId,
462
+ description: row.description,
463
+ score: row.score,
464
+ })),
465
+ trackExclusions: snapshot.plan.compilationMode === "delta",
466
+ });
467
+ const contextNarrative = [
468
+ "Prefer invariant beliefs as hard constraints while reasoning over this scope.",
469
+ "Treat open questions as unresolved work items and avoid claiming closure without evidence.",
470
+ "Use recent evidence for implementation context before creating new beliefs.",
471
+ "When contradictions exist, resolve explicitly (fork, lower confidence, or gather counter-evidence).",
472
+ `Apply injection token budget of ${injectionPolicy.tokenBudget} with section quotas before prompt assembly.`,
473
+ ];
474
+ const deltaReport = snapshot.plan.compilationMode === "delta" && snapshot.plan.worktreeId
475
+ ? {
476
+ changedItems: [],
477
+ verificationObligations: [],
478
+ referencePoint: snapshot.plan.worktreeId,
479
+ }
480
+ : undefined;
481
+ const excludedItems = [
482
+ ...(injectionPolicy.excludedItems || []),
483
+ ...suppressedEvidenceIds.map((id) => ({
484
+ id,
485
+ section: "recentEvidence",
486
+ reason: "anti_repetition",
487
+ score: recentEvidence.find((row) => row.nodeId === id)?.score ?? 0,
488
+ })),
489
+ ];
490
+ const result = {
491
+ schemaVersion: CONTEXT_PACK_SCHEMA_VERSION,
492
+ topicId: snapshot.plan.topicId,
493
+ topicName: snapshot.topic.name || "Untitled Topic",
494
+ scopedTopicIds: snapshot.plan.scopedTopicIds,
495
+ generatedAt: referenceTimeMs,
496
+ rankingProfile: snapshot.plan.rankingProfile,
497
+ summary,
498
+ invariants,
499
+ activeBeliefs,
500
+ openQuestions,
501
+ recentEvidence: effectiveEvidence,
502
+ contradictions,
503
+ ...(rankedEntities ? { relatedEntities: rankedEntities } : {}),
504
+ contextNarrative,
505
+ injectionPolicy: {
506
+ ...injectionPolicy,
507
+ ...(excludedItems.length > 0 ? { excludedItems } : {}),
508
+ },
509
+ diagnostics: {
510
+ itemsScored: invariantCandidates.length +
511
+ activeBeliefCandidates.length +
512
+ openQuestionCandidates.length +
513
+ evidenceCandidates.length +
514
+ contradictionCandidates.length +
515
+ entityCandidates.length,
516
+ tokenBudgetUtilization: injectionPolicy.tokenBudget === 0
517
+ ? 0
518
+ : Number((injectionPolicy.estimatedTokens / injectionPolicy.tokenBudget).toFixed(4)),
519
+ referenceTimeMs,
520
+ },
521
+ ...(snapshot.plan.compilationMode !== "standard"
522
+ ? { compilationMode: snapshot.plan.compilationMode }
523
+ : {}),
524
+ ...(failureContext ? { failureContext } : {}),
525
+ ...(deltaReport ? { deltaReport } : {}),
526
+ ...(snapshot.plan.packWeightOverrides &&
527
+ snapshot.plan.packWeightOverrides.length > 0
528
+ ? { appliedWeightOverrides: snapshot.plan.packWeightOverrides }
529
+ : {}),
530
+ };
531
+ assertContextPackSchema(result);
532
+ return result;
1076
533
  }
1077
-
1078
- export { compileContextPackFromSnapshot, planContextPackCompilation };
1079
- //# sourceMappingURL=contextPackCompiler.js.map
1080
534
  //# sourceMappingURL=contextPackCompiler.js.map