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
@@ -5,12 +5,19 @@
5
5
  * The CombinedNarrativeBuilder class was removed in v1.0.
6
6
  * Use CombinedNarrativeRecorder (auto-attached by setEnableNarrative()) instead.
7
7
  */
8
+ import type { AttemptRecord } from '../../attempt/types.js';
8
9
  export interface CombinedNarrativeEntry {
9
10
  type: 'stage' | 'step' | 'condition' | 'fork' | 'selector' | 'subflow' | 'loop' | 'break' | 'error' | 'pause' | 'resume' | 'emit'
10
- /** A failed attempt at a stage with a declared retry policy, which was
11
- * retried. Rendered as a depth-1 sub-item of its stage, IN ORDER between
12
- * the attempts' reads and writes. */
13
- | 'retry';
11
+ /** A failed attempt that was retried — rendered by 9.15–10.0 only. Since
12
+ * 10.1 the built-in narrative renders one `'attempt'` line per attempt
13
+ * instead; the member stays so a narrative stored by an earlier release
14
+ * still type-checks. */
15
+ | 'retry'
16
+ /** One attempt of a stage with a declared retry policy (10.1): its outcome,
17
+ * duration, cause and decision. A depth-1 sub-item of its stage, IN ORDER
18
+ * between the attempts' reads and writes; for a stage that failed, the
19
+ * lines follow its `'error'` entry. */
20
+ | 'attempt';
14
21
  text: string;
15
22
  depth: number;
16
23
  stageName?: string;
@@ -108,21 +115,14 @@ export interface ErrorRenderContext {
108
115
  validationIssues?: string;
109
116
  }
110
117
  /**
111
- * Context passed to `NarrativeFormatter.renderRetry` — one failed attempt at a
112
- * stage with a declared retry policy, which the engine then retried. Fires only
113
- * for attempts followed by another attempt; the final failure goes to
114
- * `renderError`.
118
+ * Context passed to `NarrativeFormatter.renderAttempt` — one attempt of a stage
119
+ * with a declared retry policy (10.1), whatever its outcome.
115
120
  */
116
- export interface RetryRenderContext {
121
+ export interface AttemptRenderContext {
122
+ /** The stage the attempt ran. */
117
123
  stageName: string;
118
- /** Which attempt just failed, 1-based. */
119
- attempt: number;
120
- /** Total attempts the policy allows, including the first. */
121
- maxAttempts: number;
122
- /** Milliseconds waited before the next attempt. `0` = immediate. */
123
- delayMs: number;
124
- /** The failed attempt's error message. */
125
- message: string;
124
+ /** The attempt: outcome, duration, category, the served error, and the retry-or-stop decision. */
125
+ record: AttemptRecord;
126
126
  }
127
127
  /**
128
128
  * Context passed to `NarrativeFormatter.renderEmit` — fires for every
@@ -193,11 +193,17 @@ export interface NarrativeFormatter {
193
193
  renderBreak?(ctx: BreakRenderContext): string;
194
194
  renderError?(ctx: ErrorRenderContext): string;
195
195
  /**
196
- * Format a retried attempt into a narrative line. Rendered as a depth-1
197
- * sub-item of its stage, positioned between the attempts' reads and writes
198
- * so the narrative reads in the order things actually happened.
196
+ * Format one attempt of a retried stage (10.1) into a narrative line — a
197
+ * depth-1 sub-item of its stage, between the attempts' reads and writes (for
198
+ * a stage that failed for good, beneath its error line). It replaces the
199
+ * 9.15–10.0 `renderRetry`, which is removed: this line says "retrying" too.
200
+ *
201
+ * - `string` → use as the narrative line
202
+ * - `null` → deliberately exclude this entry
203
+ * - `undefined` → fall back to the library's default sentence
204
+ * (`Attempt 2 of 3 at Fetch failed in 12ms (…), retrying in 1s.`)
199
205
  */
200
- renderRetry?(ctx: RetryRenderContext): string;
206
+ renderAttempt?(ctx: AttemptRenderContext): string | null | undefined;
201
207
  /**
202
208
  * Format a consumer-emitted event (from `scope.$emit(name, payload)`)
203
209
  * into a narrative line.
@@ -9,6 +9,14 @@
9
9
  * The manifest reflects only subflows that were actually entered during
10
10
  * execution — unvisited branches are not included.
11
11
  *
12
+ * Attempts (10.1): a stage whose retry series retried, gave up or timed out gets a row —
13
+ * `{ stageId, stageName, runtimeStageId, attempts: AttemptSummary }` — on the
14
+ * entry of the subflow it ran in (`ManifestEntry.attempts`). The manifest has
15
+ * no entry for the top-level chart, so a top-level stage's row (or one whose
16
+ * subflow entry this recorder never saw) is served by `getRootAttempts()` and
17
+ * rides the snapshot bundle's `meta.rootAttempts` (absent when empty — the
18
+ * bundle's `data` keeps its shape).
19
+ *
12
20
  * @example
13
21
  * ```typescript
14
22
  * const manifest = new ManifestFlowRecorder();
@@ -22,7 +30,18 @@
22
30
  * const spec = manifest.getSpec('sf-credit-check');
23
31
  * ```
24
32
  */
25
- import type { FlowRecorder, FlowSubflowEvent, FlowSubflowRegisteredEvent } from '../types.js';
33
+ import type { AttemptSummary } from '../../../attempt/types.js';
34
+ import type { FlowAttemptEvent, FlowRecorder, FlowSubflowEvent, FlowSubflowRegisteredEvent } from '../types.js';
35
+ /** One stage execution whose retry series retried, gave up or timed out, at a glance. */
36
+ export interface ManifestAttemptRow {
37
+ /** Stable stage id (path-prefixed inside a subflow). */
38
+ stageId: string;
39
+ stageName: string;
40
+ /** The execution — the series' `runtimeStageId`. */
41
+ runtimeStageId: string;
42
+ /** The series at a glance — equal to the stage's `StageSnapshot.attemptSummary`. */
43
+ attempts: AttemptSummary;
44
+ }
26
45
  /** A single entry in the subflow manifest tree. */
27
46
  export interface ManifestEntry {
28
47
  /** Subflow identifier — use for on-demand spec lookup. */
@@ -33,6 +52,8 @@ export interface ManifestEntry {
33
52
  description?: string;
34
53
  /** Nested subflows entered within this subflow. */
35
54
  children: ManifestEntry[];
55
+ /** Stages run directly in this subflow whose series retried, gave up or timed out — absent when none did. */
56
+ attempts?: ManifestAttemptRow[];
36
57
  }
37
58
  export declare class ManifestFlowRecorder implements FlowRecorder {
38
59
  readonly id: string;
@@ -42,12 +63,31 @@ export declare class ManifestFlowRecorder implements FlowRecorder {
42
63
  private roots;
43
64
  /** Full specs stored from dynamic registration events. */
44
65
  private specs;
66
+ /**
67
+ * Open entries by subflowId — where a stage's row lands. Not the stack: parallel subflow siblings exit out of
68
+ * stack order, so the entry a row belongs to may no longer be on it.
69
+ */
70
+ private openEntries;
71
+ /** Rows of top-level stages — the manifest has no entry for the top-level chart. */
72
+ private rootAttempts;
73
+ /** Per-series tallies of the series that retried, gave up or timed out. */
74
+ private readonly attemptBook;
45
75
  constructor(id?: string);
46
76
  onSubflowEntry(event: FlowSubflowEvent): void;
47
- onSubflowExit(_event: FlowSubflowEvent): void;
77
+ onSubflowExit(event: FlowSubflowEvent): void;
78
+ /**
79
+ * A series' row lands once, when it ends, on the open entry of the subflow the stage ran in; a top-level
80
+ * stage's (or one whose entry this recorder never saw) on the root rows.
81
+ */
82
+ onAttempt(event: FlowAttemptEvent): void;
48
83
  onSubflowRegistered(event: FlowSubflowRegisteredEvent): void;
49
84
  /** Returns the manifest tree — lightweight, suitable for snapshot inclusion. */
50
85
  getManifest(): ManifestEntry[];
86
+ /**
87
+ * Rows of top-level stages whose series retried, gave up or timed out, in the order the series ended — plus any row of a
88
+ * subflow stage whose entry this recorder never saw (its path-prefixed `stageId` says where it ran).
89
+ */
90
+ getRootAttempts(): ManifestAttemptRow[];
51
91
  /**
52
92
  * Returns the full spec for a dynamically-registered subflow.
53
93
  * Only populated for subflows auto-registered at runtime (via StageNode
@@ -59,6 +99,9 @@ export declare class ManifestFlowRecorder implements FlowRecorder {
59
99
  /** Returns all stored spec IDs. */
60
100
  getSpecIds(): string[];
61
101
  toSnapshot(): {
102
+ meta?: {
103
+ rootAttempts: ManifestAttemptRow[];
104
+ } | undefined;
62
105
  name: string;
63
106
  description: string;
64
107
  preferredOperation: "translate";
@@ -1,5 +1,5 @@
1
1
  export { AdaptiveNarrativeFlowRecorder } from './AdaptiveNarrativeFlowRecorder.js';
2
- export type { ManifestEntry } from './ManifestFlowRecorder.js';
2
+ export type { ManifestAttemptRow, ManifestEntry } from './ManifestFlowRecorder.js';
3
3
  export { ManifestFlowRecorder } from './ManifestFlowRecorder.js';
4
4
  export { MilestoneNarrativeFlowRecorder } from './MilestoneNarrativeFlowRecorder.js';
5
5
  export { ProgressiveNarrativeFlowRecorder } from './ProgressiveNarrativeFlowRecorder.js';
@@ -6,8 +6,10 @@
6
6
  *
7
7
  * @module
8
8
  */
9
+ import type { AttemptRecord, RunCorrelation } from '../../attempt/types.js';
9
10
  import type { DecisionEvidence, SelectionEvidence } from '../../decide/types.js';
10
11
  import type { StructuredErrorInfo } from '../../errors/errorInfo.js';
12
+ import type { TerminalFailureContext } from '../../errors/terminalFailure.js';
11
13
  /**
12
14
  *
13
15
  * Uses Null Object pattern: NullControlFlowNarrativeGenerator satisfies this
@@ -63,11 +65,28 @@ export interface IControlFlowNarrative {
63
65
  * `RedactionRule.retainStageError` (the diagnostic policy applied once), elsewhere `extractErrorInfo`.
64
66
  */
65
67
  onError(stageName: string, errorMessage: string, structuredError: StructuredErrorInfo, traversalContext?: TraversalContext): void;
68
+ /**
69
+ * Called at the END of every attempt (10.1) — every outcome, with the
70
+ * attempt's {@link AttemptRecord} (timing, outcome, category, the
71
+ * retry-or-stop decision): a stage's own (`record.kind === 'stage'`, under a
72
+ * retry policy, a `timeoutMs` or a run deadline), and the calls it makes
73
+ * (`'call'`, `scope.$call`) and outside attempts it reports (`'observed'`)
74
+ * during the stage (P2). A stage attempt fires before `onStageRetry` when it
75
+ * is retried, and before `onError` / `onStageExecuted` for the last.
76
+ * `structuredError` is the attempt's served error (`raw` included unless the
77
+ * policy masked it; never for an observed attempt); absent for a success or
78
+ * a pause.
79
+ *
80
+ * Event arithmetic: one per attempt — for a stage, the number of attempts it
81
+ * made plus one per call or observed attempt (filter on `record.kind`).
82
+ */
83
+ onAttempt(stageName: string, stageId: string, record: AttemptRecord, structuredError: StructuredErrorInfo | undefined, traversalContext?: TraversalContext): void;
66
84
  /**
67
85
  * Called when an attempt at a stage with a declared `retry` policy failed
68
- * AND another attempt will run. Fires after the failed attempt's staged
69
- * writes are discarded and BEFORE the backoff wait, so a live monitor learns
70
- * "retrying in 500 ms" when the decision is made, not after the wait.
86
+ * AND another attempt will run. Fires after that attempt's `onAttempt`,
87
+ * after its staged writes are discarded and BEFORE the backoff wait, so a
88
+ * live monitor learns "retrying in 500 ms" when the decision is made, not
89
+ * after the wait.
71
90
  *
72
91
  * Event arithmetic: an exhausted policy fires `attempts - 1` of these and
73
92
  * then one `onError`; a `retryOn` that declines fires ZERO of these and one
@@ -113,7 +132,7 @@ export interface IControlFlowNarrative {
113
132
  * error, so it does not fire this. Subflow-traversers do NOT fire it;
114
133
  * their errors propagate to the parent and surface at the top level.
115
134
  */
116
- onRunFailed(error: StructuredErrorInfo, traversalContext?: TraversalContext): void;
135
+ onRunFailed(error: StructuredErrorInfo, traversalContext?: TraversalContext, failure?: TerminalFailureContext): void;
117
136
  /** Returns accumulated narrative sentences in execution order. */
118
137
  getSentences(): string[];
119
138
  }
@@ -193,6 +212,12 @@ export interface TraversalContext {
193
212
  * checkpoint predates 9.37.0 (it did not record the paused execution).
194
213
  */
195
214
  readonly resumedFrom?: ResumeLink;
215
+ /**
216
+ * The run's correlation (10.1) — `env.traceparent`, or `env.traceId` + `env.operationId`, resolved once per
217
+ * leg. The SAME frozen object, by reference, on every stamp of the leg (subflows included) and on
218
+ * `getSnapshot().correlation`. Absent — no key — when the env gives none.
219
+ */
220
+ readonly correlation?: RunCorrelation;
196
221
  }
197
222
  /**
198
223
  * The paused execution a resume continues — `TraversalContext.resumedFrom`.
@@ -339,6 +364,39 @@ export interface FlowThrottledEvent {
339
364
  /** Explicit channel discriminant — see {@link FlowErrorEvent.channel}. */
340
365
  channel?: 'flow';
341
366
  }
367
+ /**
368
+ * Event passed to FlowRecorder.onAttempt — one attempt, at its end (10.1): a
369
+ * stage's own under its retry policy, a `timeoutMs` or a run deadline
370
+ * (`record.kind === 'stage'`), or — during the stage — a call it made
371
+ * (`'call'`, `scope.$call`) or an outside attempt it reported (`'observed'`,
372
+ * P2). `stageName` / `stageId` / `traversalContext` are the stage's in every
373
+ * case; filter on `record.kind` to count one kind.
374
+ *
375
+ * WHY this event exists: `onStageRetry` says "attempt N failed, retrying" and
376
+ * nothing else — not how long a try took, not why the series stopped, and
377
+ * nothing at all when `retryOn` declined. Every attempt is an
378
+ * {@link AttemptRecord} instead, whatever its outcome, with the decision that
379
+ * followed it in the shape `decide()` records — the same records the stage's
380
+ * execution-tree node keeps (`StageSnapshot.attempts`).
381
+ *
382
+ * Fires once per attempt, before `onStageRetry` (when the attempt is retried)
383
+ * and before `onError` / `onStageExecuted` (for the last). The record is
384
+ * frozen and survives `structuredClone`; `structuredError` is the served error
385
+ * with `raw`, as on {@link FlowStageRetryEvent} — except for an observed
386
+ * attempt, whose error the library never threw (`raw` is undefined).
387
+ */
388
+ export interface FlowAttemptEvent {
389
+ stageName: string;
390
+ /** Stable stage identifier from the builder (matches spec node id). */
391
+ stageId: string;
392
+ /** The attempt: timing, outcome, category, decision, and the served error without `raw`. */
393
+ record: AttemptRecord;
394
+ /** The attempt's served error with `raw` — absent for a success or a pause. */
395
+ structuredError?: StructuredErrorInfo;
396
+ traversalContext?: TraversalContext;
397
+ /** Explicit channel discriminant — see {@link FlowErrorEvent.channel}. */
398
+ channel?: 'flow';
399
+ }
342
400
  /**
343
401
  * Event passed to FlowRecorder.onStageRetry — one failed attempt at a stage
344
402
  * that carries a declared {@link import('../types.js').RetryPolicy}, and which
@@ -352,7 +410,9 @@ export interface FlowThrottledEvent {
352
410
  * Fires only for attempts followed by another attempt. The final failure takes
353
411
  * the ordinary error path (`onError`), so the two never double-report the same
354
412
  * failure: an exhausted `attempts: 3` policy emits 2 retry events + 1 error
355
- * event; a `retryOn` that declines emits 0 retry events + 1 error event.
413
+ * event; a `retryOn` that declines emits 0 retry events + 1 error event. Each
414
+ * attempt — retried or not — also fires {@link FlowAttemptEvent} first (10.1),
415
+ * which is where a declined stop is recorded (`reason: 'declined'`).
356
416
  */
357
417
  export interface FlowStageRetryEvent {
358
418
  stageName: string;
@@ -428,6 +488,8 @@ export interface FlowRunFailedEvent {
428
488
  /** Structured details of the error that terminated the run. */
429
489
  structuredError: StructuredErrorInfo;
430
490
  traversalContext?: TraversalContext;
491
+ /** Native terminal ownership, independent of served error details. Absent on legacy manually emitted events. */
492
+ readonly failure?: TerminalFailureContext;
431
493
  }
432
494
  /**
433
495
  * FlowRecorder — Pluggable observer for control flow events.
@@ -461,6 +523,13 @@ export interface FlowRecorder {
461
523
  onLoop?(event: FlowLoopEvent): void;
462
524
  onBreak?(event: FlowBreakEvent): void;
463
525
  onError?(event: FlowErrorEvent): void;
526
+ /**
527
+ * Called at the end of EVERY attempt — a stage's own, and the calls and
528
+ * observed attempts it makes during the stage (filter on `record.kind`) —
529
+ * with its record and the decision that followed (10.1). See
530
+ * {@link FlowAttemptEvent}.
531
+ */
532
+ onAttempt?(event: FlowAttemptEvent): void;
464
533
  /**
465
534
  * Called once per failed attempt that WILL be retried, for stages carrying a
466
535
  * declared `retry` policy. The final failure arrives via `onError` instead,
@@ -22,6 +22,7 @@
22
22
  * Break semantics: If a stage calls breakFn(), commit and STOP.
23
23
  * Patch model: Stage writes into local patch; commitPatch() after return or throw.
24
24
  */
25
+ import type { RunCorrelation } from '../../attempt/types.js';
25
26
  import type { ScopeProtectionMode } from '../../scope/protection/types.js';
26
27
  import type { QueuedPause, ResumeEntry } from '../handlers/ResumeEntry.js';
27
28
  import { FlowRecorderDispatcher } from '../narrative/FlowRecorderDispatcher.js';
@@ -128,6 +129,11 @@ export interface TraverserOptions<TOut = any, TScope = any> {
128
129
  * needs it. See `runner/runId.ts`.
129
130
  */
130
131
  runId: string;
132
+ /**
133
+ * The leg's correlation (10.1, `attempt/correlation.ts · resolveCorrelation`) — stamped onto every
134
+ * TraversalContext and the snapshot, inherited by subflow traversers BY REFERENCE. Absent when the env gave none.
135
+ */
136
+ correlation?: RunCorrelation;
131
137
  }
132
138
  /**
133
139
  * Traverser-local overlay entry for a node whose stage function returned a
@@ -173,6 +179,11 @@ export declare class FlowchartTraverser<TOut = any, TScope = any> {
173
179
  private subflows;
174
180
  private readonly logger;
175
181
  private readonly signal?;
182
+ /**
183
+ * The run's deadline, epoch ms (`env.deadline`, stamped by the executor's `armRun`; a subflow inherits the env).
184
+ * Under one, EVERY stage runs on the attempt runner, so a lone stage the deadline cuts still leaves its attempt.
185
+ */
186
+ private readonly deadline?;
176
187
  private readonly parentSubflowId?;
177
188
  /** RFC-003 D1: runtimeStageId of the subflow mount stage in the parent
178
189
  * traverser. Fallback `parentRuntimeStageId` for stages whose context has
@@ -187,6 +198,8 @@ export declare class FlowchartTraverser<TOut = any, TScope = any> {
187
198
  /** Per-`executor.run()` identifier. Stamped onto every TraversalContext.
188
199
  * Inherited by subflow traversers so all events of one run share one runId. */
189
200
  private readonly runId;
201
+ /** The leg's correlation — one frozen object, stamped on every TraversalContext; inherited by subflows. */
202
+ private readonly correlation?;
190
203
  private readonly nodeResolver;
191
204
  private readonly childrenExecutor;
192
205
  private readonly subflowExecutor;
@@ -327,6 +340,7 @@ export declare class FlowchartTraverser<TOut = any, TScope = any> {
327
340
  getSnapshot(options?: {
328
341
  redact?: boolean;
329
342
  }): {
343
+ correlation?: RunCorrelation | undefined;
330
344
  runId: string;
331
345
  sharedState: Record<string, unknown>;
332
346
  executionTree: unknown;
@@ -383,29 +397,55 @@ export declare class FlowchartTraverser<TOut = any, TScope = any> {
383
397
  * this method as `runStage`), and by extension fork children and
384
398
  * subflow-internal stages, which re-enter Phase 3 in their own traverser.
385
399
  *
386
- * Which is exactly why the declarative retry loop lives HERE and nowhere
387
- * else: one implementation gives `retry` to every stage kind that has a
388
- * function to retry. (Putting it in `StageRunner` would have been wrong —
389
- * the runner owns the scope and the interrupt boundary, but not the
390
- * `StageContext` whose staged writes a failed attempt must discard.)
400
+ * Which is exactly why a declared `retry` policy is honoured HERE and
401
+ * nowhere else: one call gives `retry` to every stage kind that has a
402
+ * function to retry. The loop itself is the attempt runner's
403
+ * (`attempt/runner.ts · runAttempts`, 10.1 — one runner, one record); this
404
+ * method hands it the engine's half: one attempt (`StageRunner · run`, a
405
+ * fresh scope each time), the discard between attempts
406
+ * (`StageContext · discardStaged` — the runner cannot reach a frame), the
407
+ * served form of an attempt's error (`servedStageError`, the run's
408
+ * redaction rule), and where each record goes (the frame, for the
409
+ * execution tree; `onAttempt` and `onStageRetry`, for recorders).
391
410
  *
392
- * With no `retry` policy this is a single call, byte-identical to the
393
- * pre-9.15 path.
411
+ * NOT `async`, on purpose — the microtask shape of a stage is part of what
412
+ * the engine keeps byte-identical (parallel siblings settle in the order
413
+ * they always did):
414
+ * - no policy (or `attempts: 1`, a declared-but-off policy): one call
415
+ * through an async frame ({@link runStageOnce}), exactly the pre-10.1
416
+ * shape — and no attempt is recorded;
417
+ * - a policy: the runner's own promise, whose one await per attempt is the
418
+ * same one await the 9.15 loop had.
394
419
  */
395
420
  private executeStage;
396
421
  /**
397
- * R5 for ids a stage ADOPTS at run time (a returned StageNode's `next` chain,
398
- * `children` and subflow ids): the same refusal the builder's doors apply —
399
- * `ids/reservedIds.ts · refuseReservedId` — so "no user id carries a
400
- * grammar delimiter" stays true by construction. Loop-ref stubs (they name an
401
- * existing node) and the chart's own nodes (admitted at build; a prefixed id
402
- * carries `/` on purpose) are not new ids and are skipped. A subflow
403
- * definition's own tree is a built chart and is not walked.
404
- */
405
- private admitDynamicIds;
406
- /** `retryOn` gate. A throwing predicate counts as "do not retry" — a broken
407
- * predicate must never turn a failing stage into an endless retry loop. */
408
- private shouldRetry;
422
+ * A touching stage's side-effect target for THIS execution (P3, design §3.3). The law first — a chart edited
423
+ * after `build()` reaches the stage without the builder's refusal, so the stage asks `touchesProblem` itself (the
424
+ * last door). Then the key: the declared rule runs ONCE per execution, before attempt 1, handed the frozen input,
425
+ * the run id and this execution's id; its answer is admitted (`admitIdempotencyKey` — the format, never echoed) and
426
+ * served under the run's diagnostic rule as `{ idempotencyKey }` for the records. Throws on any refusal.
427
+ */
428
+ private effectTarget;
429
+ /** One call of a stage with no retry policy, through an async frame — the pre-10.1 microtask shape. */
430
+ private runStageOnce;
431
+ /**
432
+ * The run-time door for nodes a stage RETURNS (its `next` chain, `children`
433
+ * and subflow ids) — the builder never saw them, so this applies the
434
+ * builder's refusals:
435
+ * - R5, ids: `ids/reservedIds.ts · refuseReservedId`, so "no user id
436
+ * carries a grammar delimiter" stays true by construction. Loop-ref stubs
437
+ * (they name an existing node) and the chart's own nodes (admitted at
438
+ * build; a prefixed id carries `/` on purpose) are not new ids and are
439
+ * skipped.
440
+ * - a declared `retry`: `attempt/policy.ts · retryPolicyProblem`, the rule
441
+ * `FlowChartBuilder · applyRetryPolicy` applies at build — `attempts`
442
+ * must be a whole number >= 1, never `NaN`, `Infinity` or `0`.
443
+ * - a declared `touches`: `attempt/effect.ts · touchesProblem`, the rule
444
+ * `FlowChartBuilder · applyTouches` applies at build — a node that
445
+ * touches an outside system and may retry must declare a key rule.
446
+ * A subflow definition's own tree is a built chart and is not walked.
447
+ */
448
+ private admitDynamicNodes;
409
449
  /**
410
450
  * Trampoline driver — pre-order DFS traversal entry point.
411
451
  *
@@ -19,6 +19,7 @@
19
19
  * has always done.
20
20
  */
21
21
  import { type RuntimeStageId } from 'foottrace';
22
+ import type { RunCorrelation } from '../attempt/types.js';
22
23
  import type { ResumeLink, TraversalContext } from './narrative/types.js';
23
24
  /** Everything a stamp can carry; optional keys are written only when PRESENT on this object. */
24
25
  export interface TraversalStamp {
@@ -32,11 +33,13 @@ export interface TraversalStamp {
32
33
  readonly subflowId?: string;
33
34
  readonly subflowPath?: string;
34
35
  readonly resumedFrom?: ResumeLink;
36
+ /** The leg's correlation — the same frozen object on every stamp; written last, only when present. */
37
+ readonly correlation?: RunCorrelation;
35
38
  }
36
39
  /**
37
40
  * Build the stamp. `parentStageId` / `subflowId` / `subflowPath` are copied
38
41
  * when the key is present (even as `undefined`); `parentRuntimeStageId`,
39
- * `loopIteration` and `resumedFrom` only when they hold a value.
42
+ * `loopIteration`, `resumedFrom` and `correlation` only when they hold a value.
40
43
  */
41
44
  export declare function traversalContextFor(stamp: TraversalStamp): TraversalContext;
42
45
  /**
@@ -44,7 +47,7 @@ export declare function traversalContextFor(stamp: TraversalStamp): TraversalCon
44
47
  * depth 0) so the `runId` is reliably available on run events without forcing
45
48
  * recorders to handle `traversalContext === undefined`.
46
49
  */
47
- export declare function rootTraversalContext(runId: string): TraversalContext;
50
+ export declare function rootTraversalContext(runId: string, correlation?: RunCorrelation): TraversalContext;
48
51
  /**
49
52
  * The `onResume` stamp. Names the stand-in's own execution (`runtimeStageId`,
50
53
  * the id its commit carries), the REAL subflow it runs in — `subflowId` is the
@@ -62,4 +65,6 @@ export declare function resumeTraversalContext(resume: {
62
65
  /** `checkpoint.subflowPath`: the prefixed id of every subflow on the way down, outermost first. */
63
66
  readonly subflowPath: readonly string[];
64
67
  readonly resumedFrom?: ResumeLink;
68
+ /** The RESUMED leg's correlation (from `resume()`'s env) — never the paused leg's. */
69
+ readonly correlation?: RunCorrelation;
65
70
  }): TraversalContext;
@@ -4,7 +4,7 @@
4
4
  * Centralizes type definitions to avoid circular dependencies.
5
5
  * Every handler receives HandlerDeps (the DI bag) instead of importing the traverser.
6
6
  */
7
- import type { LogAddress } from 'foottrace';
7
+ import type { LogAddress, LogOutcome, Meta } from 'foottrace';
8
8
  import type { SharedMemory } from 'foottrace/write';
9
9
  import type { FlowControlType, FlowMessage } from '../memory/frameTypes.js';
10
10
  import type { StageContext } from '../memory/StageContext.js';
@@ -104,57 +104,7 @@ export interface ParallelForEachConfig<TItem = any, TScope = any> {
104
104
  */
105
105
  failFast?: boolean;
106
106
  }
107
- /**
108
- * Declarative per-stage retry policy.
109
- *
110
- * WHY this exists: a retry hand-rolled inside a stage function is invisible to
111
- * the trace. The stage shows one execution, the commit log shows one bundle,
112
- * and the two failed calls that preceded the successful one left no mark
113
- * anywhere — an unexplained behaviour in a library whose whole thesis is that
114
- * nothing invisible happens. Declared here instead, every attempt is part of
115
- * the record: each failed attempt fires `FlowRecorder.onStageRetry` with the
116
- * attempt number, the wait, and the structured error.
117
- *
118
- * A POLICY, not a stage kind — `retry` sits on a normal stage the way
119
- * `isPausable` / `isStreaming` do. The serialized node `type` is unchanged and
120
- * every existing consumer keeps rendering the stage exactly as before.
121
- *
122
- * @example
123
- * ```ts
124
- * flowChart<State>('Fetch user', fetchFn, 'fetch-user')
125
- * .retry({ attempts: 3, backoffMs: (n) => 100 * 2 ** (n - 1) })
126
- * ```
127
- */
128
- export interface RetryPolicy {
129
- /**
130
- * How many times the stage function may run in total, INCLUDING the first
131
- * run. Must be an integer >= 1; `1` means "no retry" (a declared no-op,
132
- * accepted so a policy can be switched off without deleting it).
133
- */
134
- attempts: number;
135
- /**
136
- * How long to wait before the NEXT attempt. Either a fixed number of
137
- * milliseconds, or a function of the attempt that just FAILED (1-based)
138
- * returning milliseconds — `(n) => 100 * 2 ** (n - 1)` is exponential
139
- * backoff. Omitted (or a non-finite / negative result) means no wait.
140
- *
141
- * The wait is a plain awaited timer that is CANCELLED by the run's
142
- * `AbortSignal`. It is not a pause: a chart cannot be checkpointed in the
143
- * middle of a backoff.
144
- */
145
- backoffMs?: number | ((attempt: number) => number);
146
- /**
147
- * Is THIS error worth another attempt? Defaults to retrying every error.
148
- * Returning `false` ends the stage immediately on the normal error path —
149
- * exactly as if no policy had been declared, and with no retry event (the
150
- * policy chose not to act; there is nothing to report that the error event
151
- * does not already say).
152
- *
153
- * A throw from this predicate is treated as `false` — a broken predicate
154
- * must not turn a failing stage into an infinite retry loop.
155
- */
156
- retryOn?: (error: unknown) => boolean;
157
- }
107
+ export type { RetryPolicy, StageTouches } from '../attempt/types.js';
158
108
  /**
159
109
  * Controls how array values from outputMapper are merged into parent scope.
160
110
  */
@@ -438,6 +388,14 @@ export interface IExecutionRuntime {
438
388
  };
439
389
  setRootObject(path: string[], key: string, value: unknown): void;
440
390
  getPipelines(): string[];
391
+ /**
392
+ * Where a mount's own log writes as it lands (10.1, P6) — the run's sink at this log's address plus the mount's
393
+ * `runtimeStageId`. `undefined` when this runtime's log writes to no sink. `SubflowExecutor` hands it to the
394
+ * nested runtime it constructs.
395
+ */
396
+ recordFor?(mountRuntimeStageId: string, meta?: Meta): unknown;
397
+ /** Tell the sink this runtime's log ended (10.1, P6) — a mount's at its exit. No-op without a sink. */
398
+ closeRecord?(outcome: LogOutcome, meta?: Meta): void;
441
399
  }
442
400
  /**
443
401
  * ExecutionEnv — infrastructure values that propagate through nested executors.
@@ -452,12 +410,39 @@ export interface IExecutionRuntime {
452
410
  * parent and child flowcharts.
453
411
  */
454
412
  export interface ExecutionEnv {
455
- /** AbortSignal for cooperative cancellation across nested executors. */
413
+ /**
414
+ * AbortSignal for cooperative cancellation across nested executors. Honoured by the engine (10.1): it ends the
415
+ * run like `RunOptions.signal`. Under a run that has a signal or a deadline AND an env, a stage reads the run's
416
+ * ONE effective signal here — `RunOptions.signal`, this one and the deadline's timer, composed.
417
+ */
456
418
  readonly signal?: AbortSignal;
457
- /** Timeout budget in milliseconds. */
419
+ /** Timeout budget in milliseconds. Readable only — the run's deadline is {@link deadline}. */
458
420
  readonly timeoutMs?: number;
459
- /** Trace identifier for distributed tracing / observability. */
421
+ /**
422
+ * Trace identifier for distributed tracing / observability. With `operationId` (or alone) it becomes the run's
423
+ * `RunCorrelation`; it wins over the trace id of `traceparent`. 1–256 printable ASCII characters with no space
424
+ * (since 10.1 anything else rejects the run with a `TypeError` naming the field — the id rides every event);
425
+ * an empty string is no id.
426
+ */
460
427
  readonly traceId?: string;
428
+ /**
429
+ * The caller's unit of work (W3C's parent-id) — part of the run's `RunCorrelation`; wins over the header's
430
+ * parent-id. Needs a trace: `traceId` or `traceparent` (refused alone). Same character rule as `traceId`.
431
+ */
432
+ readonly operationId?: string;
433
+ /**
434
+ * A W3C `traceparent` header, usually straight from an inbound request. Parsed STRICTLY once per run — a
435
+ * malformed one refuses the run with a `TraceparentError` naming the reason (never the header). Stages read
436
+ * back (`$getEnv()`) exactly `RunCorrelation.traceparent` — the canonical header of the effective ids — or no
437
+ * key when the run's correlation carries none. Correlation only: never identity or authorisation.
438
+ */
439
+ readonly traceparent?: string;
440
+ /**
441
+ * The run's deadline, epoch milliseconds (10.1) — the earliest of `RunOptions.deadline`, `now + RunOptions.timeoutMs`
442
+ * and a deadline given here. The run's signal aborts when it passes; every attempt is capped by the time left.
443
+ * Inherited by subflows. Read it through `scope.$attempt().timeLeftMs()`.
444
+ */
445
+ readonly deadline?: number;
461
446
  }
462
447
  /**
463
448
  * HandlerDeps — Dependency injection bag passed to all handler modules.
@@ -496,10 +481,20 @@ export interface HandlerDeps<TOut = any, TScope = any> {
496
481
  }
497
482
  /** Options for FlowChartExecutor.run(). */
498
483
  export interface RunOptions {
499
- /** AbortSignal for cooperative cancellation. */
484
+ /** AbortSignal for cooperative cancellation. Composed with `env.signal` and the deadline (10.1). */
500
485
  signal?: AbortSignal;
501
- /** Timeout in milliseconds. Creates an internal AbortController. */
486
+ /**
487
+ * Timeout in milliseconds: the run's deadline is `now + timeoutMs`. The run aborts when it passes (rejecting with
488
+ * `Execution timed out after <timeoutMs>ms`), stages read it as `env.deadline`, and every stage records its
489
+ * attempt (`StageSnapshot.attempts`). Honoured beside a `signal` since 10.1 (it used to be ignored there).
490
+ */
502
491
  timeoutMs?: number;
492
+ /**
493
+ * The run's deadline, epoch milliseconds (10.1) — `Date.now() + 120_000`. Same effect as `timeoutMs`; when both
494
+ * are given, the earlier wins. A deadline already past stops the run before its first stage. A resumed leg has
495
+ * its own: pass it again to `resume()`.
496
+ */
497
+ deadline?: number;
503
498
  /**
504
499
  * Runtime input data for the pipeline.
505
500
  * Becomes the readOnlyContext accessible via `scope.getArgs()`.
@@ -0,0 +1,29 @@
1
+ import type { AttemptCategory } from '../attempt/types.js';
2
+ /** Safe context for the failure that escaped a native run; never the exception itself. */
3
+ export interface TerminalFailureContext {
4
+ readonly category: AttemptCategory;
5
+ /** Absent when no native stage owns this failure (for example input admission or run retention). */
6
+ readonly stage?: {
7
+ readonly runId: string;
8
+ readonly runtimeStageId: string;
9
+ };
10
+ }
11
+ /**
12
+ * @internal One execution chain's failure ownership, not an error history.
13
+ * Sequential frames share it; forks and subflows do not. Only an explicitly
14
+ * selected escaping rejection may transfer ownership to its parent chain.
15
+ * Raw identity lives in a private slot and is released when the leg settles.
16
+ */
17
+ export declare class NativeFailureState {
18
+ #private;
19
+ get result(): TerminalFailureContext | undefined;
20
+ capture(error: unknown, category: AttemptCategory, stage: NonNullable<TerminalFailureContext['stage']>): void;
21
+ /** A runner already classified this exact native failure before it was served. */
22
+ owns(error: unknown): boolean;
23
+ adopt(child: NativeFailureState, error: unknown): void;
24
+ /** Publish at the run event boundary; keep ownership until executor settlement. */
25
+ announce(error: unknown): TerminalFailureContext;
26
+ finish(error: unknown): void;
27
+ /** Success or pause has no terminal failure. Also closes contained branch ownership. */
28
+ complete(): void;
29
+ }