@caupulican/pi-adaptative 0.80.86 → 0.80.89

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 (353) hide show
  1. package/CHANGELOG.md +178 -0
  2. package/dist/core/agent-session.d.ts +412 -1
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +2053 -41
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/autonomy/approval-gate.d.ts +4 -0
  7. package/dist/core/autonomy/approval-gate.d.ts.map +1 -0
  8. package/dist/core/autonomy/approval-gate.js +27 -0
  9. package/dist/core/autonomy/approval-gate.js.map +1 -0
  10. package/dist/core/autonomy/bounded-completion.d.ts +27 -0
  11. package/dist/core/autonomy/bounded-completion.d.ts.map +1 -0
  12. package/dist/core/autonomy/bounded-completion.js +44 -0
  13. package/dist/core/autonomy/bounded-completion.js.map +1 -0
  14. package/dist/core/autonomy/contracts.d.ts +129 -0
  15. package/dist/core/autonomy/contracts.d.ts.map +1 -0
  16. package/dist/core/autonomy/contracts.js +2 -0
  17. package/dist/core/autonomy/contracts.js.map +1 -0
  18. package/dist/core/autonomy/gates.d.ts +15 -0
  19. package/dist/core/autonomy/gates.d.ts.map +1 -0
  20. package/dist/core/autonomy/gates.js +205 -0
  21. package/dist/core/autonomy/gates.js.map +1 -0
  22. package/dist/core/autonomy/lane-tracker.d.ts +48 -0
  23. package/dist/core/autonomy/lane-tracker.d.ts.map +1 -0
  24. package/dist/core/autonomy/lane-tracker.js +125 -0
  25. package/dist/core/autonomy/lane-tracker.js.map +1 -0
  26. package/dist/core/autonomy/path-scope.d.ts +9 -0
  27. package/dist/core/autonomy/path-scope.d.ts.map +1 -0
  28. package/dist/core/autonomy/path-scope.js +122 -0
  29. package/dist/core/autonomy/path-scope.js.map +1 -0
  30. package/dist/core/autonomy/risk-assessment.d.ts +3 -0
  31. package/dist/core/autonomy/risk-assessment.d.ts.map +1 -0
  32. package/dist/core/autonomy/risk-assessment.js +122 -0
  33. package/dist/core/autonomy/risk-assessment.js.map +1 -0
  34. package/dist/core/autonomy/session-lane-record.d.ts +10 -0
  35. package/dist/core/autonomy/session-lane-record.d.ts.map +1 -0
  36. package/dist/core/autonomy/session-lane-record.js +36 -0
  37. package/dist/core/autonomy/session-lane-record.js.map +1 -0
  38. package/dist/core/autonomy/status.d.ts +40 -0
  39. package/dist/core/autonomy/status.d.ts.map +1 -0
  40. package/dist/core/autonomy/status.js +107 -0
  41. package/dist/core/autonomy/status.js.map +1 -0
  42. package/dist/core/autonomy/subagent-prompt.d.ts +21 -0
  43. package/dist/core/autonomy/subagent-prompt.d.ts.map +1 -0
  44. package/dist/core/autonomy/subagent-prompt.js +28 -0
  45. package/dist/core/autonomy/subagent-prompt.js.map +1 -0
  46. package/dist/core/autonomy/telemetry-events.d.ts +18 -0
  47. package/dist/core/autonomy/telemetry-events.d.ts.map +1 -0
  48. package/dist/core/autonomy/telemetry-events.js +60 -0
  49. package/dist/core/autonomy/telemetry-events.js.map +1 -0
  50. package/dist/core/context/artifact-retrieval.d.ts +49 -0
  51. package/dist/core/context/artifact-retrieval.d.ts.map +1 -0
  52. package/dist/core/context/artifact-retrieval.js +49 -0
  53. package/dist/core/context/artifact-retrieval.js.map +1 -0
  54. package/dist/core/context/brain-curator.d.ts +88 -0
  55. package/dist/core/context/brain-curator.d.ts.map +1 -0
  56. package/dist/core/context/brain-curator.js +192 -0
  57. package/dist/core/context/brain-curator.js.map +1 -0
  58. package/dist/core/context/context-artifacts.d.ts +94 -0
  59. package/dist/core/context/context-artifacts.d.ts.map +1 -0
  60. package/dist/core/context/context-artifacts.js +307 -0
  61. package/dist/core/context/context-artifacts.js.map +1 -0
  62. package/dist/core/context/context-audit.d.ts +66 -0
  63. package/dist/core/context/context-audit.d.ts.map +1 -0
  64. package/dist/core/context/context-audit.js +173 -0
  65. package/dist/core/context/context-audit.js.map +1 -0
  66. package/dist/core/context/context-composition.d.ts +122 -0
  67. package/dist/core/context/context-composition.d.ts.map +1 -0
  68. package/dist/core/context/context-composition.js +163 -0
  69. package/dist/core/context/context-composition.js.map +1 -0
  70. package/dist/core/context/context-item.d.ts +117 -0
  71. package/dist/core/context/context-item.d.ts.map +1 -0
  72. package/dist/core/context/context-item.js +36 -0
  73. package/dist/core/context/context-item.js.map +1 -0
  74. package/dist/core/context/context-prompt-enforcement.d.ts +86 -0
  75. package/dist/core/context/context-prompt-enforcement.d.ts.map +1 -0
  76. package/dist/core/context/context-prompt-enforcement.js +168 -0
  77. package/dist/core/context/context-prompt-enforcement.js.map +1 -0
  78. package/dist/core/context/context-prompt-policy.d.ts +90 -0
  79. package/dist/core/context/context-prompt-policy.d.ts.map +1 -0
  80. package/dist/core/context/context-prompt-policy.js +73 -0
  81. package/dist/core/context/context-prompt-policy.js.map +1 -0
  82. package/dist/core/context/context-retention.d.ts +36 -0
  83. package/dist/core/context/context-retention.d.ts.map +1 -0
  84. package/dist/core/context/context-retention.js +108 -0
  85. package/dist/core/context/context-retention.js.map +1 -0
  86. package/dist/core/context/context-store.d.ts +37 -0
  87. package/dist/core/context/context-store.d.ts.map +1 -0
  88. package/dist/core/context/context-store.js +45 -0
  89. package/dist/core/context/context-store.js.map +1 -0
  90. package/dist/core/context/memory-diagnostics.d.ts +50 -0
  91. package/dist/core/context/memory-diagnostics.d.ts.map +1 -0
  92. package/dist/core/context/memory-diagnostics.js +43 -0
  93. package/dist/core/context/memory-diagnostics.js.map +1 -0
  94. package/dist/core/context/memory-index-store.d.ts +28 -0
  95. package/dist/core/context/memory-index-store.d.ts.map +1 -0
  96. package/dist/core/context/memory-index-store.js +38 -0
  97. package/dist/core/context/memory-index-store.js.map +1 -0
  98. package/dist/core/context/memory-prompt-block.d.ts +34 -0
  99. package/dist/core/context/memory-prompt-block.d.ts.map +1 -0
  100. package/dist/core/context/memory-prompt-block.js +58 -0
  101. package/dist/core/context/memory-prompt-block.js.map +1 -0
  102. package/dist/core/context/memory-provider-contract.d.ts +114 -0
  103. package/dist/core/context/memory-provider-contract.d.ts.map +1 -0
  104. package/dist/core/context/memory-provider-contract.js +121 -0
  105. package/dist/core/context/memory-provider-contract.js.map +1 -0
  106. package/dist/core/context/memory-retrieval.d.ts +27 -0
  107. package/dist/core/context/memory-retrieval.d.ts.map +1 -0
  108. package/dist/core/context/memory-retrieval.js +91 -0
  109. package/dist/core/context/memory-retrieval.js.map +1 -0
  110. package/dist/core/context/okf-memory-provider.d.ts +26 -0
  111. package/dist/core/context/okf-memory-provider.d.ts.map +1 -0
  112. package/dist/core/context/okf-memory-provider.js +154 -0
  113. package/dist/core/context/okf-memory-provider.js.map +1 -0
  114. package/dist/core/context/okf-memory.d.ts +42 -0
  115. package/dist/core/context/okf-memory.d.ts.map +1 -0
  116. package/dist/core/context/okf-memory.js +175 -0
  117. package/dist/core/context/okf-memory.js.map +1 -0
  118. package/dist/core/context/policy-engine.d.ts +66 -0
  119. package/dist/core/context/policy-engine.d.ts.map +1 -0
  120. package/dist/core/context/policy-engine.js +171 -0
  121. package/dist/core/context/policy-engine.js.map +1 -0
  122. package/dist/core/context/policy-types.d.ts +102 -0
  123. package/dist/core/context/policy-types.d.ts.map +1 -0
  124. package/dist/core/context/policy-types.js +7 -0
  125. package/dist/core/context/policy-types.js.map +1 -0
  126. package/dist/core/context/sqlite-runtime-index.d.ts +19 -0
  127. package/dist/core/context/sqlite-runtime-index.d.ts.map +1 -0
  128. package/dist/core/context/sqlite-runtime-index.js +344 -0
  129. package/dist/core/context/sqlite-runtime-index.js.map +1 -0
  130. package/dist/core/context/storage-authority.d.ts +20 -0
  131. package/dist/core/context/storage-authority.d.ts.map +1 -0
  132. package/dist/core/context/storage-authority.js +51 -0
  133. package/dist/core/context/storage-authority.js.map +1 -0
  134. package/dist/core/context/tool-output-packer.d.ts +75 -0
  135. package/dist/core/context/tool-output-packer.d.ts.map +1 -0
  136. package/dist/core/context/tool-output-packer.js +77 -0
  137. package/dist/core/context/tool-output-packer.js.map +1 -0
  138. package/dist/core/context-gc.d.ts +13 -0
  139. package/dist/core/context-gc.d.ts.map +1 -1
  140. package/dist/core/context-gc.js +6 -0
  141. package/dist/core/context-gc.js.map +1 -1
  142. package/dist/core/cost/session-usage.d.ts +20 -0
  143. package/dist/core/cost/session-usage.d.ts.map +1 -0
  144. package/dist/core/cost/session-usage.js +164 -0
  145. package/dist/core/cost/session-usage.js.map +1 -0
  146. package/dist/core/delegation/session-worker-result.d.ts +10 -0
  147. package/dist/core/delegation/session-worker-result.d.ts.map +1 -0
  148. package/dist/core/delegation/session-worker-result.js +36 -0
  149. package/dist/core/delegation/session-worker-result.js.map +1 -0
  150. package/dist/core/delegation/worker-result.d.ts +9 -0
  151. package/dist/core/delegation/worker-result.d.ts.map +1 -0
  152. package/dist/core/delegation/worker-result.js +152 -0
  153. package/dist/core/delegation/worker-result.js.map +1 -0
  154. package/dist/core/delegation/worker-runner.d.ts +58 -0
  155. package/dist/core/delegation/worker-runner.d.ts.map +1 -0
  156. package/dist/core/delegation/worker-runner.js +188 -0
  157. package/dist/core/delegation/worker-runner.js.map +1 -0
  158. package/dist/core/extensions/builtin.d.ts +5 -1
  159. package/dist/core/extensions/builtin.d.ts.map +1 -1
  160. package/dist/core/extensions/builtin.js +23 -1
  161. package/dist/core/extensions/builtin.js.map +1 -1
  162. package/dist/core/footer-data-provider.d.ts +5 -1
  163. package/dist/core/footer-data-provider.d.ts.map +1 -1
  164. package/dist/core/footer-data-provider.js +13 -0
  165. package/dist/core/footer-data-provider.js.map +1 -1
  166. package/dist/core/goals/goal-continuation-controller.d.ts +22 -0
  167. package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -0
  168. package/dist/core/goals/goal-continuation-controller.js +88 -0
  169. package/dist/core/goals/goal-continuation-controller.js.map +1 -0
  170. package/dist/core/goals/goal-continuation-defaults.d.ts +10 -0
  171. package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -0
  172. package/dist/core/goals/goal-continuation-defaults.js +10 -0
  173. package/dist/core/goals/goal-continuation-defaults.js.map +1 -0
  174. package/dist/core/goals/goal-continuation-prompt.d.ts +18 -0
  175. package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -0
  176. package/dist/core/goals/goal-continuation-prompt.js +141 -0
  177. package/dist/core/goals/goal-continuation-prompt.js.map +1 -0
  178. package/dist/core/goals/goal-runtime-snapshot.d.ts +19 -0
  179. package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -0
  180. package/dist/core/goals/goal-runtime-snapshot.js +23 -0
  181. package/dist/core/goals/goal-runtime-snapshot.js.map +1 -0
  182. package/dist/core/goals/goal-state.d.ts +87 -0
  183. package/dist/core/goals/goal-state.d.ts.map +1 -0
  184. package/dist/core/goals/goal-state.js +259 -0
  185. package/dist/core/goals/goal-state.js.map +1 -0
  186. package/dist/core/goals/goal-tool-core.d.ts +66 -0
  187. package/dist/core/goals/goal-tool-core.d.ts.map +1 -0
  188. package/dist/core/goals/goal-tool-core.js +146 -0
  189. package/dist/core/goals/goal-tool-core.js.map +1 -0
  190. package/dist/core/goals/session-goal-state.d.ts +10 -0
  191. package/dist/core/goals/session-goal-state.d.ts.map +1 -0
  192. package/dist/core/goals/session-goal-state.js +35 -0
  193. package/dist/core/goals/session-goal-state.js.map +1 -0
  194. package/dist/core/learning/learning-audit.d.ts +45 -0
  195. package/dist/core/learning/learning-audit.d.ts.map +1 -0
  196. package/dist/core/learning/learning-audit.js +139 -0
  197. package/dist/core/learning/learning-audit.js.map +1 -0
  198. package/dist/core/learning/learning-gate.d.ts +29 -0
  199. package/dist/core/learning/learning-gate.d.ts.map +1 -0
  200. package/dist/core/learning/learning-gate.js +150 -0
  201. package/dist/core/learning/learning-gate.js.map +1 -0
  202. package/dist/core/learning/session-learning-decision.d.ts +10 -0
  203. package/dist/core/learning/session-learning-decision.d.ts.map +1 -0
  204. package/dist/core/learning/session-learning-decision.js +36 -0
  205. package/dist/core/learning/session-learning-decision.js.map +1 -0
  206. package/dist/core/model-capability.d.ts +41 -0
  207. package/dist/core/model-capability.d.ts.map +1 -0
  208. package/dist/core/model-capability.js +101 -0
  209. package/dist/core/model-capability.js.map +1 -0
  210. package/dist/core/model-router/config-diagnostics.d.ts.map +1 -1
  211. package/dist/core/model-router/config-diagnostics.js +1 -0
  212. package/dist/core/model-router/config-diagnostics.js.map +1 -1
  213. package/dist/core/model-router/intent-classifier.d.ts +2 -0
  214. package/dist/core/model-router/intent-classifier.d.ts.map +1 -1
  215. package/dist/core/model-router/intent-classifier.js +154 -9
  216. package/dist/core/model-router/intent-classifier.js.map +1 -1
  217. package/dist/core/model-router/route-judge.d.ts +54 -0
  218. package/dist/core/model-router/route-judge.d.ts.map +1 -0
  219. package/dist/core/model-router/route-judge.js +128 -0
  220. package/dist/core/model-router/route-judge.js.map +1 -0
  221. package/dist/core/model-router/status.d.ts +4 -1
  222. package/dist/core/model-router/status.d.ts.map +1 -1
  223. package/dist/core/model-router/status.js +30 -6
  224. package/dist/core/model-router/status.js.map +1 -1
  225. package/dist/core/model-router/tool-escalation.d.ts +4 -6
  226. package/dist/core/model-router/tool-escalation.d.ts.map +1 -1
  227. package/dist/core/model-router/tool-escalation.js +1 -1
  228. package/dist/core/model-router/tool-escalation.js.map +1 -1
  229. package/dist/core/models/fitness-store.d.ts +40 -0
  230. package/dist/core/models/fitness-store.d.ts.map +1 -0
  231. package/dist/core/models/fitness-store.js +61 -0
  232. package/dist/core/models/fitness-store.js.map +1 -0
  233. package/dist/core/profile-registry.d.ts.map +1 -1
  234. package/dist/core/profile-registry.js +1 -1
  235. package/dist/core/profile-registry.js.map +1 -1
  236. package/dist/core/prompt-templates.d.ts +2 -0
  237. package/dist/core/prompt-templates.d.ts.map +1 -1
  238. package/dist/core/prompt-templates.js +12 -4
  239. package/dist/core/prompt-templates.js.map +1 -1
  240. package/dist/core/research/automata-provider.d.ts +5 -0
  241. package/dist/core/research/automata-provider.d.ts.map +1 -0
  242. package/dist/core/research/automata-provider.js +15 -0
  243. package/dist/core/research/automata-provider.js.map +1 -0
  244. package/dist/core/research/evidence-bundle.d.ts +10 -0
  245. package/dist/core/research/evidence-bundle.d.ts.map +1 -0
  246. package/dist/core/research/evidence-bundle.js +116 -0
  247. package/dist/core/research/evidence-bundle.js.map +1 -0
  248. package/dist/core/research/model-fitness.d.ts +82 -0
  249. package/dist/core/research/model-fitness.d.ts.map +1 -0
  250. package/dist/core/research/model-fitness.js +308 -0
  251. package/dist/core/research/model-fitness.js.map +1 -0
  252. package/dist/core/research/research-gate.d.ts +11 -0
  253. package/dist/core/research/research-gate.d.ts.map +1 -0
  254. package/dist/core/research/research-gate.js +82 -0
  255. package/dist/core/research/research-gate.js.map +1 -0
  256. package/dist/core/research/research-runner.d.ts +59 -0
  257. package/dist/core/research/research-runner.d.ts.map +1 -0
  258. package/dist/core/research/research-runner.js +155 -0
  259. package/dist/core/research/research-runner.js.map +1 -0
  260. package/dist/core/research/session-evidence-bundle.d.ts +11 -0
  261. package/dist/core/research/session-evidence-bundle.d.ts.map +1 -0
  262. package/dist/core/research/session-evidence-bundle.js +55 -0
  263. package/dist/core/research/session-evidence-bundle.js.map +1 -0
  264. package/dist/core/resource-loader.d.ts.map +1 -1
  265. package/dist/core/resource-loader.js +4 -0
  266. package/dist/core/resource-loader.js.map +1 -1
  267. package/dist/core/settings-manager.d.ts +160 -4
  268. package/dist/core/settings-manager.d.ts.map +1 -1
  269. package/dist/core/settings-manager.js +304 -9
  270. package/dist/core/settings-manager.js.map +1 -1
  271. package/dist/core/skills.d.ts +4 -0
  272. package/dist/core/skills.d.ts.map +1 -1
  273. package/dist/core/skills.js +18 -6
  274. package/dist/core/skills.js.map +1 -1
  275. package/dist/core/slash-commands.d.ts.map +1 -1
  276. package/dist/core/slash-commands.js +10 -1
  277. package/dist/core/slash-commands.js.map +1 -1
  278. package/dist/core/toolkit/script-registry.d.ts +34 -0
  279. package/dist/core/toolkit/script-registry.d.ts.map +1 -0
  280. package/dist/core/toolkit/script-registry.js +71 -0
  281. package/dist/core/toolkit/script-registry.js.map +1 -0
  282. package/dist/core/toolkit/script-runner.d.ts +28 -0
  283. package/dist/core/toolkit/script-runner.d.ts.map +1 -0
  284. package/dist/core/toolkit/script-runner.js +48 -0
  285. package/dist/core/toolkit/script-runner.js.map +1 -0
  286. package/dist/core/tools/artifact-retrieve.d.ts +23 -0
  287. package/dist/core/tools/artifact-retrieve.d.ts.map +1 -0
  288. package/dist/core/tools/artifact-retrieve.js +110 -0
  289. package/dist/core/tools/artifact-retrieve.js.map +1 -0
  290. package/dist/core/tools/delegate.d.ts +32 -0
  291. package/dist/core/tools/delegate.d.ts.map +1 -0
  292. package/dist/core/tools/delegate.js +60 -0
  293. package/dist/core/tools/delegate.js.map +1 -0
  294. package/dist/core/tools/fff-search-backend.d.ts +103 -0
  295. package/dist/core/tools/fff-search-backend.d.ts.map +1 -0
  296. package/dist/core/tools/fff-search-backend.js +151 -0
  297. package/dist/core/tools/fff-search-backend.js.map +1 -0
  298. package/dist/core/tools/find.d.ts +21 -1
  299. package/dist/core/tools/find.d.ts.map +1 -1
  300. package/dist/core/tools/find.js +183 -10
  301. package/dist/core/tools/find.js.map +1 -1
  302. package/dist/core/tools/goal.d.ts +35 -0
  303. package/dist/core/tools/goal.d.ts.map +1 -0
  304. package/dist/core/tools/goal.js +122 -0
  305. package/dist/core/tools/goal.js.map +1 -0
  306. package/dist/core/tools/grep.d.ts +21 -1
  307. package/dist/core/tools/grep.d.ts.map +1 -1
  308. package/dist/core/tools/grep.js +272 -27
  309. package/dist/core/tools/grep.js.map +1 -1
  310. package/dist/core/tools/index.d.ts +4 -1
  311. package/dist/core/tools/index.d.ts.map +1 -1
  312. package/dist/core/tools/index.js +9 -0
  313. package/dist/core/tools/index.js.map +1 -1
  314. package/dist/core/tools/model-fitness.d.ts +30 -0
  315. package/dist/core/tools/model-fitness.d.ts.map +1 -0
  316. package/dist/core/tools/model-fitness.js +38 -0
  317. package/dist/core/tools/model-fitness.js.map +1 -0
  318. package/dist/core/tools/run-toolkit-script.d.ts +24 -0
  319. package/dist/core/tools/run-toolkit-script.d.ts.map +1 -0
  320. package/dist/core/tools/run-toolkit-script.js +103 -0
  321. package/dist/core/tools/run-toolkit-script.js.map +1 -0
  322. package/dist/core/tools/search-router.d.ts +75 -0
  323. package/dist/core/tools/search-router.d.ts.map +1 -0
  324. package/dist/core/tools/search-router.js +85 -0
  325. package/dist/core/tools/search-router.js.map +1 -0
  326. package/dist/modes/interactive/components/fitness-role-selector.d.ts +13 -0
  327. package/dist/modes/interactive/components/fitness-role-selector.d.ts.map +1 -0
  328. package/dist/modes/interactive/components/fitness-role-selector.js +65 -0
  329. package/dist/modes/interactive/components/fitness-role-selector.js.map +1 -0
  330. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  331. package/dist/modes/interactive/components/footer.js +18 -16
  332. package/dist/modes/interactive/components/footer.js.map +1 -1
  333. package/dist/modes/interactive/components/settings-selector.d.ts +16 -1
  334. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  335. package/dist/modes/interactive/components/settings-selector.js +555 -11
  336. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  337. package/dist/modes/interactive/interactive-mode.d.ts +9 -0
  338. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  339. package/dist/modes/interactive/interactive-mode.js +308 -39
  340. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  341. package/dist/utils/tools-manager.d.ts +2 -0
  342. package/dist/utils/tools-manager.d.ts.map +1 -1
  343. package/dist/utils/tools-manager.js +154 -2
  344. package/dist/utils/tools-manager.js.map +1 -1
  345. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  346. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  347. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  348. package/examples/extensions/sandbox/package-lock.json +2 -2
  349. package/examples/extensions/sandbox/package.json +1 -1
  350. package/examples/extensions/with-deps/package-lock.json +2 -2
  351. package/examples/extensions/with-deps/package.json +1 -1
  352. package/npm-shrinkwrap.json +368 -12
  353. package/package.json +5 -4
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Pure policy-engine primitives (Phase 0.6): a hard-constraint evaluator, break-even
3
+ * scoring helpers, and reason-code formatting. No provider calls, no I/O, no wiring into
4
+ * prompt construction, model routing, or validation yet.
5
+ *
6
+ * The one invariant every helper here must uphold: a hard constraint can never be
7
+ * overridden by a positive expected saving. Scoring only runs for candidates that already
8
+ * cleared the hard-constraint layer.
9
+ */
10
+ const AGGRESSIVE_CONTEXT_ACTIONS = new Set([
11
+ "summarize",
12
+ "drop_from_prompt",
13
+ "pack_to_artifact",
14
+ ]);
15
+ function pushUnique(codes, code) {
16
+ if (!codes.includes(code))
17
+ codes.push(code);
18
+ }
19
+ /**
20
+ * Evaluate hard constraints for a single candidate action. Returns the (possibly empty)
21
+ * list of violated constraint codes; any non-empty result means the action must be
22
+ * rejected outright, never merely down-weighted by scoring.
23
+ */
24
+ export function evaluateHardConstraints(action, features, flags) {
25
+ const codes = [];
26
+ if (AGGRESSIVE_CONTEXT_ACTIONS.has(action)) {
27
+ if (features.isPinned)
28
+ pushUnique(codes, "pinned_user_instruction");
29
+ if (flags.isApprovalOrDenial)
30
+ pushUnique(codes, "approval_or_denial");
31
+ if (flags.isSafetyConstraint)
32
+ pushUnique(codes, "safety_constraint");
33
+ if (features.isOpenRequirement)
34
+ pushUnique(codes, "open_requirement");
35
+ if (flags.isActiveBlocker)
36
+ pushUnique(codes, "active_blocker");
37
+ if (features.isLatestFailure)
38
+ pushUnique(codes, "latest_unresolved_failure");
39
+ if (features.isCurrentDiff)
40
+ pushUnique(codes, "current_diff_summary");
41
+ if (flags.isCurrentValidationResult)
42
+ pushUnique(codes, "current_validation_result");
43
+ if (flags.isPathOrToolScope)
44
+ pushUnique(codes, "path_or_tool_scope");
45
+ }
46
+ // drop_from_prompt discards content outright, so it requires a retrieval path that
47
+ // already exists. pack_to_artifact is the first-capture operation that *creates* the
48
+ // retrieval path (tool-output-artifacts.md: measure -> digest/preview/artifact -> prompt
49
+ // item), so it must not be rejected merely for lacking one; it only needs a working
50
+ // artifact store to write into.
51
+ if (action === "drop_from_prompt" && !flags.hasAvailableRetrievalPath) {
52
+ pushUnique(codes, "missing_retrieval_path");
53
+ }
54
+ if (action === "pack_to_artifact" && !flags.artifactStoreAvailable) {
55
+ pushUnique(codes, "missing_retrieval_path");
56
+ }
57
+ if (action === "summarize" && features.isDecisionBearing && !flags.hasEvidenceRefForSummary) {
58
+ pushUnique(codes, "missing_retrieval_path");
59
+ }
60
+ if (action === "route_cheap") {
61
+ if (features.taskRisk === "high" || features.taskRisk === "unknown" || features.taskRisk === undefined) {
62
+ pushUnique(codes, "unknown_risk");
63
+ }
64
+ if (flags.isHighImpactOrBroadMultiFileEdit)
65
+ pushUnique(codes, "unknown_risk");
66
+ if (flags.priorAttemptFailedForReasoningOrArchitecture)
67
+ pushUnique(codes, "unknown_risk");
68
+ if (!flags.validationAvailableAndStrong)
69
+ pushUnique(codes, "unknown_risk");
70
+ if (!flags.pathOrToolBoundariesEnforced)
71
+ pushUnique(codes, "path_or_tool_scope");
72
+ }
73
+ return codes;
74
+ }
75
+ export function computeContextRetentionSaving(inputs) {
76
+ const rawCost = inputs.expectedRemainingTurns * inputs.rawTokens * inputs.marginalInputTokenCost;
77
+ const compactCost = inputs.expectedRemainingTurns * inputs.compactTokens * inputs.marginalInputTokenCost;
78
+ const oneTimeCost = inputs.packCostTokens +
79
+ inputs.probabilityNeededAgain * inputs.retrievalCostTokens +
80
+ inputs.probabilityErrorIfDropped * inputs.errorCostTokens +
81
+ inputs.cacheImpactTokens;
82
+ return rawCost - compactCost - oneTimeCost;
83
+ }
84
+ /**
85
+ * N_break_even(i) from decision-math-and-research.md: the number of remaining turns at
86
+ * which packing/summarizing first becomes worthwhile. Returns +Infinity when the raw vs.
87
+ * compact token gap never pays for itself (per-turn saving is zero or negative).
88
+ */
89
+ export function computeBreakEvenRemainingTurns(inputs) {
90
+ const perTurnSaving = (inputs.rawTokens - inputs.compactTokens) * inputs.marginalInputTokenCost;
91
+ if (perTurnSaving <= 0)
92
+ return Number.POSITIVE_INFINITY;
93
+ const oneTimeCost = inputs.packCostTokens +
94
+ inputs.probabilityNeededAgain * inputs.retrievalCostTokens +
95
+ inputs.probabilityErrorIfDropped * inputs.errorCostTokens +
96
+ inputs.cacheImpactTokens +
97
+ inputs.margin;
98
+ return oneTimeCost / perTurnSaving;
99
+ }
100
+ /**
101
+ * Hard cap override from policy-engine-spec.md: oversized raw tool output must be packed
102
+ * regardless of break-even math, unless the item is pinned, current, or the latest
103
+ * failure.
104
+ */
105
+ export function exceedsHardOutputCap(rawTokens, maxRawToolOutputTokens, features) {
106
+ if (features.isPinned || features.isCurrentDiff || features.isLatestFailure)
107
+ return false;
108
+ return rawTokens > maxRawToolOutputTokens;
109
+ }
110
+ /**
111
+ * Score one context-retention candidate. Hard constraints are checked first and, if any
112
+ * fire, the candidate is returned as unappliable (infinite cost, zero savings) no matter
113
+ * what the break-even math says — a hard constraint can never be overridden by savings.
114
+ */
115
+ export function scoreContextRetentionCandidate(input) {
116
+ const hardConstraints = evaluateHardConstraints(input.action, input.features, input.flags);
117
+ if (hardConstraints.length > 0) {
118
+ return {
119
+ action: input.action,
120
+ expectedCostTokens: Number.POSITIVE_INFINITY,
121
+ expectedSavingsTokens: 0,
122
+ expectedReliabilityRisk: 1,
123
+ cacheImpactTokens: input.saving.cacheImpactTokens,
124
+ reworkRiskTokens: input.saving.probabilityErrorIfDropped * input.saving.errorCostTokens,
125
+ confidence: "low",
126
+ reasonCodes: hardConstraints,
127
+ };
128
+ }
129
+ const saving = computeContextRetentionSaving(input.saving);
130
+ const applied = saving > input.margin;
131
+ const decisionBearingLowConfidence = input.features.isDecisionBearing && input.confidence === "low";
132
+ return {
133
+ action: input.action,
134
+ expectedCostTokens: input.saving.packCostTokens + input.saving.cacheImpactTokens,
135
+ expectedSavingsTokens: Math.max(0, saving),
136
+ expectedReliabilityRisk: input.saving.probabilityErrorIfDropped,
137
+ cacheImpactTokens: input.saving.cacheImpactTokens,
138
+ reworkRiskTokens: input.saving.probabilityErrorIfDropped * input.saving.errorCostTokens,
139
+ confidence: input.confidence,
140
+ reasonCodes: applied && !decisionBearingLowConfidence
141
+ ? ["saving_above_margin"]
142
+ : decisionBearingLowConfidence
143
+ ? ["low_confidence_decision_bearing"]
144
+ : ["saving_below_margin"],
145
+ };
146
+ }
147
+ const HARD_CONSTRAINT_REASON_TEXT = {
148
+ pinned_user_instruction: "item is a pinned user instruction and must remain present verbatim",
149
+ approval_or_denial: "item records a user approval or denial and cannot be summarized or dropped",
150
+ safety_constraint: "item is a safety/security constraint and must remain present verbatim",
151
+ open_requirement: "item is an open requirement for the active goal and cannot be dropped while active",
152
+ active_blocker: "item is an active blocker and must remain present until resolved",
153
+ latest_unresolved_failure: "item is the latest unresolved failure; dropping it risks repeating the mistake",
154
+ current_diff_summary: "item is the current diff summary during active code changes",
155
+ current_validation_result: "item is the current validation command/result and cannot be dropped while pending",
156
+ missing_retrieval_path: "no retrieval path (artifact/evidence ref) exists to recover this content if evicted",
157
+ path_or_tool_scope: "item encodes an active path/tool scope restriction that must stay enforced",
158
+ unknown_risk: "task risk is high or unknown and this action requires stronger reliability guarantees",
159
+ };
160
+ export function formatHardConstraintReason(code) {
161
+ return HARD_CONSTRAINT_REASON_TEXT[code];
162
+ }
163
+ /** Human-readable, deterministic summary of a scored candidate's reason codes. */
164
+ export function formatCandidateReason(candidate) {
165
+ const hardCodes = candidate.reasonCodes.filter((code) => code in HARD_CONSTRAINT_REASON_TEXT);
166
+ if (hardCodes.length > 0) {
167
+ return `${candidate.action} rejected: ${hardCodes.map(formatHardConstraintReason).join("; ")}`;
168
+ }
169
+ return `${candidate.action}: ${candidate.reasonCodes.join(", ")}`;
170
+ }
171
+ //# sourceMappingURL=policy-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-engine.js","sourceRoot":"","sources":["../../../src/core/context/policy-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAUH,MAAM,0BAA0B,GAA8B,IAAI,GAAG,CAAC;IACrE,WAAW;IACX,kBAAkB;IAClB,kBAAkB;CAClB,CAAC,CAAC;AAEH,SAAS,UAAU,CAAC,KAAiC,EAAE,IAA8B,EAAQ;IAC5F,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CAC5C;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACtC,MAAoB,EACpB,QAAwB,EACxB,KAA0B,EACG;IAC7B,MAAM,KAAK,GAA+B,EAAE,CAAC;IAE7C,IAAI,0BAA0B,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5C,IAAI,QAAQ,CAAC,QAAQ;YAAE,UAAU,CAAC,KAAK,EAAE,yBAAyB,CAAC,CAAC;QACpE,IAAI,KAAK,CAAC,kBAAkB;YAAE,UAAU,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;QACtE,IAAI,KAAK,CAAC,kBAAkB;YAAE,UAAU,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC;QACrE,IAAI,QAAQ,CAAC,iBAAiB;YAAE,UAAU,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;QACtE,IAAI,KAAK,CAAC,eAAe;YAAE,UAAU,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAC/D,IAAI,QAAQ,CAAC,eAAe;YAAE,UAAU,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QAC7E,IAAI,QAAQ,CAAC,aAAa;YAAE,UAAU,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC;QACtE,IAAI,KAAK,CAAC,yBAAyB;YAAE,UAAU,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QACpF,IAAI,KAAK,CAAC,iBAAiB;YAAE,UAAU,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;IACtE,CAAC;IAED,mFAAmF;IACnF,qFAAqF;IACrF,yFAAyF;IACzF,oFAAoF;IACpF,gCAAgC;IAChC,IAAI,MAAM,KAAK,kBAAkB,IAAI,CAAC,KAAK,CAAC,yBAAyB,EAAE,CAAC;QACvE,UAAU,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,MAAM,KAAK,kBAAkB,IAAI,CAAC,KAAK,CAAC,sBAAsB,EAAE,CAAC;QACpE,UAAU,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,MAAM,KAAK,WAAW,IAAI,QAAQ,CAAC,iBAAiB,IAAI,CAAC,KAAK,CAAC,wBAAwB,EAAE,CAAC;QAC7F,UAAU,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;QAC9B,IAAI,QAAQ,CAAC,QAAQ,KAAK,MAAM,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACxG,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,KAAK,CAAC,gCAAgC;YAAE,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;QAC9E,IAAI,KAAK,CAAC,4CAA4C;YAAE,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;QAC1F,IAAI,CAAC,KAAK,CAAC,4BAA4B;YAAE,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;QAC3E,IAAI,CAAC,KAAK,CAAC,4BAA4B;YAAE,UAAU,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,KAAK,CAAC;AAAA,CACb;AAoBD,MAAM,UAAU,6BAA6B,CAAC,MAAoC,EAAU;IAC3F,MAAM,OAAO,GAAG,MAAM,CAAC,sBAAsB,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,sBAAsB,CAAC;IACjG,MAAM,WAAW,GAAG,MAAM,CAAC,sBAAsB,GAAG,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC,sBAAsB,CAAC;IACzG,MAAM,WAAW,GAChB,MAAM,CAAC,cAAc;QACrB,MAAM,CAAC,sBAAsB,GAAG,MAAM,CAAC,mBAAmB;QAC1D,MAAM,CAAC,yBAAyB,GAAG,MAAM,CAAC,eAAe;QACzD,MAAM,CAAC,iBAAiB,CAAC;IAC1B,OAAO,OAAO,GAAG,WAAW,GAAG,WAAW,CAAC;AAAA,CAC3C;AAED;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAC7C,MAAyF,EAChF;IACT,MAAM,aAAa,GAAG,CAAC,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC,sBAAsB,CAAC;IAChG,IAAI,aAAa,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC,iBAAiB,CAAC;IACxD,MAAM,WAAW,GAChB,MAAM,CAAC,cAAc;QACrB,MAAM,CAAC,sBAAsB,GAAG,MAAM,CAAC,mBAAmB;QAC1D,MAAM,CAAC,yBAAyB,GAAG,MAAM,CAAC,eAAe;QACzD,MAAM,CAAC,iBAAiB;QACxB,MAAM,CAAC,MAAM,CAAC;IACf,OAAO,WAAW,GAAG,aAAa,CAAC;AAAA,CACnC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CACnC,SAAiB,EACjB,sBAA8B,EAC9B,QAAgF,EACtE;IACV,IAAI,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,aAAa,IAAI,QAAQ,CAAC,eAAe;QAAE,OAAO,KAAK,CAAC;IAC1F,OAAO,SAAS,GAAG,sBAAsB,CAAC;AAAA,CAC1C;AAWD;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAAC,KAAqC,EAAwB;IAC3G,MAAM,eAAe,GAAG,uBAAuB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3F,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,OAAO;YACN,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,kBAAkB,EAAE,MAAM,CAAC,iBAAiB;YAC5C,qBAAqB,EAAE,CAAC;YACxB,uBAAuB,EAAE,CAAC;YAC1B,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,iBAAiB;YACjD,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,yBAAyB,GAAG,KAAK,CAAC,MAAM,CAAC,eAAe;YACvF,UAAU,EAAE,KAAK;YACjB,WAAW,EAAE,eAAe;SAC5B,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,6BAA6B,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IACtC,MAAM,4BAA4B,GAAG,KAAK,CAAC,QAAQ,CAAC,iBAAiB,IAAI,KAAK,CAAC,UAAU,KAAK,KAAK,CAAC;IAEpG,OAAO;QACN,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,iBAAiB;QAChF,qBAAqB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC;QAC1C,uBAAuB,EAAE,KAAK,CAAC,MAAM,CAAC,yBAAyB;QAC/D,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,iBAAiB;QACjD,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,yBAAyB,GAAG,KAAK,CAAC,MAAM,CAAC,eAAe;QACvF,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,WAAW,EACV,OAAO,IAAI,CAAC,4BAA4B;YACvC,CAAC,CAAC,CAAC,qBAAqB,CAAC;YACzB,CAAC,CAAC,4BAA4B;gBAC7B,CAAC,CAAC,CAAC,iCAAiC,CAAC;gBACrC,CAAC,CAAC,CAAC,qBAAqB,CAAC;KAC5B,CAAC;AAAA,CACF;AAED,MAAM,2BAA2B,GAA6C;IAC7E,uBAAuB,EAAE,oEAAoE;IAC7F,kBAAkB,EAAE,4EAA4E;IAChG,iBAAiB,EAAE,uEAAuE;IAC1F,gBAAgB,EAAE,oFAAoF;IACtG,cAAc,EAAE,kEAAkE;IAClF,yBAAyB,EAAE,gFAAgF;IAC3G,oBAAoB,EAAE,6DAA6D;IACnF,yBAAyB,EAAE,mFAAmF;IAC9G,sBAAsB,EAAE,qFAAqF;IAC7G,kBAAkB,EAAE,4EAA4E;IAChG,YAAY,EAAE,uFAAuF;CACrG,CAAC;AAEF,MAAM,UAAU,0BAA0B,CAAC,IAA8B,EAAU;IAClF,OAAO,2BAA2B,CAAC,IAAI,CAAC,CAAC;AAAA,CACzC;AAED,kFAAkF;AAClF,MAAM,UAAU,qBAAqB,CAAC,SAA+D,EAAU;IAC9G,MAAM,SAAS,GAAG,SAAS,CAAC,WAAW,CAAC,MAAM,CAC7C,CAAC,IAAI,EAAoC,EAAE,CAAC,IAAI,IAAI,2BAA2B,CAC/E,CAAC;IACF,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,GAAG,SAAS,CAAC,MAAM,cAAc,SAAS,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAChG,CAAC;IACD,OAAO,GAAG,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAAA,CAClE","sourcesContent":["/**\n * Pure policy-engine primitives (Phase 0.6): a hard-constraint evaluator, break-even\n * scoring helpers, and reason-code formatting. No provider calls, no I/O, no wiring into\n * prompt construction, model routing, or validation yet.\n *\n * The one invariant every helper here must uphold: a hard constraint can never be\n * overridden by a positive expected saving. Scoring only runs for candidates that already\n * cleared the hard-constraint layer.\n */\n\nimport type {\n\tHardConstraintFlags,\n\tPolicyAction,\n\tPolicyCandidateScore,\n\tPolicyFeatures,\n\tPolicyHardConstraintCode,\n} from \"./policy-types.ts\";\n\nconst AGGRESSIVE_CONTEXT_ACTIONS: ReadonlySet<PolicyAction> = new Set([\n\t\"summarize\",\n\t\"drop_from_prompt\",\n\t\"pack_to_artifact\",\n]);\n\nfunction pushUnique(codes: PolicyHardConstraintCode[], code: PolicyHardConstraintCode): void {\n\tif (!codes.includes(code)) codes.push(code);\n}\n\n/**\n * Evaluate hard constraints for a single candidate action. Returns the (possibly empty)\n * list of violated constraint codes; any non-empty result means the action must be\n * rejected outright, never merely down-weighted by scoring.\n */\nexport function evaluateHardConstraints(\n\taction: PolicyAction,\n\tfeatures: PolicyFeatures,\n\tflags: HardConstraintFlags,\n): PolicyHardConstraintCode[] {\n\tconst codes: PolicyHardConstraintCode[] = [];\n\n\tif (AGGRESSIVE_CONTEXT_ACTIONS.has(action)) {\n\t\tif (features.isPinned) pushUnique(codes, \"pinned_user_instruction\");\n\t\tif (flags.isApprovalOrDenial) pushUnique(codes, \"approval_or_denial\");\n\t\tif (flags.isSafetyConstraint) pushUnique(codes, \"safety_constraint\");\n\t\tif (features.isOpenRequirement) pushUnique(codes, \"open_requirement\");\n\t\tif (flags.isActiveBlocker) pushUnique(codes, \"active_blocker\");\n\t\tif (features.isLatestFailure) pushUnique(codes, \"latest_unresolved_failure\");\n\t\tif (features.isCurrentDiff) pushUnique(codes, \"current_diff_summary\");\n\t\tif (flags.isCurrentValidationResult) pushUnique(codes, \"current_validation_result\");\n\t\tif (flags.isPathOrToolScope) pushUnique(codes, \"path_or_tool_scope\");\n\t}\n\n\t// drop_from_prompt discards content outright, so it requires a retrieval path that\n\t// already exists. pack_to_artifact is the first-capture operation that *creates* the\n\t// retrieval path (tool-output-artifacts.md: measure -> digest/preview/artifact -> prompt\n\t// item), so it must not be rejected merely for lacking one; it only needs a working\n\t// artifact store to write into.\n\tif (action === \"drop_from_prompt\" && !flags.hasAvailableRetrievalPath) {\n\t\tpushUnique(codes, \"missing_retrieval_path\");\n\t}\n\tif (action === \"pack_to_artifact\" && !flags.artifactStoreAvailable) {\n\t\tpushUnique(codes, \"missing_retrieval_path\");\n\t}\n\n\tif (action === \"summarize\" && features.isDecisionBearing && !flags.hasEvidenceRefForSummary) {\n\t\tpushUnique(codes, \"missing_retrieval_path\");\n\t}\n\n\tif (action === \"route_cheap\") {\n\t\tif (features.taskRisk === \"high\" || features.taskRisk === \"unknown\" || features.taskRisk === undefined) {\n\t\t\tpushUnique(codes, \"unknown_risk\");\n\t\t}\n\t\tif (flags.isHighImpactOrBroadMultiFileEdit) pushUnique(codes, \"unknown_risk\");\n\t\tif (flags.priorAttemptFailedForReasoningOrArchitecture) pushUnique(codes, \"unknown_risk\");\n\t\tif (!flags.validationAvailableAndStrong) pushUnique(codes, \"unknown_risk\");\n\t\tif (!flags.pathOrToolBoundariesEnforced) pushUnique(codes, \"path_or_tool_scope\");\n\t}\n\n\treturn codes;\n}\n\n/**\n * Inputs to the context-retention break-even formula from decision-math-and-research.md:\n * saving(i) = N_remaining * (T_raw - T_digest) * C_token - C_pack - P_need*C_retrieve\n * - P_error*C_error - C_cache\n */\nexport interface ContextRetentionSavingInputs {\n\trawTokens: number;\n\tcompactTokens: number;\n\texpectedRemainingTurns: number;\n\tmarginalInputTokenCost: number;\n\tpackCostTokens: number;\n\tprobabilityNeededAgain: number;\n\tretrievalCostTokens: number;\n\tprobabilityErrorIfDropped: number;\n\terrorCostTokens: number;\n\tcacheImpactTokens: number;\n}\n\nexport function computeContextRetentionSaving(inputs: ContextRetentionSavingInputs): number {\n\tconst rawCost = inputs.expectedRemainingTurns * inputs.rawTokens * inputs.marginalInputTokenCost;\n\tconst compactCost = inputs.expectedRemainingTurns * inputs.compactTokens * inputs.marginalInputTokenCost;\n\tconst oneTimeCost =\n\t\tinputs.packCostTokens +\n\t\tinputs.probabilityNeededAgain * inputs.retrievalCostTokens +\n\t\tinputs.probabilityErrorIfDropped * inputs.errorCostTokens +\n\t\tinputs.cacheImpactTokens;\n\treturn rawCost - compactCost - oneTimeCost;\n}\n\n/**\n * N_break_even(i) from decision-math-and-research.md: the number of remaining turns at\n * which packing/summarizing first becomes worthwhile. Returns +Infinity when the raw vs.\n * compact token gap never pays for itself (per-turn saving is zero or negative).\n */\nexport function computeBreakEvenRemainingTurns(\n\tinputs: Omit<ContextRetentionSavingInputs, \"expectedRemainingTurns\"> & { margin: number },\n): number {\n\tconst perTurnSaving = (inputs.rawTokens - inputs.compactTokens) * inputs.marginalInputTokenCost;\n\tif (perTurnSaving <= 0) return Number.POSITIVE_INFINITY;\n\tconst oneTimeCost =\n\t\tinputs.packCostTokens +\n\t\tinputs.probabilityNeededAgain * inputs.retrievalCostTokens +\n\t\tinputs.probabilityErrorIfDropped * inputs.errorCostTokens +\n\t\tinputs.cacheImpactTokens +\n\t\tinputs.margin;\n\treturn oneTimeCost / perTurnSaving;\n}\n\n/**\n * Hard cap override from policy-engine-spec.md: oversized raw tool output must be packed\n * regardless of break-even math, unless the item is pinned, current, or the latest\n * failure.\n */\nexport function exceedsHardOutputCap(\n\trawTokens: number,\n\tmaxRawToolOutputTokens: number,\n\tfeatures: Pick<PolicyFeatures, \"isPinned\" | \"isCurrentDiff\" | \"isLatestFailure\">,\n): boolean {\n\tif (features.isPinned || features.isCurrentDiff || features.isLatestFailure) return false;\n\treturn rawTokens > maxRawToolOutputTokens;\n}\n\nexport interface ContextRetentionCandidateInput {\n\taction: PolicyAction;\n\tfeatures: PolicyFeatures;\n\tflags: HardConstraintFlags;\n\tsaving: ContextRetentionSavingInputs;\n\tmargin: number;\n\tconfidence: \"low\" | \"medium\" | \"high\";\n}\n\n/**\n * Score one context-retention candidate. Hard constraints are checked first and, if any\n * fire, the candidate is returned as unappliable (infinite cost, zero savings) no matter\n * what the break-even math says — a hard constraint can never be overridden by savings.\n */\nexport function scoreContextRetentionCandidate(input: ContextRetentionCandidateInput): PolicyCandidateScore {\n\tconst hardConstraints = evaluateHardConstraints(input.action, input.features, input.flags);\n\tif (hardConstraints.length > 0) {\n\t\treturn {\n\t\t\taction: input.action,\n\t\t\texpectedCostTokens: Number.POSITIVE_INFINITY,\n\t\t\texpectedSavingsTokens: 0,\n\t\t\texpectedReliabilityRisk: 1,\n\t\t\tcacheImpactTokens: input.saving.cacheImpactTokens,\n\t\t\treworkRiskTokens: input.saving.probabilityErrorIfDropped * input.saving.errorCostTokens,\n\t\t\tconfidence: \"low\",\n\t\t\treasonCodes: hardConstraints,\n\t\t};\n\t}\n\n\tconst saving = computeContextRetentionSaving(input.saving);\n\tconst applied = saving > input.margin;\n\tconst decisionBearingLowConfidence = input.features.isDecisionBearing && input.confidence === \"low\";\n\n\treturn {\n\t\taction: input.action,\n\t\texpectedCostTokens: input.saving.packCostTokens + input.saving.cacheImpactTokens,\n\t\texpectedSavingsTokens: Math.max(0, saving),\n\t\texpectedReliabilityRisk: input.saving.probabilityErrorIfDropped,\n\t\tcacheImpactTokens: input.saving.cacheImpactTokens,\n\t\treworkRiskTokens: input.saving.probabilityErrorIfDropped * input.saving.errorCostTokens,\n\t\tconfidence: input.confidence,\n\t\treasonCodes:\n\t\t\tapplied && !decisionBearingLowConfidence\n\t\t\t\t? [\"saving_above_margin\"]\n\t\t\t\t: decisionBearingLowConfidence\n\t\t\t\t\t? [\"low_confidence_decision_bearing\"]\n\t\t\t\t\t: [\"saving_below_margin\"],\n\t};\n}\n\nconst HARD_CONSTRAINT_REASON_TEXT: Record<PolicyHardConstraintCode, string> = {\n\tpinned_user_instruction: \"item is a pinned user instruction and must remain present verbatim\",\n\tapproval_or_denial: \"item records a user approval or denial and cannot be summarized or dropped\",\n\tsafety_constraint: \"item is a safety/security constraint and must remain present verbatim\",\n\topen_requirement: \"item is an open requirement for the active goal and cannot be dropped while active\",\n\tactive_blocker: \"item is an active blocker and must remain present until resolved\",\n\tlatest_unresolved_failure: \"item is the latest unresolved failure; dropping it risks repeating the mistake\",\n\tcurrent_diff_summary: \"item is the current diff summary during active code changes\",\n\tcurrent_validation_result: \"item is the current validation command/result and cannot be dropped while pending\",\n\tmissing_retrieval_path: \"no retrieval path (artifact/evidence ref) exists to recover this content if evicted\",\n\tpath_or_tool_scope: \"item encodes an active path/tool scope restriction that must stay enforced\",\n\tunknown_risk: \"task risk is high or unknown and this action requires stronger reliability guarantees\",\n};\n\nexport function formatHardConstraintReason(code: PolicyHardConstraintCode): string {\n\treturn HARD_CONSTRAINT_REASON_TEXT[code];\n}\n\n/** Human-readable, deterministic summary of a scored candidate's reason codes. */\nexport function formatCandidateReason(candidate: Pick<PolicyCandidateScore, \"action\" | \"reasonCodes\">): string {\n\tconst hardCodes = candidate.reasonCodes.filter(\n\t\t(code): code is PolicyHardConstraintCode => code in HARD_CONSTRAINT_REASON_TEXT,\n\t);\n\tif (hardCodes.length > 0) {\n\t\treturn `${candidate.action} rejected: ${hardCodes.map(formatHardConstraintReason).join(\"; \")}`;\n\t}\n\treturn `${candidate.action}: ${candidate.reasonCodes.join(\", \")}`;\n}\n"]}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Pure policy-engine contracts (Phase 0.6). No behavior change: nothing here is wired
3
+ * into prompt construction, model routing, or validation yet. See
4
+ * docs/context-management-rework/policy-engine-spec.md for the design this mirrors.
5
+ */
6
+ import type { ContextArtifactRef, ContextEvidenceRef, ContextRetentionClass } from "./context-item.ts";
7
+ export type PolicyMode = "off" | "shadow" | "enforce_safe" | "enforce_all";
8
+ export type PolicyDecisionKind = "context_retention" | "artifact_retrieval" | "tool_rerun" | "model_route" | "validation" | "goal_continuation";
9
+ export type PolicyAction = "keep_raw" | "pack_to_artifact" | "summarize" | "drop_from_prompt" | "retrieve_artifact_slice" | "rerun_narrowed_tool" | "route_cheap" | "route_medium" | "route_expensive" | "run_validation" | "skip_optional_validation" | "continue_goal" | "stop_and_ask";
10
+ /**
11
+ * Fixed, closed set of hard-constraint reason codes. The policy engine never invents a
12
+ * new code at runtime: every hard rejection maps to one of these.
13
+ */
14
+ export type PolicyHardConstraintCode = "pinned_user_instruction" | "approval_or_denial" | "safety_constraint" | "open_requirement" | "active_blocker" | "latest_unresolved_failure" | "current_diff_summary" | "current_validation_result" | "missing_retrieval_path" | "path_or_tool_scope" | "unknown_risk";
15
+ export interface PolicyFeatures {
16
+ turnIndex: number;
17
+ expectedRemainingTurns: number;
18
+ inputTokens: number;
19
+ outputTokens: number;
20
+ cacheReadTokens: number;
21
+ cacheWriteTokens: number;
22
+ artifactBytes: number;
23
+ charEstimate: number;
24
+ calibratedTokenEstimate: number;
25
+ promptSection: "stable_prefix" | "volatile_tail" | "artifact" | "memory";
26
+ retentionClass?: ContextRetentionClass;
27
+ isReproducible: boolean;
28
+ isDecisionBearing: boolean;
29
+ isPinned: boolean;
30
+ isOpenRequirement: boolean;
31
+ isLatestFailure: boolean;
32
+ isCurrentDiff: boolean;
33
+ cacheHitProbability?: number;
34
+ cacheMissCostTokens?: number;
35
+ probabilityNeededAgain: number;
36
+ probabilityErrorIfDropped: number;
37
+ retrievalCostTokens: number;
38
+ packCostTokens: number;
39
+ retryCostTokens: number;
40
+ failureCostTokens: number;
41
+ validationCostTokens: number;
42
+ modelTier?: "cheap" | "medium" | "expensive" | "learning";
43
+ taskRisk?: "low" | "medium" | "high" | "unknown";
44
+ }
45
+ export interface PolicyCandidateScore {
46
+ action: PolicyAction;
47
+ expectedCostTokens: number;
48
+ expectedSavingsTokens: number;
49
+ expectedReliabilityRisk: number;
50
+ cacheImpactTokens: number;
51
+ reworkRiskTokens: number;
52
+ confidence: "low" | "medium" | "high";
53
+ reasonCodes: string[];
54
+ }
55
+ export interface PolicyDecision {
56
+ kind: PolicyDecisionKind;
57
+ selectedAction: PolicyAction;
58
+ mode: PolicyMode;
59
+ applied: boolean;
60
+ hardConstraints: PolicyHardConstraintCode[];
61
+ candidates: PolicyCandidateScore[];
62
+ selectedReasonCodes: string[];
63
+ estimatedCostTokens: number;
64
+ estimatedSavingsTokens: number;
65
+ estimatedReliabilityRisk: number;
66
+ cacheImpactTokens: number;
67
+ reworkRiskTokens: number;
68
+ artifactRefs: ContextArtifactRef[];
69
+ evidenceRefs: ContextEvidenceRef[];
70
+ }
71
+ /**
72
+ * Flags a caller supplies alongside `PolicyFeatures` so the hard-constraint evaluator can
73
+ * distinguish reason codes `PolicyFeatures` alone does not carry (e.g. approvals/denials
74
+ * and safety constraints are not modeled as separate `PolicyFeatures` booleans).
75
+ */
76
+ export interface HardConstraintFlags {
77
+ isApprovalOrDenial: boolean;
78
+ isSafetyConstraint: boolean;
79
+ isActiveBlocker: boolean;
80
+ isCurrentValidationResult: boolean;
81
+ isPathOrToolScope: boolean;
82
+ /**
83
+ * True only if the item's existing ref is currently resolvable, not merely present.
84
+ * An artifact ref is resolvable only if the artifact store/payload is available; a
85
+ * transcript/memory/runtime ref is resolvable independent of the artifact store. Callers
86
+ * must compute this by checking the concrete ref kind against its backing store, not by
87
+ * treating "some ref is attached" as sufficient.
88
+ */
89
+ hasAvailableRetrievalPath: boolean;
90
+ artifactStoreAvailable: boolean;
91
+ /** Only relevant when the candidate action is "summarize" on decision-bearing content. */
92
+ hasEvidenceRefForSummary: boolean;
93
+ /** Only relevant for model-routing candidates ("route_cheap"). */
94
+ pathOrToolBoundariesEnforced: boolean;
95
+ /** Only relevant for model-routing candidates ("route_cheap"). */
96
+ validationAvailableAndStrong: boolean;
97
+ /** Only relevant for model-routing candidates ("route_cheap"). */
98
+ priorAttemptFailedForReasoningOrArchitecture: boolean;
99
+ /** Only relevant for model-routing candidates ("route_cheap"). */
100
+ isHighImpactOrBroadMultiFileEdit: boolean;
101
+ }
102
+ //# sourceMappingURL=policy-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-types.d.ts","sourceRoot":"","sources":["../../../src/core/context/policy-types.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure policy-engine contracts (Phase 0.6). No behavior change: nothing here is wired\n * into prompt construction, model routing, or validation yet. See\n * docs/context-management-rework/policy-engine-spec.md for the design this mirrors.\n */\n\nimport type { ContextArtifactRef, ContextEvidenceRef, ContextRetentionClass } from \"./context-item.ts\";\n\nexport type PolicyMode = \"off\" | \"shadow\" | \"enforce_safe\" | \"enforce_all\";\n\nexport type PolicyDecisionKind =\n\t| \"context_retention\"\n\t| \"artifact_retrieval\"\n\t| \"tool_rerun\"\n\t| \"model_route\"\n\t| \"validation\"\n\t| \"goal_continuation\";\n\nexport type PolicyAction =\n\t| \"keep_raw\"\n\t| \"pack_to_artifact\"\n\t| \"summarize\"\n\t| \"drop_from_prompt\"\n\t| \"retrieve_artifact_slice\"\n\t| \"rerun_narrowed_tool\"\n\t| \"route_cheap\"\n\t| \"route_medium\"\n\t| \"route_expensive\"\n\t| \"run_validation\"\n\t| \"skip_optional_validation\"\n\t| \"continue_goal\"\n\t| \"stop_and_ask\";\n\n/**\n * Fixed, closed set of hard-constraint reason codes. The policy engine never invents a\n * new code at runtime: every hard rejection maps to one of these.\n */\nexport type PolicyHardConstraintCode =\n\t| \"pinned_user_instruction\"\n\t| \"approval_or_denial\"\n\t| \"safety_constraint\"\n\t| \"open_requirement\"\n\t| \"active_blocker\"\n\t| \"latest_unresolved_failure\"\n\t| \"current_diff_summary\"\n\t| \"current_validation_result\"\n\t| \"missing_retrieval_path\"\n\t| \"path_or_tool_scope\"\n\t| \"unknown_risk\";\n\nexport interface PolicyFeatures {\n\tturnIndex: number;\n\texpectedRemainingTurns: number;\n\tinputTokens: number;\n\toutputTokens: number;\n\tcacheReadTokens: number;\n\tcacheWriteTokens: number;\n\tartifactBytes: number;\n\tcharEstimate: number;\n\tcalibratedTokenEstimate: number;\n\tpromptSection: \"stable_prefix\" | \"volatile_tail\" | \"artifact\" | \"memory\";\n\tretentionClass?: ContextRetentionClass;\n\tisReproducible: boolean;\n\tisDecisionBearing: boolean;\n\tisPinned: boolean;\n\tisOpenRequirement: boolean;\n\tisLatestFailure: boolean;\n\tisCurrentDiff: boolean;\n\tcacheHitProbability?: number;\n\tcacheMissCostTokens?: number;\n\tprobabilityNeededAgain: number;\n\tprobabilityErrorIfDropped: number;\n\tretrievalCostTokens: number;\n\tpackCostTokens: number;\n\tretryCostTokens: number;\n\tfailureCostTokens: number;\n\tvalidationCostTokens: number;\n\tmodelTier?: \"cheap\" | \"medium\" | \"expensive\" | \"learning\";\n\ttaskRisk?: \"low\" | \"medium\" | \"high\" | \"unknown\";\n}\n\nexport interface PolicyCandidateScore {\n\taction: PolicyAction;\n\texpectedCostTokens: number;\n\texpectedSavingsTokens: number;\n\texpectedReliabilityRisk: number;\n\tcacheImpactTokens: number;\n\treworkRiskTokens: number;\n\tconfidence: \"low\" | \"medium\" | \"high\";\n\treasonCodes: string[];\n}\n\nexport interface PolicyDecision {\n\tkind: PolicyDecisionKind;\n\tselectedAction: PolicyAction;\n\tmode: PolicyMode;\n\tapplied: boolean;\n\thardConstraints: PolicyHardConstraintCode[];\n\tcandidates: PolicyCandidateScore[];\n\tselectedReasonCodes: string[];\n\testimatedCostTokens: number;\n\testimatedSavingsTokens: number;\n\testimatedReliabilityRisk: number;\n\tcacheImpactTokens: number;\n\treworkRiskTokens: number;\n\tartifactRefs: ContextArtifactRef[];\n\tevidenceRefs: ContextEvidenceRef[];\n}\n\n/**\n * Flags a caller supplies alongside `PolicyFeatures` so the hard-constraint evaluator can\n * distinguish reason codes `PolicyFeatures` alone does not carry (e.g. approvals/denials\n * and safety constraints are not modeled as separate `PolicyFeatures` booleans).\n */\nexport interface HardConstraintFlags {\n\tisApprovalOrDenial: boolean;\n\tisSafetyConstraint: boolean;\n\tisActiveBlocker: boolean;\n\tisCurrentValidationResult: boolean;\n\tisPathOrToolScope: boolean;\n\t/**\n\t * True only if the item's existing ref is currently resolvable, not merely present.\n\t * An artifact ref is resolvable only if the artifact store/payload is available; a\n\t * transcript/memory/runtime ref is resolvable independent of the artifact store. Callers\n\t * must compute this by checking the concrete ref kind against its backing store, not by\n\t * treating \"some ref is attached\" as sufficient.\n\t */\n\thasAvailableRetrievalPath: boolean;\n\tartifactStoreAvailable: boolean;\n\t/** Only relevant when the candidate action is \"summarize\" on decision-bearing content. */\n\thasEvidenceRefForSummary: boolean;\n\t/** Only relevant for model-routing candidates (\"route_cheap\"). */\n\tpathOrToolBoundariesEnforced: boolean;\n\t/** Only relevant for model-routing candidates (\"route_cheap\"). */\n\tvalidationAvailableAndStrong: boolean;\n\t/** Only relevant for model-routing candidates (\"route_cheap\"). */\n\tpriorAttemptFailedForReasoningOrArchitecture: boolean;\n\t/** Only relevant for model-routing candidates (\"route_cheap\"). */\n\tisHighImpactOrBroadMultiFileEdit: boolean;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Pure policy-engine contracts (Phase 0.6). No behavior change: nothing here is wired
3
+ * into prompt construction, model routing, or validation yet. See
4
+ * docs/context-management-rework/policy-engine-spec.md for the design this mirrors.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=policy-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-types.js","sourceRoot":"","sources":["../../../src/core/context/policy-types.ts"],"names":[],"mappings":"AAAA;;;;GAIG","sourcesContent":["/**\n * Pure policy-engine contracts (Phase 0.6). No behavior change: nothing here is wired\n * into prompt construction, model routing, or validation yet. See\n * docs/context-management-rework/policy-engine-spec.md for the design this mirrors.\n */\n\nimport type { ContextArtifactRef, ContextEvidenceRef, ContextRetentionClass } from \"./context-item.ts\";\n\nexport type PolicyMode = \"off\" | \"shadow\" | \"enforce_safe\" | \"enforce_all\";\n\nexport type PolicyDecisionKind =\n\t| \"context_retention\"\n\t| \"artifact_retrieval\"\n\t| \"tool_rerun\"\n\t| \"model_route\"\n\t| \"validation\"\n\t| \"goal_continuation\";\n\nexport type PolicyAction =\n\t| \"keep_raw\"\n\t| \"pack_to_artifact\"\n\t| \"summarize\"\n\t| \"drop_from_prompt\"\n\t| \"retrieve_artifact_slice\"\n\t| \"rerun_narrowed_tool\"\n\t| \"route_cheap\"\n\t| \"route_medium\"\n\t| \"route_expensive\"\n\t| \"run_validation\"\n\t| \"skip_optional_validation\"\n\t| \"continue_goal\"\n\t| \"stop_and_ask\";\n\n/**\n * Fixed, closed set of hard-constraint reason codes. The policy engine never invents a\n * new code at runtime: every hard rejection maps to one of these.\n */\nexport type PolicyHardConstraintCode =\n\t| \"pinned_user_instruction\"\n\t| \"approval_or_denial\"\n\t| \"safety_constraint\"\n\t| \"open_requirement\"\n\t| \"active_blocker\"\n\t| \"latest_unresolved_failure\"\n\t| \"current_diff_summary\"\n\t| \"current_validation_result\"\n\t| \"missing_retrieval_path\"\n\t| \"path_or_tool_scope\"\n\t| \"unknown_risk\";\n\nexport interface PolicyFeatures {\n\tturnIndex: number;\n\texpectedRemainingTurns: number;\n\tinputTokens: number;\n\toutputTokens: number;\n\tcacheReadTokens: number;\n\tcacheWriteTokens: number;\n\tartifactBytes: number;\n\tcharEstimate: number;\n\tcalibratedTokenEstimate: number;\n\tpromptSection: \"stable_prefix\" | \"volatile_tail\" | \"artifact\" | \"memory\";\n\tretentionClass?: ContextRetentionClass;\n\tisReproducible: boolean;\n\tisDecisionBearing: boolean;\n\tisPinned: boolean;\n\tisOpenRequirement: boolean;\n\tisLatestFailure: boolean;\n\tisCurrentDiff: boolean;\n\tcacheHitProbability?: number;\n\tcacheMissCostTokens?: number;\n\tprobabilityNeededAgain: number;\n\tprobabilityErrorIfDropped: number;\n\tretrievalCostTokens: number;\n\tpackCostTokens: number;\n\tretryCostTokens: number;\n\tfailureCostTokens: number;\n\tvalidationCostTokens: number;\n\tmodelTier?: \"cheap\" | \"medium\" | \"expensive\" | \"learning\";\n\ttaskRisk?: \"low\" | \"medium\" | \"high\" | \"unknown\";\n}\n\nexport interface PolicyCandidateScore {\n\taction: PolicyAction;\n\texpectedCostTokens: number;\n\texpectedSavingsTokens: number;\n\texpectedReliabilityRisk: number;\n\tcacheImpactTokens: number;\n\treworkRiskTokens: number;\n\tconfidence: \"low\" | \"medium\" | \"high\";\n\treasonCodes: string[];\n}\n\nexport interface PolicyDecision {\n\tkind: PolicyDecisionKind;\n\tselectedAction: PolicyAction;\n\tmode: PolicyMode;\n\tapplied: boolean;\n\thardConstraints: PolicyHardConstraintCode[];\n\tcandidates: PolicyCandidateScore[];\n\tselectedReasonCodes: string[];\n\testimatedCostTokens: number;\n\testimatedSavingsTokens: number;\n\testimatedReliabilityRisk: number;\n\tcacheImpactTokens: number;\n\treworkRiskTokens: number;\n\tartifactRefs: ContextArtifactRef[];\n\tevidenceRefs: ContextEvidenceRef[];\n}\n\n/**\n * Flags a caller supplies alongside `PolicyFeatures` so the hard-constraint evaluator can\n * distinguish reason codes `PolicyFeatures` alone does not carry (e.g. approvals/denials\n * and safety constraints are not modeled as separate `PolicyFeatures` booleans).\n */\nexport interface HardConstraintFlags {\n\tisApprovalOrDenial: boolean;\n\tisSafetyConstraint: boolean;\n\tisActiveBlocker: boolean;\n\tisCurrentValidationResult: boolean;\n\tisPathOrToolScope: boolean;\n\t/**\n\t * True only if the item's existing ref is currently resolvable, not merely present.\n\t * An artifact ref is resolvable only if the artifact store/payload is available; a\n\t * transcript/memory/runtime ref is resolvable independent of the artifact store. Callers\n\t * must compute this by checking the concrete ref kind against its backing store, not by\n\t * treating \"some ref is attached\" as sufficient.\n\t */\n\thasAvailableRetrievalPath: boolean;\n\tartifactStoreAvailable: boolean;\n\t/** Only relevant when the candidate action is \"summarize\" on decision-bearing content. */\n\thasEvidenceRefForSummary: boolean;\n\t/** Only relevant for model-routing candidates (\"route_cheap\"). */\n\tpathOrToolBoundariesEnforced: boolean;\n\t/** Only relevant for model-routing candidates (\"route_cheap\"). */\n\tvalidationAvailableAndStrong: boolean;\n\t/** Only relevant for model-routing candidates (\"route_cheap\"). */\n\tpriorAttemptFailedForReasoningOrArchitecture: boolean;\n\t/** Only relevant for model-routing candidates (\"route_cheap\"). */\n\tisHighImpactOrBroadMultiFileEdit: boolean;\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ import type { ContextStore } from "./context-store.ts";
3
+ import type { MemoryIndexStore } from "./memory-index-store.ts";
4
+ export declare const SQLITE_RUNTIME_INDEX_SCHEMA_VERSION = 1;
5
+ export declare const SQLITE_CONTEXT_INDEX_TABLES: readonly ["context_items", "artifact_metadata", "policy_score_cache", "policy_decisions", "retrieval_records", "memory_index"];
6
+ export interface SqliteRuntimeIndexOptions {
7
+ databasePath: string;
8
+ busyTimeoutMs?: number;
9
+ }
10
+ export interface SqliteContextStore extends ContextStore {
11
+ close(): void;
12
+ }
13
+ export interface SqliteMemoryIndexStore extends MemoryIndexStore {
14
+ close(): void;
15
+ }
16
+ export declare function migrateSqliteRuntimeIndex(database: DatabaseSync): void;
17
+ export declare function createSqliteContextStore(options: SqliteRuntimeIndexOptions): SqliteContextStore;
18
+ export declare function createSqliteMemoryIndexStore(options: SqliteRuntimeIndexOptions): SqliteMemoryIndexStore;
19
+ //# sourceMappingURL=sqlite-runtime-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-runtime-index.d.ts","sourceRoot":"","sources":["../../../src/core/context/sqlite-runtime-index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,YAAY,EAAyC,MAAM,oBAAoB,CAAC;AAC9F,OAAO,KAAK,EAAqB,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGnF,eAAO,MAAM,mCAAmC,IAAI,CAAC;AAErD,eAAO,MAAM,2BAA2B,gIAO9B,CAAC;AAEX,MAAM,WAAW,yBAAyB;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACvD,KAAK,IAAI,IAAI,CAAC;CACd;AAED,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC/D,KAAK,IAAI,IAAI,CAAC;CACd;AA4BD,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CA+FtE;AA4GD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,yBAAyB,GAAG,kBAAkB,CAqH/F;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,yBAAyB,GAAG,sBAAsB,CAkEvG","sourcesContent":["import { mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport type { ContextItem } from \"./context-item.ts\";\nimport type { ContextStore, PolicyDecisionRecord, RetrievalRecord } from \"./context-store.ts\";\nimport type { MemoryIndexRecord, MemoryIndexStore } from \"./memory-index-store.ts\";\nimport type { PolicyDecision } from \"./policy-types.ts\";\n\nexport const SQLITE_RUNTIME_INDEX_SCHEMA_VERSION = 1;\n\nexport const SQLITE_CONTEXT_INDEX_TABLES = [\n\t\"context_items\",\n\t\"artifact_metadata\",\n\t\"policy_score_cache\",\n\t\"policy_decisions\",\n\t\"retrieval_records\",\n\t\"memory_index\",\n] as const;\n\nexport interface SqliteRuntimeIndexOptions {\n\tdatabasePath: string;\n\tbusyTimeoutMs?: number;\n}\n\nexport interface SqliteContextStore extends ContextStore {\n\tclose(): void;\n}\n\nexport interface SqliteMemoryIndexStore extends MemoryIndexStore {\n\tclose(): void;\n}\n\nfunction prepareDatabasePath(databasePath: string): void {\n\tif (databasePath === \":memory:\") return;\n\tmkdirSync(dirname(databasePath), { recursive: true });\n}\n\nfunction openDatabase(options: SqliteRuntimeIndexOptions): DatabaseSync {\n\tprepareDatabasePath(options.databasePath);\n\tconst database = new DatabaseSync(options.databasePath, {\n\t\tenableForeignKeyConstraints: true,\n\t\ttimeout: options.busyTimeoutMs ?? 5_000,\n\t});\n\tdatabase.exec(`\n\t\tPRAGMA foreign_keys = ON;\n\t\tPRAGMA busy_timeout = ${options.busyTimeoutMs ?? 5_000};\n\t\tPRAGMA journal_mode = WAL;\n\t`);\n\tmigrateSqliteRuntimeIndex(database);\n\treturn database;\n}\n\nfunction currentSchemaVersion(database: DatabaseSync): number {\n\tconst row = database.prepare(\"PRAGMA user_version\").get();\n\tconst value = row?.user_version;\n\treturn typeof value === \"number\" ? value : 0;\n}\n\nexport function migrateSqliteRuntimeIndex(database: DatabaseSync): void {\n\tconst version = currentSchemaVersion(database);\n\tif (version > SQLITE_RUNTIME_INDEX_SCHEMA_VERSION) {\n\t\tthrow new Error(\n\t\t\t`Unsupported Pi context runtime-index schema version ${version}; current runtime supports ${SQLITE_RUNTIME_INDEX_SCHEMA_VERSION}`,\n\t\t);\n\t}\n\n\ttry {\n\t\tdatabase.exec(`\n\t\t\tBEGIN IMMEDIATE;\n\n\t\t\tCREATE TABLE IF NOT EXISTS context_items (\n\t\t\t\tid TEXT PRIMARY KEY NOT NULL,\n\t\t\t\tkind TEXT NOT NULL,\n\t\t\t\tretention_class TEXT NOT NULL,\n\t\t\t\tsource TEXT NOT NULL,\n\t\t\t\tcreated_at_turn INTEGER NOT NULL,\n\t\t\t\tlast_used_at_turn INTEGER,\n\t\t\t\ttoken_estimate INTEGER NOT NULL,\n\t\t\t\tbyte_estimate INTEGER NOT NULL,\n\t\t\t\tpayload_json TEXT NOT NULL\n\t\t\t) STRICT;\n\n\t\t\tCREATE TABLE IF NOT EXISTS artifact_metadata (\n\t\t\t\tid TEXT PRIMARY KEY NOT NULL,\n\t\t\t\tkind TEXT NOT NULL,\n\t\t\t\tstorage_path TEXT,\n\t\t\t\tsession_entry_id TEXT,\n\t\t\t\ttool_name TEXT,\n\t\t\t\tcommand TEXT,\n\t\t\t\tpath TEXT,\n\t\t\t\tbyte_length INTEGER NOT NULL,\n\t\t\t\tline_count INTEGER,\n\t\t\t\tcreated_at_turn INTEGER NOT NULL,\n\t\t\t\treproducible INTEGER NOT NULL CHECK (reproducible IN (0, 1)),\n\t\t\t\tpayload_exists INTEGER NOT NULL DEFAULT 1 CHECK (payload_exists IN (0, 1)),\n\t\t\t\tpayload_json TEXT NOT NULL\n\t\t\t) STRICT;\n\n\t\t\tCREATE TABLE IF NOT EXISTS policy_score_cache (\n\t\t\t\tcache_key TEXT PRIMARY KEY NOT NULL,\n\t\t\t\tcreated_at_turn INTEGER NOT NULL,\n\t\t\t\tpayload_json TEXT NOT NULL\n\t\t\t) STRICT;\n\n\t\t\tCREATE TABLE IF NOT EXISTS policy_decisions (\n\t\t\t\tid TEXT PRIMARY KEY NOT NULL,\n\t\t\t\tcontext_item_id TEXT,\n\t\t\t\trecorded_at_turn INTEGER NOT NULL,\n\t\t\t\tdecision_kind TEXT NOT NULL,\n\t\t\t\tselected_action TEXT NOT NULL,\n\t\t\t\tmode TEXT NOT NULL,\n\t\t\t\tapplied INTEGER NOT NULL CHECK (applied IN (0, 1)),\n\t\t\t\tpayload_json TEXT NOT NULL\n\t\t\t) STRICT;\n\n\t\t\tCREATE INDEX IF NOT EXISTS idx_policy_decisions_context_item_id\n\t\t\t\tON policy_decisions(context_item_id, recorded_at_turn);\n\n\t\t\tCREATE TABLE IF NOT EXISTS retrieval_records (\n\t\t\t\tid TEXT PRIMARY KEY NOT NULL,\n\t\t\t\tcontext_item_id TEXT NOT NULL,\n\t\t\t\trequested_at_turn INTEGER NOT NULL,\n\t\t\t\tslice_kind TEXT NOT NULL,\n\t\t\t\tresult_summary TEXT NOT NULL,\n\t\t\t\tpayload_json TEXT NOT NULL\n\t\t\t) STRICT;\n\n\t\t\tCREATE INDEX IF NOT EXISTS idx_retrieval_records_context_item_id\n\t\t\t\tON retrieval_records(context_item_id, requested_at_turn);\n\n\t\t\tCREATE TABLE IF NOT EXISTS memory_index (\n\t\t\t\tprovider_id TEXT NOT NULL,\n\t\t\t\titem_id TEXT NOT NULL,\n\t\t\t\tscope TEXT NOT NULL,\n\t\t\t\tkind TEXT NOT NULL,\n\t\t\t\ttitle TEXT,\n\t\t\t\tsummary TEXT NOT NULL,\n\t\t\t\tindexed_at_turn INTEGER NOT NULL,\n\t\t\t\tstale INTEGER NOT NULL CHECK (stale IN (0, 1)),\n\t\t\t\tpayload_json TEXT NOT NULL,\n\t\t\t\tPRIMARY KEY (provider_id, item_id)\n\t\t\t) STRICT;\n\n\t\t\tCREATE INDEX IF NOT EXISTS idx_memory_index_scope\n\t\t\t\tON memory_index(scope, provider_id, item_id);\n\n\t\t\tPRAGMA user_version = ${SQLITE_RUNTIME_INDEX_SCHEMA_VERSION};\n\t\t\tCOMMIT;\n\t\t`);\n\t} catch (error) {\n\t\tif (database.isTransaction) database.exec(\"ROLLBACK;\");\n\t\tthrow error;\n\t}\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseJsonRecord<T>(json: string, isValid: (value: unknown) => value is T): T | undefined {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(json);\n\t\treturn isValid(parsed) ? parsed : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction textColumn(row: Record<string, unknown> | undefined, column: string): string | undefined {\n\tconst value = row?.[column];\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nfunction isContextItem(value: unknown): value is ContextItem {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\ttypeof value.kind === \"string\" &&\n\t\ttypeof value.retentionClass === \"string\" &&\n\t\ttypeof value.source === \"string\" &&\n\t\ttypeof value.createdAtTurn === \"number\" &&\n\t\ttypeof value.tokenEstimate === \"number\" &&\n\t\ttypeof value.byteEstimate === \"number\"\n\t);\n}\n\nfunction isPolicyDecision(value: unknown): value is PolicyDecision {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.kind === \"string\" &&\n\t\ttypeof value.selectedAction === \"string\" &&\n\t\ttypeof value.mode === \"string\" &&\n\t\ttypeof value.applied === \"boolean\" &&\n\t\tArray.isArray(value.hardConstraints) &&\n\t\tArray.isArray(value.candidates) &&\n\t\tArray.isArray(value.selectedReasonCodes) &&\n\t\ttypeof value.estimatedCostTokens === \"number\" &&\n\t\ttypeof value.estimatedSavingsTokens === \"number\" &&\n\t\ttypeof value.estimatedReliabilityRisk === \"number\" &&\n\t\ttypeof value.cacheImpactTokens === \"number\" &&\n\t\ttypeof value.reworkRiskTokens === \"number\" &&\n\t\tArray.isArray(value.artifactRefs) &&\n\t\tArray.isArray(value.evidenceRefs)\n\t);\n}\n\nfunction isPolicyDecisionRecord(value: unknown): value is PolicyDecisionRecord {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\t(value.contextItemId === undefined || typeof value.contextItemId === \"string\") &&\n\t\ttypeof value.recordedAtTurn === \"number\" &&\n\t\tisPolicyDecision(value.decision)\n\t);\n}\n\nfunction isRetrievalRecord(value: unknown): value is RetrievalRecord {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\ttypeof value.contextItemId === \"string\" &&\n\t\ttypeof value.requestedAtTurn === \"number\" &&\n\t\ttypeof value.sliceKind === \"string\" &&\n\t\ttypeof value.resultSummary === \"string\"\n\t);\n}\n\nfunction isMemoryIndexRecord(value: unknown): value is MemoryIndexRecord {\n\tif (!isRecord(value) || !isRecord(value.ref)) return false;\n\treturn (\n\t\ttypeof value.ref.providerId === \"string\" &&\n\t\ttypeof value.ref.itemId === \"string\" &&\n\t\ttypeof value.ref.scope === \"string\" &&\n\t\ttypeof value.ref.kind === \"string\" &&\n\t\t(value.title === undefined || typeof value.title === \"string\") &&\n\t\ttypeof value.summary === \"string\" &&\n\t\ttypeof value.indexedAtTurn === \"number\" &&\n\t\ttypeof value.stale === \"boolean\"\n\t);\n}\n\nfunction contextItemFromRow(row: Record<string, unknown> | undefined): ContextItem | undefined {\n\tconst payload = textColumn(row, \"payload_json\");\n\treturn payload === undefined ? undefined : parseJsonRecord(payload, isContextItem);\n}\n\nfunction policyDecisionRecordFromRow(row: Record<string, unknown> | undefined): PolicyDecisionRecord | undefined {\n\tconst payload = textColumn(row, \"payload_json\");\n\treturn payload === undefined ? undefined : parseJsonRecord(payload, isPolicyDecisionRecord);\n}\n\nfunction retrievalRecordFromRow(row: Record<string, unknown> | undefined): RetrievalRecord | undefined {\n\tconst payload = textColumn(row, \"payload_json\");\n\treturn payload === undefined ? undefined : parseJsonRecord(payload, isRetrievalRecord);\n}\n\nfunction memoryIndexRecordFromRow(row: Record<string, unknown> | undefined): MemoryIndexRecord | undefined {\n\tconst payload = textColumn(row, \"payload_json\");\n\treturn payload === undefined ? undefined : parseJsonRecord(payload, isMemoryIndexRecord);\n}\n\nexport function createSqliteContextStore(options: SqliteRuntimeIndexOptions): SqliteContextStore {\n\tconst database = openDatabase(options);\n\tconst upsertItem = database.prepare(`\n\t\tINSERT INTO context_items (\n\t\t\tid, kind, retention_class, source, created_at_turn, last_used_at_turn, token_estimate, byte_estimate, payload_json\n\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\tON CONFLICT(id) DO UPDATE SET\n\t\t\tkind = excluded.kind,\n\t\t\tretention_class = excluded.retention_class,\n\t\t\tsource = excluded.source,\n\t\t\tcreated_at_turn = excluded.created_at_turn,\n\t\t\tlast_used_at_turn = excluded.last_used_at_turn,\n\t\t\ttoken_estimate = excluded.token_estimate,\n\t\t\tbyte_estimate = excluded.byte_estimate,\n\t\t\tpayload_json = excluded.payload_json\n\t`);\n\tconst getItem = database.prepare(\"SELECT payload_json FROM context_items WHERE id = ?\");\n\tconst listItems = database.prepare(\"SELECT payload_json FROM context_items ORDER BY created_at_turn, id\");\n\tconst removeItem = database.prepare(\"DELETE FROM context_items WHERE id = ?\");\n\tconst recordPolicyDecision = database.prepare(`\n\t\tINSERT INTO policy_decisions (\n\t\t\tid, context_item_id, recorded_at_turn, decision_kind, selected_action, mode, applied, payload_json\n\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n\t`);\n\tconst listAllPolicyDecisions = database.prepare(\n\t\t\"SELECT payload_json FROM policy_decisions ORDER BY recorded_at_turn, id\",\n\t);\n\tconst listPolicyDecisionsByItem = database.prepare(\n\t\t\"SELECT payload_json FROM policy_decisions WHERE context_item_id = ? ORDER BY recorded_at_turn, id\",\n\t);\n\tconst recordRetrieval = database.prepare(`\n\t\tINSERT INTO retrieval_records (\n\t\t\tid, context_item_id, requested_at_turn, slice_kind, result_summary, payload_json\n\t\t) VALUES (?, ?, ?, ?, ?, ?)\n\t`);\n\tconst listAllRetrievals = database.prepare(\n\t\t\"SELECT payload_json FROM retrieval_records ORDER BY requested_at_turn, id\",\n\t);\n\tconst listRetrievalsByItem = database.prepare(\n\t\t\"SELECT payload_json FROM retrieval_records WHERE context_item_id = ? ORDER BY requested_at_turn, id\",\n\t);\n\n\treturn {\n\t\tupsertItem(item: ContextItem): void {\n\t\t\tupsertItem.run(\n\t\t\t\titem.id,\n\t\t\t\titem.kind,\n\t\t\t\titem.retentionClass,\n\t\t\t\titem.source,\n\t\t\t\titem.createdAtTurn,\n\t\t\t\titem.lastUsedAtTurn ?? null,\n\t\t\t\titem.tokenEstimate,\n\t\t\t\titem.byteEstimate,\n\t\t\t\tJSON.stringify(item),\n\t\t\t);\n\t\t},\n\n\t\tgetItem(id: string): ContextItem | undefined {\n\t\t\treturn contextItemFromRow(getItem.get(id));\n\t\t},\n\n\t\tlistItems(): ContextItem[] {\n\t\t\treturn listItems.all().flatMap((row) => {\n\t\t\t\tconst item = contextItemFromRow(row);\n\t\t\t\treturn item === undefined ? [] : [item];\n\t\t\t});\n\t\t},\n\n\t\tremoveItem(id: string): void {\n\t\t\tremoveItem.run(id);\n\t\t},\n\n\t\trecordPolicyDecision(record: PolicyDecisionRecord): void {\n\t\t\trecordPolicyDecision.run(\n\t\t\t\trecord.id,\n\t\t\t\trecord.contextItemId ?? null,\n\t\t\t\trecord.recordedAtTurn,\n\t\t\t\trecord.decision.kind,\n\t\t\t\trecord.decision.selectedAction,\n\t\t\t\trecord.decision.mode,\n\t\t\t\trecord.decision.applied ? 1 : 0,\n\t\t\t\tJSON.stringify(record),\n\t\t\t);\n\t\t},\n\n\t\tlistPolicyDecisions(contextItemId?: string): PolicyDecisionRecord[] {\n\t\t\tconst rows =\n\t\t\t\tcontextItemId === undefined ? listAllPolicyDecisions.all() : listPolicyDecisionsByItem.all(contextItemId);\n\t\t\treturn rows.flatMap((row) => {\n\t\t\t\tconst record = policyDecisionRecordFromRow(row);\n\t\t\t\treturn record === undefined ? [] : [record];\n\t\t\t});\n\t\t},\n\n\t\trecordRetrieval(record: RetrievalRecord): void {\n\t\t\trecordRetrieval.run(\n\t\t\t\trecord.id,\n\t\t\t\trecord.contextItemId,\n\t\t\t\trecord.requestedAtTurn,\n\t\t\t\trecord.sliceKind,\n\t\t\t\trecord.resultSummary,\n\t\t\t\tJSON.stringify(record),\n\t\t\t);\n\t\t},\n\n\t\tlistRetrievals(contextItemId?: string): RetrievalRecord[] {\n\t\t\tconst rows = contextItemId === undefined ? listAllRetrievals.all() : listRetrievalsByItem.all(contextItemId);\n\t\t\treturn rows.flatMap((row) => {\n\t\t\t\tconst record = retrievalRecordFromRow(row);\n\t\t\t\treturn record === undefined ? [] : [record];\n\t\t\t});\n\t\t},\n\n\t\tclose(): void {\n\t\t\tdatabase[Symbol.dispose]();\n\t\t},\n\t};\n}\n\nexport function createSqliteMemoryIndexStore(options: SqliteRuntimeIndexOptions): SqliteMemoryIndexStore {\n\tconst database = openDatabase(options);\n\tconst upsert = database.prepare(`\n\t\tINSERT INTO memory_index (\n\t\t\tprovider_id, item_id, scope, kind, title, summary, indexed_at_turn, stale, payload_json\n\t\t) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\tON CONFLICT(provider_id, item_id) DO UPDATE SET\n\t\t\tscope = excluded.scope,\n\t\t\tkind = excluded.kind,\n\t\t\ttitle = excluded.title,\n\t\t\tsummary = excluded.summary,\n\t\t\tindexed_at_turn = excluded.indexed_at_turn,\n\t\t\tstale = excluded.stale,\n\t\t\tpayload_json = excluded.payload_json\n\t`);\n\tconst get = database.prepare(\"SELECT payload_json FROM memory_index WHERE provider_id = ? AND item_id = ?\");\n\tconst listAll = database.prepare(\"SELECT payload_json FROM memory_index ORDER BY provider_id, item_id\");\n\tconst listByScope = database.prepare(\n\t\t\"SELECT payload_json FROM memory_index WHERE scope = ? ORDER BY provider_id, item_id\",\n\t);\n\tconst markStale = database.prepare(\n\t\t\"UPDATE memory_index SET stale = 1, payload_json = ? WHERE provider_id = ? AND item_id = ?\",\n\t);\n\tconst remove = database.prepare(\"DELETE FROM memory_index WHERE provider_id = ? AND item_id = ?\");\n\n\treturn {\n\t\tupsert(record: MemoryIndexRecord): void {\n\t\t\tupsert.run(\n\t\t\t\trecord.ref.providerId,\n\t\t\t\trecord.ref.itemId,\n\t\t\t\trecord.ref.scope,\n\t\t\t\trecord.ref.kind,\n\t\t\t\trecord.title ?? null,\n\t\t\t\trecord.summary,\n\t\t\t\trecord.indexedAtTurn,\n\t\t\t\trecord.stale ? 1 : 0,\n\t\t\t\tJSON.stringify(record),\n\t\t\t);\n\t\t},\n\n\t\tget(providerId: string, itemId: string): MemoryIndexRecord | undefined {\n\t\t\treturn memoryIndexRecordFromRow(get.get(providerId, itemId));\n\t\t},\n\n\t\tlist(scope?: MemoryIndexRecord[\"ref\"][\"scope\"]): MemoryIndexRecord[] {\n\t\t\tconst rows = scope === undefined ? listAll.all() : listByScope.all(scope);\n\t\t\treturn rows.flatMap((row) => {\n\t\t\t\tconst record = memoryIndexRecordFromRow(row);\n\t\t\t\treturn record === undefined ? [] : [record];\n\t\t\t});\n\t\t},\n\n\t\tmarkStale(providerId: string, itemId: string): void {\n\t\t\tconst existing = memoryIndexRecordFromRow(get.get(providerId, itemId));\n\t\t\tif (existing === undefined) return;\n\t\t\tmarkStale.run(JSON.stringify({ ...existing, stale: true }), providerId, itemId);\n\t\t},\n\n\t\tremove(providerId: string, itemId: string): void {\n\t\t\tremove.run(providerId, itemId);\n\t\t},\n\n\t\tclose(): void {\n\t\t\tdatabase[Symbol.dispose]();\n\t\t},\n\t};\n}\n"]}