agentfootprint 2.14.5 → 3.1.0

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 (314) hide show
  1. package/README.md +1 -1
  2. package/dist/cache/CacheDecisionSubflow.js +13 -16
  3. package/dist/cache/CacheDecisionSubflow.js.map +1 -1
  4. package/dist/cache/CacheGateDecider.js +18 -3
  5. package/dist/cache/CacheGateDecider.js.map +1 -1
  6. package/dist/cache/cacheRecorder.js +12 -3
  7. package/dist/cache/cacheRecorder.js.map +1 -1
  8. package/dist/conventions.js +155 -4
  9. package/dist/conventions.js.map +1 -1
  10. package/dist/core/Agent.js +115 -32
  11. package/dist/core/Agent.js.map +1 -1
  12. package/dist/core/LLMCall.js +213 -41
  13. package/dist/core/LLMCall.js.map +1 -1
  14. package/dist/core/RunnerBase.js +187 -0
  15. package/dist/core/RunnerBase.js.map +1 -1
  16. package/dist/core/agent/buildAgentChart.js +127 -48
  17. package/dist/core/agent/buildAgentChart.js.map +1 -1
  18. package/dist/core/agent/buildAgentMessageApiChart.js +201 -0
  19. package/dist/core/agent/buildAgentMessageApiChart.js.map +1 -0
  20. package/dist/core/agent/buildCacheSubflow.js +62 -0
  21. package/dist/core/agent/buildCacheSubflow.js.map +1 -0
  22. package/dist/core/agent/buildDynamicAgentChart.js +364 -0
  23. package/dist/core/agent/buildDynamicAgentChart.js.map +1 -0
  24. package/dist/core/agent/buildMessageApiChart.js +154 -0
  25. package/dist/core/agent/buildMessageApiChart.js.map +1 -0
  26. package/dist/core/agent/stages/callLLM.js +11 -0
  27. package/dist/core/agent/stages/callLLM.js.map +1 -1
  28. package/dist/core/agent/stages/reliabilityExecution.js +64 -9
  29. package/dist/core/agent/stages/reliabilityExecution.js.map +1 -1
  30. package/dist/core/humanizeLLMError.js +66 -0
  31. package/dist/core/humanizeLLMError.js.map +1 -0
  32. package/dist/core/runner.js +4 -3
  33. package/dist/core/runner.js.map +1 -1
  34. package/dist/core/slots/buildMessagesSlot.js +2 -2
  35. package/dist/core/slots/buildMessagesSlot.js.map +1 -1
  36. package/dist/core/slots/buildSystemPromptSlot.js +1 -1
  37. package/dist/core/slots/buildSystemPromptSlot.js.map +1 -1
  38. package/dist/core/slots/buildThinkingSubflow.js +1 -1
  39. package/dist/core/slots/buildThinkingSubflow.js.map +1 -1
  40. package/dist/core/slots/buildToolsSlot.js +3 -1
  41. package/dist/core/slots/buildToolsSlot.js.map +1 -1
  42. package/dist/core/translator.js +32 -0
  43. package/dist/core/translator.js.map +1 -0
  44. package/dist/core-flow/Conditional.js +72 -10
  45. package/dist/core-flow/Conditional.js.map +1 -1
  46. package/dist/core-flow/Loop.js +59 -16
  47. package/dist/core-flow/Loop.js.map +1 -1
  48. package/dist/core-flow/Parallel.js +239 -92
  49. package/dist/core-flow/Parallel.js.map +1 -1
  50. package/dist/core-flow/Sequence.js +50 -8
  51. package/dist/core-flow/Sequence.js.map +1 -1
  52. package/dist/esm/cache/CacheDecisionSubflow.js +11 -15
  53. package/dist/esm/cache/CacheDecisionSubflow.js.map +1 -1
  54. package/dist/esm/cache/CacheGateDecider.js +18 -3
  55. package/dist/esm/cache/CacheGateDecider.js.map +1 -1
  56. package/dist/esm/cache/cacheRecorder.js +12 -3
  57. package/dist/esm/cache/cacheRecorder.js.map +1 -1
  58. package/dist/esm/conventions.js +151 -3
  59. package/dist/esm/conventions.js.map +1 -1
  60. package/dist/esm/core/Agent.js +116 -33
  61. package/dist/esm/core/Agent.js.map +1 -1
  62. package/dist/esm/core/LLMCall.js +213 -41
  63. package/dist/esm/core/LLMCall.js.map +1 -1
  64. package/dist/esm/core/RunnerBase.js +187 -0
  65. package/dist/esm/core/RunnerBase.js.map +1 -1
  66. package/dist/esm/core/agent/buildAgentChart.js +128 -49
  67. package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
  68. package/dist/esm/core/agent/buildAgentMessageApiChart.js +197 -0
  69. package/dist/esm/core/agent/buildAgentMessageApiChart.js.map +1 -0
  70. package/dist/esm/core/agent/buildCacheSubflow.js +58 -0
  71. package/dist/esm/core/agent/buildCacheSubflow.js.map +1 -0
  72. package/dist/esm/core/agent/buildDynamicAgentChart.js +360 -0
  73. package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -0
  74. package/dist/esm/core/agent/buildMessageApiChart.js +150 -0
  75. package/dist/esm/core/agent/buildMessageApiChart.js.map +1 -0
  76. package/dist/esm/core/agent/stages/callLLM.js +11 -0
  77. package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
  78. package/dist/esm/core/agent/stages/reliabilityExecution.js +64 -9
  79. package/dist/esm/core/agent/stages/reliabilityExecution.js.map +1 -1
  80. package/dist/esm/core/humanizeLLMError.js +61 -0
  81. package/dist/esm/core/humanizeLLMError.js.map +1 -0
  82. package/dist/esm/core/runner.js +4 -3
  83. package/dist/esm/core/runner.js.map +1 -1
  84. package/dist/esm/core/slots/buildMessagesSlot.js +2 -2
  85. package/dist/esm/core/slots/buildMessagesSlot.js.map +1 -1
  86. package/dist/esm/core/slots/buildSystemPromptSlot.js +1 -1
  87. package/dist/esm/core/slots/buildSystemPromptSlot.js.map +1 -1
  88. package/dist/esm/core/slots/buildThinkingSubflow.js +1 -1
  89. package/dist/esm/core/slots/buildThinkingSubflow.js.map +1 -1
  90. package/dist/esm/core/slots/buildToolsSlot.js +3 -1
  91. package/dist/esm/core/slots/buildToolsSlot.js.map +1 -1
  92. package/dist/esm/core/translator.js +31 -0
  93. package/dist/esm/core/translator.js.map +1 -0
  94. package/dist/esm/core-flow/Conditional.js +72 -10
  95. package/dist/esm/core-flow/Conditional.js.map +1 -1
  96. package/dist/esm/core-flow/Loop.js +59 -16
  97. package/dist/esm/core-flow/Loop.js.map +1 -1
  98. package/dist/esm/core-flow/Parallel.js +240 -93
  99. package/dist/esm/core-flow/Parallel.js.map +1 -1
  100. package/dist/esm/core-flow/Sequence.js +50 -8
  101. package/dist/esm/core-flow/Sequence.js.map +1 -1
  102. package/dist/esm/events/registry.js +10 -0
  103. package/dist/esm/events/registry.js.map +1 -1
  104. package/dist/esm/index.js +22 -1
  105. package/dist/esm/index.js.map +1 -1
  106. package/dist/esm/lib/injection-engine/buildInjectionEngineSubflow.js +16 -9
  107. package/dist/esm/lib/injection-engine/buildInjectionEngineSubflow.js.map +1 -1
  108. package/dist/esm/memory/causal/snapshotPipeline.js +6 -2
  109. package/dist/esm/memory/causal/snapshotPipeline.js.map +1 -1
  110. package/dist/esm/memory/pipeline/auto.js +2 -2
  111. package/dist/esm/memory/pipeline/auto.js.map +1 -1
  112. package/dist/esm/memory/pipeline/default.js +4 -2
  113. package/dist/esm/memory/pipeline/default.js.map +1 -1
  114. package/dist/esm/memory/pipeline/ephemeral.js +3 -1
  115. package/dist/esm/memory/pipeline/ephemeral.js.map +1 -1
  116. package/dist/esm/memory/pipeline/fact.js +4 -2
  117. package/dist/esm/memory/pipeline/fact.js.map +1 -1
  118. package/dist/esm/memory/pipeline/narrative.js +4 -2
  119. package/dist/esm/memory/pipeline/narrative.js.map +1 -1
  120. package/dist/esm/memory/pipeline/semantic.js +2 -2
  121. package/dist/esm/memory/pipeline/semantic.js.map +1 -1
  122. package/dist/esm/observe.js +1 -1
  123. package/dist/esm/observe.js.map +1 -1
  124. package/dist/esm/patterns/MapReduce.js +5 -5
  125. package/dist/esm/patterns/MapReduce.js.map +1 -1
  126. package/dist/esm/patterns/Swarm.js +1 -1
  127. package/dist/esm/patterns/Swarm.js.map +1 -1
  128. package/dist/esm/recorders/core/ContextEvaluatedRecorder.js +31 -0
  129. package/dist/esm/recorders/core/ContextEvaluatedRecorder.js.map +1 -0
  130. package/dist/esm/recorders/core/ContextRecorder.js +12 -14
  131. package/dist/esm/recorders/core/ContextRecorder.js.map +1 -1
  132. package/dist/esm/recorders/core/ErrorBridge.js +59 -0
  133. package/dist/esm/recorders/core/ErrorBridge.js.map +1 -0
  134. package/dist/esm/recorders/core/ReliabilityRecorder.js +29 -0
  135. package/dist/esm/recorders/core/ReliabilityRecorder.js.map +1 -0
  136. package/dist/esm/recorders/observability/BoundaryRecorder.js +338 -36
  137. package/dist/esm/recorders/observability/BoundaryRecorder.js.map +1 -1
  138. package/dist/esm/recorders/observability/FlowchartRecorder.js +10 -0
  139. package/dist/esm/recorders/observability/FlowchartRecorder.js.map +1 -1
  140. package/dist/esm/recorders/observability/LiveStateRecorder.js +120 -21
  141. package/dist/esm/recorders/observability/LiveStateRecorder.js.map +1 -1
  142. package/dist/esm/recorders/observability/RunStepRecorder.js +652 -0
  143. package/dist/esm/recorders/observability/RunStepRecorder.js.map +1 -0
  144. package/dist/esm/recorders/observability/commentary/commentaryTemplates.js +1 -0
  145. package/dist/esm/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
  146. package/dist/esm/recorders/observability/internal/ActorArrowClassifier.js +34 -0
  147. package/dist/esm/recorders/observability/internal/ActorArrowClassifier.js.map +1 -0
  148. package/dist/esm/recorders/observability/internal/CandidateAnswerBuffer.js +32 -0
  149. package/dist/esm/recorders/observability/internal/CandidateAnswerBuffer.js.map +1 -0
  150. package/dist/esm/recorders/observability/internal/ForkTracker.js +84 -0
  151. package/dist/esm/recorders/observability/internal/ForkTracker.js.map +1 -0
  152. package/dist/esm/recorders/observability/internal/RootInferrer.js +114 -0
  153. package/dist/esm/recorders/observability/internal/RootInferrer.js.map +1 -0
  154. package/dist/esm/recorders/observability/internal/SequenceSiblingTracker.js +31 -0
  155. package/dist/esm/recorders/observability/internal/SequenceSiblingTracker.js.map +1 -0
  156. package/dist/esm/recorders/observability/observeRunId.js +21 -0
  157. package/dist/esm/recorders/observability/observeRunId.js.map +1 -0
  158. package/dist/esm/reliability/buildReliabilityGateChart.js +11 -5
  159. package/dist/esm/reliability/buildReliabilityGateChart.js.map +1 -1
  160. package/dist/events/registry.js +10 -0
  161. package/dist/events/registry.js.map +1 -1
  162. package/dist/index.js +30 -3
  163. package/dist/index.js.map +1 -1
  164. package/dist/lib/injection-engine/buildInjectionEngineSubflow.js +16 -9
  165. package/dist/lib/injection-engine/buildInjectionEngineSubflow.js.map +1 -1
  166. package/dist/memory/causal/snapshotPipeline.js +6 -2
  167. package/dist/memory/causal/snapshotPipeline.js.map +1 -1
  168. package/dist/memory/pipeline/auto.js +2 -2
  169. package/dist/memory/pipeline/auto.js.map +1 -1
  170. package/dist/memory/pipeline/default.js +4 -2
  171. package/dist/memory/pipeline/default.js.map +1 -1
  172. package/dist/memory/pipeline/ephemeral.js +3 -1
  173. package/dist/memory/pipeline/ephemeral.js.map +1 -1
  174. package/dist/memory/pipeline/fact.js +4 -2
  175. package/dist/memory/pipeline/fact.js.map +1 -1
  176. package/dist/memory/pipeline/narrative.js +4 -2
  177. package/dist/memory/pipeline/narrative.js.map +1 -1
  178. package/dist/memory/pipeline/semantic.js +2 -2
  179. package/dist/memory/pipeline/semantic.js.map +1 -1
  180. package/dist/observe.js +1 -1
  181. package/dist/observe.js.map +1 -1
  182. package/dist/patterns/MapReduce.js +5 -5
  183. package/dist/patterns/MapReduce.js.map +1 -1
  184. package/dist/patterns/Swarm.js +1 -1
  185. package/dist/patterns/Swarm.js.map +1 -1
  186. package/dist/recorders/core/ContextEvaluatedRecorder.js +35 -0
  187. package/dist/recorders/core/ContextEvaluatedRecorder.js.map +1 -0
  188. package/dist/recorders/core/ContextRecorder.js +11 -13
  189. package/dist/recorders/core/ContextRecorder.js.map +1 -1
  190. package/dist/recorders/core/ErrorBridge.js +64 -0
  191. package/dist/recorders/core/ErrorBridge.js.map +1 -0
  192. package/dist/recorders/core/ReliabilityRecorder.js +33 -0
  193. package/dist/recorders/core/ReliabilityRecorder.js.map +1 -0
  194. package/dist/recorders/observability/BoundaryRecorder.js +337 -35
  195. package/dist/recorders/observability/BoundaryRecorder.js.map +1 -1
  196. package/dist/recorders/observability/FlowchartRecorder.js +10 -0
  197. package/dist/recorders/observability/FlowchartRecorder.js.map +1 -1
  198. package/dist/recorders/observability/LiveStateRecorder.js +119 -20
  199. package/dist/recorders/observability/LiveStateRecorder.js.map +1 -1
  200. package/dist/recorders/observability/RunStepRecorder.js +658 -0
  201. package/dist/recorders/observability/RunStepRecorder.js.map +1 -0
  202. package/dist/recorders/observability/commentary/commentaryTemplates.js +1 -0
  203. package/dist/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
  204. package/dist/recorders/observability/internal/ActorArrowClassifier.js +38 -0
  205. package/dist/recorders/observability/internal/ActorArrowClassifier.js.map +1 -0
  206. package/dist/recorders/observability/internal/CandidateAnswerBuffer.js +36 -0
  207. package/dist/recorders/observability/internal/CandidateAnswerBuffer.js.map +1 -0
  208. package/dist/recorders/observability/internal/ForkTracker.js +88 -0
  209. package/dist/recorders/observability/internal/ForkTracker.js.map +1 -0
  210. package/dist/recorders/observability/internal/RootInferrer.js +118 -0
  211. package/dist/recorders/observability/internal/RootInferrer.js.map +1 -0
  212. package/dist/recorders/observability/internal/SequenceSiblingTracker.js +35 -0
  213. package/dist/recorders/observability/internal/SequenceSiblingTracker.js.map +1 -0
  214. package/dist/recorders/observability/observeRunId.js +25 -0
  215. package/dist/recorders/observability/observeRunId.js.map +1 -0
  216. package/dist/reliability/buildReliabilityGateChart.js +11 -5
  217. package/dist/reliability/buildReliabilityGateChart.js.map +1 -1
  218. package/dist/types/cache/CacheDecisionSubflow.d.ts +7 -10
  219. package/dist/types/cache/CacheDecisionSubflow.d.ts.map +1 -1
  220. package/dist/types/cache/CacheGateDecider.d.ts +16 -2
  221. package/dist/types/cache/CacheGateDecider.d.ts.map +1 -1
  222. package/dist/types/cache/cacheRecorder.d.ts.map +1 -1
  223. package/dist/types/conventions.d.ts +101 -1
  224. package/dist/types/conventions.d.ts.map +1 -1
  225. package/dist/types/core/Agent.d.ts +28 -18
  226. package/dist/types/core/Agent.d.ts.map +1 -1
  227. package/dist/types/core/LLMCall.d.ts +73 -11
  228. package/dist/types/core/LLMCall.d.ts.map +1 -1
  229. package/dist/types/core/RunnerBase.d.ts +136 -4
  230. package/dist/types/core/RunnerBase.d.ts.map +1 -1
  231. package/dist/types/core/agent/buildAgentChart.d.ts +38 -19
  232. package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
  233. package/dist/types/core/agent/buildAgentMessageApiChart.d.ts +41 -0
  234. package/dist/types/core/agent/buildAgentMessageApiChart.d.ts.map +1 -0
  235. package/dist/types/core/agent/buildCacheSubflow.d.ts +36 -0
  236. package/dist/types/core/agent/buildCacheSubflow.d.ts.map +1 -0
  237. package/dist/types/core/agent/buildDynamicAgentChart.d.ts +57 -0
  238. package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -0
  239. package/dist/types/core/agent/buildMessageApiChart.d.ts +48 -0
  240. package/dist/types/core/agent/buildMessageApiChart.d.ts.map +1 -0
  241. package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
  242. package/dist/types/core/agent/stages/reliabilityExecution.d.ts.map +1 -1
  243. package/dist/types/core/agent/types.d.ts +96 -0
  244. package/dist/types/core/agent/types.d.ts.map +1 -1
  245. package/dist/types/core/humanizeLLMError.d.ts +24 -0
  246. package/dist/types/core/humanizeLLMError.d.ts.map +1 -0
  247. package/dist/types/core/runner.d.ts +51 -5
  248. package/dist/types/core/runner.d.ts.map +1 -1
  249. package/dist/types/core/slots/buildMessagesSlot.d.ts.map +1 -1
  250. package/dist/types/core/slots/buildSystemPromptSlot.d.ts.map +1 -1
  251. package/dist/types/core/slots/buildThinkingSubflow.d.ts.map +1 -1
  252. package/dist/types/core/slots/buildToolsSlot.d.ts.map +1 -1
  253. package/dist/types/core/translator.d.ts +95 -0
  254. package/dist/types/core/translator.d.ts.map +1 -0
  255. package/dist/types/core-flow/Conditional.d.ts +48 -4
  256. package/dist/types/core-flow/Conditional.d.ts.map +1 -1
  257. package/dist/types/core-flow/Loop.d.ts +42 -3
  258. package/dist/types/core-flow/Loop.d.ts.map +1 -1
  259. package/dist/types/core-flow/Parallel.d.ts +99 -4
  260. package/dist/types/core-flow/Parallel.d.ts.map +1 -1
  261. package/dist/types/core-flow/Sequence.d.ts +49 -3
  262. package/dist/types/core-flow/Sequence.d.ts.map +1 -1
  263. package/dist/types/events/payloads.d.ts +99 -1
  264. package/dist/types/events/payloads.d.ts.map +1 -1
  265. package/dist/types/events/registry.d.ts +11 -1
  266. package/dist/types/events/registry.d.ts.map +1 -1
  267. package/dist/types/index.d.ts +8 -3
  268. package/dist/types/index.d.ts.map +1 -1
  269. package/dist/types/lib/injection-engine/buildInjectionEngineSubflow.d.ts.map +1 -1
  270. package/dist/types/memory/causal/snapshotPipeline.d.ts.map +1 -1
  271. package/dist/types/memory/pipeline/auto.d.ts.map +1 -1
  272. package/dist/types/memory/pipeline/default.d.ts.map +1 -1
  273. package/dist/types/memory/pipeline/ephemeral.d.ts.map +1 -1
  274. package/dist/types/memory/pipeline/fact.d.ts.map +1 -1
  275. package/dist/types/memory/pipeline/narrative.d.ts.map +1 -1
  276. package/dist/types/memory/pipeline/semantic.d.ts.map +1 -1
  277. package/dist/types/observe.d.ts +2 -2
  278. package/dist/types/observe.d.ts.map +1 -1
  279. package/dist/types/recorders/core/ContextEvaluatedRecorder.d.ts +24 -0
  280. package/dist/types/recorders/core/ContextEvaluatedRecorder.d.ts.map +1 -0
  281. package/dist/types/recorders/core/ContextRecorder.d.ts +0 -2
  282. package/dist/types/recorders/core/ContextRecorder.d.ts.map +1 -1
  283. package/dist/types/recorders/core/ErrorBridge.d.ts +39 -0
  284. package/dist/types/recorders/core/ErrorBridge.d.ts.map +1 -0
  285. package/dist/types/recorders/core/ReliabilityRecorder.d.ts +25 -0
  286. package/dist/types/recorders/core/ReliabilityRecorder.d.ts.map +1 -0
  287. package/dist/types/recorders/observability/BoundaryRecorder.d.ts +167 -6
  288. package/dist/types/recorders/observability/BoundaryRecorder.d.ts.map +1 -1
  289. package/dist/types/recorders/observability/FlowchartRecorder.d.ts.map +1 -1
  290. package/dist/types/recorders/observability/LiveStateRecorder.d.ts +42 -6
  291. package/dist/types/recorders/observability/LiveStateRecorder.d.ts.map +1 -1
  292. package/dist/types/recorders/observability/RunStepRecorder.d.ts +232 -0
  293. package/dist/types/recorders/observability/RunStepRecorder.d.ts.map +1 -0
  294. package/dist/types/recorders/observability/commentary/commentaryTemplates.d.ts.map +1 -1
  295. package/dist/types/recorders/observability/internal/ActorArrowClassifier.d.ts +26 -0
  296. package/dist/types/recorders/observability/internal/ActorArrowClassifier.d.ts.map +1 -0
  297. package/dist/types/recorders/observability/internal/CandidateAnswerBuffer.d.ts +29 -0
  298. package/dist/types/recorders/observability/internal/CandidateAnswerBuffer.d.ts.map +1 -0
  299. package/dist/types/recorders/observability/internal/ForkTracker.d.ts +61 -0
  300. package/dist/types/recorders/observability/internal/ForkTracker.d.ts.map +1 -0
  301. package/dist/types/recorders/observability/internal/RootInferrer.d.ts +52 -0
  302. package/dist/types/recorders/observability/internal/RootInferrer.d.ts.map +1 -0
  303. package/dist/types/recorders/observability/internal/SequenceSiblingTracker.d.ts +25 -0
  304. package/dist/types/recorders/observability/internal/SequenceSiblingTracker.d.ts.map +1 -0
  305. package/dist/types/recorders/observability/observeRunId.d.ts +37 -0
  306. package/dist/types/recorders/observability/observeRunId.d.ts.map +1 -0
  307. package/dist/types/reliability/buildReliabilityGateChart.d.ts.map +1 -1
  308. package/package.json +6 -5
  309. package/dist/core/agent/stages/iterationStart.js +0 -24
  310. package/dist/core/agent/stages/iterationStart.js.map +0 -1
  311. package/dist/esm/core/agent/stages/iterationStart.js +0 -20
  312. package/dist/esm/core/agent/stages/iterationStart.js.map +0 -1
  313. package/dist/types/core/agent/stages/iterationStart.d.ts +0 -16
  314. package/dist/types/core/agent/stages/iterationStart.d.ts.map +0 -1
