footprintjs 10.0.1 → 10.2.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 (368) hide show
  1. package/AGENTS.md +2 -1
  2. package/CLAUDE.md +61 -7
  3. package/README.md +136 -312
  4. package/dist/esm/index.d.ts +62 -2
  5. package/dist/esm/index.js +13 -6
  6. package/dist/esm/lib/attempt/anySignal.d.ts +19 -0
  7. package/dist/esm/lib/attempt/anySignal.js +39 -0
  8. package/dist/esm/lib/attempt/call.d.ts +88 -0
  9. package/dist/esm/lib/attempt/call.js +129 -0
  10. package/dist/esm/lib/attempt/category.d.ts +37 -0
  11. package/dist/esm/lib/attempt/category.js +131 -0
  12. package/dist/esm/lib/attempt/correlation.d.ts +95 -0
  13. package/dist/esm/lib/attempt/correlation.js +178 -0
  14. package/dist/esm/lib/attempt/deadline.d.ts +44 -0
  15. package/dist/esm/lib/attempt/deadline.js +101 -0
  16. package/dist/esm/lib/attempt/decision.d.ts +52 -0
  17. package/dist/esm/lib/attempt/decision.js +134 -0
  18. package/dist/esm/lib/attempt/effect.d.ts +76 -0
  19. package/dist/esm/lib/attempt/effect.js +160 -0
  20. package/dist/esm/lib/attempt/errors.d.ts +41 -0
  21. package/dist/esm/lib/attempt/errors.js +44 -0
  22. package/dist/esm/lib/attempt/index.d.ts +18 -0
  23. package/dist/esm/lib/attempt/index.js +15 -0
  24. package/dist/esm/lib/attempt/name.d.ts +21 -0
  25. package/dist/esm/lib/attempt/name.js +43 -0
  26. package/dist/esm/lib/attempt/observed.d.ts +66 -0
  27. package/dist/esm/lib/attempt/observed.js +171 -0
  28. package/dist/esm/lib/attempt/policy.d.ts +45 -0
  29. package/dist/esm/lib/attempt/policy.js +83 -0
  30. package/dist/esm/lib/attempt/record.d.ts +11 -0
  31. package/dist/esm/lib/attempt/record.js +24 -0
  32. package/dist/esm/lib/attempt/retryLoopContext.d.ts +18 -0
  33. package/dist/esm/lib/attempt/retryLoopContext.js +24 -0
  34. package/dist/esm/lib/attempt/retryLoopTypes.d.ts +18 -0
  35. package/dist/esm/lib/attempt/retryLoopTypes.js +2 -0
  36. package/dist/esm/lib/attempt/runner.d.ts +157 -0
  37. package/dist/esm/lib/attempt/runner.js +523 -0
  38. package/dist/esm/lib/attempt/standalone.d.ts +47 -0
  39. package/dist/esm/lib/attempt/standalone.js +126 -0
  40. package/dist/esm/lib/attempt/types.d.ts +453 -0
  41. package/dist/esm/lib/attempt/types.js +16 -0
  42. package/dist/esm/lib/budget/index.d.ts +9 -0
  43. package/dist/esm/lib/budget/index.js +9 -0
  44. package/dist/esm/lib/budget/timeBudget.d.ts +136 -0
  45. package/dist/esm/lib/budget/timeBudget.js +666 -0
  46. package/dist/esm/lib/builder/FlowChartBuilder.d.ts +88 -3
  47. package/dist/esm/lib/builder/FlowChartBuilder.js +199 -9
  48. package/dist/esm/lib/builder/retryLoop.d.ts +56 -0
  49. package/dist/esm/lib/builder/retryLoop.js +283 -0
  50. package/dist/esm/lib/builder/types.d.ts +35 -1
  51. package/dist/esm/lib/builder/types.js +1 -1
  52. package/dist/esm/lib/decide/decide.js +2 -2
  53. package/dist/esm/lib/decide/index.d.ts +1 -1
  54. package/dist/esm/lib/decide/index.js +2 -2
  55. package/dist/esm/lib/decide/types.d.ts +3 -0
  56. package/dist/esm/lib/decide/types.js +1 -8
  57. package/dist/esm/lib/engine/graph/StageNode.d.ts +11 -1
  58. package/dist/esm/lib/engine/graph/StageNode.js +1 -1
  59. package/dist/esm/lib/engine/graph/prefixNodeTree.js +5 -1
  60. package/dist/esm/lib/engine/handlers/ChildrenExecutor.js +36 -6
  61. package/dist/esm/lib/engine/handlers/DeciderHandler.js +9 -5
  62. package/dist/esm/lib/engine/handlers/ResumeEntry.js +3 -1
  63. package/dist/esm/lib/engine/handlers/SelectorHandler.js +6 -5
  64. package/dist/esm/lib/engine/handlers/StageRunner.d.ts +8 -1
  65. package/dist/esm/lib/engine/handlers/StageRunner.js +36 -9
  66. package/dist/esm/lib/engine/handlers/SubflowExecutor.js +24 -5
  67. package/dist/esm/lib/engine/handlers/commitStage.d.ts +7 -0
  68. package/dist/esm/lib/engine/handlers/commitStage.js +22 -4
  69. package/dist/esm/lib/engine/handlers/stageError.d.ts +9 -0
  70. package/dist/esm/lib/engine/handlers/stageError.js +23 -1
  71. package/dist/esm/lib/engine/index.d.ts +2 -2
  72. package/dist/esm/lib/engine/index.js +1 -1
  73. package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +27 -13
  74. package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +68 -40
  75. package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.d.ts +4 -1
  76. package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.js +19 -2
  77. package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.d.ts +22 -3
  78. package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.js +61 -9
  79. package/dist/esm/lib/engine/narrative/NullControlFlowNarrativeGenerator.d.ts +1 -0
  80. package/dist/esm/lib/engine/narrative/NullControlFlowNarrativeGenerator.js +2 -1
  81. package/dist/esm/lib/engine/narrative/formatting/sentences.d.ts +23 -0
  82. package/dist/esm/lib/engine/narrative/formatting/sentences.js +127 -1
  83. package/dist/esm/lib/engine/narrative/index.d.ts +2 -2
  84. package/dist/esm/lib/engine/narrative/index.js +1 -1
  85. package/dist/esm/lib/engine/narrative/narrativeTypes.d.ts +27 -21
  86. package/dist/esm/lib/engine/narrative/narrativeTypes.js +1 -1
  87. package/dist/esm/lib/engine/narrative/recorders/ManifestFlowRecorder.d.ts +45 -2
  88. package/dist/esm/lib/engine/narrative/recorders/ManifestFlowRecorder.js +55 -2
  89. package/dist/esm/lib/engine/narrative/recorders/index.d.ts +1 -1
  90. package/dist/esm/lib/engine/narrative/recorders/index.js +1 -1
  91. package/dist/esm/lib/engine/narrative/types.d.ts +74 -5
  92. package/dist/esm/lib/engine/narrative/types.js +1 -1
  93. package/dist/esm/lib/engine/traversal/FlowchartTraverser.d.ts +59 -19
  94. package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +194 -118
  95. package/dist/esm/lib/engine/traversalContext.d.ts +7 -2
  96. package/dist/esm/lib/engine/traversalContext.js +6 -3
  97. package/dist/esm/lib/engine/types.d.ts +52 -57
  98. package/dist/esm/lib/engine/types.js +1 -1
  99. package/dist/esm/lib/errors/terminalFailure.d.ts +29 -0
  100. package/dist/esm/lib/errors/terminalFailure.js +60 -0
  101. package/dist/esm/lib/{decide → filter}/evaluator.d.ts +7 -2
  102. package/dist/esm/lib/filter/evaluator.js +135 -0
  103. package/dist/esm/lib/ids/idempotencyKey.d.ts +14 -0
  104. package/dist/esm/lib/ids/idempotencyKey.js +24 -0
  105. package/dist/esm/lib/memory/StageContext.d.ts +123 -3
  106. package/dist/esm/lib/memory/StageContext.js +245 -4
  107. package/dist/esm/lib/memory/attention.d.ts +26 -0
  108. package/dist/esm/lib/memory/attention.js +171 -0
  109. package/dist/esm/lib/memory/borrowedMutation.d.ts +8 -0
  110. package/dist/esm/lib/memory/borrowedMutation.js +14 -1
  111. package/dist/esm/lib/memory/frameTypes.d.ts +38 -0
  112. package/dist/esm/lib/memory/frameTypes.js +3 -1
  113. package/dist/esm/lib/memory/redaction.d.ts +12 -0
  114. package/dist/esm/lib/memory/redaction.js +54 -5
  115. package/dist/esm/lib/pause/record.js +10 -1
  116. package/dist/esm/lib/pause/types.d.ts +19 -0
  117. package/dist/esm/lib/pause/types.js +17 -1
  118. package/dist/esm/lib/reactive/createTypedScope.js +3 -1
  119. package/dist/esm/lib/reactive/types.d.ts +36 -4
  120. package/dist/esm/lib/reactive/types.js +3 -1
  121. package/dist/esm/lib/recorder/AttemptRecorder.d.ts +141 -0
  122. package/dist/esm/lib/recorder/AttemptRecorder.js +412 -0
  123. package/dist/esm/lib/recorder/ControlDepRecorder.d.ts +36 -2
  124. package/dist/esm/lib/recorder/ControlDepRecorder.js +50 -2
  125. package/dist/esm/lib/recorder/EmitRecorder.d.ts +3 -0
  126. package/dist/esm/lib/recorder/EmitRecorder.js +1 -1
  127. package/dist/esm/lib/recorder/InOutRecorder.d.ts +37 -1
  128. package/dist/esm/lib/recorder/InOutRecorder.js +75 -6
  129. package/dist/esm/lib/recorder/QualityRecorder.d.ts +32 -5
  130. package/dist/esm/lib/recorder/QualityRecorder.js +87 -29
  131. package/dist/esm/lib/recorder/TopologyRecorder.d.ts +35 -5
  132. package/dist/esm/lib/recorder/TopologyRecorder.js +76 -2
  133. package/dist/esm/lib/recorder/attemptMetricRows.d.ts +11 -0
  134. package/dist/esm/lib/recorder/attemptMetricRows.js +202 -0
  135. package/dist/esm/lib/recorder/attemptMetrics.d.ts +7 -0
  136. package/dist/esm/lib/recorder/attemptMetrics.js +165 -0
  137. package/dist/esm/lib/recorder/attemptMetricsTypes.d.ts +114 -0
  138. package/dist/esm/lib/recorder/attemptMetricsTypes.js +2 -0
  139. package/dist/esm/lib/recorder/attemptOTel.d.ts +78 -0
  140. package/dist/esm/lib/recorder/attemptOTel.js +107 -0
  141. package/dist/esm/lib/recorder/attemptSeries.d.ts +81 -0
  142. package/dist/esm/lib/recorder/attemptSeries.js +103 -0
  143. package/dist/esm/lib/recorder/hooks.d.ts +9 -0
  144. package/dist/esm/lib/recorder/hooks.js +4 -1
  145. package/dist/esm/lib/runner/DeferredObserverTier.js +13 -1
  146. package/dist/esm/lib/runner/ExecutionRuntime.d.ts +54 -6
  147. package/dist/esm/lib/runner/ExecutionRuntime.js +57 -5
  148. package/dist/esm/lib/runner/FlowChartExecutor.d.ts +46 -2
  149. package/dist/esm/lib/runner/FlowChartExecutor.js +330 -101
  150. package/dist/esm/lib/runner/RunnableChart.d.ts +6 -0
  151. package/dist/esm/lib/runner/RunnableChart.js +5 -1
  152. package/dist/esm/lib/runner/attach.d.ts +2 -1
  153. package/dist/esm/lib/runner/attach.js +8 -2
  154. package/dist/esm/lib/runner/checkpoint.js +3 -1
  155. package/dist/esm/lib/runner/deadline.d.ts +42 -0
  156. package/dist/esm/lib/runner/deadline.js +90 -0
  157. package/dist/esm/lib/runner/index.d.ts +3 -1
  158. package/dist/esm/lib/runner/index.js +2 -1
  159. package/dist/esm/lib/runner/options.d.ts +17 -0
  160. package/dist/esm/lib/runner/options.js +3 -1
  161. package/dist/esm/lib/runner/recordSink.d.ts +128 -0
  162. package/dist/esm/lib/runner/recordSink.js +296 -0
  163. package/dist/esm/lib/runner/resume.d.ts +3 -0
  164. package/dist/esm/lib/runner/resume.js +22 -2
  165. package/dist/esm/lib/runner/snapshot.d.ts +2 -2
  166. package/dist/esm/lib/runner/snapshot.js +6 -2
  167. package/dist/esm/lib/scope/ScopeFacade.d.ts +118 -4
  168. package/dist/esm/lib/scope/ScopeFacade.js +304 -7
  169. package/dist/esm/lib/scope/recorders/DebugRecorder.d.ts +17 -3
  170. package/dist/esm/lib/scope/recorders/DebugRecorder.js +79 -13
  171. package/dist/esm/lib/scope/recorders/MetricRecorder.d.ts +10 -0
  172. package/dist/esm/lib/scope/recorders/MetricRecorder.js +15 -2
  173. package/dist/esm/lib/scope/runtime.d.ts +3 -0
  174. package/dist/esm/lib/scope/runtime.js +1 -1
  175. package/dist/esm/lib/scope/types.d.ts +6 -0
  176. package/dist/esm/lib/scope/types.js +1 -1
  177. package/dist/esm/lib/sinks/fileSink.d.ts +135 -0
  178. package/dist/esm/lib/sinks/fileSink.js +387 -0
  179. package/dist/esm/recorders.d.ts +8 -2
  180. package/dist/esm/recorders.js +7 -1
  181. package/dist/esm/sinks.d.ts +23 -0
  182. package/dist/esm/sinks.js +23 -0
  183. package/dist/esm/trace.d.ts +2 -2
  184. package/dist/esm/trace.js +1 -1
  185. package/dist/index.js +77 -60
  186. package/dist/lib/attempt/anySignal.js +43 -0
  187. package/dist/lib/attempt/call.js +134 -0
  188. package/dist/lib/attempt/category.js +136 -0
  189. package/dist/lib/attempt/correlation.js +186 -0
  190. package/dist/lib/attempt/deadline.js +112 -0
  191. package/dist/lib/attempt/decision.js +139 -0
  192. package/dist/lib/attempt/effect.js +174 -0
  193. package/dist/lib/attempt/errors.js +49 -0
  194. package/dist/lib/attempt/index.js +26 -0
  195. package/dist/lib/attempt/name.js +48 -0
  196. package/dist/lib/attempt/observed.js +177 -0
  197. package/dist/lib/attempt/policy.js +92 -0
  198. package/dist/lib/attempt/record.js +29 -0
  199. package/dist/lib/attempt/retryLoopContext.js +31 -0
  200. package/dist/lib/attempt/retryLoopTypes.js +3 -0
  201. package/dist/lib/attempt/runner.js +530 -0
  202. package/dist/lib/attempt/standalone.js +130 -0
  203. package/dist/lib/attempt/types.js +17 -0
  204. package/dist/lib/budget/index.js +17 -0
  205. package/dist/lib/budget/timeBudget.js +674 -0
  206. package/dist/lib/builder/FlowChartBuilder.js +199 -9
  207. package/dist/lib/builder/retryLoop.js +287 -0
  208. package/dist/lib/builder/types.js +1 -1
  209. package/dist/lib/decide/decide.js +2 -2
  210. package/dist/lib/decide/index.js +2 -2
  211. package/dist/lib/decide/types.js +1 -8
  212. package/dist/lib/engine/graph/StageNode.js +1 -1
  213. package/dist/lib/engine/graph/prefixNodeTree.js +5 -1
  214. package/dist/lib/engine/handlers/ChildrenExecutor.js +36 -6
  215. package/dist/lib/engine/handlers/DeciderHandler.js +7 -3
  216. package/dist/lib/engine/handlers/ResumeEntry.js +3 -1
  217. package/dist/lib/engine/handlers/SelectorHandler.js +4 -3
  218. package/dist/lib/engine/handlers/StageRunner.js +36 -9
  219. package/dist/lib/engine/handlers/SubflowExecutor.js +24 -5
  220. package/dist/lib/engine/handlers/commitStage.js +24 -5
  221. package/dist/lib/engine/handlers/stageError.js +26 -2
  222. package/dist/lib/engine/index.js +1 -1
  223. package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +67 -39
  224. package/dist/lib/engine/narrative/FlowRecorderDispatcher.js +19 -2
  225. package/dist/lib/engine/narrative/NarrativeFlowRecorder.js +60 -8
  226. package/dist/lib/engine/narrative/NullControlFlowNarrativeGenerator.js +2 -1
  227. package/dist/lib/engine/narrative/formatting/sentences.js +131 -2
  228. package/dist/lib/engine/narrative/index.js +1 -1
  229. package/dist/lib/engine/narrative/narrativeTypes.js +1 -1
  230. package/dist/lib/engine/narrative/recorders/ManifestFlowRecorder.js +55 -2
  231. package/dist/lib/engine/narrative/recorders/index.js +1 -1
  232. package/dist/lib/engine/narrative/types.js +1 -1
  233. package/dist/lib/engine/traversal/FlowchartTraverser.js +192 -116
  234. package/dist/lib/engine/traversalContext.js +6 -3
  235. package/dist/lib/engine/types.js +1 -1
  236. package/dist/lib/errors/terminalFailure.js +64 -0
  237. package/dist/lib/filter/evaluator.js +139 -0
  238. package/dist/lib/ids/idempotencyKey.js +28 -0
  239. package/dist/lib/memory/StageContext.js +246 -5
  240. package/dist/lib/memory/attention.js +175 -0
  241. package/dist/lib/memory/borrowedMutation.js +16 -2
  242. package/dist/lib/memory/frameTypes.js +3 -1
  243. package/dist/lib/memory/redaction.js +54 -5
  244. package/dist/lib/pause/record.js +10 -1
  245. package/dist/lib/pause/types.js +17 -1
  246. package/dist/lib/reactive/createTypedScope.js +3 -1
  247. package/dist/lib/reactive/types.js +3 -1
  248. package/dist/lib/recorder/AttemptRecorder.js +417 -0
  249. package/dist/lib/recorder/ControlDepRecorder.js +50 -2
  250. package/dist/lib/recorder/EmitRecorder.js +1 -1
  251. package/dist/lib/recorder/InOutRecorder.js +75 -6
  252. package/dist/lib/recorder/QualityRecorder.js +87 -29
  253. package/dist/lib/recorder/TopologyRecorder.js +76 -2
  254. package/dist/lib/recorder/attemptMetricRows.js +209 -0
  255. package/dist/lib/recorder/attemptMetrics.js +174 -0
  256. package/dist/lib/recorder/attemptMetricsTypes.js +3 -0
  257. package/dist/lib/recorder/attemptOTel.js +111 -0
  258. package/dist/lib/recorder/attemptSeries.js +113 -0
  259. package/dist/lib/recorder/hooks.js +4 -1
  260. package/dist/lib/runner/DeferredObserverTier.js +13 -1
  261. package/dist/lib/runner/ExecutionRuntime.js +57 -5
  262. package/dist/lib/runner/FlowChartExecutor.js +330 -101
  263. package/dist/lib/runner/RunnableChart.js +5 -1
  264. package/dist/lib/runner/attach.js +8 -2
  265. package/dist/lib/runner/checkpoint.js +3 -1
  266. package/dist/lib/runner/deadline.js +94 -0
  267. package/dist/lib/runner/index.js +4 -2
  268. package/dist/lib/runner/options.js +3 -1
  269. package/dist/lib/runner/recordSink.js +302 -0
  270. package/dist/lib/runner/resume.js +22 -2
  271. package/dist/lib/runner/snapshot.js +6 -2
  272. package/dist/lib/scope/ScopeFacade.js +303 -6
  273. package/dist/lib/scope/recorders/DebugRecorder.js +79 -13
  274. package/dist/lib/scope/recorders/MetricRecorder.js +15 -2
  275. package/dist/lib/scope/runtime.js +1 -1
  276. package/dist/lib/scope/types.js +1 -1
  277. package/dist/lib/sinks/fileSink.js +392 -0
  278. package/dist/recorders.js +10 -2
  279. package/dist/sinks.js +32 -0
  280. package/dist/trace.js +1 -1
  281. package/dist/types/index.d.ts +62 -2
  282. package/dist/types/lib/attempt/anySignal.d.ts +19 -0
  283. package/dist/types/lib/attempt/call.d.ts +88 -0
  284. package/dist/types/lib/attempt/category.d.ts +37 -0
  285. package/dist/types/lib/attempt/correlation.d.ts +95 -0
  286. package/dist/types/lib/attempt/deadline.d.ts +44 -0
  287. package/dist/types/lib/attempt/decision.d.ts +52 -0
  288. package/dist/types/lib/attempt/effect.d.ts +76 -0
  289. package/dist/types/lib/attempt/errors.d.ts +41 -0
  290. package/dist/types/lib/attempt/index.d.ts +18 -0
  291. package/dist/types/lib/attempt/name.d.ts +21 -0
  292. package/dist/types/lib/attempt/observed.d.ts +66 -0
  293. package/dist/types/lib/attempt/policy.d.ts +45 -0
  294. package/dist/types/lib/attempt/record.d.ts +11 -0
  295. package/dist/types/lib/attempt/retryLoopContext.d.ts +18 -0
  296. package/dist/types/lib/attempt/retryLoopTypes.d.ts +18 -0
  297. package/dist/types/lib/attempt/runner.d.ts +157 -0
  298. package/dist/types/lib/attempt/standalone.d.ts +47 -0
  299. package/dist/types/lib/attempt/types.d.ts +453 -0
  300. package/dist/types/lib/budget/index.d.ts +9 -0
  301. package/dist/types/lib/budget/timeBudget.d.ts +136 -0
  302. package/dist/types/lib/builder/FlowChartBuilder.d.ts +88 -3
  303. package/dist/types/lib/builder/retryLoop.d.ts +56 -0
  304. package/dist/types/lib/builder/types.d.ts +35 -1
  305. package/dist/types/lib/decide/index.d.ts +1 -1
  306. package/dist/types/lib/decide/types.d.ts +3 -0
  307. package/dist/types/lib/engine/graph/StageNode.d.ts +11 -1
  308. package/dist/types/lib/engine/handlers/StageRunner.d.ts +8 -1
  309. package/dist/types/lib/engine/handlers/commitStage.d.ts +7 -0
  310. package/dist/types/lib/engine/handlers/stageError.d.ts +9 -0
  311. package/dist/types/lib/engine/index.d.ts +2 -2
  312. package/dist/types/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +27 -13
  313. package/dist/types/lib/engine/narrative/FlowRecorderDispatcher.d.ts +4 -1
  314. package/dist/types/lib/engine/narrative/NarrativeFlowRecorder.d.ts +22 -3
  315. package/dist/types/lib/engine/narrative/NullControlFlowNarrativeGenerator.d.ts +1 -0
  316. package/dist/types/lib/engine/narrative/formatting/sentences.d.ts +23 -0
  317. package/dist/types/lib/engine/narrative/index.d.ts +2 -2
  318. package/dist/types/lib/engine/narrative/narrativeTypes.d.ts +27 -21
  319. package/dist/types/lib/engine/narrative/recorders/ManifestFlowRecorder.d.ts +45 -2
  320. package/dist/types/lib/engine/narrative/recorders/index.d.ts +1 -1
  321. package/dist/types/lib/engine/narrative/types.d.ts +74 -5
  322. package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +59 -19
  323. package/dist/types/lib/engine/traversalContext.d.ts +7 -2
  324. package/dist/types/lib/engine/types.d.ts +52 -57
  325. package/dist/types/lib/errors/terminalFailure.d.ts +29 -0
  326. package/dist/types/lib/{decide → filter}/evaluator.d.ts +7 -2
  327. package/dist/types/lib/ids/idempotencyKey.d.ts +14 -0
  328. package/dist/types/lib/memory/StageContext.d.ts +123 -3
  329. package/dist/types/lib/memory/attention.d.ts +26 -0
  330. package/dist/types/lib/memory/borrowedMutation.d.ts +8 -0
  331. package/dist/types/lib/memory/frameTypes.d.ts +38 -0
  332. package/dist/types/lib/memory/redaction.d.ts +12 -0
  333. package/dist/types/lib/pause/types.d.ts +19 -0
  334. package/dist/types/lib/reactive/types.d.ts +36 -4
  335. package/dist/types/lib/recorder/AttemptRecorder.d.ts +141 -0
  336. package/dist/types/lib/recorder/ControlDepRecorder.d.ts +36 -2
  337. package/dist/types/lib/recorder/EmitRecorder.d.ts +3 -0
  338. package/dist/types/lib/recorder/InOutRecorder.d.ts +37 -1
  339. package/dist/types/lib/recorder/QualityRecorder.d.ts +32 -5
  340. package/dist/types/lib/recorder/TopologyRecorder.d.ts +35 -5
  341. package/dist/types/lib/recorder/attemptMetricRows.d.ts +11 -0
  342. package/dist/types/lib/recorder/attemptMetrics.d.ts +7 -0
  343. package/dist/types/lib/recorder/attemptMetricsTypes.d.ts +114 -0
  344. package/dist/types/lib/recorder/attemptOTel.d.ts +78 -0
  345. package/dist/types/lib/recorder/attemptSeries.d.ts +81 -0
  346. package/dist/types/lib/recorder/hooks.d.ts +9 -0
  347. package/dist/types/lib/runner/ExecutionRuntime.d.ts +54 -6
  348. package/dist/types/lib/runner/FlowChartExecutor.d.ts +46 -2
  349. package/dist/types/lib/runner/RunnableChart.d.ts +6 -0
  350. package/dist/types/lib/runner/attach.d.ts +2 -1
  351. package/dist/types/lib/runner/deadline.d.ts +42 -0
  352. package/dist/types/lib/runner/index.d.ts +3 -1
  353. package/dist/types/lib/runner/options.d.ts +17 -0
  354. package/dist/types/lib/runner/recordSink.d.ts +128 -0
  355. package/dist/types/lib/runner/resume.d.ts +3 -0
  356. package/dist/types/lib/runner/snapshot.d.ts +2 -2
  357. package/dist/types/lib/scope/ScopeFacade.d.ts +118 -4
  358. package/dist/types/lib/scope/recorders/DebugRecorder.d.ts +17 -3
  359. package/dist/types/lib/scope/recorders/MetricRecorder.d.ts +10 -0
  360. package/dist/types/lib/scope/runtime.d.ts +3 -0
  361. package/dist/types/lib/scope/types.d.ts +6 -0
  362. package/dist/types/lib/sinks/fileSink.d.ts +135 -0
  363. package/dist/types/recorders.d.ts +8 -2
  364. package/dist/types/sinks.d.ts +23 -0
  365. package/dist/types/trace.d.ts +2 -2
  366. package/package.json +20 -6
  367. package/dist/esm/lib/decide/evaluator.js +0 -130
  368. package/dist/lib/decide/evaluator.js +0 -134
