@caupulican/pi-adaptative 0.80.86 → 0.80.88

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 (337) hide show
  1. package/CHANGELOG.md +149 -0
  2. package/dist/core/agent-session.d.ts +377 -1
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +1791 -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/context-artifacts.d.ts +94 -0
  55. package/dist/core/context/context-artifacts.d.ts.map +1 -0
  56. package/dist/core/context/context-artifacts.js +307 -0
  57. package/dist/core/context/context-artifacts.js.map +1 -0
  58. package/dist/core/context/context-audit.d.ts +66 -0
  59. package/dist/core/context/context-audit.d.ts.map +1 -0
  60. package/dist/core/context/context-audit.js +173 -0
  61. package/dist/core/context/context-audit.js.map +1 -0
  62. package/dist/core/context/context-item.d.ts +117 -0
  63. package/dist/core/context/context-item.d.ts.map +1 -0
  64. package/dist/core/context/context-item.js +36 -0
  65. package/dist/core/context/context-item.js.map +1 -0
  66. package/dist/core/context/context-prompt-enforcement.d.ts +73 -0
  67. package/dist/core/context/context-prompt-enforcement.d.ts.map +1 -0
  68. package/dist/core/context/context-prompt-enforcement.js +153 -0
  69. package/dist/core/context/context-prompt-enforcement.js.map +1 -0
  70. package/dist/core/context/context-prompt-policy.d.ts +90 -0
  71. package/dist/core/context/context-prompt-policy.d.ts.map +1 -0
  72. package/dist/core/context/context-prompt-policy.js +73 -0
  73. package/dist/core/context/context-prompt-policy.js.map +1 -0
  74. package/dist/core/context/context-retention.d.ts +36 -0
  75. package/dist/core/context/context-retention.d.ts.map +1 -0
  76. package/dist/core/context/context-retention.js +108 -0
  77. package/dist/core/context/context-retention.js.map +1 -0
  78. package/dist/core/context/context-store.d.ts +37 -0
  79. package/dist/core/context/context-store.d.ts.map +1 -0
  80. package/dist/core/context/context-store.js +45 -0
  81. package/dist/core/context/context-store.js.map +1 -0
  82. package/dist/core/context/memory-diagnostics.d.ts +50 -0
  83. package/dist/core/context/memory-diagnostics.d.ts.map +1 -0
  84. package/dist/core/context/memory-diagnostics.js +43 -0
  85. package/dist/core/context/memory-diagnostics.js.map +1 -0
  86. package/dist/core/context/memory-index-store.d.ts +28 -0
  87. package/dist/core/context/memory-index-store.d.ts.map +1 -0
  88. package/dist/core/context/memory-index-store.js +38 -0
  89. package/dist/core/context/memory-index-store.js.map +1 -0
  90. package/dist/core/context/memory-prompt-block.d.ts +34 -0
  91. package/dist/core/context/memory-prompt-block.d.ts.map +1 -0
  92. package/dist/core/context/memory-prompt-block.js +58 -0
  93. package/dist/core/context/memory-prompt-block.js.map +1 -0
  94. package/dist/core/context/memory-provider-contract.d.ts +114 -0
  95. package/dist/core/context/memory-provider-contract.d.ts.map +1 -0
  96. package/dist/core/context/memory-provider-contract.js +121 -0
  97. package/dist/core/context/memory-provider-contract.js.map +1 -0
  98. package/dist/core/context/memory-retrieval.d.ts +27 -0
  99. package/dist/core/context/memory-retrieval.d.ts.map +1 -0
  100. package/dist/core/context/memory-retrieval.js +91 -0
  101. package/dist/core/context/memory-retrieval.js.map +1 -0
  102. package/dist/core/context/okf-memory-provider.d.ts +26 -0
  103. package/dist/core/context/okf-memory-provider.d.ts.map +1 -0
  104. package/dist/core/context/okf-memory-provider.js +154 -0
  105. package/dist/core/context/okf-memory-provider.js.map +1 -0
  106. package/dist/core/context/okf-memory.d.ts +42 -0
  107. package/dist/core/context/okf-memory.d.ts.map +1 -0
  108. package/dist/core/context/okf-memory.js +175 -0
  109. package/dist/core/context/okf-memory.js.map +1 -0
  110. package/dist/core/context/policy-engine.d.ts +66 -0
  111. package/dist/core/context/policy-engine.d.ts.map +1 -0
  112. package/dist/core/context/policy-engine.js +171 -0
  113. package/dist/core/context/policy-engine.js.map +1 -0
  114. package/dist/core/context/policy-types.d.ts +102 -0
  115. package/dist/core/context/policy-types.d.ts.map +1 -0
  116. package/dist/core/context/policy-types.js +7 -0
  117. package/dist/core/context/policy-types.js.map +1 -0
  118. package/dist/core/context/sqlite-runtime-index.d.ts +19 -0
  119. package/dist/core/context/sqlite-runtime-index.d.ts.map +1 -0
  120. package/dist/core/context/sqlite-runtime-index.js +344 -0
  121. package/dist/core/context/sqlite-runtime-index.js.map +1 -0
  122. package/dist/core/context/storage-authority.d.ts +20 -0
  123. package/dist/core/context/storage-authority.d.ts.map +1 -0
  124. package/dist/core/context/storage-authority.js +51 -0
  125. package/dist/core/context/storage-authority.js.map +1 -0
  126. package/dist/core/context/tool-output-packer.d.ts +75 -0
  127. package/dist/core/context/tool-output-packer.d.ts.map +1 -0
  128. package/dist/core/context/tool-output-packer.js +77 -0
  129. package/dist/core/context/tool-output-packer.js.map +1 -0
  130. package/dist/core/cost/session-usage.d.ts +20 -0
  131. package/dist/core/cost/session-usage.d.ts.map +1 -0
  132. package/dist/core/cost/session-usage.js +164 -0
  133. package/dist/core/cost/session-usage.js.map +1 -0
  134. package/dist/core/delegation/session-worker-result.d.ts +10 -0
  135. package/dist/core/delegation/session-worker-result.d.ts.map +1 -0
  136. package/dist/core/delegation/session-worker-result.js +36 -0
  137. package/dist/core/delegation/session-worker-result.js.map +1 -0
  138. package/dist/core/delegation/worker-result.d.ts +9 -0
  139. package/dist/core/delegation/worker-result.d.ts.map +1 -0
  140. package/dist/core/delegation/worker-result.js +152 -0
  141. package/dist/core/delegation/worker-result.js.map +1 -0
  142. package/dist/core/delegation/worker-runner.d.ts +58 -0
  143. package/dist/core/delegation/worker-runner.d.ts.map +1 -0
  144. package/dist/core/delegation/worker-runner.js +188 -0
  145. package/dist/core/delegation/worker-runner.js.map +1 -0
  146. package/dist/core/extensions/builtin.d.ts +5 -1
  147. package/dist/core/extensions/builtin.d.ts.map +1 -1
  148. package/dist/core/extensions/builtin.js +23 -1
  149. package/dist/core/extensions/builtin.js.map +1 -1
  150. package/dist/core/footer-data-provider.d.ts +5 -1
  151. package/dist/core/footer-data-provider.d.ts.map +1 -1
  152. package/dist/core/footer-data-provider.js +13 -0
  153. package/dist/core/footer-data-provider.js.map +1 -1
  154. package/dist/core/goals/goal-continuation-controller.d.ts +22 -0
  155. package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -0
  156. package/dist/core/goals/goal-continuation-controller.js +88 -0
  157. package/dist/core/goals/goal-continuation-controller.js.map +1 -0
  158. package/dist/core/goals/goal-continuation-defaults.d.ts +10 -0
  159. package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -0
  160. package/dist/core/goals/goal-continuation-defaults.js +10 -0
  161. package/dist/core/goals/goal-continuation-defaults.js.map +1 -0
  162. package/dist/core/goals/goal-continuation-prompt.d.ts +18 -0
  163. package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -0
  164. package/dist/core/goals/goal-continuation-prompt.js +141 -0
  165. package/dist/core/goals/goal-continuation-prompt.js.map +1 -0
  166. package/dist/core/goals/goal-runtime-snapshot.d.ts +19 -0
  167. package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -0
  168. package/dist/core/goals/goal-runtime-snapshot.js +23 -0
  169. package/dist/core/goals/goal-runtime-snapshot.js.map +1 -0
  170. package/dist/core/goals/goal-state.d.ts +87 -0
  171. package/dist/core/goals/goal-state.d.ts.map +1 -0
  172. package/dist/core/goals/goal-state.js +259 -0
  173. package/dist/core/goals/goal-state.js.map +1 -0
  174. package/dist/core/goals/goal-tool-core.d.ts +66 -0
  175. package/dist/core/goals/goal-tool-core.d.ts.map +1 -0
  176. package/dist/core/goals/goal-tool-core.js +146 -0
  177. package/dist/core/goals/goal-tool-core.js.map +1 -0
  178. package/dist/core/goals/session-goal-state.d.ts +10 -0
  179. package/dist/core/goals/session-goal-state.d.ts.map +1 -0
  180. package/dist/core/goals/session-goal-state.js +35 -0
  181. package/dist/core/goals/session-goal-state.js.map +1 -0
  182. package/dist/core/learning/learning-audit.d.ts +45 -0
  183. package/dist/core/learning/learning-audit.d.ts.map +1 -0
  184. package/dist/core/learning/learning-audit.js +139 -0
  185. package/dist/core/learning/learning-audit.js.map +1 -0
  186. package/dist/core/learning/learning-gate.d.ts +29 -0
  187. package/dist/core/learning/learning-gate.d.ts.map +1 -0
  188. package/dist/core/learning/learning-gate.js +150 -0
  189. package/dist/core/learning/learning-gate.js.map +1 -0
  190. package/dist/core/learning/session-learning-decision.d.ts +10 -0
  191. package/dist/core/learning/session-learning-decision.d.ts.map +1 -0
  192. package/dist/core/learning/session-learning-decision.js +36 -0
  193. package/dist/core/learning/session-learning-decision.js.map +1 -0
  194. package/dist/core/model-capability.d.ts +41 -0
  195. package/dist/core/model-capability.d.ts.map +1 -0
  196. package/dist/core/model-capability.js +101 -0
  197. package/dist/core/model-capability.js.map +1 -0
  198. package/dist/core/model-router/config-diagnostics.d.ts.map +1 -1
  199. package/dist/core/model-router/config-diagnostics.js +1 -0
  200. package/dist/core/model-router/config-diagnostics.js.map +1 -1
  201. package/dist/core/model-router/intent-classifier.d.ts +2 -0
  202. package/dist/core/model-router/intent-classifier.d.ts.map +1 -1
  203. package/dist/core/model-router/intent-classifier.js +154 -9
  204. package/dist/core/model-router/intent-classifier.js.map +1 -1
  205. package/dist/core/model-router/route-judge.d.ts +54 -0
  206. package/dist/core/model-router/route-judge.d.ts.map +1 -0
  207. package/dist/core/model-router/route-judge.js +128 -0
  208. package/dist/core/model-router/route-judge.js.map +1 -0
  209. package/dist/core/model-router/status.d.ts +4 -1
  210. package/dist/core/model-router/status.d.ts.map +1 -1
  211. package/dist/core/model-router/status.js +30 -6
  212. package/dist/core/model-router/status.js.map +1 -1
  213. package/dist/core/model-router/tool-escalation.d.ts +4 -6
  214. package/dist/core/model-router/tool-escalation.d.ts.map +1 -1
  215. package/dist/core/model-router/tool-escalation.js +1 -1
  216. package/dist/core/model-router/tool-escalation.js.map +1 -1
  217. package/dist/core/models/fitness-store.d.ts +40 -0
  218. package/dist/core/models/fitness-store.d.ts.map +1 -0
  219. package/dist/core/models/fitness-store.js +61 -0
  220. package/dist/core/models/fitness-store.js.map +1 -0
  221. package/dist/core/profile-registry.d.ts.map +1 -1
  222. package/dist/core/profile-registry.js +1 -1
  223. package/dist/core/profile-registry.js.map +1 -1
  224. package/dist/core/prompt-templates.d.ts +2 -0
  225. package/dist/core/prompt-templates.d.ts.map +1 -1
  226. package/dist/core/prompt-templates.js +12 -4
  227. package/dist/core/prompt-templates.js.map +1 -1
  228. package/dist/core/research/automata-provider.d.ts +5 -0
  229. package/dist/core/research/automata-provider.d.ts.map +1 -0
  230. package/dist/core/research/automata-provider.js +15 -0
  231. package/dist/core/research/automata-provider.js.map +1 -0
  232. package/dist/core/research/evidence-bundle.d.ts +10 -0
  233. package/dist/core/research/evidence-bundle.d.ts.map +1 -0
  234. package/dist/core/research/evidence-bundle.js +116 -0
  235. package/dist/core/research/evidence-bundle.js.map +1 -0
  236. package/dist/core/research/model-fitness.d.ts +79 -0
  237. package/dist/core/research/model-fitness.d.ts.map +1 -0
  238. package/dist/core/research/model-fitness.js +257 -0
  239. package/dist/core/research/model-fitness.js.map +1 -0
  240. package/dist/core/research/research-gate.d.ts +11 -0
  241. package/dist/core/research/research-gate.d.ts.map +1 -0
  242. package/dist/core/research/research-gate.js +82 -0
  243. package/dist/core/research/research-gate.js.map +1 -0
  244. package/dist/core/research/research-runner.d.ts +59 -0
  245. package/dist/core/research/research-runner.d.ts.map +1 -0
  246. package/dist/core/research/research-runner.js +155 -0
  247. package/dist/core/research/research-runner.js.map +1 -0
  248. package/dist/core/research/session-evidence-bundle.d.ts +11 -0
  249. package/dist/core/research/session-evidence-bundle.d.ts.map +1 -0
  250. package/dist/core/research/session-evidence-bundle.js +55 -0
  251. package/dist/core/research/session-evidence-bundle.js.map +1 -0
  252. package/dist/core/resource-loader.d.ts.map +1 -1
  253. package/dist/core/resource-loader.js +4 -0
  254. package/dist/core/resource-loader.js.map +1 -1
  255. package/dist/core/settings-manager.d.ts +147 -4
  256. package/dist/core/settings-manager.d.ts.map +1 -1
  257. package/dist/core/settings-manager.js +285 -9
  258. package/dist/core/settings-manager.js.map +1 -1
  259. package/dist/core/skills.d.ts +4 -0
  260. package/dist/core/skills.d.ts.map +1 -1
  261. package/dist/core/skills.js +18 -6
  262. package/dist/core/skills.js.map +1 -1
  263. package/dist/core/slash-commands.d.ts.map +1 -1
  264. package/dist/core/slash-commands.js +4 -0
  265. package/dist/core/slash-commands.js.map +1 -1
  266. package/dist/core/toolkit/script-registry.d.ts +34 -0
  267. package/dist/core/toolkit/script-registry.d.ts.map +1 -0
  268. package/dist/core/toolkit/script-registry.js +71 -0
  269. package/dist/core/toolkit/script-registry.js.map +1 -0
  270. package/dist/core/toolkit/script-runner.d.ts +28 -0
  271. package/dist/core/toolkit/script-runner.d.ts.map +1 -0
  272. package/dist/core/toolkit/script-runner.js +48 -0
  273. package/dist/core/toolkit/script-runner.js.map +1 -0
  274. package/dist/core/tools/artifact-retrieve.d.ts +23 -0
  275. package/dist/core/tools/artifact-retrieve.d.ts.map +1 -0
  276. package/dist/core/tools/artifact-retrieve.js +110 -0
  277. package/dist/core/tools/artifact-retrieve.js.map +1 -0
  278. package/dist/core/tools/delegate.d.ts +32 -0
  279. package/dist/core/tools/delegate.d.ts.map +1 -0
  280. package/dist/core/tools/delegate.js +60 -0
  281. package/dist/core/tools/delegate.js.map +1 -0
  282. package/dist/core/tools/fff-search-backend.d.ts +103 -0
  283. package/dist/core/tools/fff-search-backend.d.ts.map +1 -0
  284. package/dist/core/tools/fff-search-backend.js +151 -0
  285. package/dist/core/tools/fff-search-backend.js.map +1 -0
  286. package/dist/core/tools/find.d.ts +21 -1
  287. package/dist/core/tools/find.d.ts.map +1 -1
  288. package/dist/core/tools/find.js +183 -10
  289. package/dist/core/tools/find.js.map +1 -1
  290. package/dist/core/tools/goal.d.ts +35 -0
  291. package/dist/core/tools/goal.d.ts.map +1 -0
  292. package/dist/core/tools/goal.js +122 -0
  293. package/dist/core/tools/goal.js.map +1 -0
  294. package/dist/core/tools/grep.d.ts +21 -1
  295. package/dist/core/tools/grep.d.ts.map +1 -1
  296. package/dist/core/tools/grep.js +272 -27
  297. package/dist/core/tools/grep.js.map +1 -1
  298. package/dist/core/tools/index.d.ts +4 -1
  299. package/dist/core/tools/index.d.ts.map +1 -1
  300. package/dist/core/tools/index.js +9 -0
  301. package/dist/core/tools/index.js.map +1 -1
  302. package/dist/core/tools/model-fitness.d.ts +30 -0
  303. package/dist/core/tools/model-fitness.d.ts.map +1 -0
  304. package/dist/core/tools/model-fitness.js +38 -0
  305. package/dist/core/tools/model-fitness.js.map +1 -0
  306. package/dist/core/tools/run-toolkit-script.d.ts +24 -0
  307. package/dist/core/tools/run-toolkit-script.d.ts.map +1 -0
  308. package/dist/core/tools/run-toolkit-script.js +103 -0
  309. package/dist/core/tools/run-toolkit-script.js.map +1 -0
  310. package/dist/core/tools/search-router.d.ts +75 -0
  311. package/dist/core/tools/search-router.d.ts.map +1 -0
  312. package/dist/core/tools/search-router.js +85 -0
  313. package/dist/core/tools/search-router.js.map +1 -0
  314. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  315. package/dist/modes/interactive/components/footer.js +18 -16
  316. package/dist/modes/interactive/components/footer.js.map +1 -1
  317. package/dist/modes/interactive/components/settings-selector.d.ts +13 -1
  318. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  319. package/dist/modes/interactive/components/settings-selector.js +471 -11
  320. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  321. package/dist/modes/interactive/interactive-mode.d.ts +4 -0
  322. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  323. package/dist/modes/interactive/interactive-mode.js +217 -39
  324. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  325. package/dist/utils/tools-manager.d.ts +2 -0
  326. package/dist/utils/tools-manager.d.ts.map +1 -1
  327. package/dist/utils/tools-manager.js +154 -2
  328. package/dist/utils/tools-manager.js.map +1 -1
  329. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  330. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  331. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  332. package/examples/extensions/sandbox/package-lock.json +2 -2
  333. package/examples/extensions/sandbox/package.json +1 -1
  334. package/examples/extensions/with-deps/package-lock.json +2 -2
  335. package/examples/extensions/with-deps/package.json +1 -1
  336. package/npm-shrinkwrap.json +368 -12
  337. package/package.json +5 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-audit.js","sourceRoot":"","sources":["../../../src/core/context/context-audit.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Live observe-only bridge from AgentMessage[] to the ContextItem/policy-engine layer\n * (Phase 1 audit pass). This module only ever reads messages and the artifact store; it\n * never mutates messages, the transcript, or artifact references. It is the first thing to\n * consume the context-item.ts/context-retention.ts/policy-engine.ts contracts against live\n * session state, but it does not yet change what the model sees -- see\n * docs/context-management-rework/implementation-phases.md for where this sits.\n *\n * Scope for this pass: only `toolResult` messages become `ContextItem`s (kind\n * \"tool_output\"). Other roles (user/assistant) are skipped; representing them is later\n * work once their ContextItemKind mapping (user_instruction/approval/etc.) is designed.\n *\n * Retrieval-path semantics (deliberately narrower than context-retention.ts's item-level\n * `hasReferencedEvidence`): a transcript ref is attached to every item as provenance\n * evidence (which live message this item came from), but it never counts toward\n * `HardConstraintFlags.hasAvailableRetrievalPath` on its own -- there is no live mechanism\n * today for the model to fetch an older message back into context by session-entry id, so\n * claiming that would overclaim retrievability (the same fail-closed principle\n * `artifact_retrieve` follows). Only a resolved artifact ref (the store still has the\n * payload) counts as an available retrieval path.\n */\n\nimport type { AgentMessage } from \"@caupulican/pi-agent-core\";\nimport type { ToolResultMessage } from \"@caupulican/pi-ai\";\nimport type { ArtifactStore } from \"./context-artifacts.ts\";\nimport {\n\ttype ContextEvidenceRef,\n\ttype ContextItem,\n\testimateByteLength,\n\testimateTokensFromText,\n} from \"./context-item.ts\";\nimport { evaluateRetentionEligibility, type RetentionEligibility } from \"./context-retention.ts\";\nimport { evaluateHardConstraints } from \"./policy-engine.ts\";\nimport type { HardConstraintFlags, PolicyFeatures, PolicyHardConstraintCode } from \"./policy-types.ts\";\n\nexport interface ContextAuditOptions {\n\t/** Current turn index (AgentSession's own per-run counter); used as `createdAtTurn`. */\n\tturnIndex: number;\n\t/** Session-scoped artifact store, if one has been constructed. Read-only here. */\n\tartifactStore?: ArtifactStore;\n\t/** Resolve the persisted session-entry id for a toolResult message's toolCallId, if known. */\n\tsessionEntryIdForToolCallId?: (toolCallId: string) => string | undefined;\n}\n\nexport interface ContextAuditItemReport {\n\titem: ContextItem;\n\t/** The source toolResult message's own id and position, always available (unlike refs). */\n\ttoolCallId: string;\n\tmessageIndex: number;\n\t/** Coarse, store-free eligibility from context-retention.ts (treats any ref as retrievable). */\n\tretention: RetentionEligibility;\n\t/** Store-aware hard-constraint codes for keep_raw; always empty (no evaluated action restricts it), included for reportability. */\n\tkeepRawHardConstraints: PolicyHardConstraintCode[];\n\t/** Store-aware hard-constraint codes for pack_to_artifact; empty means no hard rejection. */\n\tpackToArtifactHardConstraints: PolicyHardConstraintCode[];\n\t/** Store-aware hard-constraint codes for drop_from_prompt; empty means no hard rejection. */\n\tdropFromPromptHardConstraints: PolicyHardConstraintCode[];\n\t/** Store-aware hard-constraint codes for summarize; empty means no hard rejection. */\n\tsummarizeHardConstraints: PolicyHardConstraintCode[];\n}\n\nexport interface ContextAuditReport {\n\tturnIndex: number;\n\titems: ContextAuditItemReport[];\n}\n\nfunction extractToolResultArtifactId(message: ToolResultMessage): string | undefined {\n\tconst details = message.details;\n\tif (typeof details !== \"object\" || details === null) return undefined;\n\tconst artifactId = (details as { artifactId?: unknown }).artifactId;\n\treturn typeof artifactId === \"string\" ? artifactId : undefined;\n}\n\nfunction toolResultText(message: ToolResultMessage): string {\n\tconst parts: string[] = [];\n\tfor (const part of message.content) {\n\t\tif (part.type === \"text\") parts.push(part.text);\n\t}\n\treturn parts.join(\"\\n\");\n}\n\ninterface BuiltToolOutputItem {\n\titem: ContextItem;\n\t/** True only if an artifact ref was found AND resolved against a live store. */\n\thasResolvedArtifact: boolean;\n}\n\nfunction buildToolOutputItem(\n\tmessage: ToolResultMessage,\n\tmessageIndex: number,\n\toptions: ContextAuditOptions,\n): BuiltToolOutputItem {\n\tconst text = toolResultText(message);\n\tconst artifactId = extractToolResultArtifactId(message);\n\tconst sessionEntryId = options.sessionEntryIdForToolCallId?.(message.toolCallId);\n\n\tlet primaryRef: ContextEvidenceRef | undefined;\n\tlet hasResolvedArtifact = false;\n\t// createdAtTurn defaults to the current audit turn (an approximation -- see below) and\n\t// is overridden with the real capture turn when an artifact ref resolves.\n\tlet createdAtTurn = options.turnIndex;\n\tif (artifactId && options.artifactStore) {\n\t\t// Metadata-only: never loads the artifact's payload just to check resolvability and\n\t\t// grab ref fields (a per-turn audit pass over every artifact-backed result would\n\t\t// otherwise re-read every payload off disk each turn for no reason).\n\t\tconst ref = options.artifactStore.readRef(artifactId);\n\t\tif (ref) {\n\t\t\tprimaryRef = { type: \"artifact\", ref };\n\t\t\thasResolvedArtifact = true;\n\t\t\tcreatedAtTurn = ref.createdAtTurn;\n\t\t}\n\t}\n\n\tconst evidenceRefs: ContextEvidenceRef[] = [];\n\tif (sessionEntryId) {\n\t\tconst transcriptRef: ContextEvidenceRef = {\n\t\t\ttype: \"transcript\",\n\t\t\tref: { sessionEntryId, messageIndex },\n\t\t};\n\t\tif (!primaryRef) primaryRef = transcriptRef;\n\t\telse evidenceRefs.push(transcriptRef);\n\t}\n\n\tconst item: ContextItem = {\n\t\tid: `tool-output:${message.toolCallId}`,\n\t\tkind: \"tool_output\",\n\t\tretentionClass: \"ephemeral\",\n\t\tsource: \"tool\",\n\t\t// Transcript-only items (no artifact ref) have no real creation-turn source threaded\n\t\t// in yet, so this falls back to the current audit turn as an approximation --\n\t\t// deliberately not left silently wrong: no evaluator reads createdAtTurn today, but\n\t\t// any future staleness/break-even math must use the real per-item value above, not\n\t\t// this fallback, once one exists for non-artifact items too.\n\t\tcreatedAtTurn,\n\t\tsummary: `${message.toolName} tool result`,\n\t\tprimaryRef,\n\t\tevidenceRefs: evidenceRefs.length > 0 ? evidenceRefs : undefined,\n\t\ttokenEstimate: estimateTokensFromText(text),\n\t\tbyteEstimate: estimateByteLength(text),\n\t};\n\n\treturn { item, hasResolvedArtifact };\n}\n\n/**\n * Economic/probability fields are zeroed: `evaluateHardConstraints` does not read them for\n * pack_to_artifact/drop_from_prompt (only the break-even scoring math this audit\n * deliberately does not invoke would need real numbers here).\n */\nfunction buildPolicyFeatures(item: ContextItem, built: BuiltToolOutputItem, turnIndex: number): PolicyFeatures {\n\treturn {\n\t\tturnIndex,\n\t\texpectedRemainingTurns: 0,\n\t\tinputTokens: 0,\n\t\toutputTokens: 0,\n\t\tcacheReadTokens: 0,\n\t\tcacheWriteTokens: 0,\n\t\tartifactBytes: built.hasResolvedArtifact ? item.byteEstimate : 0,\n\t\tcharEstimate: item.byteEstimate,\n\t\tcalibratedTokenEstimate: item.tokenEstimate,\n\t\tpromptSection: \"volatile_tail\",\n\t\tretentionClass: item.retentionClass,\n\t\tisReproducible: true,\n\t\tisDecisionBearing: false,\n\t\tisPinned: false,\n\t\tisOpenRequirement: false,\n\t\tisLatestFailure: false,\n\t\tisCurrentDiff: false,\n\t\tprobabilityNeededAgain: 0,\n\t\tprobabilityErrorIfDropped: 0,\n\t\tretrievalCostTokens: 0,\n\t\tpackCostTokens: 0,\n\t\tretryCostTokens: 0,\n\t\tfailureCostTokens: 0,\n\t\tvalidationCostTokens: 0,\n\t};\n}\n\nfunction buildHardConstraintFlags(built: BuiltToolOutputItem, artifactStoreAvailable: boolean): HardConstraintFlags {\n\treturn {\n\t\tisApprovalOrDenial: false,\n\t\tisSafetyConstraint: false,\n\t\tisActiveBlocker: false,\n\t\tisCurrentValidationResult: false,\n\t\tisPathOrToolScope: false,\n\t\t// Only a resolved artifact counts; a transcript ref is provenance, not a live\n\t\t// retrieval mechanism -- see the module doc comment.\n\t\thasAvailableRetrievalPath: built.hasResolvedArtifact,\n\t\tartifactStoreAvailable,\n\t\thasEvidenceRefForSummary: built.item.primaryRef !== undefined || (built.item.evidenceRefs?.length ?? 0) > 0,\n\t\tpathOrToolBoundariesEnforced: true,\n\t\tvalidationAvailableAndStrong: false,\n\t\tpriorAttemptFailedForReasoningOrArchitecture: false,\n\t\tisHighImpactOrBroadMultiFileEdit: false,\n\t};\n}\n\n/** Build the ContextItem for a single toolResult message, for direct unit testing. */\nexport function buildToolResultContextItem(\n\tmessage: ToolResultMessage,\n\tmessageIndex: number,\n\toptions: ContextAuditOptions,\n): ContextItem {\n\treturn buildToolOutputItem(message, messageIndex, options).item;\n}\n\n/**\n * Read-only audit pass: converts live toolResult messages into ContextItems and runs the\n * existing pure retention/hard-constraint evaluators over them. Never mutates `messages`,\n * the transcript, or artifact references -- deterministic given the same messages,\n * `turnIndex`, and artifact-store state (not a cross-turn stability guarantee: turnIndex\n * and artifact-backed createdAtTurn values are expected to change turn over turn).\n */\nexport function runContextAudit(messages: AgentMessage[], options: ContextAuditOptions): ContextAuditReport {\n\tconst items: ContextAuditItemReport[] = [];\n\tmessages.forEach((message, messageIndex) => {\n\t\tif (message.role !== \"toolResult\") return;\n\t\tconst built = buildToolOutputItem(message, messageIndex, options);\n\t\tconst features = buildPolicyFeatures(built.item, built, options.turnIndex);\n\t\tconst flags = buildHardConstraintFlags(built, options.artifactStore !== undefined);\n\t\titems.push({\n\t\t\titem: built.item,\n\t\t\ttoolCallId: message.toolCallId,\n\t\t\tmessageIndex,\n\t\t\tretention: evaluateRetentionEligibility(built.item),\n\t\t\tkeepRawHardConstraints: evaluateHardConstraints(\"keep_raw\", features, flags),\n\t\t\tpackToArtifactHardConstraints: evaluateHardConstraints(\"pack_to_artifact\", features, flags),\n\t\t\tdropFromPromptHardConstraints: evaluateHardConstraints(\"drop_from_prompt\", features, flags),\n\t\t\tsummarizeHardConstraints: evaluateHardConstraints(\"summarize\", features, flags),\n\t\t});\n\t});\n\treturn { turnIndex: options.turnIndex, items };\n}\n"]}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Pure, provider-free context contracts.