@@ -80,6 +80,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
80
80
  exports.BoundaryRecorder = exports.boundaryRecorder = void 0;
81
81
  const trace_1 = require("footprintjs/trace");
82
82
  const conventions_js_1 = require("../../conventions.js");
83
+ const observeRunId_js_1 = require("./observeRunId.js");
83
84
  /** Closed set of routing/wrapper subflow IDs that are pure plumbing.
84
85
  * Slot subflows (`sf-system-prompt` / `sf-messages` / `sf-tools`) are
85
86
  * NOT in this set — they're real context-engineering moments.
@@ -93,15 +94,21 @@ const conventions_js_1 = require("../../conventions.js");
93
94
  const AGENT_INTERNAL_LOCAL_IDS = new Set([
94
95
  // Subflow ids (`sf-*`)
95
96
  conventions_js_1.SUBFLOW_IDS.INJECTION_ENGINE, // collects activeInjections; pure plumbing
97
+ conventions_js_1.SUBFLOW_IDS.LLM_CALL, // LLMCall's inner invocation wrapper — the meaningful step is the call-llm stage INSIDE; the wrapper itself is a chart-shape container
96
98
  conventions_js_1.SUBFLOW_IDS.ROUTE,
97
99
  conventions_js_1.SUBFLOW_IDS.TOOL_CALLS,
98
100
  conventions_js_1.SUBFLOW_IDS.FINAL,
99
101
  conventions_js_1.SUBFLOW_IDS.MERGE,
102
+ conventions_js_1.SUBFLOW_IDS.CACHE, // v2.14 — per-turn cache decision wrapper; pure plumbing
100
103
  conventions_js_1.SUBFLOW_IDS.CACHE_DECISION, // v2.6 — emits cacheMarkers; not a user step
101
104
  conventions_js_1.SUBFLOW_IDS.THINKING, // v2.14 — normalize result lands on parent LLM step
102
105
  // Decider stage ids (the same set is used to filter `decision.branch`
103
106
  // events whose deciding stage is plumbing rather than user-facing).
104
107
  conventions_js_1.STAGE_IDS.CACHE_GATE, // v2.6 — apply-markers / no-markers routing; plumbing
108
+ // LLMCall outer wrapper stage + post-invocation marker — pure chart
109
+ // shape, not user-meaningful steps.
110
+ conventions_js_1.STAGE_IDS.CLIENT,
111
+ conventions_js_1.STAGE_IDS.EXTRACT_FINAL,
105
112
  ]);
106
113
  // Constructed as a set on a separate line so we can extend with the
107
114
  // thinking-handler inner-subflow ids below without the literal set
@@ -127,6 +134,53 @@ function isAgentInternalId(localId) {
127
134
  }
128
135
  return false;
129
136
  }
137
+ function toBoundaryLabel(e) {
138
+ if (e.type === 'subflow.entry') {
139
+ return {
140
+ type: 'subflow.entry',
141
+ runtimeStageId: e.runtimeStageId,
142
+ subflowPath: e.subflowPath,
143
+ depth: e.depth,
144
+ ts: e.ts,
145
+ subflowId: e.subflowId,
146
+ localSubflowId: e.localSubflowId,
147
+ subflowName: e.subflowName,
148
+ ...(e.description !== undefined ? { description: e.description } : {}),
149
+ ...(e.primitiveKind !== undefined ? { primitiveKind: e.primitiveKind } : {}),
150
+ ...(e.slotKind !== undefined ? { slotKind: e.slotKind } : {}),
151
+ isAgentInternal: e.isAgentInternal,
152
+ };
153
+ }
154
+ return {
155
+ type: 'run.entry',
156
+ runtimeStageId: e.runtimeStageId,
157
+ subflowPath: e.subflowPath,
158
+ depth: e.depth,
159
+ ts: e.ts,
160
+ };
161
+ }
162
+ /** Build a BoundaryRangeLabel for the open side of a composition pair. */
163
+ function toCompositionBoundaryLabel(e) {
164
+ return {
165
+ type: 'composition.start',
166
+ runtimeStageId: e.runtimeStageId,
167
+ subflowPath: e.subflowPath,
168
+ depth: e.depth,
169
+ ts: e.ts,
170
+ compositionKind: e.kind,
171
+ compositionName: e.name,
172
+ };
173
+ }
174
+ /** Clamp `getCommitCount()` returns to a safe non-negative integer.
175
+ * Defensive against malformed injections returning NaN/Infinity/negatives
176
+ * (security panel review YELLOW #2). */
177
+ function sanitizeCommitCount(n) {
178
+ if (!Number.isFinite(n))
179
+ return 0;
180
+ if (n < 0)
181
+ return 0;
182
+ return n;
183
+ }
130
184
  let _counter = 0;