@@ -0,0 +1,135 @@
1
+ /**
2
+ * filter/evaluator -- Prisma-style filter evaluator for decision rules.
3
+ *
4
+ * Pure function. Takes a WhereFilter, a value getter, and a redaction checker.
5
+ * Evaluates each condition, records the result, returns matched/conditions.
6
+ *
7
+ * All keys in the filter are ANDed (all must match for the rule to match).
8
+ * Decoupled from ScopeFacade — receives callbacks, not scope.
9
+ *
10
+ * A LEAF module of its own (P2, 10.1): `decide()` (decide/) and the attempt rule table (attempt/decision.ts) share
11
+ * this one law, and neither may reach the other's dependencies through it. In decide/ it made `attempt/` reach
12
+ * `scope/` (decide.ts imports the scope runtime), so a `scope → attempt` edge — `scope.$call` — closed a module
13
+ * cycle.
14
+ */
15
+ import { summarizeValue } from '../capture/summarize.js';
16
+ import { isDevMode } from '../devMode.js';
17
+ import { SCOPE_PLACEHOLDER } from '../memory/redaction.js';
18
+ const OPERATOR_HANDLERS = {
19
+ eq: (a, t) => a === t,
20
+ ne: (a, t) => a !== t,
21
+ gt: (a, t) => a > t,
22
+ gte: (a, t) => a >= t,
23
+ lt: (a, t) => a < t,
24
+ lte: (a, t) => a <= t,
25
+ in: (a, t) => {
26
+ if (!Array.isArray(t))
27
+ return false;
28
+ if (t.length > MAX_IN_ARRAY_SIZE) {
29
+ throw new Error(`in/notIn array exceeds maximum size of ${MAX_IN_ARRAY_SIZE}`);
30
+ }
31
+ return t.includes(a);
32
+ },
33
+ notIn: (a, t) => {
34
+ if (!Array.isArray(t))
35
+ return true; // not in a non-array = vacuously true
36
+ if (t.length > MAX_IN_ARRAY_SIZE) {
37
+ throw new Error(`in/notIn array exceeds maximum size of ${MAX_IN_ARRAY_SIZE}`);
38
+ }
39
+ return !t.includes(a);
40
+ },
41
+ };
42
+ // -- Security: prototype pollution denylist ----------------------------------
43
+ const DENIED_KEYS = new Set([
44
+ '__proto__',
45
+ 'constructor',
46
+ 'prototype',
47
+ 'toString',
48
+ 'valueOf',
49
+ 'hasOwnProperty',
50
+ 'isPrototypeOf',
51
+ 'propertyIsEnumerable',
52
+ '__defineGetter__',
53
+ '__defineSetter__',
54
+ '__lookupGetter__',
55
+ '__lookupSetter__',
56
+ ]);
57
+ // -- Constants ---------------------------------------------------------------
58
+ const MAX_IN_ARRAY_SIZE = 1000;
59
+ const MAX_VALUE_LEN = 80;
60
+ // -- Evaluator ---------------------------------------------------------------
61
+ /**
62
+ * Evaluates a Prisma-style filter against scope values.
63
+ *
64
+ * ## Empty filter → NO match (anti-vacuous-truth — inverts Prisma/SQL)
65
+ *
66
+ * A filter with no evaluable conditions (`{}`, or only denied/non-object
67
+ * keys) returns `matched: false`. This deliberately INVERTS the Prisma/SQL
68
+ * intuition where `where: {}` matches everything: in a decision rule, a rule
69
+ * that asserts nothing should never win a branch — "all zero conditions
70
+ * passed" is vacuous truth, and silently routing on it would fabricate
71
+ * decision evidence. Want a catch-all? Use the explicit `defaultBranch`
72
+ * argument of `decide()` instead of an empty `when`.
73
+ *
74
+ * ## Unknown operators → condition fails (+ dev-mode warning)
75
+ *
76
+ * An operator outside the supported set (`eq, ne, gt, gte, lt, lte, in,
77
+ * notIn`) records a failed condition — the rule can never spuriously match
78
+ * through a typo (`gte` misspelled `gle`). With dev mode enabled
79
+ * (`enableDevMode()`), a console warning names the unknown operator and key.
80
+ *
81
+ * @param getValueFn - Reads a value from scope by key (raw, for comparison)
82
+ * @param isRedactedFn - Checks if a key is redacted (for evidence display)
83
+ * @param filter - The WhereFilter to evaluate
84
+ * @returns { matched, conditions } — matched = all conditions passed
85
+ */
86
+ export function evaluateFilter(getValueFn, isRedactedFn, filter) {
87
+ const conditions = [];
88
+ let allMatched = true;
89
+ for (const [key, ops] of Object.entries(filter)) {
90
+ // Security: denied keys cause rule to fail (consistent with unknown operator behavior)
91
+ if (DENIED_KEYS.has(key)) {
92
+ allMatched = false;
93
+ continue;
94
+ }
95
+ if (!ops || typeof ops !== 'object')
96
+ continue;
97
+ const actual = getValueFn(key);
98
+ const redacted = isRedactedFn(key);
99
+ const displayValue = redacted ? SCOPE_PLACEHOLDER : summarizeValue(actual, MAX_VALUE_LEN);
100
+ // Evaluate each operator in the FilterOps for this key
101
+ for (const [op, threshold] of Object.entries(ops)) {
102
+ const handler = OPERATOR_HANDLERS[op];
103
+ if (!handler) {
104
+ // Unknown operator: treat as failed condition so rule doesn't spuriously match
105
+ if (isDevMode()) {
106
+ // eslint-disable-next-line no-console
107
+ console.warn(`[footprint] decide()/select() filter: unknown operator "${op}" on key "${key}" — ` +
108
+ `condition never matches (valid operators: ${Object.keys(OPERATOR_HANDLERS).join(', ')})`);
109
+ }
110
+ conditions.push({ key, op, threshold, actualSummary: displayValue, result: false, redacted });
111
+ allMatched = false;
112
+ continue;
113
+ }
114
+ const result = handler(actual, threshold);
115
+ conditions.push({
116
+ key,
117
+ op,
118
+ threshold,
119
+ actualSummary: displayValue,
120
+ result,
121
+ redacted,
122
+ });
123
+ if (!result)
124
+ allMatched = false;
125
+ }
126
+ }
127
+ // Empty filter (no evaluable conditions) should NOT match — prevents vacuous
128
+ // truth. NOTE: this deliberately inverts Prisma/SQL `where: {}` ("match
129
+ // everything") — see the function JSDoc. Catch-alls belong in decide()'s
130
+ // explicit defaultBranch, not in an empty rule.
131
+ if (conditions.length === 0)
132
+ return { matched: false, conditions };
133
+ return { matched: allMatched, conditions };
134
+ }
135
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZhbHVhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9maWx0ZXIvZXZhbHVhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFFSCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFekQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQU0zRCxNQUFNLGlCQUFpQixHQUErQjtJQUNwRCxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQztJQUNyQixFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQztJQUNyQixFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBRSxDQUFZLEdBQUksQ0FBWTtJQUMzQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBRSxDQUFZLElBQUssQ0FBWTtJQUM3QyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBRSxDQUFZLEdBQUksQ0FBWTtJQUMzQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBRSxDQUFZLElBQUssQ0FBWTtJQUM3QyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDWCxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUNwQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEdBQUcsaUJBQWlCLEVBQUUsQ0FBQztZQUNqQyxNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxpQkFBaUIsRUFB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LEtBQUssQ0FBQztnQkFDbkIsU0FBUztZQUNYLENBQUM7WUFFRCxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQzFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7Z0JBQ2QsR0FBRztnQkFDSCxFQUFFO2dCQUNGLFNBQVM7Z0JBQ1QsYUFBYSxFQUFFLFlBQVk7Z0JBQzNCLE1BQU07Z0JBQ04sUUFBUTthQUNULENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxNQUFNO2dCQUFFLFVBQVUsR0FBRyxLQUFLLENBQUM7UUFDbEMsQ0FBQztJQUNILENBQUM7SUFFRCw2RUFBNkU7SUFDN0Usd0VBQXdFO0lBQ3hFLHlFQUF5RTtJQUN6RSxnREFBZ0Q7SUFDaEQsSUFBSSxVQUFVLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsQ0FBQztJQUVuRSxPQUFPLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsQ0FBQztBQUM3QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBmaWx0ZXIvZXZhbHVhdG9yIC0tIFByaXNtYS1zdHlsZSBmaWx0ZXIgZXZhbHVhdG9yIGZvciBkZWNpc2lvbiBydWxlcy5cbiAqXG4gKiBQdXJlIGZ1bmN0aW9uLiBUYWtlcyBhIFdoZXJlRmlsdGVyLCBhIHZhbHVlIGdldHRlciwgYW5kIGEgcmVkYWN0aW9uIGNoZWNrZXIuXG4gKiBFdmFsdWF0ZXMgZWFjaCBjb25kaXRpb24sIHJlY29yZHMgdGhlIHJlc3VsdCwgcmV0dXJucyBtYXRjaGVkL2NvbmRpdGlvbnMuXG4gKlxuICogQWxsIGtleXMgaW4gdGhlIGZpbHRlciBhcmUgQU5EZWQgKGFsbCBtdXN0IG1hdGNoIGZvciB0aGUgcnVsZSB0byBtYXRjaCkuXG4gKiBEZWNvdXBsZWQgZnJvbSBTY29wZUZhY2FkZSDigJQgcmVjZWl2ZXMgY2FsbGJhY2tzLCBub3Qgc2NvcGUuXG4gKlxuICogQSBMRUFGIG1vZHVsZSBvZiBpdHMgb3duIChQMiwgMTAuMSk6IGBkZWNpZGUoKWAgKGRlY2lkZS8pIGFuZCB0aGUgYXR0ZW1wdCBydWxlIHRhYmxlIChhdHRlbXB0L2RlY2lzaW9uLnRzKSBzaGFyZVxuICogdGhpcyBvbmUgbGF3LCBhbmQgbmVpdGhlciBtYXkgcmVhY2ggdGhlIG90aGVyJ3MgZGVwZW5kZW5jaWVzIHRocm91Z2ggaXQuIEluIGRlY2lkZS8gaXQgbWFkZSBgYXR0ZW1wdC9gIHJlYWNoXG4gKiBgc2NvcGUvYCAoZGVjaWRlLnRzIGltcG9ydHMgdGhlIHNjb3BlIHJ1bnRpbWUpLCBzbyBhIGBzY29wZSDihpIgYXR0ZW1wdGAgZWRnZSDigJQgYHNjb3BlLiRjYWxsYCDigJQgY2xvc2VkIGEgbW9kdWxlXG4gKiBjeWNsZS5cbiAqL1xuXG5pbXBvcnQgeyBzdW1tYXJpemVWYWx1ZSB9IGZyb20gJy4uL2NhcHR1cmUvc3VtbWFyaXplLmpzJztcbmltcG9ydCB0eXBlIHsgRmlsdGVyQ29uZGl0aW9uLCBXaGVyZUZpbHRlciB9IGZyb20gJy4uL2RlY2lkZS90eXBlcy5qcyc7XG5pbXBvcnQgeyBpc0Rldk1vZGUgfSBmcm9tICcuLi9kZXZNb2RlLmpzJztcbmltcG9ydCB7IFNDT1BFX1BMQUNFSE9MREVSIH0gZnJvbSAnLi4vbWVtb3J5L3JlZGFjdGlvbi5qcyc7XG5cbi8vIC0tIE9wZXJhdG9yIGRpc3BhdGNoIHRhYmxlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxudHlwZSBPcGVyYXRvckZuID0gKGFjdHVhbDogdW5rbm93biwgdGhyZXNob2xkOiB1bmtub3duKSA9PiBib29sZWFuO1xuXG5jb25zdCBPUEVSQVRPUl9IQU5ETEVSUzogUmVjb3JkPHN0cmluZywgT3BlcmF0b3JGbj4gPSB7XG4gIGVxOiAoYSwgdCkgPT4gYSA9PT0gdCxcbiAgbmU6IChhLCB0KSA9PiBhICE9PSB0LFxuICBndDogKGEsIHQpID0+IChhIGFzIG51bWJlcikgPiAodCBhcyBudW1iZXIpLFxuICBndGU6IChhLCB0KSA9PiAoYSBhcyBudW1iZXIpID49ICh0IGFzIG51bWJlciksXG4gIGx0OiAoYSwgdCkgPT4gKGEgYXMgbnVtYmVyKSA8ICh0IGFzIG51bWJlciksXG4gIGx0ZTogKGEsIHQpID0+IChhIGFzIG51bWJlcikgPD0gKHQgYXMgbnVtYmVyKSxcbiAgaW46IChhLCB0KSA9PiB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHQpKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKHQubGVuZ3RoID4gTUFYX0lOX0FSUkFZX1NJWkUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW4vbm90SW4gYXJyYXkgZXhjZWVkcyBtYXhpbXVtIHNpemUgb2YgJHtNQVhfSU5fQVJSQVlfU0laRX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHQuaW5jbHVkZXMoYSk7XG4gIH0sXG4gIG5vdEluOiAoYSwgdCkgPT4ge1xuICAgIGlmICghQXJyYXkuaXNBcnJheSh0KSkgcmV0dXJuIHRydWU7IC8vIG5vdCBpbiBhIG5vbi1hcnJheSA9IHZhY3VvdXNseSB0cnVlXG4gICAgaWYgKHQubGVuZ3RoID4gTUFYX0lOX0FSUkFZX1NJWkUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW4vbm90SW4gYXJyYXkgZXhjZWVkcyBtYXhpbXVtIHNpemUgb2YgJHtNQVhfSU5fQVJSQVlfU0laRX1gKTtcbiAgICB9XG4gICAgcmV0dXJuICF0LmluY2x1ZGVzKGEpO1xuICB9LFxufTtcblxuLy8gLS0gU2VjdXJpdHk6IHByb3RvdHlwZSBwb2xsdXRpb24gZGVueWxpc3QgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5jb25zdCBERU5JRURfS0VZUyA9IG5ldyBTZXQoW1xuICAnX19wcm90b19fJyxcbiAgJ2NvbnN0cnVjdG9yJyxcbiAgJ3Byb3RvdHlwZScsXG4gICd0b1N0cmluZycsXG4gICd2YWx1ZU9mJyxcbiAgJ2hhc093blByb3BlcnR5JyxcbiAgJ2lzUHJvdG90eXBlT2YnLFxuICAncHJvcGVydHlJc0VudW1lcmFibGUnLFxuICAnX19kZWZpbmVHZXR0ZXJfXycsXG4gICdfX2RlZmluZVNldHRlcl9fJyxcbiAgJ19fbG9va3VwR2V0dGVyX18nLFxuICAnX19sb29rdXBTZXR0ZXJfXycsXG5dKTtcblxuLy8gLS0gQ29uc3RhbnRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5jb25zdCBNQVhfSU5fQVJSQVlfU0laRSA9IDEwMDA7XG5jb25zdCBNQVhfVkFMVUVfTEVOID0gODA7XG5cbi8vIC0tIEV2YWx1YXRvciAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBFdmFsdWF0ZXMgYSBQcmlzbWEtc3R5bGUgZmlsdGVyIGFnYWluc3Qgc2NvcGUgdmFsdWVzLlxuICpcbiAqICMjIEVtcHR5IGZpbHRlciDihpIgTk8gbWF0Y2ggKGFudGktdmFjdW91cy10cnV0aCDigJQgaW52ZXJ0cyBQcmlzbWEvU1FMKVxuICpcbiAqIEEgZmlsdGVyIHdpdGggbm8gZXZhbHVhYmxlIGNvbmRpdGlvbnMgKGB7fWAsIG9yIG9ubHkgZGVuaWVkL25vbi1vYmplY3RcbiAqIGtleXMpIHJldHVybnMgYG1hdGNoZWQ6IGZhbHNlYC4gVGhpcyBkZWxpYmVyYXRlbHkgSU5WRVJUUyB0aGUgUHJpc21hL1NRTFxuICogaW50dWl0aW9uIHdoZXJlIGB3aGVyZToge31gIG1hdGNoZXMgZXZlcnl0aGluZzogaW4gYSBkZWNpc2lvbiBydWxlLCBhIHJ1bGVcbiAqIHRoYXQgYXNzZXJ0cyBub3RoaW5nIHNob3VsZCBuZXZlciB3aW4gYSBicmFuY2gg4oCUIFwiYWxsIHplcm8gY29uZGl0aW9uc1xuICogcGFzc2VkXCIgaXMgdmFjdW91cyB0cnV0aCwgYW5kIHNpbGVudGx5IHJvdXRpbmcgb24gaXQgd291bGQgZmFicmljYXRlXG4gKiBkZWNpc2lvbiBldmlkZW5jZS4gV2FudCBhIGNhdGNoLWFsbD8gVXNlIHRoZSBleHBsaWNpdCBgZGVmYXVsdEJyYW5jaGBcbiAqIGFyZ3VtZW50IG9mIGBkZWNpZGUoKWAgaW5zdGVhZCBvZiBhbiBlbXB0eSBgd2hlbmAuXG4gKlxuICogIyMgVW5rbm93biBvcGVyYXRvcnMg4oaSIGNvbmRpdGlvbiBmYWlscyAoKyBkZXYtbW9kZSB3YXJuaW5nKVxuICpcbiAqIEFuIG9wZXJhdG9yIG91dHNpZGUgdGhlIHN1cHBvcnRlZCBzZXQgKGBlcSwgbmUsIGd0LCBndGUsIGx0LCBsdGUsIGluLFxuICogbm90SW5gKSByZWNvcmRzIGEgZmFpbGVkIGNvbmRpdGlvbiDigJQgdGhlIHJ1bGUgY2FuIG5ldmVyIHNwdXJpb3VzbHkgbWF0Y2hcbiAqIHRocm91Z2ggYSB0eXBvIChgZ3RlYCBtaXNzcGVsbGVkIGBnbGVgKS4gV2l0aCBkZXYgbW9kZSBlbmFibGVkXG4gKiAoYGVuYWJsZURldk1vZGUoKWApLCBhIGNvbnNvbGUgd2FybmluZyBuYW1lcyB0aGUgdW5rbm93biBvcGVyYXRvciBhbmQga2V5LlxuICpcbiAqIEBwYXJhbSBnZXRWYWx1ZUZuIC0gUmVhZHMgYSB2YWx1ZSBmcm9tIHNjb3BlIGJ5IGtleSAocmF3LCBmb3IgY29tcGFyaXNvbilcbiAqIEBwYXJhbSBpc1JlZGFjdGVkRm4gLSBDaGVja3MgaWYgYSBrZXkgaXMgcmVkYWN0ZWQgKGZvciBldmlkZW5jZSBkaXNwbGF5KVxuICogQHBhcmFtIGZpbHRlciAtIFRoZSBXaGVyZUZpbHRlciB0byBldmFsdWF0ZVxuICogQHJldHVybnMgeyBtYXRjaGVkLCBjb25kaXRpb25zIH0g4oCUIG1hdGNoZWQgPSBhbGwgY29uZGl0aW9ucyBwYXNzZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV2YWx1YXRlRmlsdGVyPFQgZXh0ZW5kcyBvYmplY3Q+KFxuICBnZXRWYWx1ZUZuOiAoa2V5OiBzdHJpbmcpID0+IHVua25vd24sXG4gIGlzUmVkYWN0ZWRGbjogKGtleTogc3RyaW5nKSA9PiBib29sZWFuLFxuICBmaWx0ZXI6IFdoZXJlRmlsdGVyPFQ+LFxuKTogeyBtYXRjaGVkOiBib29sZWFuOyBjb25kaXRpb25zOiBGaWx0ZXJDb25kaXRpb25bXSB9IHtcbiAgY29uc3QgY29uZGl0aW9uczogRmlsdGVyQ29uZGl0aW9uW10gPSBbXTtcbiAgbGV0IGFsbE1hdGNoZWQgPSB0cnVlO1xuXG4gIGZvciAoY29uc3QgW2tleSwgb3BzXSBvZiBPYmplY3QuZW50cmllcyhmaWx0ZXIpKSB7XG4gICAgLy8gU2VjdXJpdHk6IGRlbmllZCBrZXlzIGNhdXNlIHJ1bGUgdG8gZmFpbCAoY29uc2lzdGVudCB3aXRoIHVua25vd24gb3BlcmF0b3IgYmVoYXZpb3IpXG4gICAgaWYgKERFTklFRF9LRVlTLmhhcyhrZXkpKSB7XG4gICAgICBhbGxNYXRjaGVkID0gZmFsc2U7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKCFvcHMgfHwgdHlwZW9mIG9wcyAhPT0gJ29iamVjdCcpIGNvbnRpbnVlO1xuXG4gICAgY29uc3QgYWN0dWFsID0gZ2V0VmFsdWVGbihrZXkpO1xuICAgIGNvbnN0IHJlZGFjdGVkID0gaXNSZWRhY3RlZEZuKGtleSk7XG4gICAgY29uc3QgZGlzcGxheVZhbHVlID0gcmVkYWN0ZWQgPyBTQ09QRV9QTEFDRUhPTERFUiA6IHN1bW1hcml6ZVZhbHVlKGFjdHVhbCwgTUFYX1ZBTFVFX0xFTik7XG5cbiAgICAvLyBFdmFsdWF0ZSBlYWNoIG9wZXJhdG9yIGluIHRoZSBGaWx0ZXJPcHMgZm9yIHRoaXMga2V5XG4gICAgZm9yIChjb25zdCBbb3AsIHRocmVzaG9sZF0gb2YgT2JqZWN0LmVudHJpZXMob3BzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSkge1xuICAgICAgY29uc3QgaGFuZGxlciA9IE9QRVJBVE9SX0hBTkRMRVJTW29wXTtcbiAgICAgIGlmICghaGFuZGxlcikge1xuICAgICAgICAvLyBVbmtub3duIG9wZXJhdG9yOiB0cmVhdCBhcyBmYWlsZWQgY29uZGl0aW9uIHNvIHJ1bGUgZG9lc24ndCBzcHVyaW91c2x5IG1hdGNoXG4gICAgICAgIGlmIChpc0Rldk1vZGUoKSkge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgYFtmb290cHJpbnRdIGRlY2lkZSgpL3NlbGVjdCgpIGZpbHRlcjogdW5rbm93biBvcGVyYXRvciBcIiR7b3B9XCIgb24ga2V5IFwiJHtrZXl9XCIg4oCUIGAgK1xuICAgICAgICAgICAgICBgY29uZGl0aW9uIG5ldmVyIG1hdGNoZXMgKHZhbGlkIG9wZXJhdG9yczogJHtPYmplY3Qua2V5cyhPUEVSQVRPUl9IQU5ETEVSUykuam9pbignLCAnKX0pYCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGNvbmRpdGlvbnMucHVzaCh7IGtleSwgb3AsIHRocmVzaG9sZCwgYWN0dWFsU3VtbWFyeTogZGlzcGxheVZhbHVlLCByZXN1bHQ6IGZhbHNlLCByZWRhY3RlZCB9KTtcbiAgICAgICAgYWxsTWF0Y2hlZCA9IGZhbHNlO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzdWx0ID0gaGFuZGxlcihhY3R1YWwsIHRocmVzaG9sZCk7XG4gICAgICBjb25kaXRpb25zLnB1c2goe1xuICAgICAgICBrZXksXG4gICAgICAgIG9wLFxuICAgICAgICB0aHJlc2hvbGQsXG4gICAgICAgIGFjdHVhbFN1bW1hcnk6IGRpc3BsYXlWYWx1ZSxcbiAgICAgICAgcmVzdWx0LFxuICAgICAgICByZWRhY3RlZCxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoIXJlc3VsdCkgYWxsTWF0Y2hlZCA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8vIEVtcHR5IGZpbHRlciAobm8gZXZhbHVhYmxlIGNvbmRpdGlvbnMpIHNob3VsZCBOT1QgbWF0Y2gg4oCUIHByZXZlbnRzIHZhY3VvdXNcbiAgLy8gdHJ1dGguIE5PVEU6IHRoaXMgZGVsaWJlcmF0ZWx5IGludmVydHMgUHJpc21hL1NRTCBgd2hlcmU6IHt9YCAoXCJtYXRjaFxuICAvLyBldmVyeXRoaW5nXCIpIOKAlCBzZWUgdGhlIGZ1bmN0aW9uIEpTRG9jLiBDYXRjaC1hbGxzIGJlbG9uZyBpbiBkZWNpZGUoKSdzXG4gIC8vIGV4cGxpY2l0IGRlZmF1bHRCcmFuY2gsIG5vdCBpbiBhbiBlbXB0eSBydWxlLlxuICBpZiAoY29uZGl0aW9ucy5sZW5ndGggPT09IDApIHJldHVybiB7IG1hdGNoZWQ6IGZhbHNlLCBjb25kaXRpb25zIH07XG5cbiAgcmV0dXJuIHsgbWF0Y2hlZDogYWxsTWF0Y2hlZCwgY29uZGl0aW9ucyB9O1xufVxuIl19
@@ -0,0 +1,14 @@
1
+ /**
2
+ * ids/idempotencyKey.ts — the ONE format rule for an idempotency key (design §3.3, packet P3). A leaf: the attempt
3
+ * law (`attempt/effect.ts · admitIdempotencyKey`, a key a stage's rule or a `$call` gives) and the checkpoint decoder
4
+ * (`pause/record.ts`, a key a paused execution carries to its resume) both ask it, so a key a stored checkpoint
5
+ * smuggles in is held to the same rule as one the code made.
6
+ *
7
+ * 1–255 printable ASCII characters (`\x21`–`\x7e`), no space: a key travels in a request header
8
+ * (`Idempotency-Key`), so a CR/LF could forge one, and 255 is Stripe's limit, inside every header limit. The
9
+ * problem names the rule, never the value.
10
+ */
11
+ /** The longest idempotency key. */
12
+ export declare const MAX_IDEMPOTENCY_KEY_LENGTH = 255;
13
+ /** Why `value` is not an idempotency key, or `undefined` when it is one. */
14
+ export declare function idempotencyKeyProblem(value: unknown): string | undefined;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * ids/idempotencyKey.ts — the ONE format rule for an idempotency key (design §3.3, packet P3). A leaf: the attempt
3
+ * law (`attempt/effect.ts · admitIdempotencyKey`, a key a stage's rule or a `$call` gives) and the checkpoint decoder
4
+ * (`pause/record.ts`, a key a paused execution carries to its resume) both ask it, so a key a stored checkpoint
5
+ * smuggles in is held to the same rule as one the code made.
6
+ *
7
+ * 1–255 printable ASCII characters (`\x21`–`\x7e`), no space: a key travels in a request header
8
+ * (`Idempotency-Key`), so a CR/LF could forge one, and 255 is Stripe's limit, inside every header limit. The
9
+ * problem names the rule, never the value.
10
+ */
11
+ /** The longest idempotency key. */
12
+ export const MAX_IDEMPOTENCY_KEY_LENGTH = 255;
13
+ const KEY_CHARACTERS = /^[\x21-\x7e]+$/;
14
+ /** Why `value` is not an idempotency key, or `undefined` when it is one. */
15
+ export function idempotencyKeyProblem(value) {
16
+ if (typeof value !== 'string' || value.length === 0 || value.length > MAX_IDEMPOTENCY_KEY_LENGTH) {
17
+ return `must be a string of 1–${MAX_IDEMPOTENCY_KEY_LENGTH} characters`;
18
+ }
19
+ if (!KEY_CHARACTERS.test(value)) {
20
+ return 'must be printable ASCII with no space or control character — it travels in a request header';
21
+ }
22
+ return undefined;
23
+ }
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRlbXBvdGVuY3lLZXkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2lkcy9pZGVtcG90ZW5jeUtleS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7O0dBU0c7QUFFSCxtQ0FBbUM7QUFDbkMsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQUcsR0FBRyxDQUFDO0FBRTlDLE1BQU0sY0FBYyxHQUFHLGdCQUFnQixDQUFDO0FBRXhDLDRFQUE0RTtBQUM1RSxNQUFNLFVBQVUscUJBQXFCLENBQUMsS0FBYztJQUNsRCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHLDBCQUEwQixFQUFFLENBQUM7UUFDakcsT0FBTyx5QkFBeUIsMEJBQTBCLGFBQWEsQ0FBQztJQUMxRSxDQUFDO0lBQ0QsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNoQyxPQUFPLDZGQUE2RixDQUFDO0lBQ3ZHLENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBpZHMvaWRlbXBvdGVuY3lLZXkudHMg4oCUIHRoZSBPTkUgZm9ybWF0IHJ1bGUgZm9yIGFuIGlkZW1wb3RlbmN5IGtleSAoZGVzaWduIMKnMy4zLCBwYWNrZXQgUDMpLiBBIGxlYWY6IHRoZSBhdHRlbXB0XG4gKiBsYXcgKGBhdHRlbXB0L2VmZmVjdC50cyDCtyBhZG1pdElkZW1wb3RlbmN5S2V5YCwgYSBrZXkgYSBzdGFnZSdzIHJ1bGUgb3IgYSBgJGNhbGxgIGdpdmVzKSBhbmQgdGhlIGNoZWNrcG9pbnQgZGVjb2RlclxuICogKGBwYXVzZS9yZWNvcmQudHNgLCBhIGtleSBhIHBhdXNlZCBleGVjdXRpb24gY2FycmllcyB0byBpdHMgcmVzdW1lKSBib3RoIGFzayBpdCwgc28gYSBrZXkgYSBzdG9yZWQgY2hlY2twb2ludFxuICogc211Z2dsZXMgaW4gaXMgaGVsZCB0byB0aGUgc2FtZSBydWxlIGFzIG9uZSB0aGUgY29kZSBtYWRlLlxuICpcbiAqIDHigJMyNTUgcHJpbnRhYmxlIEFTQ0lJIGNoYXJhY3RlcnMgKGBcXHgyMWDigJNgXFx4N2VgKSwgbm8gc3BhY2U6IGEga2V5IHRyYXZlbHMgaW4gYSByZXF1ZXN0IGhlYWRlclxuICogKGBJZGVtcG90ZW5jeS1LZXlgKSwgc28gYSBDUi9MRiBjb3VsZCBmb3JnZSBvbmUsIGFuZCAyNTUgaXMgU3RyaXBlJ3MgbGltaXQsIGluc2lkZSBldmVyeSBoZWFkZXIgbGltaXQuIFRoZVxuICogcHJvYmxlbSBuYW1lcyB0aGUgcnVsZSwgbmV2ZXIgdGhlIHZhbHVlLlxuICovXG5cbi8qKiBUaGUgbG9uZ2VzdCBpZGVtcG90ZW5jeSBrZXkuICovXG5leHBvcnQgY29uc3QgTUFYX0lERU1QT1RFTkNZX0tFWV9MRU5HVEggPSAyNTU7XG5cbmNvbnN0IEtFWV9DSEFSQUNURVJTID0gL15bXFx4MjEtXFx4N2VdKyQvO1xuXG4vKiogV2h5IGB2YWx1ZWAgaXMgbm90IGFuIGlkZW1wb3RlbmN5IGtleSwgb3IgYHVuZGVmaW5lZGAgd2hlbiBpdCBpcyBvbmUuICovXG5leHBvcnQgZnVuY3Rpb24gaWRlbXBvdGVuY3lLZXlQcm9ibGVtKHZhbHVlOiB1bmtub3duKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycgfHwgdmFsdWUubGVuZ3RoID09PSAwIHx8IHZhbHVlLmxlbmd0aCA+IE1BWF9JREVNUE9URU5DWV9LRVlfTEVOR1RIKSB7XG4gICAgcmV0dXJuIGBtdXN0IGJlIGEgc3RyaW5nIG9mIDHigJMke01BWF9JREVNUE9URU5DWV9LRVlfTEVOR1RIfSBjaGFyYWN0ZXJzYDtcbiAgfVxuICBpZiAoIUtFWV9DSEFSQUNURVJTLnRlc3QodmFsdWUpKSB7XG4gICAgcmV0dXJuICdtdXN0IGJlIHByaW50YWJsZSBBU0NJSSB3aXRoIG5vIHNwYWNlIG9yIGNvbnRyb2wgY2hhcmFjdGVyIOKAlCBpdCB0cmF2ZWxzIGluIGEgcmVxdWVzdCBoZWFkZXInO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG4iXX0=
@@ -13,12 +13,28 @@
13
13
  */
14
14
  import type { CommitPhase, EmitSourcePosition, UntrackedSource } from 'foottrace';
15
15
  import type { EventLog, SharedMemory } from 'foottrace/write';
16
+ import type { AttemptContext, AttemptRecord, AttemptSummary, LateWrite } from '../attempt/types.js';
17
+ import type { StructuredErrorInfo } from '../errors/errorInfo.js';
18
+ import { type TerminalFailureContext, NativeFailureState } from '../errors/terminalFailure.js';
16
19
  import { type DiagnosticChannel, DiagnosticCollector } from './DiagnosticCollector.js';
17
20
  import type { FlowControlType, StageSnapshot } from './frameTypes.js';
18
21
  import type { RedactionVerdict } from './redaction.js';
19
22
  import { RedactionRule } from './redaction.js';
20
23
  import type { RunPolicy } from './runPolicy.js';
24
+ /**
25
+ * How many call and observed attempt records one stage execution keeps (P2) — a stage that calls in a loop must
26
+ * not grow the execution tree without bound. The rest are counted (`StageSnapshot.attemptsDropped`) and still
27
+ * fired on `onAttempt`. A stage's OWN attempt records are never displaced: its policy's ceiling bounds them.
28
+ */
29
+ export declare const MAX_CALL_RECORDS = 1000;
21
30
  export declare class StageContext {
31
+ #private;
32
+ /** @internal Ownership of an escaping failure. Shared only by sequential frames, never serialized. */
33
+ failureState: NativeFailureState;
34
+ /** @internal The native frame stamp, independent of mutable recorder event context. */
35
+ get failureIdentity(): NonNullable<TerminalFailureContext['stage']> | undefined;
36
+ /** @internal Stamped before observers; never inherited by another frame or persisted. */
37
+ bindFailureIdentity(runId: string, runtimeStageId: string): void;
22
38
  /**
23
39
  * The record half of this frame (`RecordFrame.ts`, L3, C3): the heap and,
24
40
  * when the run keeps them, the redacted mirror and the log; the address;
@@ -138,6 +154,41 @@ export declare class StageContext {
138
154
  * stages that never touch an untracked path pay nothing.
139
155
  */
140
156
  private _untrackedSources?;
157
+ /**
158
+ * The attempts of this frame's execution (10.1) — its own under the attempt runner, appended as each attempt ends
159
+ * (`FlowchartTraverser · executeStage`), and those of the calls it made (P2, {@link reportCallAttempt}) — read
160
+ * by {@link snapshotSelf}. Append-only
161
+ * evidence like `debug`: NOT cleared by {@link discardStaged} (the earlier attempts are the point) and never
162
+ * part of a commit bundle. Lazily allocated: a stage without a policy pays nothing.
163
+ */
164
+ private _attempts?;
165
+ /** The attempt series at a glance, stamped once when it ends. */
166
+ private _attemptSummary?;
167
+ /** Facts collected for this execution only; retry discards deliberately keep them. */
168
+ private _attention?;
169
+ /**
170
+ * The attempt now running (P1b) — set by `StageRunner` before the scope is built, so the facade can hand it out
171
+ * (`scope.$attempt()`) and fence its own attempt. Absent for a stage the attempt runner does not run.
172
+ */
173
+ private _attempt?;
174
+ /** The run's signal, for the attempt a stage outside the runner reports (attempt 1 of 1). */
175
+ private _runSignal?;
176
+ /** Every attempt up to this number has ENDED without an answer — its scope is fenced (0 = none). */
177
+ private _endedThrough;
178
+ /** Writes an attempt tried after it ended — dropped at the scope, kept here as names. Lazily allocated. */
179
+ private _lateWrites?;
180
+ /**
181
+ * Where a call's attempt records are reported (P2) — the engine's `onAttempt` for this stage execution, set by
182
+ * `FlowchartTraverser · executeStage` with the stage's own traversal context (and its correlation).
183
+ */
184
+ private _attemptReporter?;
185
+ /** Calls made so far, per stage attempt — the `k` of a call's series. Lazily allocated. */
186
+ private _callOrdinals?;
187
+ /** Per stage attempt, the signal its calls stop by (`callsEndedSignal`). Lazily allocated. */
188
+ private _callsEnded?;
189
+ /** Call and observed records kept on the frame, and those past {@link MAX_CALL_RECORDS}. */
190
+ private _callRecords;
191
+ private _attemptsDropped;
141
192
  /** Observer called after commit() — used by ScopeFacade to fire ScopeRecorder.onCommit. */
142
193
  private _commitObserver?;
143
194
  constructor(runId: string, name: string, stageId: string, sharedMemory: SharedMemory, branchId?: string, eventLog?: EventLog, isDecider?: boolean);
@@ -404,6 +455,8 @@ export declare class StageContext {
404
455
  * reads them post-run for the execution-tree snapshot.
405
456
  */
406
457
  commit(phase?: CommitPhase): void;
458
+ /** Whether this frame has committed — a call's record arriving after it is late (P2, `ScopeFacade · call`). */
459
+ get committed(): boolean;
407
460
  /**
408
461
  * Throw away everything this stage has STAGED, without committing any of it.
409
462
  *
@@ -429,14 +482,81 @@ export declare class StageContext {
429
482
  * holds bare references — dropping it un-clones nothing);
430
483
  * - `_untrackedSources` — the D2 honesty markers, released with the rest.
431
484
  *
432
- * What is deliberately KEPT: `debug` (logs, metrics, errors, flow messages).
433
- * Diagnostics are the append-only record of what every attempt did, and the
434
- * retry feature's whole point is that the earlier attempts stay visible.
485
+ * What is deliberately KEPT: `debug` (logs, metrics, errors, flow messages)
486
+ * and the attempt records (10.1). Both are the append-only record of what
487
+ * every attempt did, and the retry feature's whole point is that the earlier
488
+ * attempts stay visible.
435
489
  *
436
490
  * No commit is recorded and no observer fires — a discarded attempt is not a
437
491
  * cursor stop, because from shared state's point of view it never happened.
438
492
  */
439
493
  discardStaged(): void;
494
+ /** Append one attempt's record — the attempt runner calls this as each attempt ends. */
495
+ recordAttempt(record: AttemptRecord): void;
496
+ /** Stamp the series' summary — once, when the runner ends the series. */
497
+ endAttempts(summary: AttemptSummary): void;
498
+ /** Reset only at the node's execution stamp, never between attempts. */
499
+ beginAttention(): void;
500
+ /** Delegate the explicit retained-error fact; attention owns validation of its proof. */
501
+ markStageFailure(): void;
502
+ /**
503
+ * The crash-safe record (10.1, P6): an attempt that ended is noted in the run's sink AT ONCE, beside this frame's
504
+ * log — so a process killed before the stage commits (mid-retry) still leaves every attempt that ended. The
505
+ * record is the one the tree keeps: frozen, `structuredClone`-safe, its error the SERVED form (no `raw`), so the
506
+ * note needs no second redaction pass. Without a sink the log does nothing (`EventLog · note`).
507
+ */
508
+ private noteAttempt;
509
+ /** The attempts of this execution so far, in order — its own and its calls'; `undefined` when there are none. */
510
+ get attempts(): readonly AttemptRecord[] | undefined;
511
+ /** The ended series' summary; `undefined` while it runs and without a policy. */
512
+ get attemptSummary(): AttemptSummary | undefined;
513
+ /** The attempt about to run (and the run's signal) — `StageRunner` sets both before it builds the scope. */
514
+ useAttempt(attempt: AttemptContext | undefined, runSignal: AbortSignal | undefined): void;
515
+ /** The attempt now running; `undefined` for a stage the attempt runner does not run. */
516
+ get attempt(): AttemptContext | undefined;
517
+ /** The run's signal, as `StageRunner` last saw it. */
518
+ get runSignal(): AbortSignal | undefined;
519
+ /**
520
+ * Attempt `attempt` ended without an answer: from now on its scope is fenced — a write, an emit or a read
521
+ * through it is refused (`ScopeFacade`). The runner calls this the moment the attempt's signal aborts.
522
+ */
523
+ endAttempt(attempt: number): void;
524
+ /** Whether attempt `attempt` has ended — its scope may no longer touch the stage. */
525
+ hasAttemptEnded(attempt: number): boolean;
526
+ /** Record a write an ended attempt tried — a name, never the value. Append-only evidence like the attempts. */
527
+ recordLateWrite(write: LateWrite): void;
528
+ /** This execution's own idempotency key may be made of a selected value (or was carried by a checkpoint). */
529
+ private _effectKeyTainted;
530
+ /** A touching `$call` with NO key started in this execution — the stage may not be re-run by a resume. */
531
+ private _keylessEffect;
532
+ /**
533
+ * Start an execution's side-effect bookkeeping (`FlowchartTraverser · executeStage`, before attempt 1) — reset,
534
+ * because a frame can be re-used by a later execution. `keyTainted`: the stage's own key may be made of a selected
535
+ * value, so a key a `$call` passes on (`$attempt().idempotencyKey`) is served the same way.
536
+ */
537
+ beginEffects(keyTainted: boolean): void;
538
+ get effectKeyTainted(): boolean;
539
+ /** A keyless touching `$call` started: an `interrupt()` after it would re-send it on resume (`StageRunner`). */
540
+ markKeylessEffect(): void;
541
+ get hasKeylessEffect(): boolean;
542
+ /** Where this execution's call records are reported — the engine sets it before the stage runs. */
543
+ useAttemptReporter(report: ((record: AttemptRecord, structuredError: StructuredErrorInfo | undefined) => void) | undefined): void;
544
+ /**
545
+ * The signal the calls of stage attempt `stageAttempt` run under besides its own (P2): aborted when that attempt is
546
+ * over — however it ended — and when the frame commits, so no call outlives the attempt that made it (no
547
+ * background retry, no wait, no listener left on the run's signal). Already aborted after the commit.
548
+ */
549
+ callsEndedSignal(stageAttempt: number): AbortSignal;
550
+ /** End the calls of `stageAttempt` (every attempt's when `undefined`) — `reason` when the attempt's signal gave one. */
551
+ private endCalls;
552
+ /** The next call's ordinal within stage attempt `stageAttempt`, 1-based (`attempt/call.ts · callSeries`). */
553
+ nextCallOrdinal(stageAttempt: number): number;
554
+ /**
555
+ * A call's (or an observed) attempt record: kept beside the stage's own attempts — the first
556
+ * {@link MAX_CALL_RECORDS}, the rest counted — and reported to the run's `onAttempt` either way. Like the stage's
557
+ * records, NOT cleared by {@link discardStaged}: a failed attempt's calls are evidence too.
558
+ */
559
+ reportCallAttempt(record: AttemptRecord, structuredError: StructuredErrorInfo | undefined): void;
440
560
  /**
441
561
  * Create (or return) this context's linked successor.
442
562
  *