3
+ *
4
+ * These types describe the curated working state the prompt builder will eventually
5
+ * consume, distinct from the immutable session transcript. Adding this module makes no
6
+ * behavior change: nothing here is wired into prompt construction yet.
7
+ */
8
+ export type ContextItemKind = "user_instruction" | "approval" | "denial" | "safety_constraint" | "goal_state" | "requirement" | "plan" | "blocker" | "evidence" | "invalidated_assumption" | "tool_output" | "tool_output_digest" | "file_snapshot" | "diff_summary" | "test_result" | "conversation_tail" | "retrieved_artifact" | "memory_item" | "memory_digest";
9
+ export type ContextRetentionClass = "pinned" | "active" | "decision_bearing" | "useful" | "ephemeral" | "expired";
10
+ export type ContextSource = "user" | "assistant" | "tool" | "runtime" | "session" | "memory" | "external_provider";
11
+ export interface ContextArtifactRef {
12
+ id: string;
13
+ kind: "tool_output" | "file_snapshot" | "test_output" | "diff" | "transcript_slice";
14
+ storagePath?: string;
15
+ sessionEntryId?: string;
16
+ toolName?: string;
17
+ command?: string;
18
+ path?: string;
19
+ byteLength: number;
20
+ lineCount?: number;
21
+ createdAtTurn: number;
22
+ reproducible: boolean;
23
+ }
24
+ export type MemoryScope = "session" | "project" | "user" | "global";
25
+ export interface ContextMemoryRef {
26
+ providerId: string;
27
+ itemId: string;
28
+ scope: MemoryScope;
29
+ kind: string;
30
+ uri?: string;
31
+ }
32
+ export interface ContextTranscriptRef {
33
+ sessionEntryId: string;
34
+ branchId?: string;
35
+ messageIndex?: number;
36
+ }
37
+ export type ContextEvidenceRef = {
38
+ type: "artifact";
39
+ ref: ContextArtifactRef;
40
+ } | {
41
+ type: "memory";
42
+ ref: ContextMemoryRef;
43
+ } | {
44
+ type: "transcript";
45
+ ref: ContextTranscriptRef;
46
+ } | {
47
+ type: "runtime";
48
+ id: string;
49
+ description: string;
50
+ };
51
+ export interface ContextItem {
52
+ id: string;
53
+ kind: ContextItemKind;
54
+ retentionClass: ContextRetentionClass;
55
+ source: ContextSource;
56
+ createdAtTurn: number;
57
+ lastUsedAtTurn?: number;
58
+ summary?: string;
59
+ content?: string;
60
+ primaryRef?: ContextEvidenceRef;
61
+ evidenceRefs?: ContextEvidenceRef[];
62
+ tokenEstimate: number;
63
+ byteEstimate: number;
64
+ supersededBy?: string;
65
+ invalidates?: string[];
66
+ pinReason?: string;
67
+ expiresAfterGoalId?: string;
68
+ }
69
+ export interface InvalidatedAssumptionItem {
70
+ id: string;
71
+ kind: "invalidated_assumption";
72
+ retentionClass: "decision_bearing" | "useful";
73
+ summary: string;
74
+ reason: string;
75
+ evidenceRefs: ContextEvidenceRef[];
76
+ expiresAfterGoalId?: string;
77
+ }
78
+ export type ModelRetentionAction = {
79
+ action: "keep";
80
+ itemId: string;
81
+ reason: string;
82
+ } | {
83
+ action: "summarize";
84
+ itemId: string;
85
+ summary: string;
86
+ reason: string;
87
+ evidenceRefs?: ContextEvidenceRef[];
88
+ } | {
89
+ action: "drop_from_prompt";
90
+ itemId: string;
91
+ reason: string;
92
+ } | {
93
+ action: "invalidate";
94
+ itemId: string;
95
+ summary: string;
96
+ reason: string;
97
+ evidenceRefs: ContextEvidenceRef[];
98
+ } | {
99
+ action: "pin_request";
100
+ itemId: string;
101
+ reason: string;
102
+ };
103
+ /**
104
+ * Kinds that are hard-retained regardless of retentionClass: their semantics must remain
105
+ * present in prompt context per the contracts-and-retention.md hard retention rules.
106
+ */
107
+ export declare const HARD_RETAINED_CONTEXT_KINDS: ReadonlySet<ContextItemKind>;
108
+ /** UTF-8 byte length, matching how the runtime measures raw payload size elsewhere. */
109
+ export declare function estimateByteLength(text: string): number;
110
+ export declare function estimateLineCount(text: string): number;
111
+ /**
112
+ * No-tokenizer sizing rule from policy-engine-spec.md: estimatedTokens = ceil(chars / 4).
113
+ * Calibrate against provider-reported usage post-call; never treat this as semantic criticality.
114
+ */
115
+ export declare function estimateTokensFromChars(charCount: number): number;
116
+ export declare function estimateTokensFromText(text: string): number;
117
+ //# sourceMappingURL=context-item.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-item.d.ts","sourceRoot":"","sources":["../../../src/core/context/context-item.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure, provider-free context contracts.\n *\n * These types describe the curated working state the prompt builder will eventually\n * consume, distinct from the immutable session transcript. Adding this module makes no\n * behavior change: nothing here is wired into prompt construction yet.\n */\n\nexport type ContextItemKind =\n\t| \"user_instruction\"\n\t| \"approval\"\n\t| \"denial\"\n\t| \"safety_constraint\"\n\t| \"goal_state\"\n\t| \"requirement\"\n\t| \"plan\"\n\t| \"blocker\"\n\t| \"evidence\"\n\t| \"invalidated_assumption\"\n\t| \"tool_output\"\n\t| \"tool_output_digest\"\n\t| \"file_snapshot\"\n\t| \"diff_summary\"\n\t| \"test_result\"\n\t| \"conversation_tail\"\n\t| \"retrieved_artifact\"\n\t| \"memory_item\"\n\t| \"memory_digest\";\n\nexport type ContextRetentionClass = \"pinned\" | \"active\" | \"decision_bearing\" | \"useful\" | \"ephemeral\" | \"expired\";\n\nexport type ContextSource = \"user\" | \"assistant\" | \"tool\" | \"runtime\" | \"session\" | \"memory\" | \"external_provider\";\n\nexport interface ContextArtifactRef {\n\tid: string;\n\tkind: \"tool_output\" | \"file_snapshot\" | \"test_output\" | \"diff\" | \"transcript_slice\";\n\tstoragePath?: string;\n\tsessionEntryId?: string;\n\ttoolName?: string;\n\tcommand?: string;\n\tpath?: string;\n\tbyteLength: number;\n\tlineCount?: number;\n\tcreatedAtTurn: number;\n\treproducible: boolean;\n}\n\nexport type MemoryScope = \"session\" | \"project\" | \"user\" | \"global\";\n\nexport interface ContextMemoryRef {\n\tproviderId: string;\n\titemId: string;\n\tscope: MemoryScope;\n\tkind: string;\n\turi?: string;\n}\n\nexport interface ContextTranscriptRef {\n\tsessionEntryId: string;\n\tbranchId?: string;\n\tmessageIndex?: number;\n}\n\nexport type ContextEvidenceRef =\n\t| { type: \"artifact\"; ref: ContextArtifactRef }\n\t| { type: \"memory\"; ref: ContextMemoryRef }\n\t| { type: \"transcript\"; ref: ContextTranscriptRef }\n\t| { type: \"runtime\"; id: string; description: string };\n\nexport interface ContextItem {\n\tid: string;\n\tkind: ContextItemKind;\n\tretentionClass: ContextRetentionClass;\n\tsource: ContextSource;\n\tcreatedAtTurn: number;\n\tlastUsedAtTurn?: number;\n\tsummary?: string;\n\tcontent?: string;\n\tprimaryRef?: ContextEvidenceRef;\n\tevidenceRefs?: ContextEvidenceRef[];\n\ttokenEstimate: number;\n\tbyteEstimate: number;\n\tsupersededBy?: string;\n\tinvalidates?: string[];\n\tpinReason?: string;\n\texpiresAfterGoalId?: string;\n}\n\nexport interface InvalidatedAssumptionItem {\n\tid: string;\n\tkind: \"invalidated_assumption\";\n\tretentionClass: \"decision_bearing\" | \"useful\";\n\tsummary: string;\n\treason: string;\n\tevidenceRefs: ContextEvidenceRef[];\n\texpiresAfterGoalId?: string;\n}\n\nexport type ModelRetentionAction =\n\t| { action: \"keep\"; itemId: string; reason: string }\n\t| { action: \"summarize\"; itemId: string; summary: string; reason: string; evidenceRefs?: ContextEvidenceRef[] }\n\t| { action: \"drop_from_prompt\"; itemId: string; reason: string }\n\t| { action: \"invalidate\"; itemId: string; summary: string; reason: string; evidenceRefs: ContextEvidenceRef[] }\n\t| { action: \"pin_request\"; itemId: string; reason: string };\n\n/**\n * Kinds that are hard-retained regardless of retentionClass: their semantics must remain\n * present in prompt context per the contracts-and-retention.md hard retention rules.\n */\nexport const HARD_RETAINED_CONTEXT_KINDS: ReadonlySet<ContextItemKind> = new Set([\n\t\"user_instruction\",\n\t\"approval\",\n\t\"denial\",\n\t\"safety_constraint\",\n]);\n\nconst NO_TOKENIZER_CHARS_PER_TOKEN = 4;\n\n/** UTF-8 byte length, matching how the runtime measures raw payload size elsewhere. */\nexport function estimateByteLength(text: string): number {\n\treturn Buffer.byteLength(text, \"utf8\");\n}\n\nexport function estimateLineCount(text: string): number {\n\treturn text.length === 0 ? 0 : text.split(\"\\n\").length;\n}\n\n/**\n * No-tokenizer sizing rule from policy-engine-spec.md: estimatedTokens = ceil(chars / 4).\n * Calibrate against provider-reported usage post-call; never treat this as semantic criticality.\n */\nexport function estimateTokensFromChars(charCount: number): number {\n\treturn Math.ceil(Math.max(0, charCount) / NO_TOKENIZER_CHARS_PER_TOKEN);\n}\n\nexport function estimateTokensFromText(text: string): number {\n\treturn estimateTokensFromChars(text.length);\n}\n"]}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Pure, provider-free context contracts.
3
+ *
4
+ * These types describe the curated working state the prompt builder will eventually
5
+ * consume, distinct from the immutable session transcript. Adding this module makes no
6
+ * behavior change: nothing here is wired into prompt construction yet.
7
+ */
8
+ /**
9
+ * Kinds that are hard-retained regardless of retentionClass: their semantics must remain
10
+ * present in prompt context per the contracts-and-retention.md hard retention rules.
11
+ */
12
+ export const HARD_RETAINED_CONTEXT_KINDS = new Set([
13
+ "user_instruction",
14
+ "approval",
15
+ "denial",
16
+ "safety_constraint",
17
+ ]);
18
+ const NO_TOKENIZER_CHARS_PER_TOKEN = 4;
19
+ /** UTF-8 byte length, matching how the runtime measures raw payload size elsewhere. */
20
+ export function estimateByteLength(text) {
21
+ return Buffer.byteLength(text, "utf8");
22
+ }
23
+ export function estimateLineCount(text) {
24
+ return text.length === 0 ? 0 : text.split("\n").length;
25
+ }
26
+ /**
27
+ * No-tokenizer sizing rule from policy-engine-spec.md: estimatedTokens = ceil(chars / 4).
28
+ * Calibrate against provider-reported usage post-call; never treat this as semantic criticality.
29
+ */
30
+ export function estimateTokensFromChars(charCount) {
31
+ return Math.ceil(Math.max(0, charCount) / NO_TOKENIZER_CHARS_PER_TOKEN);
32
+ }
33
+ export function estimateTokensFromText(text) {
34
+ return estimateTokensFromChars(text.length);
35
+ }
36
+ //# sourceMappingURL=context-item.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-item.js","sourceRoot":"","sources":["../../../src/core/context/context-item.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAmGH;;;GAGG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAiC,IAAI,GAAG,CAAC;IAChF,kBAAkB;IAClB,UAAU;IACV,QAAQ;IACR,mBAAmB;CACnB,CAAC,CAAC;AAEH,MAAM,4BAA4B,GAAG,CAAC,CAAC;AAEvC,uFAAuF;AACvF,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAU;IACxD,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAAA,CACvC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAU;IACvD,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;AAAA,CACvD;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,SAAiB,EAAU;IAClE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,4BAA4B,CAAC,CAAC;AAAA,CACxE;AAED,MAAM,UAAU,sBAAsB,CAAC,IAAY,EAAU;IAC5D,OAAO,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAAA,CAC5C","sourcesContent":["/**\n * Pure, provider-free context contracts.\n *\n * These types describe the curated working state the prompt builder will eventually\n * consume, distinct from the immutable session transcript. Adding this module makes no\n * behavior change: nothing here is wired into prompt construction yet.\n */\n\nexport type ContextItemKind =\n\t| \"user_instruction\"\n\t| \"approval\"\n\t| \"denial\"\n\t| \"safety_constraint\"\n\t| \"goal_state\"\n\t| \"requirement\"\n\t| \"plan\"\n\t| \"blocker\"\n\t| \"evidence\"\n\t| \"invalidated_assumption\"\n\t| \"tool_output\"\n\t| \"tool_output_digest\"\n\t| \"file_snapshot\"\n\t| \"diff_summary\"\n\t| \"test_result\"\n\t| \"conversation_tail\"\n\t| \"retrieved_artifact\"\n\t| \"memory_item\"\n\t| \"memory_digest\";\n\nexport type ContextRetentionClass = \"pinned\" | \"active\" | \"decision_bearing\" | \"useful\" | \"ephemeral\" | \"expired\";\n\nexport type ContextSource = \"user\" | \"assistant\" | \"tool\" | \"runtime\" | \"session\" | \"memory\" | \"external_provider\";\n\nexport interface ContextArtifactRef {\n\tid: string;\n\tkind: \"tool_output\" | \"file_snapshot\" | \"test_output\" | \"diff\" | \"transcript_slice\";\n\tstoragePath?: string;\n\tsessionEntryId?: string;\n\ttoolName?: string;\n\tcommand?: string;\n\tpath?: string;\n\tbyteLength: number;\n\tlineCount?: number;\n\tcreatedAtTurn: number;\n\treproducible: boolean;\n}\n\nexport type MemoryScope = \"session\" | \"project\" | \"user\" | \"global\";\n\nexport interface ContextMemoryRef {\n\tproviderId: string;\n\titemId: string;\n\tscope: MemoryScope;\n\tkind: string;\n\turi?: string;\n}\n\nexport interface ContextTranscriptRef {\n\tsessionEntryId: string;\n\tbranchId?: string;\n\tmessageIndex?: number;\n}\n\nexport type ContextEvidenceRef =\n\t| { type: \"artifact\"; ref: ContextArtifactRef }\n\t| { type: \"memory\"; ref: ContextMemoryRef }\n\t| { type: \"transcript\"; ref: ContextTranscriptRef }\n\t| { type: \"runtime\"; id: string; description: string };\n\nexport interface ContextItem {\n\tid: string;\n\tkind: ContextItemKind;\n\tretentionClass: ContextRetentionClass;\n\tsource: ContextSource;\n\tcreatedAtTurn: number;\n\tlastUsedAtTurn?: number;\n\tsummary?: string;\n\tcontent?: string;\n\tprimaryRef?: ContextEvidenceRef;\n\tevidenceRefs?: ContextEvidenceRef[];\n\ttokenEstimate: number;\n\tbyteEstimate: number;\n\tsupersededBy?: string;\n\tinvalidates?: string[];\n\tpinReason?: string;\n\texpiresAfterGoalId?: string;\n}\n\nexport interface InvalidatedAssumptionItem {\n\tid: string;\n\tkind: \"invalidated_assumption\";\n\tretentionClass: \"decision_bearing\" | \"useful\";\n\tsummary: string;\n\treason: string;\n\tevidenceRefs: ContextEvidenceRef[];\n\texpiresAfterGoalId?: string;\n}\n\nexport type ModelRetentionAction =\n\t| { action: \"keep\"; itemId: string; reason: string }\n\t| { action: \"summarize\"; itemId: string; summary: string; reason: string; evidenceRefs?: ContextEvidenceRef[] }\n\t| { action: \"drop_from_prompt\"; itemId: string; reason: string }\n\t| { action: \"invalidate\"; itemId: string; summary: string; reason: string; evidenceRefs: ContextEvidenceRef[] }\n\t| { action: \"pin_request\"; itemId: string; reason: string };\n\n/**\n * Kinds that are hard-retained regardless of retentionClass: their semantics must remain\n * present in prompt context per the contracts-and-retention.md hard retention rules.\n */\nexport const HARD_RETAINED_CONTEXT_KINDS: ReadonlySet<ContextItemKind> = new Set([\n\t\"user_instruction\",\n\t\"approval\",\n\t\"denial\",\n\t\"safety_constraint\",\n]);\n\nconst NO_TOKENIZER_CHARS_PER_TOKEN = 4;\n\n/** UTF-8 byte length, matching how the runtime measures raw payload size elsewhere. */\nexport function estimateByteLength(text: string): number {\n\treturn Buffer.byteLength(text, \"utf8\");\n}\n\nexport function estimateLineCount(text: string): number {\n\treturn text.length === 0 ? 0 : text.split(\"\\n\").length;\n}\n\n/**\n * No-tokenizer sizing rule from policy-engine-spec.md: estimatedTokens = ceil(chars / 4).\n * Calibrate against provider-reported usage post-call; never treat this as semantic criticality.\n */\nexport function estimateTokensFromChars(charCount: number): number {\n\treturn Math.ceil(Math.max(0, charCount) / NO_TOKENIZER_CHARS_PER_TOKEN);\n}\n\nexport function estimateTokensFromText(text: string): number {\n\treturn estimateTokensFromChars(text.length);\n}\n"]}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * First enforcement pilot for the context-policy layer (opt-in, default disabled). Unlike
3
+ * context-audit.ts/context-prompt-policy.ts (both strictly observe-only), this module CAN
4
+ * change the provider-visible message array -- but only ever via stub-in-place on
5
+ * artifact-backed tool_output results, never by removing a message or breaking
6
+ * assistant/toolResult pairing. It never touches the transcript, never releases/reclaims
7
+ * artifact references, and never writes a new artifact -- it only replaces the visible
8
+ * text of an already artifact-backed message with a bounded pointer to the existing
9
+ * artifact, retrievable via the `artifact_retrieve` tool.
10
+ *
11
+ * Eligibility for stubbing is deliberately conservative (see `enforcePromptPolicy`): the
12
+ * setting must be enabled, the item must be outside the recent-message safety window, not
13
+ * an errored tool result, not already stubbed by this module or already packed by legacy
14
+ * context-gc this turn, must have a resolvable artifact id, the `artifact_retrieve` tool
15
+ * must actually be active this turn, and must clear `hardConstraints.dropFromPrompt` (see
16
+ * below for why that specific action, not `pack_to_artifact`).
17
+ *
18
+ * Why `dropFromPrompt`, not `packToArtifact`: this operation does not create a new
19
+ * artifact -- it reuses the ref an earlier `pack_to_artifact` capture already produced (see
20
+ * tool-output-artifacts.md's "measure -> digest/preview/artifact -> prompt item" pipeline).
21
+ * `drop_from_prompt` requires an existing retrieval path and is exactly the operation being
22
+ * performed (evicting raw content from the live prompt in favor of that existing path);
23
+ * `pack_to_artifact` is the distinct first-capture operation, which we never invoke here.
24
+ *
25
+ * Why `retrievalToolAvailable` is checked separately from `hasAvailableRetrievalPath`: the
26
+ * latter only proves the artifact still exists in the store; it says nothing about whether
27
+ * the model can currently act on the stub's instruction to call `artifact_retrieve`.
28
+ * `artifact_retrieve` is a companion affordance (auto-activated alongside grep/find, not a
29
+ * default/global tool -- see agent-session.ts's companion-activation enforcement), so active
30
+ * tools can differ turn to turn. Stubbing content with an unactionable pointer would be
31
+ * strictly worse than leaving the raw content in place.
32
+ */
33
+ import type { AgentMessage } from "@caupulican/pi-agent-core";
34
+ import type { PromptPolicyShadowReport } from "./context-prompt-policy.ts";
35
+ export interface ContextPromptEnforcementSettings {
36
+ enabled: boolean;
37
+ preserveRecentMessages: number;
38
+ minChars: number;
39
+ /**
40
+ * Whether the `artifact_retrieve` tool is actually active this turn -- a runtime fact,
41
+ * not a persisted setting. Callers must derive this from the live active-tool set (e.g.
42
+ * `AgentSession.getActiveToolNames().includes("artifact_retrieve")`), never assume it.
43
+ */
44
+ retrievalToolAvailable: boolean;
45
+ }
46
+ export type PromptEnforcementSkipReason = "message_mismatch" | "within_recent_window" | "errored_tool_result" | "already_stubbed_or_packed" | "not_artifact_backed" | "retrieval_tool_unavailable" | "hard_constraint_rejected" | "missing_artifact_id" | "below_min_chars";
47
+ export interface PromptEnforcementItemReport {
48
+ itemId: string;
49
+ toolCallId: string;
50
+ messageIndex: number;
51
+ enforced: boolean;
52
+ action?: "artifact_stub";
53
+ artifactId?: string;
54
+ originalChars?: number;
55
+ skipReason?: PromptEnforcementSkipReason;
56
+ }
57
+ export interface PromptEnforcementReport {
58
+ turnIndex: number;
59
+ items: PromptEnforcementItemReport[];
60
+ }
61
+ export interface EnforcePromptPolicyResult {
62
+ messages: AgentMessage[];
63
+ report: PromptEnforcementReport;
64
+ }
65
+ /**
66
+ * Apply the first enforcement pilot to `messages` (expected to be the provider-visible
67
+ * array after existing context-gc has already run). Returns a new array only when at least
68
+ * one item was actually stubbed; otherwise returns the same `messages` reference unchanged
69
+ * (in particular, always true when `settings.enabled` is false). Never mutates `messages`
70
+ * or any message object within it -- every stubbed entry is a fresh object.
71
+ */
72
+ export declare function enforcePromptPolicy(messages: AgentMessage[], shadowReport: PromptPolicyShadowReport, settings: ContextPromptEnforcementSettings): EnforcePromptPolicyResult;
73
+ //# sourceMappingURL=context-prompt-enforcement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-prompt-enforcement.d.ts","sourceRoot":"","sources":["../../../src/core/context/context-prompt-enforcement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAE3E,MAAM,WAAW,gCAAgC;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,sBAAsB,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,MAAM,2BAA2B,GACpC,kBAAkB,GAClB,sBAAsB,GACtB,qBAAqB,GACrB,2BAA2B,GAC3B,qBAAqB,GACrB,4BAA4B,GAC5B,0BAA0B,GAC1B,qBAAqB,GACrB,iBAAiB,CAAC;AAErB,MAAM,WAAW,2BAA2B;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,2BAA2B,CAAC;CACzC;AAED,MAAM,WAAW,uBAAuB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,2BAA2B,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACzC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,MAAM,EAAE,uBAAuB,CAAC;CAChC;AA0CD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,YAAY,EAAE,EACxB,YAAY,EAAE,wBAAwB,EACtC,QAAQ,EAAE,gCAAgC,GACxC,yBAAyB,CAkF3B","sourcesContent":["/**\n * First enforcement pilot for the context-policy layer (opt-in, default disabled). Unlike\n * context-audit.ts/context-prompt-policy.ts (both strictly observe-only), this module CAN\n * change the provider-visible message array -- but only ever via stub-in-place on\n * artifact-backed tool_output results, never by removing a message or breaking\n * assistant/toolResult pairing. It never touches the transcript, never releases/reclaims\n * artifact references, and never writes a new artifact -- it only replaces the visible\n * text of an already artifact-backed message with a bounded pointer to the existing\n * artifact, retrievable via the `artifact_retrieve` tool.\n *\n * Eligibility for stubbing is deliberately conservative (see `enforcePromptPolicy`): the\n * setting must be enabled, the item must be outside the recent-message safety window, not\n * an errored tool result, not already stubbed by this module or already packed by legacy\n * context-gc this turn, must have a resolvable artifact id, the `artifact_retrieve` tool\n * must actually be active this turn, and must clear `hardConstraints.dropFromPrompt` (see\n * below for why that specific action, not `pack_to_artifact`).\n *\n * Why `dropFromPrompt`, not `packToArtifact`: this operation does not create a new\n * artifact -- it reuses the ref an earlier `pack_to_artifact` capture already produced (see\n * tool-output-artifacts.md's \"measure -> digest/preview/artifact -> prompt item\" pipeline).\n * `drop_from_prompt` requires an existing retrieval path and is exactly the operation being\n * performed (evicting raw content from the live prompt in favor of that existing path);\n * `pack_to_artifact` is the distinct first-capture operation, which we never invoke here.\n *\n * Why `retrievalToolAvailable` is checked separately from `hasAvailableRetrievalPath`: the\n * latter only proves the artifact still exists in the store; it says nothing about whether\n * the model can currently act on the stub's instruction to call `artifact_retrieve`.\n * `artifact_retrieve` is a companion affordance (auto-activated alongside grep/find, not a\n * default/global tool -- see agent-session.ts's companion-activation enforcement), so active\n * tools can differ turn to turn. Stubbing content with an unactionable pointer would be\n * strictly worse than leaving the raw content in place.\n */\n\nimport type { AgentMessage } from \"@caupulican/pi-agent-core\";\nimport type { ToolResultMessage } from \"@caupulican/pi-ai\";\nimport type { PromptPolicyShadowReport } from \"./context-prompt-policy.ts\";\n\nexport interface ContextPromptEnforcementSettings {\n\tenabled: boolean;\n\tpreserveRecentMessages: number;\n\tminChars: number;\n\t/**\n\t * Whether the `artifact_retrieve` tool is actually active this turn -- a runtime fact,\n\t * not a persisted setting. Callers must derive this from the live active-tool set (e.g.\n\t * `AgentSession.getActiveToolNames().includes(\"artifact_retrieve\")`), never assume it.\n\t */\n\tretrievalToolAvailable: boolean;\n}\n\nexport type PromptEnforcementSkipReason =\n\t| \"message_mismatch\"\n\t| \"within_recent_window\"\n\t| \"errored_tool_result\"\n\t| \"already_stubbed_or_packed\"\n\t| \"not_artifact_backed\"\n\t| \"retrieval_tool_unavailable\"\n\t| \"hard_constraint_rejected\"\n\t| \"missing_artifact_id\"\n\t| \"below_min_chars\";\n\nexport interface PromptEnforcementItemReport {\n\titemId: string;\n\ttoolCallId: string;\n\tmessageIndex: number;\n\tenforced: boolean;\n\taction?: \"artifact_stub\";\n\tartifactId?: string;\n\toriginalChars?: number;\n\tskipReason?: PromptEnforcementSkipReason;\n}\n\nexport interface PromptEnforcementReport {\n\tturnIndex: number;\n\titems: PromptEnforcementItemReport[];\n}\n\nexport interface EnforcePromptPolicyResult {\n\tmessages: AgentMessage[];\n\treport: PromptEnforcementReport;\n}\n\nfunction extractDetailsArtifactId(details: unknown): string | undefined {\n\tif (typeof details !== \"object\" || details === null) return undefined;\n\tconst artifactId = (details as { artifactId?: unknown }).artifactId;\n\treturn typeof artifactId === \"string\" ? artifactId : undefined;\n}\n\n/** True if legacy context-gc already packed this message this turn, or this module already stubbed it. */\nfunction isAlreadyStubbedOrPacked(details: unknown): boolean {\n\tif (typeof details !== \"object\" || details === null) return false;\n\tconst record = details as { promptPolicy?: { enforced?: unknown }; contextGc?: { packed?: unknown } };\n\treturn record.promptPolicy?.enforced === true || record.contextGc?.packed === true;\n}\n\nfunction toolResultText(message: ToolResultMessage): string {\n\tconst parts: string[] = [];\n\tfor (const part of message.content) {\n\t\tif (part.type === \"text\") parts.push(part.text);\n\t}\n\treturn parts.join(\"\\n\");\n}\n\nfunction buildStubText(toolName: string, originalChars: number, artifactId: string): string {\n\treturn `[content replaced by prompt-policy: originally ${originalChars} chars from a stale ${toolName} tool result. Retrieve the full output with artifact_retrieve using artifactId \"${artifactId}\".]`;\n}\n\nfunction skip(\n\titem: { itemId: string; toolCallId: string; messageIndex: number },\n\tskipReason: PromptEnforcementSkipReason,\n\textra?: { artifactId?: string; originalChars?: number },\n): PromptEnforcementItemReport {\n\treturn {\n\t\titemId: item.itemId,\n\t\ttoolCallId: item.toolCallId,\n\t\tmessageIndex: item.messageIndex,\n\t\tenforced: false,\n\t\tskipReason,\n\t\t...extra,\n\t};\n}\n\n/**\n * Apply the first enforcement pilot to `messages` (expected to be the provider-visible\n * array after existing context-gc has already run). Returns a new array only when at least\n * one item was actually stubbed; otherwise returns the same `messages` reference unchanged\n * (in particular, always true when `settings.enabled` is false). Never mutates `messages`\n * or any message object within it -- every stubbed entry is a fresh object.\n */\nexport function enforcePromptPolicy(\n\tmessages: AgentMessage[],\n\tshadowReport: PromptPolicyShadowReport,\n\tsettings: ContextPromptEnforcementSettings,\n): EnforcePromptPolicyResult {\n\tif (!settings.enabled) {\n\t\treturn { messages, report: { turnIndex: shadowReport.turnIndex, items: [] } };\n\t}\n\n\tconst recentCutoffIndex = Math.max(0, messages.length - settings.preserveRecentMessages);\n\tconst nextMessages = messages.slice();\n\tlet changed = false;\n\tconst items: PromptEnforcementItemReport[] = [];\n\n\tfor (const planItem of shadowReport.items) {\n\t\tconst message = messages[planItem.messageIndex];\n\t\tif (!message || message.role !== \"toolResult\" || message.toolCallId !== planItem.toolCallId) {\n\t\t\titems.push(skip(planItem, \"message_mismatch\"));\n\t\t\tcontinue;\n\t\t}\n\t\tif (planItem.messageIndex >= recentCutoffIndex) {\n\t\t\titems.push(skip(planItem, \"within_recent_window\"));\n\t\t\tcontinue;\n\t\t}\n\t\tif (message.isError) {\n\t\t\titems.push(skip(planItem, \"errored_tool_result\"));\n\t\t\tcontinue;\n\t\t}\n\t\tif (isAlreadyStubbedOrPacked(message.details)) {\n\t\t\titems.push(skip(planItem, \"already_stubbed_or_packed\"));\n\t\t\tcontinue;\n\t\t}\n\t\tif (!planItem.hasAvailableRetrievalPath) {\n\t\t\titems.push(skip(planItem, \"not_artifact_backed\"));\n\t\t\tcontinue;\n\t\t}\n\t\tif (!settings.retrievalToolAvailable) {\n\t\t\titems.push(skip(planItem, \"retrieval_tool_unavailable\"));\n\t\t\tcontinue;\n\t\t}\n\t\tif (planItem.hardConstraints.dropFromPrompt.length > 0) {\n\t\t\titems.push(skip(planItem, \"hard_constraint_rejected\"));\n\t\t\tcontinue;\n\t\t}\n\t\tconst artifactId = extractDetailsArtifactId(message.details);\n\t\tif (!artifactId) {\n\t\t\titems.push(skip(planItem, \"missing_artifact_id\"));\n\t\t\tcontinue;\n\t\t}\n\t\tconst originalChars = toolResultText(message).length;\n\t\tif (originalChars < settings.minChars) {\n\t\t\titems.push(skip(planItem, \"below_min_chars\", { artifactId, originalChars }));\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst existingDetails = typeof message.details === \"object\" && message.details !== null ? message.details : {};\n\t\tnextMessages[planItem.messageIndex] = {\n\t\t\t...message,\n\t\t\tcontent: [{ type: \"text\", text: buildStubText(message.toolName, originalChars, artifactId) }],\n\t\t\tdetails: {\n\t\t\t\t...existingDetails,\n\t\t\t\tpromptPolicy: {\n\t\t\t\t\tenforced: true,\n\t\t\t\t\taction: \"artifact_stub\",\n\t\t\t\t\tartifactId,\n\t\t\t\t\toriginalChars,\n\t\t\t\t\treason: \"stale_artifact_backed_tool_output\",\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\tchanged = true;\n\t\titems.push({\n\t\t\titemId: planItem.itemId,\n\t\t\ttoolCallId: planItem.toolCallId,\n\t\t\tmessageIndex: planItem.messageIndex,\n\t\t\tenforced: true,\n\t\t\taction: \"artifact_stub\",\n\t\t\tartifactId,\n\t\t\toriginalChars,\n\t\t});\n\t}\n\n\treturn {\n\t\tmessages: changed ? nextMessages : messages,\n\t\treport: { turnIndex: shadowReport.turnIndex, items },\n\t};\n}\n"]}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * First enforcement pilot for the context-policy layer (opt-in, default disabled). Unlike
3
+ * context-audit.ts/context-prompt-policy.ts (both strictly observe-only), this module CAN
4
+ * change the provider-visible message array -- but only ever via stub-in-place on
5
+ * artifact-backed tool_output results, never by removing a message or breaking
6
+ * assistant/toolResult pairing. It never touches the transcript, never releases/reclaims
7
+ * artifact references, and never writes a new artifact -- it only replaces the visible
8
+ * text of an already artifact-backed message with a bounded pointer to the existing
9
+ * artifact, retrievable via the `artifact_retrieve` tool.
10
+ *
11
+ * Eligibility for stubbing is deliberately conservative (see `enforcePromptPolicy`): the
12
+ * setting must be enabled, the item must be outside the recent-message safety window, not
13
+ * an errored tool result, not already stubbed by this module or already packed by legacy
14
+ * context-gc this turn, must have a resolvable artifact id, the `artifact_retrieve` tool
15
+ * must actually be active this turn, and must clear `hardConstraints.dropFromPrompt` (see
16
+ * below for why that specific action, not `pack_to_artifact`).
17
+ *
18
+ * Why `dropFromPrompt`, not `packToArtifact`: this operation does not create a new
19
+ * artifact -- it reuses the ref an earlier `pack_to_artifact` capture already produced (see
20
+ * tool-output-artifacts.md's "measure -> digest/preview/artifact -> prompt item" pipeline).
21
+ * `drop_from_prompt` requires an existing retrieval path and is exactly the operation being
22
+ * performed (evicting raw content from the live prompt in favor of that existing path);
23
+ * `pack_to_artifact` is the distinct first-capture operation, which we never invoke here.
24
+ *
25
+ * Why `retrievalToolAvailable` is checked separately from `hasAvailableRetrievalPath`: the
26
+ * latter only proves the artifact still exists in the store; it says nothing about whether
27
+ * the model can currently act on the stub's instruction to call `artifact_retrieve`.
28
+ * `artifact_retrieve` is a companion affordance (auto-activated alongside grep/find, not a
29
+ * default/global tool -- see agent-session.ts's companion-activation enforcement), so active
30
+ * tools can differ turn to turn. Stubbing content with an unactionable pointer would be
31
+ * strictly worse than leaving the raw content in place.
32
+ */
33
+ function extractDetailsArtifactId(details) {
34
+ if (typeof details !== "object" || details === null)
35
+ return undefined;
36
+ const artifactId = details.artifactId;
37
+ return typeof artifactId === "string" ? artifactId : undefined;
38
+ }
39
+ /** True if legacy context-gc already packed this message this turn, or this module already stubbed it. */
40
+ function isAlreadyStubbedOrPacked(details) {
41
+ if (typeof details !== "object" || details === null)
42
+ return false;
43
+ const record = details;
44
+ return record.promptPolicy?.enforced === true || record.contextGc?.packed === true;
45
+ }
46
+ function toolResultText(message) {
47
+ const parts = [];
48
+ for (const part of message.content) {
49
+ if (part.type === "text")
50
+ parts.push(part.text);
51
+ }
52
+ return parts.join("\n");
53
+ }
54
+ function buildStubText(toolName, originalChars, artifactId) {
55
+ return `[content replaced by prompt-policy: originally ${originalChars} chars from a stale ${toolName} tool result. Retrieve the full output with artifact_retrieve using artifactId "${artifactId}".]`;
56
+ }
57
+ function skip(item, skipReason, extra) {
58
+ return {
59
+ itemId: item.itemId,
60
+ toolCallId: item.toolCallId,
61
+ messageIndex: item.messageIndex,
62
+ enforced: false,
63
+ skipReason,
64
+ ...extra,
65
+ };
66
+ }
67
+ /**
68
+ * Apply the first enforcement pilot to `messages` (expected to be the provider-visible
69
+ * array after existing context-gc has already run). Returns a new array only when at least
70
+ * one item was actually stubbed; otherwise returns the same `messages` reference unchanged
71
+ * (in particular, always true when `settings.enabled` is false). Never mutates `messages`
72
+ * or any message object within it -- every stubbed entry is a fresh object.
73
+ */
74
+ export function enforcePromptPolicy(messages, shadowReport, settings) {
75
+ if (!settings.enabled) {
76
+ return { messages, report: { turnIndex: shadowReport.turnIndex, items: [] } };
77
+ }
78
+ const recentCutoffIndex = Math.max(0, messages.length - settings.preserveRecentMessages);
79
+ const nextMessages = messages.slice();
80
+ let changed = false;
81
+ const items = [];
82
+ for (const planItem of shadowReport.items) {
83
+ const message = messages[planItem.messageIndex];
84
+ if (!message || message.role !== "toolResult" || message.toolCallId !== planItem.toolCallId) {
85
+ items.push(skip(planItem, "message_mismatch"));
86
+ continue;
87
+ }
88
+ if (planItem.messageIndex >= recentCutoffIndex) {
89
+ items.push(skip(planItem, "within_recent_window"));
90
+ continue;
91
+ }
92
+ if (message.isError) {
93
+ items.push(skip(planItem, "errored_tool_result"));
94
+ continue;
95
+ }
96
+ if (isAlreadyStubbedOrPacked(message.details)) {
97
+ items.push(skip(planItem, "already_stubbed_or_packed"));
98
+ continue;
99
+ }
100
+ if (!planItem.hasAvailableRetrievalPath) {
101
+ items.push(skip(planItem, "not_artifact_backed"));
102
+ continue;
103
+ }
104
+ if (!settings.retrievalToolAvailable) {
105
+ items.push(skip(planItem, "retrieval_tool_unavailable"));
106
+ continue;
107
+ }
108
+ if (planItem.hardConstraints.dropFromPrompt.length > 0) {
109
+ items.push(skip(planItem, "hard_constraint_rejected"));
110
+ continue;
111
+ }
112
+ const artifactId = extractDetailsArtifactId(message.details);
113
+ if (!artifactId) {
114
+ items.push(skip(planItem, "missing_artifact_id"));
115
+ continue;
116
+ }
117
+ const originalChars = toolResultText(message).length;
118
+ if (originalChars < settings.minChars) {
119
+ items.push(skip(planItem, "below_min_chars", { artifactId, originalChars }));
120
+ continue;
121
+ }
122
+ const existingDetails = typeof message.details === "object" && message.details !== null ? message.details : {};
123
+ nextMessages[planItem.messageIndex] = {
124
+ ...message,
125
+ content: [{ type: "text", text: buildStubText(message.toolName, originalChars, artifactId) }],
126
+ details: {
127
+ ...existingDetails,
128
+ promptPolicy: {
129
+ enforced: true,
130
+ action: "artifact_stub",
131
+ artifactId,
132
+ originalChars,
133
+ reason: "stale_artifact_backed_tool_output",
134
+ },
135
+ },
136
+ };
137
+ changed = true;
138
+ items.push({
139
+ itemId: planItem.itemId,
140
+ toolCallId: planItem.toolCallId,
141
+ messageIndex: planItem.messageIndex,
142
+ enforced: true,
143
+ action: "artifact_stub",
144
+ artifactId,
145
+ originalChars,
146
+ });
147
+ }
148
+ return {
149
+ messages: changed ? nextMessages : messages,
150
+ report: { turnIndex: shadowReport.turnIndex, items },
151
+ };
152
+ }
153
+ //# sourceMappingURL=context-prompt-enforcement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-prompt-enforcement.js","sourceRoot":"","sources":["../../../src/core/context/context-prompt-enforcement.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * First enforcement pilot for the context-policy layer (opt-in, default disabled). Unlike\n * context-audit.ts/context-prompt-policy.ts (both strictly observe-only), this module CAN\n * change the provider-visible message array -- but only ever via stub-in-place on\n * artifact-backed tool_output results, never by removing a message or breaking\n * assistant/toolResult pairing. It never touches the transcript, never releases/reclaims\n * artifact references, and never writes a new artifact -- it only replaces the visible\n * text of an already artifact-backed message with a bounded pointer to the existing\n * artifact, retrievable via the `artifact_retrieve` tool.\n *\n * Eligibility for stubbing is deliberately conservative (see `enforcePromptPolicy`): the\n * setting must be enabled, the item must be outside the recent-message safety window, not\n * an errored tool result, not already stubbed by this module or already packed by legacy\n * context-gc this turn, must have a resolvable artifact id, the `artifact_retrieve` tool\n * must actually be active this turn, and must clear `hardConstraints.dropFromPrompt` (see\n * below for why that specific action, not `pack_to_artifact`).\n *\n * Why `dropFromPrompt`, not `packToArtifact`: this operation does not create a new\n * artifact -- it reuses the ref an earlier `pack_to_artifact` capture already produced (see\n * tool-output-artifacts.md's \"measure -> digest/preview/artifact -> prompt item\" pipeline).\n * `drop_from_prompt` requires an existing retrieval path and is exactly the operation being\n * performed (evicting raw content from the live prompt in favor of that existing path);\n * `pack_to_artifact` is the distinct first-capture operation, which we never invoke here.\n *\n * Why `retrievalToolAvailable` is checked separately from `hasAvailableRetrievalPath`: the\n * latter only proves the artifact still exists in the store; it says nothing about whether\n * the model can currently act on the stub's instruction to call `artifact_retrieve`.\n * `artifact_retrieve` is a companion affordance (auto-activated alongside grep/find, not a\n * default/global tool -- see agent-session.ts's companion-activation enforcement), so active\n * tools can differ turn to turn. Stubbing content with an unactionable pointer would be\n * strictly worse than leaving the raw content in place.\n */\n\nimport type { AgentMessage } from \"@caupulican/pi-agent-core\";\nimport type { ToolResultMessage } from \"@caupulican/pi-ai\";\nimport type { PromptPolicyShadowReport } from \"./context-prompt-policy.ts\";\n\nexport interface ContextPromptEnforcementSettings {\n\tenabled: boolean;\n\tpreserveRecentMessages: number;\n\tminChars: number;\n\t/**\n\t * Whether the `artifact_retrieve` tool is actually active this turn -- a runtime fact,\n\t * not a persisted setting. Callers must derive this from the live active-tool set (e.g.\n\t * `AgentSession.getActiveToolNames().includes(\"artifact_retrieve\")`), never assume it.\n\t */\n\tretrievalToolAvailable: boolean;\n}\n\nexport type PromptEnforcementSkipReason =\n\t| \"message_mismatch\"\n\t| \"within_recent_window\"\n\t| \"errored_tool_result\"\n\t| \"already_stubbed_or_packed\"\n\t| \"not_artifact_backed\"\n\t| \"retrieval_tool_unavailable\"\n\t| \"hard_constraint_rejected\"\n\t| \"missing_artifact_id\"\n\t| \"below_min_chars\";\n\nexport interface PromptEnforcementItemReport {\n\titemId: string;\n\ttoolCallId: string;\n\tmessageIndex: number;\n\tenforced: boolean;\n\taction?: \"artifact_stub\";\n\tartifactId?: string;\n\toriginalChars?: number;\n\tskipReason?: PromptEnforcementSkipReason;\n}\n\nexport interface PromptEnforcementReport {\n\tturnIndex: number;\n\titems: PromptEnforcementItemReport[];\n}\n\nexport interface EnforcePromptPolicyResult {\n\tmessages: AgentMessage[];\n\treport: PromptEnforcementReport;\n}\n\nfunction extractDetailsArtifactId(details: unknown): string | undefined {\n\tif (typeof details !== \"object\" || details === null) return undefined;\n\tconst artifactId = (details as { artifactId?: unknown }).artifactId;\n\treturn typeof artifactId === \"string\" ? artifactId : undefined;\n}\n\n/** True if legacy context-gc already packed this message this turn, or this module already stubbed it. */\nfunction isAlreadyStubbedOrPacked(details: unknown): boolean {\n\tif (typeof details !== \"object\" || details === null) return false;\n\tconst record = details as { promptPolicy?: { enforced?: unknown }; contextGc?: { packed?: unknown } };\n\treturn record.promptPolicy?.enforced === true || record.contextGc?.packed === true;\n}\n\nfunction toolResultText(message: ToolResultMessage): string {\n\tconst parts: string[] = [];\n\tfor (const part of message.content) {\n\t\tif (part.type === \"text\") parts.push(part.text);\n\t}\n\treturn parts.join(\"\\n\");\n}\n\nfunction buildStubText(toolName: string, originalChars: number, artifactId: string): string {\n\treturn `[content replaced by prompt-policy: originally ${originalChars} chars from a stale ${toolName} tool result. Retrieve the full output with artifact_retrieve using artifactId \"${artifactId}\".]`;\n}\n\nfunction skip(\n\titem: { itemId: string; toolCallId: string; messageIndex: number },\n\tskipReason: PromptEnforcementSkipReason,\n\textra?: { artifactId?: string; originalChars?: number },\n): PromptEnforcementItemReport {\n\treturn {\n\t\titemId: item.itemId,\n\t\ttoolCallId: item.toolCallId,\n\t\tmessageIndex: item.messageIndex,\n\t\tenforced: false,\n\t\tskipReason,\n\t\t...extra,\n\t};\n}\n\n/**\n * Apply the first enforcement pilot to `messages` (expected to be the provider-visible\n * array after existing context-gc has already run). Returns a new array only when at least\n * one item was actually stubbed; otherwise returns the same `messages` reference unchanged\n * (in particular, always true when `settings.enabled` is false). Never mutates `messages`\n * or any message object within it -- every stubbed entry is a fresh object.\n */\nexport function enforcePromptPolicy(\n\tmessages: AgentMessage[],\n\tshadowReport: PromptPolicyShadowReport,\n\tsettings: ContextPromptEnforcementSettings,\n): EnforcePromptPolicyResult {\n\tif (!settings.enabled) {\n\t\treturn { messages, report: { turnIndex: shadowReport.turnIndex, items: [] } };\n\t}\n\n\tconst recentCutoffIndex = Math.max(0, messages.length - settings.preserveRecentMessages);\n\tconst nextMessages = messages.slice();\n\tlet changed = false;\n\tconst items: PromptEnforcementItemReport[] = [];\n\n\tfor (const planItem of shadowReport.items) {\n\t\tconst message = messages[planItem.messageIndex];\n\t\tif (!message || message.role !== \"toolResult\" || message.toolCallId !== planItem.toolCallId) {\n\t\t\titems.push(skip(planItem, \"message_mismatch\"));\n\t\t\tcontinue;\n\t\t}\n\t\tif (planItem.messageIndex >= recentCutoffIndex) {\n\t\t\titems.push(skip(planItem, \"within_recent_window\"));\n\t\t\tcontinue;\n\t\t}\n\t\tif (message.isError) {\n\t\t\titems.push(skip(planItem, \"errored_tool_result\"));\n\t\t\tcontinue;\n\t\t}\n\t\tif (isAlreadyStubbedOrPacked(message.details)) {\n\t\t\titems.push(skip(planItem, \"already_stubbed_or_packed\"));\n\t\t\tcontinue;\n\t\t}\n\t\tif (!planItem.hasAvailableRetrievalPath) {\n\t\t\titems.push(skip(planItem, \"not_artifact_backed\"));\n\t\t\tcontinue;\n\t\t}\n\t\tif (!settings.retrievalToolAvailable) {\n\t\t\titems.push(skip(planItem, \"retrieval_tool_unavailable\"));\n\t\t\tcontinue;\n\t\t}\n\t\tif (planItem.hardConstraints.dropFromPrompt.length > 0) {\n\t\t\titems.push(skip(planItem, \"hard_constraint_rejected\"));\n\t\t\tcontinue;\n\t\t}\n\t\tconst artifactId = extractDetailsArtifactId(message.details);\n\t\tif (!artifactId) {\n\t\t\titems.push(skip(planItem, \"missing_artifact_id\"));\n\t\t\tcontinue;\n\t\t}\n\t\tconst originalChars = toolResultText(message).length;\n\t\tif (originalChars < settings.minChars) {\n\t\t\titems.push(skip(planItem, \"below_min_chars\", { artifactId, originalChars }));\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst existingDetails = typeof message.details === \"object\" && message.details !== null ? message.details : {};\n\t\tnextMessages[planItem.messageIndex] = {\n\t\t\t...message,\n\t\t\tcontent: [{ type: \"text\", text: buildStubText(message.toolName, originalChars, artifactId) }],\n\t\t\tdetails: {\n\t\t\t\t...existingDetails,\n\t\t\t\tpromptPolicy: {\n\t\t\t\t\tenforced: true,\n\t\t\t\t\taction: \"artifact_stub\",\n\t\t\t\t\tartifactId,\n\t\t\t\t\toriginalChars,\n\t\t\t\t\treason: \"stale_artifact_backed_tool_output\",\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\tchanged = true;\n\t\titems.push({\n\t\t\titemId: planItem.itemId,\n\t\t\ttoolCallId: planItem.toolCallId,\n\t\t\tmessageIndex: planItem.messageIndex,\n\t\t\tenforced: true,\n\t\t\taction: \"artifact_stub\",\n\t\t\tartifactId,\n\t\t\toriginalChars,\n\t\t});\n\t}\n\n\treturn {\n\t\tmessages: changed ? nextMessages : messages,\n\t\treport: { turnIndex: shadowReport.turnIndex, items },\n\t};\n}\n"]}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Observe-first shadow/planning layer, one step closer to prompt construction than
3
+ * context-audit.ts (Phase 1). This module re-shapes an already-computed `ContextAuditReport`
4
+ * into a deterministic per-item policy plan, and can correlate that plan against the
5
+ * legacy context-gc's actual packed records. It never enforces anything: `appliedAction` is
6
+ * a literal `"keep_raw"` on every item -- the type itself makes it impossible for this
7
+ * module to report having changed prompt behavior. Nothing here mutates messages, the
8
+ * transcript, or artifact references; it only reads an already-computed report.
9
+ *
10
+ * Single source of truth for feature/flag construction remains context-audit.ts
11
+ * (`buildPolicyFeatures`/`buildHardConstraintFlags`): this module reuses the hard-constraint
12
+ * codes already computed there rather than reconstructing them, so there is exactly one
13
+ * place that decides how a tool_output item's PolicyFeatures/HardConstraintFlags are built.
14
+ */
15
+ import type { ContextGcPackedRecord, ContextGcReport } from "../context-gc.ts";
16
+ import type { ContextAuditReport } from "./context-audit.ts";
17
+ import type { ContextEvidenceRef, ContextItemKind, ContextRetentionClass, ContextSource } from "./context-item.ts";
18
+ import type { RetentionAction } from "./context-retention.ts";
19
+ import type { PolicyHardConstraintCode } from "./policy-types.ts";
20
+ export interface PromptPolicyHardConstraints {
21
+ keepRaw: PolicyHardConstraintCode[];
22
+ packToArtifact: PolicyHardConstraintCode[];
23
+ dropFromPrompt: PolicyHardConstraintCode[];
24
+ summarize: PolicyHardConstraintCode[];
25
+ }
26
+ export interface PromptPolicyItemReport {
27
+ itemId: string;
28
+ kind: ContextItemKind;
29
+ retentionClass: ContextRetentionClass;
30
+ source: ContextSource;
31
+ toolCallId: string;
32
+ messageIndex: number;
33
+ primaryRefType: ContextEvidenceRef["type"] | undefined;
34
+ /**
35
+ * True only for a resolved artifact ref, never for a transcript ref -- the same
36
+ * fail-closed resolved-artifact-only rule context-audit.ts uses (a transcript ref is
37
+ * provenance, not a live retrieval mechanism; see that module's doc comment).
38
+ */
39
+ hasAvailableRetrievalPath: boolean;
40
+ /** Coarse, store-free eligibility from context-retention.ts (treats any ref as retrievable). */
41
+ allowedRetentionActions: RetentionAction[];
42
+ hardConstraints: PromptPolicyHardConstraints;
43
+ /**
44
+ * This shadow/planning pass never changes behavior: the applied action is always
45
+ * "keep_raw", regardless of what the hard-constraint/retention analysis above would
46
+ * otherwise allow. Typed as a literal so nothing here can ever report applying anything
47
+ * else.
48
+ */
49
+ appliedAction: "keep_raw";
50
+ }
51
+ export interface PromptPolicyShadowReport {
52
+ turnIndex: number;
53
+ items: PromptPolicyItemReport[];
54
+ }
55
+ /**
56
+ * Deterministic re-shaping of an audit report into the shadow policy plan shape. Pure: no
57
+ * I/O, no mutation, given the same audit report this always returns an equal result.
58
+ */
59
+ export declare function planPromptPolicy(auditReport: ContextAuditReport): PromptPolicyShadowReport;
60
+ export interface PromptPolicyGcCorrelationEntry {
61
+ itemId: string;
62
+ toolCallId: string;
63
+ /** True if the legacy context-gc pass actually packed this item's tool result this turn. */
64
+ actuallyPackedByLegacyGc: boolean;
65
+ gcPackReason?: ContextGcPackedRecord["reason"];
66
+ /** True if the shadow plan's pack_to_artifact hard constraints did not reject packing. */
67
+ policyWouldAllowPack: boolean;
68
+ /** True if the shadow plan's drop_from_prompt hard constraints did not reject dropping. */
69
+ policyWouldAllowDrop: boolean;
70
+ }
71
+ export interface PromptPolicyGcCorrelationReport {
72
+ turnIndex: number;
73
+ entries: PromptPolicyGcCorrelationEntry[];
74
+ }
75
+ /**
76
+ * Report-only correlation between the shadow plan and what the legacy context-gc pass
77
+ * actually did this turn. Does not influence context-gc in any way -- it runs after gc has
78
+ * already produced its report, purely to observe what each side did/would do.
79
+ *
80
+ * Deliberately does not derive an "agrees with legacy gc" boolean: legacy context-gc
81
+ * "packing" summarizes/stubs a tool result in place (provider-visible content shrinks in
82
+ * place), while the policy action `pack_to_artifact` means artifact-backed capture and
83
+ * out-of-band retrieval -- a different operation with different semantics, not a
84
+ * calibrated equivalent. Collapsing them into one "agreement" boolean would overclaim
85
+ * semantic agreement between the two and risk a later enforcement slice mistaking this
86
+ * observe-only diagnostic for a calibrated authority. The raw booleans below are reported
87
+ * as-is; comparing them is left to the reader.
88
+ */
89
+ export declare function correlateWithContextGc(shadowReport: PromptPolicyShadowReport, gcReport: ContextGcReport): PromptPolicyGcCorrelationReport;
90
+ //# sourceMappingURL=context-prompt-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-prompt-policy.d.ts","sourceRoot":"","sources":["../../../src/core/context/context-prompt-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACnH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAElE,MAAM,WAAW,2BAA2B;IAC3C,OAAO,EAAE,wBAAwB,EAAE,CAAC;IACpC,cAAc,EAAE,wBAAwB,EAAE,CAAC;IAC3C,cAAc,EAAE,wBAAwB,EAAE,CAAC;IAC3C,SAAS,EAAE,wBAAwB,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,sBAAsB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,eAAe,CAAC;IACtB,cAAc,EAAE,qBAAqB,CAAC;IACtC,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,kBAAkB,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IACvD;;;;OAIG;IACH,yBAAyB,EAAE,OAAO,CAAC;IACnC,gGAAgG;IAChG,uBAAuB,EAAE,eAAe,EAAE,CAAC;IAC3C,eAAe,EAAE,2BAA2B,CAAC;IAC7C;;;;;OAKG;IACH,aAAa,EAAE,UAAU,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,sBAAsB,EAAE,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,kBAAkB,GAAG,wBAAwB,CAsB1F;AAED,MAAM,WAAW,8BAA8B;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,wBAAwB,EAAE,OAAO,CAAC;IAClC,YAAY,CAAC,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC/C,0FAA0F;IAC1F,oBAAoB,EAAE,OAAO,CAAC;IAC9B,2FAA2F;IAC3F,oBAAoB,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,+BAA+B;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,8BAA8B,EAAE,CAAC;CAC1C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACrC,YAAY,EAAE,wBAAwB,EACtC,QAAQ,EAAE,eAAe,GACvB,+BAA+B,CAiBjC","sourcesContent":["/**\n * Observe-first shadow/planning layer, one step closer to prompt construction than\n * context-audit.ts (Phase 1). This module re-shapes an already-computed `ContextAuditReport`\n * into a deterministic per-item policy plan, and can correlate that plan against the\n * legacy context-gc's actual packed records. It never enforces anything: `appliedAction` is\n * a literal `\"keep_raw\"` on every item -- the type itself makes it impossible for this\n * module to report having changed prompt behavior. Nothing here mutates messages, the\n * transcript, or artifact references; it only reads an already-computed report.\n *\n * Single source of truth for feature/flag construction remains context-audit.ts\n * (`buildPolicyFeatures`/`buildHardConstraintFlags`): this module reuses the hard-constraint\n * codes already computed there rather than reconstructing them, so there is exactly one\n * place that decides how a tool_output item's PolicyFeatures/HardConstraintFlags are built.\n */\n\nimport type { ContextGcPackedRecord, ContextGcReport } from \"../context-gc.ts\";\nimport type { ContextAuditReport } from \"./context-audit.ts\";\nimport type { ContextEvidenceRef, ContextItemKind, ContextRetentionClass, ContextSource } from \"./context-item.ts\";\nimport type { RetentionAction } from \"./context-retention.ts\";\nimport type { PolicyHardConstraintCode } from \"./policy-types.ts\";\n\nexport interface PromptPolicyHardConstraints {\n\tkeepRaw: PolicyHardConstraintCode[];\n\tpackToArtifact: PolicyHardConstraintCode[];\n\tdropFromPrompt: PolicyHardConstraintCode[];\n\tsummarize: PolicyHardConstraintCode[];\n}\n\nexport interface PromptPolicyItemReport {\n\titemId: string;\n\tkind: ContextItemKind;\n\tretentionClass: ContextRetentionClass;\n\tsource: ContextSource;\n\ttoolCallId: string;\n\tmessageIndex: number;\n\tprimaryRefType: ContextEvidenceRef[\"type\"] | undefined;\n\t/**\n\t * True only for a resolved artifact ref, never for a transcript ref -- the same\n\t * fail-closed resolved-artifact-only rule context-audit.ts uses (a transcript ref is\n\t * provenance, not a live retrieval mechanism; see that module's doc comment).\n\t */\n\thasAvailableRetrievalPath: boolean;\n\t/** Coarse, store-free eligibility from context-retention.ts (treats any ref as retrievable). */\n\tallowedRetentionActions: RetentionAction[];\n\thardConstraints: PromptPolicyHardConstraints;\n\t/**\n\t * This shadow/planning pass never changes behavior: the applied action is always\n\t * \"keep_raw\", regardless of what the hard-constraint/retention analysis above would\n\t * otherwise allow. Typed as a literal so nothing here can ever report applying anything\n\t * else.\n\t */\n\tappliedAction: \"keep_raw\";\n}\n\nexport interface PromptPolicyShadowReport {\n\tturnIndex: number;\n\titems: PromptPolicyItemReport[];\n}\n\n/**\n * Deterministic re-shaping of an audit report into the shadow policy plan shape. Pure: no\n * I/O, no mutation, given the same audit report this always returns an equal result.\n */\nexport function planPromptPolicy(auditReport: ContextAuditReport): PromptPolicyShadowReport {\n\treturn {\n\t\tturnIndex: auditReport.turnIndex,\n\t\titems: auditReport.items.map((entry) => ({\n\t\t\titemId: entry.item.id,\n\t\t\tkind: entry.item.kind,\n\t\t\tretentionClass: entry.item.retentionClass,\n\t\t\tsource: entry.item.source,\n\t\t\ttoolCallId: entry.toolCallId,\n\t\t\tmessageIndex: entry.messageIndex,\n\t\t\tprimaryRefType: entry.item.primaryRef?.type,\n\t\t\thasAvailableRetrievalPath: entry.item.primaryRef?.type === \"artifact\",\n\t\t\tallowedRetentionActions: entry.retention.allowedActions,\n\t\t\thardConstraints: {\n\t\t\t\tkeepRaw: entry.keepRawHardConstraints,\n\t\t\t\tpackToArtifact: entry.packToArtifactHardConstraints,\n\t\t\t\tdropFromPrompt: entry.dropFromPromptHardConstraints,\n\t\t\t\tsummarize: entry.summarizeHardConstraints,\n\t\t\t},\n\t\t\tappliedAction: \"keep_raw\",\n\t\t})),\n\t};\n}\n\nexport interface PromptPolicyGcCorrelationEntry {\n\titemId: string;\n\ttoolCallId: string;\n\t/** True if the legacy context-gc pass actually packed this item's tool result this turn. */\n\tactuallyPackedByLegacyGc: boolean;\n\tgcPackReason?: ContextGcPackedRecord[\"reason\"];\n\t/** True if the shadow plan's pack_to_artifact hard constraints did not reject packing. */\n\tpolicyWouldAllowPack: boolean;\n\t/** True if the shadow plan's drop_from_prompt hard constraints did not reject dropping. */\n\tpolicyWouldAllowDrop: boolean;\n}\n\nexport interface PromptPolicyGcCorrelationReport {\n\tturnIndex: number;\n\tentries: PromptPolicyGcCorrelationEntry[];\n}\n\n/**\n * Report-only correlation between the shadow plan and what the legacy context-gc pass\n * actually did this turn. Does not influence context-gc in any way -- it runs after gc has\n * already produced its report, purely to observe what each side did/would do.\n *\n * Deliberately does not derive an \"agrees with legacy gc\" boolean: legacy context-gc\n * \"packing\" summarizes/stubs a tool result in place (provider-visible content shrinks in\n * place), while the policy action `pack_to_artifact` means artifact-backed capture and\n * out-of-band retrieval -- a different operation with different semantics, not a\n * calibrated equivalent. Collapsing them into one \"agreement\" boolean would overclaim\n * semantic agreement between the two and risk a later enforcement slice mistaking this\n * observe-only diagnostic for a calibrated authority. The raw booleans below are reported\n * as-is; comparing them is left to the reader.\n */\nexport function correlateWithContextGc(\n\tshadowReport: PromptPolicyShadowReport,\n\tgcReport: ContextGcReport,\n): PromptPolicyGcCorrelationReport {\n\tconst packedByToolCallId = new Map<string, ContextGcPackedRecord>();\n\tfor (const record of gcReport.records) packedByToolCallId.set(record.toolCallId, record);\n\n\tconst entries: PromptPolicyGcCorrelationEntry[] = shadowReport.items.map((item) => {\n\t\tconst gcRecord = packedByToolCallId.get(item.toolCallId);\n\t\treturn {\n\t\t\titemId: item.itemId,\n\t\t\ttoolCallId: item.toolCallId,\n\t\t\tactuallyPackedByLegacyGc: gcRecord !== undefined,\n\t\t\tgcPackReason: gcRecord?.reason,\n\t\t\tpolicyWouldAllowPack: item.hardConstraints.packToArtifact.length === 0,\n\t\t\tpolicyWouldAllowDrop: item.hardConstraints.dropFromPrompt.length === 0,\n\t\t};\n\t});\n\n\treturn { turnIndex: shadowReport.turnIndex, entries };\n}\n"]}