131
185
  /** Factory — matches the `inOutRecorder()` / `topologyRecorder()` style. */
132
186
  function boundaryRecorder(options = {}) {
@@ -138,12 +192,35 @@ exports.boundaryRecorder = boundaryRecorder;
138
192
  * attach to the executor's FlowRecorder channel; exposes `subscribe()`
139
193
  * to wire to the agentfootprint typed-event dispatcher.
140
194
  *
141
- * Internally stores events in a `SequenceRecorder<DomainEvent>` so the
142
- * usual time-travel utilities (`getEntryRanges`, `accumulate`) work
143
- * out of the box.
195
+ * v5: composes a `SequenceStore<DomainEvent>` (storage) instead of
196
+ * extending the deprecated `SequenceRecorder<T>` base. Time-travel
197
+ * utilities (`getEntryRanges`, `accumulate`) are accessed through the
198
+ * store via the public read API on this class.
144
199
  */
145
- class BoundaryRecorder extends trace_1.SequenceRecorder {
200
+ class BoundaryRecorder {
146
201
  id;
202
+ /** Composition: storage shelf. */
203
+ store = new trace_1.SequenceStore();
204
+ /**
205
+ * Phase 5 Layer 2 — interval index over commit indices, populated
206
+ * live as boundary entry/exit pairs fire. Consumers (Lens) read
207
+ * `enclosing(commitIdx)` for breadcrumbs and `overlapping(slice)`
208
+ * for time-range queries. Empty when `getCommitCount` is not
209
+ * injected. See `docs/design/boundary-commit-ranges.md`.
210
+ */
211
+ boundaryIndex = new trace_1.CommitRangeIndex();
212
+ /** Open-range tokens keyed by `runtimeStageId` so the matching exit
213
+ * can close the correct range. Pure side-table; cleared on runId
214
+ * reset. Not exposed externally. */
215
+ openTokens = new Map();
216
+ /** Live commit-count accessor injected by the runner. Sanitized
217
+ * (NaN/Infinity/negative → 0) before use. */
218
+ getCommitCount;
219
+ /** True when `getCommitCount` was explicitly injected. In LEGACY
220
+ * MODE (false), `boundaryIndex` is intentionally NOT populated —
221
+ * zero-width [0,0] ranges would mislead consumers querying the
222
+ * index. Multi-panel review flagged this footgun. */
223
+ hasCommitTracking;
147
224
  /**
148
225
  * Tracks whether the most recent `llm.end` had toolCalls. Used to
149
226
  * classify the NEXT `llm.start` as `'tool→llm'` (vs `'user→llm'` if
@@ -151,50 +228,184 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
151
228
  * `llm.start` event after the classification is applied.
152
229
  */
153
230
  prevLLMEndHadTools = false;
231
+ /**
232
+ * Run-boundary observer — fires resetForNewRun() when
233
+ * traversalContext.runId changes between events AND no boundary is
234
+ * currently open. The "no open boundary" gate distinguishes:
235
+ *
236
+ * - **Legitimate new run** — consumer reuses one recorder across
237
+ * sequential `executor.run()` calls. All prior boundaries closed
238
+ * before the second run began; openTokens is empty when the new
239
+ * runId arrives → safe to wipe state so the second run doesn't
240
+ * alias with the first.
241
+ * - **Composition sub-run** — primitives like `LLMCall`, `Sequence`,
242
+ * and `Parallel` internally spawn their own `FlowChartExecutor`
243
+ * instances. Each sub-executor mints a NEW runId. When that
244
+ * sub-executor fires events on the SHARED recorder, the recorder
245
+ * is still inside the parent run — `openTokens` is non-empty.
246
+ * Resetting here would wipe the parent's boundary index mid-run
247
+ * (the bug Layer 4 surfaced in agentfootprint-lens fanout).
248
+ *
249
+ * The `openTokens.size === 0` check is the cleanest semantic signal:
250
+ * if nothing is in-flight, a runId change means "the consumer started
251
+ * fresh"; if something is open, the new runId is from a sub-executor
252
+ * nested inside the still-ongoing parent.
253
+ */
254
+ runIdGuard = (0, observeRunId_js_1.createRunIdObserver)(() => {
255
+ if (this.openTokens.size > 0) {
256
+ // Inside an active run — new runId is from a composition sub-
257
+ // executor (LLMCall / Sequence / Parallel). Do NOT reset.
258
+ return;
259
+ }
260
+ this.store.clear();
261
+ this.boundaryIndex.clear();
262
+ this.openTokens.clear();
263
+ this.prevLLMEndHadTools = false;
264
+ });
154
265
  constructor(options = {}) {
155
- super();
156
266
  this.id = options.id ?? `boundary-${++_counter}`;
267
+ this.hasCommitTracking = options.getCommitCount !== undefined;
268
+ const raw = options.getCommitCount;
269
+ this.getCommitCount = raw === undefined ? () => 0 : () => sanitizeCommitCount(raw());
157
270
  }
271
+ /**
272
+ * Reset all transient state.
273
+ *
274
+ * **Composition-safe gate (Phase 5 Layer 4):** if `openTokens.size > 0`
275
+ * the call is a no-op. Rationale: `FlowChartExecutor.run()` calls
276
+ * `r.clear?.()` on every attached recorder during its pre-run loop.
277
+ * When agentfootprint composition primitives (LLMCall, Sequence,
278
+ * Parallel, etc.) propagate the parent's recorders to nested
279
+ * sub-executors, EACH sub-executor's pre-run clear loop calls
280
+ * `clear()` on the SHARED parent recorder mid-run — wiping live
281
+ * parent state. The `openTokens.size > 0` check distinguishes:
282
+ *
283
+ * - **Legitimate reset** — consumer or executor calls `clear()`
284
+ * when no boundary is in-flight (`openTokens` empty). Safe to
285
+ * wipe; the recorder is idle.
286
+ * - **Composition wipe** — sub-executor's pre-run clear fires
287
+ * while the parent has open boundaries (`openTokens` non-empty).
288
+ * Skip the wipe; the parent's state must be preserved.
289
+ *
290
+ * If a consumer needs to forcibly wipe state even with open tokens
291
+ * (e.g., manual recovery after a crashed run), pair `clear()` with
292
+ * an explicit `forceClear()` (TODO — add when the use case shows up;
293
+ * today the recorder lifecycle pattern is "one recorder per logical
294
+ * run" so leaked tokens shouldn't occur).
295
+ */
158
296
  clear() {
159
- super.clear();
297
+ if (this.openTokens.size > 0) {
298
+ // Mid-run wipe attempt — almost certainly a sub-executor's
299
+ // pre-run clear via composition propagation. Skip.
300
+ return;
301
+ }
302
+ this.store.clear();
303
+ this.boundaryIndex.clear();
304
+ this.openTokens.clear();
160
305
  this.prevLLMEndHadTools = false;
306
+ this.runIdGuard.reset();
307
+ }
308
+ observeRunId(runId) {
309
+ this.runIdGuard.observe(runId);
161
310
  }
162
311
  // ── FlowRecorder hooks (footprintjs side) ───────────────────────────
163
312
  onRunStart(event) {
164
- this.emit(buildRunEvent('run.entry', event.payload));
313
+ this.observeRunId(event.traversalContext?.runId);
314
+ const commitIdxBefore = this.getCommitCount();
315
+ const e = buildRunEvent('run.entry', event.payload, commitIdxBefore);
316
+ // Open range BEFORE the store push so a failed push doesn't leak
317
+ // an unclosed range (DS+logic panel review). The label is the
318
+ // stripped projection (no payload) — security-panel YELLOW #1.
319
+ if (this.hasCommitTracking) {
320
+ const token = this.boundaryIndex.open(toBoundaryLabel(e), commitIdxBefore);
321
+ this.openTokens.set(e.runtimeStageId, token);
322
+ }
323
+ this.store.push(e);
165
324
  }
166
325
  onRunEnd(event) {
167
- this.emit(buildRunEvent('run.exit', event.payload));
326
+ this.observeRunId(event.traversalContext?.runId);
327
+ const commitIdxBefore = this.getCommitCount();
328
+ const e = buildRunEvent('run.exit', event.payload, commitIdxBefore);
329
+ // Close the range BEFORE store.push so a failed push doesn't
330
+ // leak a permanently-open range. The range is the canonical
331
+ // truth; the store entry is downstream telemetry.
332
+ if (this.hasCommitTracking) {
333
+ const token = this.openTokens.get(e.runtimeStageId);
334
+ if (token) {
335
+ this.boundaryIndex.close(token, commitIdxBefore);
336
+ this.openTokens.delete(e.runtimeStageId);
337
+ }
338
+ }
339
+ this.store.push(e);
340
+ }
341
+ onRunFailed(event) {
342
+ this.observeRunId(event.traversalContext?.runId);
343
+ const commitIdxBefore = this.getCommitCount();
344
+ // A failed run still TERMINATES — close the root range (mirror
345
+ // onRunEnd) so consumers get a terminal "Run · failed" boundary
346
+ // position instead of a slider that stops mid-call. The error rides
347
+ // as the exit payload so the WHY is reachable at that boundary.
348
+ const e = buildRunEvent('run.exit', { error: event.structuredError.message }, commitIdxBefore);
349
+ if (this.hasCommitTracking) {
350
+ const token = this.openTokens.get(e.runtimeStageId);
351
+ if (token) {
352
+ this.boundaryIndex.close(token, commitIdxBefore);
353
+ this.openTokens.delete(e.runtimeStageId);
354
+ }
355
+ }
356
+ this.store.push(e);
168
357
  }
169
358
  onSubflowEntry(event) {
170
- const e = buildSubflowEvent(event, 'subflow.entry');
171
- if (e)
172
- this.emit(e);
359
+ this.observeRunId(event.traversalContext?.runId);
360
+ const commitIdxBefore = this.getCommitCount();
361
+ const e = buildSubflowEvent(event, 'subflow.entry', commitIdxBefore);
362
+ if (!e)
363
+ return;
364
+ if (this.hasCommitTracking) {
365
+ const token = this.boundaryIndex.open(toBoundaryLabel(e), commitIdxBefore);
366
+ this.openTokens.set(e.runtimeStageId, token);
367
+ }
368
+ this.store.push(e);
173
369
  }
174
370
  onSubflowExit(event) {
175
- const e = buildSubflowEvent(event, 'subflow.exit');
176
- if (e)
177
- this.emit(e);
371
+ this.observeRunId(event.traversalContext?.runId);
372
+ const commitIdxBefore = this.getCommitCount();
373
+ const e = buildSubflowEvent(event, 'subflow.exit', commitIdxBefore);
374
+ if (!e)
375
+ return;
376
+ if (this.hasCommitTracking) {
377
+ const token = this.openTokens.get(e.runtimeStageId);
378
+ if (token) {
379
+ this.boundaryIndex.close(token, commitIdxBefore);
380
+ this.openTokens.delete(e.runtimeStageId);
381
+ }
382
+ }
383
+ this.store.push(e);
178
384
  }
179
385
  onFork(event) {
386
+ this.observeRunId(event.traversalContext?.runId);
180
387
  const ts = Date.now();
181
388
  const ctx = event.traversalContext;
182
389
  const runtimeStageId = ctx?.runtimeStageId ?? '';
183
390
  const segments = ctx?.subflowPath ? ctx.subflowPath.split('/').filter(Boolean) : [];
184
391
  const subflowPath = [trace_1.ROOT_SUBFLOW_ID, ...segments];
392
+ const commitIdxBefore = this.getCommitCount();
185
393
  for (const childName of event.children) {
186
- this.emit({
394
+ this.store.push({
187
395
  type: 'fork.branch',
188
396
  runtimeStageId,
189
397
  subflowPath,
190
398
  depth: subflowPath.length - 1,
191
399
  ts,
400
+ commitIdxBefore,
401
+ commitIdxAfter: commitIdxBefore,
192
402
  parentSubflowId: event.parent,
193
403
  childName,
194
404
  });
195
405
  }
196
406
  }
197
407
  onDecision(event) {
408
+ this.observeRunId(event.traversalContext?.runId);
198
409
  const ctx = event.traversalContext;
199
410
  // Agent-internal decisions (Route picking tool-calls / final) are
200
411
  // identified by the deciding stage's stableId matching one of the
@@ -208,12 +419,15 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
208
419
  ? stageId.slice(stageId.lastIndexOf('/') + 1)
209
420
  : stageId;
210
421
  const isAgentInternal = isAgentInternalId(localStageId);
211
- this.emit({
422
+ const commitIdxBefore = this.getCommitCount();
423
+ this.store.push({
212
424
  type: 'decision.branch',
213
425
  runtimeStageId: ctx?.runtimeStageId ?? '',
214
426
  subflowPath: pathFromCtx(ctx?.subflowPath),
215
427
  depth: ctxDepth(ctx?.subflowPath),
216
428
  ts: Date.now(),
429
+ commitIdxBefore,
430
+ commitIdxAfter: commitIdxBefore,
217
431
  decider: event.decider,
218
432
  chosen: event.chosen,
219
433
  ...(event.rationale ? { rationale: event.rationale } : {}),
@@ -221,13 +435,17 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
221
435
  });
222
436
  }
223
437
  onLoop(event) {
438
+ this.observeRunId(event.traversalContext?.runId);
224
439
  const ctx = event.traversalContext;
225
- this.emit({
440
+ const commitIdxBefore = this.getCommitCount();
441
+ this.store.push({
226
442
  type: 'loop.iteration',
227
443
  runtimeStageId: ctx?.runtimeStageId ?? '',
228
444
  subflowPath: pathFromCtx(ctx?.subflowPath),
229
445
  depth: ctxDepth(ctx?.subflowPath),
230
446
  ts: Date.now(),
447
+ commitIdxBefore,
448
+ commitIdxAfter: commitIdxBefore,
231
449
  target: event.target,
232
450
  iteration: event.iteration,
233
451
  });
@@ -245,11 +463,22 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
245
463
  return dispatcher.on('*', (event) => this.ingestTypedEvent(event));
246
464
  }
247
465
  ingestTypedEvent(event) {
466
+ // NOTE: deliberately does NOT call observeRunId(event.meta.runId).
467
+ // The agentfootprint dispatcher's runId is generated by a DIFFERENT
468
+ // generator than footprintjs's traversalContext.runId. Mixing them
469
+ // would toggle lastRunId on every event and trigger a false reset.
470
+ // Run-boundary detection happens reliably via the FlowRecorder hooks
471
+ // (onRunStart fires FIRST in any new run, before any typed event).
248
472
  const meta = event.meta;
249
473
  const runtimeStageId = meta.runtimeStageId ?? '';
250
474
  const subflowPath = [trace_1.ROOT_SUBFLOW_ID, ...(meta.subflowPath ?? [])];
251
475
  const depth = subflowPath.length - 1;
252
476
  const ts = meta.wallClockMs;
477
+ // Phase 5 Layer 2: stamp commit index on every typed event for
478
+ // consumers that want to join domain events with the commit log
479
+ // (e.g., "which LLM call happened during this commit slice?").
480
+ // Typed events don't write to scope themselves, so before === after.
481
+ const commitIdxBefore = this.getCommitCount();
253
482
  switch (event.type) {
254
483
  case 'agentfootprint.stream.llm_start': {
255
484
  const p = event.payload;
@@ -261,12 +490,14 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
261
490
  ? 'tool→llm'
262
491
  : 'user→llm';
263
492
  this.prevLLMEndHadTools = false;
264
- this.emit({
493
+ this.store.push({
265
494
  type: 'llm.start',
266
495
  runtimeStageId,
267
496
  subflowPath,
268
497
  depth,
269
498
  ts,
499
+ commitIdxBefore,
500
+ commitIdxAfter: commitIdxBefore,
270
501
  model: p.model,
271
502
  provider: p.provider,
272
503
  ...(p.systemPromptChars !== undefined ? { systemPromptChars: p.systemPromptChars } : {}),
@@ -283,12 +514,14 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
283
514
  // terminal call (toolCallCount === 0) leaves the flag false so
284
515
  // a hypothetical follow-up call would correctly be 'user→llm'.
285
516
  this.prevLLMEndHadTools = p.toolCallCount > 0;
286
- this.emit({
517
+ this.store.push({
287
518
  type: 'llm.end',
288
519
  runtimeStageId,
289
520
  subflowPath,
290
521
  depth,
291
522
  ts,
523
+ commitIdxBefore,
524
+ commitIdxAfter: commitIdxBefore,
292
525
  content: p.content,
293
526
  toolCallCount: p.toolCallCount,
294
527
  usage: { input: p.usage.input, output: p.usage.output },
@@ -299,12 +532,14 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
299
532
  }
300
533
  case 'agentfootprint.stream.tool_start': {
301
534
  const p = event.payload;
302
- this.emit({
535
+ this.store.push({
303
536
  type: 'tool.start',
304
537
  runtimeStageId,
305
538
  subflowPath,
306
539
  depth,
307
540
  ts,
541
+ commitIdxBefore,
542
+ commitIdxAfter: commitIdxBefore,
308
543
  toolName: p.toolName,
309
544
  toolCallId: p.toolCallId,
310
545
  ...(p.args !== undefined ? { args: p.args } : {}),
@@ -313,12 +548,14 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
313
548
  }
314
549
  case 'agentfootprint.stream.tool_end': {
315
550
  const p = event.payload;
316
- this.emit({
551
+ this.store.push({
317
552
  type: 'tool.end',
318
553
  runtimeStageId,
319
554
  subflowPath,
320
555
  depth,
321
556
  ts,
557
+ commitIdxBefore,
558
+ commitIdxAfter: commitIdxBefore,
322
559
  toolCallId: p.toolCallId,
323
560
  ...(p.result !== undefined ? { result: p.result } : {}),
324
561
  ...(p.durationMs !== undefined ? { durationMs: p.durationMs } : {}),
@@ -328,12 +565,14 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
328
565
  }
329
566
  case 'agentfootprint.context.injected': {
330
567
  const p = event.payload;
331
- this.emit({
568
+ this.store.push({
332
569
  type: 'context.injected',
333
570
  runtimeStageId,
334
571
  subflowPath,
335
572
  depth,
336
573
  ts,
574
+ commitIdxBefore,
575
+ commitIdxAfter: commitIdxBefore,
337
576
  slot: p.slot,
338
577
  source: p.source ?? 'unknown',
339
578
  ...(p.sourceId ? { sourceId: p.sourceId } : {}),
@@ -351,23 +590,82 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
351
590
  });
352
591
  break;
353
592
  }
593
+ case 'agentfootprint.composition.enter': {
594
+ // Open a boundary range for the composition. The MATCHING KEY
595
+ // for open/close is `payload.id` (the composition's stable id),
596
+ // NOT `meta.runtimeStageId`. Reason: the composition's enter
597
+ // event fires from a different stage (entry hook) than its
598
+ // exit event (merge / exit hook) — different `meta.runtimeStageId`s.
599
+ // The composition's `id` is the only field that's the same on
600
+ // both. The boundary range's runtimeStageId (used as the Lens
601
+ // group identity) is the ENTER event's `meta.runtimeStageId`
602
+ // (the entry stage's id) — that's the "fork moment."
603
+ const p = event.payload;
604
+ const e = {
605
+ type: 'composition.start',
606
+ runtimeStageId,
607
+ subflowPath,
608
+ depth,
609
+ ts,
610
+ commitIdxBefore,
611
+ commitIdxAfter: commitIdxBefore,
612
+ kind: p.kind,
613
+ compositionId: p.id,
614
+ name: p.name,
615
+ };
616
+ if (this.hasCommitTracking) {
617
+ const token = this.boundaryIndex.open(toCompositionBoundaryLabel(e), commitIdxBefore);
618
+ this.openTokens.set(`composition:${p.id}`, token);
619
+ }
620
+ this.store.push(e);
621
+ break;
622
+ }
623
+ case 'agentfootprint.composition.exit': {
624
+ // Close the matching composition range. Keyed by `payload.id`
625
+ // — see the enter handler for why this differs from
626
+ // meta.runtimeStageId.
627
+ const p = event.payload;
628
+ const e = {
629
+ type: 'composition.end',
630
+ runtimeStageId,
631
+ subflowPath,
632
+ depth,
633
+ ts,
634
+ commitIdxBefore,
635
+ commitIdxAfter: commitIdxBefore,
636
+ kind: p.kind,
637
+ compositionId: p.id,
638
+ name: p.name ?? '',
639
+ status: p.status,
640
+ durationMs: p.durationMs,
641
+ };
642
+ if (this.hasCommitTracking) {
643
+ const key = `composition:${p.id}`;
644
+ const token = this.openTokens.get(key);
645
+ if (token) {
646
+ this.boundaryIndex.close(token, commitIdxBefore);
647
+ this.openTokens.delete(key);
648
+ }
649
+ }
650
+ this.store.push(e);
651
+ break;
652
+ }
354
653
  default:
355
- // Other typed events (composition.*, agent.*, etc.) are not
356
- // mapped to DomainEvent for now — they're either implied by
357
- // FlowRecorder events (composition) or higher-level summaries
358
- // (agent.turn_*) that downstream selectors derive on demand.
654
+ // Other typed events (agent.*, eval.*, etc.) are not mapped to
655
+ // DomainEvent for now — they're higher-level summaries that
656
+ // downstream selectors derive on demand.
359
657
  break;
360
658
  }
361
659
  }
362
660
  // ── Read API ────────────────────────────────────────────────────────
363
661
  /** All events in capture order (the canonical projection). */
364
662
  getEvents() {
365
- return this.getEntries();
663
+ return this.store.getAll();
366
664
  }
367
665
  /** Type-narrowed lookup: all events of one kind. */
368
666
  getEventsByType(type) {
369
667
  const out = [];
370
- for (const e of this.getEntries()) {
668
+ for (const e of this.store.getAll()) {
371
669
  if (e.type === type)
372
670
  out.push(e);
373
671
  }
@@ -377,7 +675,7 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
377
675
  /** All boundary events (run + subflow, entry + exit interleaved). */
378
676
  getBoundaries() {
379
677
  const out = [];
380
- for (const e of this.getEntries()) {
678
+ for (const e of this.store.getAll()) {
381
679
  if (e.type === 'run.entry' ||
382
680
  e.type === 'run.exit' ||
383
681
  e.type === 'subflow.entry' ||
@@ -397,7 +695,7 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
397
695
  }
398
696
  /** Entry/exit pair for one chart execution by `runtimeStageId`. */
399
697
  getBoundary(runtimeStageId) {
400
- const matches = this.getEntriesForStep(runtimeStageId);
698
+ const matches = this.store.getByKey(runtimeStageId);
401
699
  let entry;
402
700
  let exit;
403
701
  for (const e of matches) {
@@ -424,7 +722,7 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
424
722
  const systemPrompt = [];
425
723
  const messages = [];
426
724
  const tools = [];
427
- for (const e of this.getEntries()) {
725
+ for (const e of this.store.getAll()) {
428
726
  if (e.type !== 'subflow.entry' && e.type !== 'subflow.exit')
429
727
  continue;
430
728
  if (e.slotKind === 'system-prompt')
@@ -463,7 +761,7 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
463
761
  * matches `runtimeStageId`.
464
762
  */
465
763
  aggregateForBoundary(runtimeStageId) {
466
- const events = this.getEntries();
764
+ const events = this.store.getAll();
467
765
  let entry;
468
766
  let exit;
469
767
  for (const e of events) {
@@ -488,7 +786,7 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
488
786
  * not user-facing rollup units.
489
787
  */
490
788
  aggregateAllBoundaries() {
491
- const events = this.getEntries();
789
+ const events = this.store.getAll();
492
790
  const out = [];
493
791
  // Index exits by runtimeStageId for O(1) pair-up.
494
792
  const exitByRid = new Map();
@@ -518,18 +816,20 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
518
816
  }
519
817
  exports.BoundaryRecorder = BoundaryRecorder;
520
818
  // ── Internal helpers ─────────────────────────────────────────────────
521
- function buildRunEvent(type, payload) {
819
+ function buildRunEvent(type, payload, commitIdxBefore) {
522
820
  return {
523
821
  type,
524
822
  runtimeStageId: trace_1.ROOT_RUNTIME_STAGE_ID,
525
823
  subflowPath: [trace_1.ROOT_SUBFLOW_ID],
526
824
  depth: 0,
527
825
  ts: Date.now(),
826
+ commitIdxBefore,
827
+ commitIdxAfter: commitIdxBefore,
528
828
  payload,
529
829
  isRoot: true,
530
830
  };
531
831
  }
532
- function buildSubflowEvent(event, type) {
832
+ function buildSubflowEvent(event, type, commitIdxBefore) {
533
833
  const subflowId = event.subflowId;
534
834
  if (!subflowId)
535
835
  return undefined;
@@ -550,6 +850,8 @@ function buildSubflowEvent(event, type) {
550
850
  subflowPath,
551
851
  depth,
552
852
  ts: Date.now(),
853
+ commitIdxBefore,
854
+ commitIdxAfter: commitIdxBefore,
553
855
  subflowId,
554
856
  localSubflowId,
555
857
  subflowName: event.name,