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
package/README.md CHANGED
@@ -1,371 +1,195 @@
1
- <p align="center">
2
- <h1 align="center">FootPrint</h1>
3
- <p align="center">
4
- <strong>The flowchart pattern for backend code &mdash; self-explainable systems that AI can reason about.</strong>
5
- </p>
6
- </p>
7
-
8
- <p align="center"><sub>Part of the <a href="https://footprintjs.github.io/"><b>footprintjs ecosystem</b></a> &mdash; the self-explaining stack.</sub></p>
9
-
10
- <p align="center">
11
- <a href="https://github.com/footprintjs/footPrint/actions"><img src="https://github.com/footprintjs/footPrint/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
12
- <!-- coverage-badge --><img src="https://img.shields.io/badge/coverage-93%25-brightgreen.svg" alt="coverage: 93%"><!-- /coverage-badge -->
13
- <a href="https://www.npmjs.com/package/footprintjs"><img src="https://img.shields.io/npm/v/footprintjs.svg?style=flat" alt="npm version"></a>
14
- <a href="https://bundlephobia.com/package/footprintjs"><img src="https://img.shields.io/bundlephobia/minzip/footprintjs?label=minzipped" alt="minzipped size"></a>
15
- <a href="#tree-shakeable--esm-first"><img src="https://img.shields.io/badge/tree--shakeable-%E2%9C%93-success?style=flat" alt="tree-shakeable"></a>
16
- <a href="https://github.com/footprintjs/footPrint/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License"></a>
17
- <a href="https://www.npmjs.com/package/footprintjs"><img src="https://img.shields.io/npm/dm/footprintjs.svg" alt="Downloads"></a>
18
- <a href="https://footprintjs.github.io/footprint-playground/samples/llm-agent-tool"><img src="https://img.shields.io/badge/Try_with_LLM-Live_Demo-7c6cf0?style=flat" alt="Try with LLM"></a>
19
- <a href="https://footprintjs.github.io/footprint-playground/"><img src="https://img.shields.io/badge/Playground-37%2B_samples-6366f1?style=flat" alt="Interactive Playground"></a>
20
- <a href="https://footprintjs.github.io/footPrint/"><img src="https://img.shields.io/badge/Docs-footprintjs-3178c6?style=flat&logo=typescript&logoColor=white" alt="Docs"></a>
21
- </p>
22
-
23
- <br>
24
-
25
- <p align="center">
26
- <img src="assets/hero.gif" alt="FootPrint demo — loan application with animated flowchart, memory inspector, and causal trace" width="800">
27
- </p>
28
-
29
- **MVC is a pattern for backends. FootPrint is a different pattern** &mdash; the flowchart pattern &mdash; where your business logic is a graph of functions with transactional state. The code becomes self-explainable: AI reads the structure, traces every decision, and explains what happened &mdash; no hallucination.
1
+ # FootPrint
30
2
 
31
- ```bash
32
- npm install footprintjs
33
- ```
34
-
35
- Requires **Node.js 22 or newer**. CI tests Node 22 and 24; Node 24 LTS is the default for development, documentation builds and publishing. See [Contributing](CONTRIBUTING.md#development-setup) for setup instructions.
3
+ **Connected runtime logs for people and AI agents.**
36
4
 
37
- ---
5
+ > Don't make the agent guess connections your program already knew.
38
6
 
39
- ## The Problem
7
+ FootPrint is the **flowchart pattern for inspectable workflows**. Write your logic as named stages, tracked state, and explicit decisions. As the workflow executes, FootPrint captures connected evidence of its data activity, execution path, and evaluated decisions.
40
8
 
41
- Your LLM needs to explain why your code made a decision. Without structure, it reconstructs reasoning from scattered logs &mdash; expensive, slow, and hallucinates.
9
+ **The evidence is captured during execution—not reconstructed by an LLM afterward.** People and AI agents can investigate the same recorded run. No model is required to generate the record.
42
10
 
43
- | | MVC / Traditional | Flowchart Pattern (FootPrint) |
44
- |---|---|---|
45
- | **LLM explains a decision** | Reconstruct from scattered logs | Read the causal trace directly |
46
- | **Tool descriptions for agents** | Write and maintain by hand | Auto-generated from the graph |
47
- | **State management** | Global/manual, race-prone | Transactional scope with per-stage staged commits |
48
- | **Debugging** | `console.log` + guesswork | Time-travel replay to any stage |
11
+ [Documentation](https://footprintjs.github.io/footPrint/) · [Playground](https://footprintjs.github.io/footprint-playground/) · [AI instructions](https://github.com/footprintjs/footPrint/tree/main/ai-instructions) · [Provenance, governance and limits](docs/provenance-governance-and-limits.md)
49
12
 
50
- ---
13
+ ## AI can read your logs. Can it follow the decision?
51
14
 
52
- ## How It Works
15
+ An image export is rejected. The application did not crash. It produced an outcome somebody needs to investigate.
53
16
 
54
- A loan pipeline rejects Bob. The user asks: **"Why was I rejected?"**
17
+ Messages such as “Image loaded,” “Resolution checked,” and “Export rejected” leave questions unanswered: **which width was checked, where did it come from, and which rule selected rejection?**
55
18
 
56
- The runtime auto-generates this trace from what the code actually did:
19
+ FootPrint records tracked data activity and evaluated decision evidence as the flow executes. Its control-dependency recorder connects executed branches to their governing decisions. Later queries follow that evidence; they do not ask a model to invent the connections.
57
20
 
58
- ```
59
- Stage 1: The process began with ReceiveApplication.
60
- Step 1: Write creditScore = 580, dti = 0.6, employmentStatus = "self-employed"
61
- Stage 2: Next step: Evaluate risk tier from all flags.
62
- Step 1: Read creditScore = 580
63
- Step 2: Write riskTier = "high"
64
- Step 3: Write riskFactors = (3 items)
65
- Stage 3: Next step: Route based on risk tier.
66
- Step 1: Read riskTier = "high"
67
- [Condition]: It evaluated "High risk": riskTier "high" eq "high" ✓, and chose RejectApplication.
68
- Stage 4: Next step: Generate rejection.
69
- Step 1: Write decision = "REJECTED — below-average credit; DTI exceeds 43%; Self-employed < 2yr"
70
- ```
21
+ ## One workflow, one recorded investigation
71
22
 
72
- The LLM backtracks through the trace, reading `&larr;` as *caused-by* &mdash; each value links to the write that produced it: `riskTier="high"` &larr; `riskFactors` &larr; `creditScore=580`, `dti=0.6`. Every variable links to its cause:
23
+ This example uses **synthetic image metadata** and performs no real export. The execution output below comes from the reviewed run with `footprintjs` **10.0.0** and `foottrace` **1.0.3**.
73
24
 
74
- > **LLM:** "Your application was rejected because your debt-to-income ratio of 60% exceeds the 43% maximum, your credit score of 580 falls in the 'fair' tier, and your self-employment tenure of 1 year is below the 2-year minimum."
25
+ Requires Node.js 22 or newer. To use the same library versions:
75
26
 
76
- That answer came from the trace &mdash; not from the LLM's imagination.
27
+ ```bash
28
+ npm install footprintjs@10.0.0 foottrace@1.0.3
29
+ ```
77
30
 
78
- ---
31
+ Save the following as [`example.mts`](example.mts) and run it with your TypeScript runner, for example `npx tsx example.mts`.
79
32
 
80
- ## Quick Start
33
+ **Why two import paths?** Recorders belong to the execution engine (`footprintjs/trace`); querying the captured record belongs to `foottrace`.
81
34
 
82
35
  ```typescript
83
- import { flowChart, decide, narrative } from 'footprintjs';
84
-
85
- // 1. Define your state
86
- interface State {
87
- user: { name: string; tier: string };
88
- discount: number;
89
- lane: string;
90
- }
91
-
92
- // 2. Build the flowchart
93
- const chart = flowChart<State>('FetchUser', async (scope) => {
94
- scope.user = { name: 'Alice', tier: 'premium' };
95
- }, 'fetch-user')
96
- .addFunction('ApplyDiscount', async (scope) => {
97
- scope.discount = scope.user.tier === 'premium' ? 0.2 : 0.05;
98
- }, 'apply-discount')
99
- .addDeciderFunction('Route', (scope) => {
100
- return decide(scope, [
101
- { when: { discount: { gt: 0.1 } }, then: 'vip', label: 'High discount' },
102
- ], 'standard');
103
- }, 'route', 'Route by discount tier')
104
- .addFunctionBranch('vip', 'VIPCheckout', async (scope) => {
105
- scope.lane = 'VIP express';
36
+ import { flowChart, decide, FlowChartExecutor } from 'footprintjs';
37
+ import { controlDepRecorder } from 'footprintjs/trace';
38
+
39
+ type ExportState = {
40
+ width: number;
41
+ status: 'exported' | 'rejected';
42
+ };
43
+
44
+ const chart = flowChart<ExportState>('LoadImage', (scope) => {
45
+ scope.width = 640; // Example data; no image service is called.
46
+ }, 'load-image')
47
+ .addDeciderFunction('CheckResolution', (scope) => decide(scope, [
48
+ {
49
+ when: { width: { gte: 1280 } },
50
+ then: 'export',
51
+ label: 'Image is wide enough',
52
+ },
53
+ ], 'reject'), 'check-resolution')
54
+ .addFunctionBranch('export', 'ExportImage', (scope) => {
55
+ scope.status = 'exported';
106
56
  })
107
- .addFunctionBranch('standard', 'StandardCheckout', async (scope) => {
108
- scope.lane = 'Standard';
57
+ .addFunctionBranch('reject', 'RejectExport', (scope) => {
58
+ scope.status = 'rejected';
109
59
  })
110
- .setDefault('standard')
60
+ .setDefault('reject')
111
61
  .end()
112
62
  .build();
113
63
 
114
- // 3. Run — capture the narrative recorder so you can read the trace back
115
- const trace = narrative();
116
- const result = await chart.recorder(trace).run();
117
-
118
- console.log(result.state.lane); // "VIP express"
119
- console.log(trace.getEntries().map((e) => e.text).join('\n'));
120
- // Stage 1: The process began with FetchUser.
121
- // Step 1: Write user = {name, tier}
122
- // Stage 2: Next, it moved on to ApplyDiscount.
123
- // Step 1: Read user = {name, tier}
124
- // Step 2: Write discount = 0.2
125
- // Stage 3: Next step: Route by discount tier.
126
- // Step 1: Read discount = 0.2
127
- // [Condition]: It evaluated Rule 0 "High discount": discount 0.2 gt 0.1 ✓, and chose VIPCheckout.
128
- // Stage 4: Next, it moved on to VIPCheckout.
129
- // Step 1: Write lane = "VIP express"
64
+ const executor = new FlowChartExecutor(chart);
65
+ const control = controlDepRecorder();
66
+
67
+ // Enable before execution: collect the narrative and governing decisions.
68
+ executor.setReadTracking('full');
69
+ executor.enableNarrative();
70
+ executor.attachCombinedRecorder(control);
71
+ await executor.run();
72
+
73
+ const snapshot = executor.getSnapshot();
74
+ console.log(snapshot.sharedState.status); // Expected: "rejected".
75
+ console.log(executor.getNarrativeEntries().map(e => e.text).join('\n'));
76
+ console.dir(control.getDecisions(), { depth: null });
77
+
78
+ import {
79
+ causalChain,
80
+ findLastWriter,
81
+ formatCausalChain,
82
+ keysReadFromExecutionTree,
83
+ } from 'foottrace';
84
+
85
+ // Continue from the completed run above.
86
+ const writer = findLastWriter(snapshot.commitLog, 'status');
87
+ if (!writer) throw new Error('No recorded writer for status.');
88
+
89
+ const reads = keysReadFromExecutionTree(snapshot.executionTree);
90
+ const chain = causalChain(
91
+ snapshot.commitLog,
92
+ writer.runtimeStageId,
93
+ reads.lookup,
94
+ { controlDeps: control.asLookup() },
95
+ );
96
+
97
+ if (!chain) throw new Error('No causal chain.');
98
+ console.log(formatCausalChain(chain));
130
99
  ```
131
100
 
132
- > **[Try it in the browser](https://footprintjs.github.io/footprint-playground/)** &mdash; no install needed
133
- >
134
- > **[Browse 37+ examples](https://footprintjs.github.io/footprint-playground/)** &mdash; patterns, recorders, subflows, integrations, and a full loan underwriting demo
135
-
136
- ---
137
-
138
- ## Vocabulary
139
-
140
- If you know agent or backend systems, you already know these &mdash; here's footprint's name for each:
141
-
142
- | footprint term | = the thing you already know |
143
- |---|---|
144
- | **scope** | the run's shared **state** (an agent's working memory) &mdash; but every read/write is tracked |
145
- | **stage** | a **step** / node in the flowchart |
146
- | **decider** / **selector** | a **router** (picks one branch) / **parallel fan-out** (picks many) |
147
- | **subflow** | a nested flowchart you compose like a **function** |
148
- | **recorder** | an **observer** &mdash; called on each read, write, and decision |
149
- | **narrative** | the execution **trace** rendered as plain-English sentences (the LLM-readable form) |
150
- | **commit log** | the ordered record of **what each step wrote** &mdash; powers time-travel replay |
151
-
152
- ---
101
+ ### What the run recorded
153
102
 
154
- ## Try With Your LLM
103
+ Narrative excerpt from the reviewed run:
155
104
 
156
- Expose any flowchart as an MCP tool in one line &mdash; the description, input schema, and step list are auto-generated from the graph.
157
-
158
- ```typescript
159
- const tool = chart.toMCPTool();
160
- // { name: 'AssessCredit', description: 'FlowChart: AssessCredit\nSteps:\n1. AssessCredit\n2. ...', inputSchema: { type: 'object', properties: {} } }
161
-
162
- // Register with any MCP server or pass directly to the Anthropic SDK:
163
- const anthropicTool = { name: tool.name, description: tool.description, input_schema: tool.inputSchema };
105
+ ```text
106
+ Stage 1: The process began with LoadImage.
107
+ Step 1: Write width = 640
108
+ Stage 2: Next, it moved on to CheckResolution.
109
+ Step 1: Read width = 640
110
+ [Condition]: No rules matched, fell back to default: RejectExport.
111
+ Stage 3: Next, it moved on to RejectExport.
112
+ Step 1: Write status = "rejected"
164
113
  ```
165
114
 
166
- The LLM calls the tool, gets back the decision and causal trace, and explains the result to the user &mdash; all from the same graph that runs in production.
167
-
168
- > **[Live demo: Claude calls a credit-decision flowchart as an MCP tool](https://footprintjs.github.io/footprint-playground/samples/llm-agent-tool)** &mdash; enter your API key, watch the tool call happen, see the trace.
169
-
170
- ---
171
-
172
- ## Human-in-the-Loop
173
-
174
- A stage can stop in the middle of its body to ask a person, and pick the run back up later &mdash; minutes or days later, in a different process.
175
-
176
- ```typescript
177
- import { flowChart, FlowChartExecutor, interrupt } from 'footprintjs';
178
-
179
- interface RefundState { amount: number; approved: boolean; [key: string]: unknown }
180
-
181
- const refundChart = flowChart<RefundState>('Assess refund', (scope) => {
182
- scope.amount = 4200; // runs AGAIN on resume — keep it idempotent
183
-
184
- const answer = interrupt<{ approved: boolean }>(scope, {
185
- reason: `Approve a $${scope.amount} refund?`,
186
- expects: { approved: 'boolean' }, // carried verbatim, so a UI can render the form
187
- });
115
+ The structured decision record also reports the evaluated condition: `width`, operator `gte`, threshold `1280`, observed value `640`, result `false`. That evidence comes from the rule evaluation—not from an LLM describing it afterward.
188
116
 
189
- scope.approved = answer.approved; // reached only after resume()
190
- }, 'assess').build();
117
+ The dependency query prints:
191
118
 
192
- const refundExecutor = new FlowChartExecutor(refundChart);
193
- await refundExecutor.run();
194
-
195
- if (refundExecutor.isPaused()) {
196
- const checkpoint = refundExecutor.getCheckpoint()!; // plain JSON — persist it anywhere
197
- // ...a human answers; then, possibly on another server:
198
- await new FlowChartExecutor(refundChart).resume(checkpoint, { approved: true });
199
- }
119
+ ```text
120
+ RejectExport (reject#2) [wrote: status]
121
+ CheckResolution (check-resolution#1) ← [control]
122
+ LoadImage (load-image#0) ← via width [wrote: width]
200
123
  ```
201
124
 
202
- Resume re-enters the stage **from its top** &mdash; stages are atomic, so everything before the `interrupt()` call runs again and the answer comes back out of that call. When you don't want the first half re-run, `addPausableFunction` is the declared alternative: it splits the stage into an `execute` half and a `resume` half.
203
-
204
- ---
205
-
206
- ## Features
207
-
208
- | Feature | Description |
209
- |---------|-------------|
210
- | **Causal Traces** | Every read/write captured &mdash; LLMs backtrack through variables to find causes |
211
- | **Decision Evidence** | `decide()` / `select()` auto-capture WHY a branch was chosen &mdash; operators, thresholds, pass/fail |
212
- | **TypedScope&lt;T&gt;** | Typed property access &mdash; `scope.creditScore = 750` instead of `scope.setValue('creditScore', 750)` |
213
- | **Auto Narrative** | Build-time descriptions for tool selection, runtime traces for explanation |
214
- | **7 Patterns** | Linear, parallel fork, conditional, multi-select, subflow, streaming, loops |
215
- | **Transactional State** | Per-stage staged commits, safe merges, time-travel replay |
216
- | **PII Redaction** | Per-key or declarative `RedactionPolicy` with audit trail |
217
- | **Flow Recorders** | 7 loop-compression strategies (+ a subflow Manifest recorder) |
218
- | **Combined Recorders** | Single-hook observers that span data-flow + control-flow &mdash; `executor.attachCombinedRecorder(r)` |
219
- | **Deferred observers** *(new in 9.6)* | `attach*Recorder(rec, { delivery: 'deferred' })` &mdash; observers run "one beat behind" on a bounded queue instead of inside the engine hot path. Honest backpressure (`drop-oldest`/`sample`/`block`), terminal flush at run resolve/reject/pause, `snapshot.observerStats`. [Guide →](./docs/guides/observers-deferred.md) |
220
- | **Contracts** | I/O schemas (Zod/JSON Schema) + OpenAPI 3.1 + MCP tool generation |
221
- | **Cancellation** | AbortSignal, timeout, early termination via `scope.$break(reason?)` with optional reason |
222
- | **Declarative retry** *(new in 9.15)* | `.retry({ attempts, backoffMs, retryOn })` on a stage &mdash; because a retry hand-rolled inside a stage function is invisible to the trace. Every failed attempt fires `onStageRetry` and appears in the narrative, in order, inside its own stage. A failed attempt's writes are discarded (the next attempt starts from committed state); the final attempt keeps commit-on-error exactly. One `runtimeStageId`, one commit bundle, however many attempts ran. [Guide &rarr;](./docs/guides/error-handling.md#declarative-retry) |
223
- | **Subflow break propagation** | Mount a subflow with `propagateBreak: true` &mdash; inner `$break` terminates the parent loop, with drill-down preserved |
224
- | **Emit channel** | `scope.$emit(name, payload)` &mdash; user-authored structured events to `EmitRecorder`, pass-through, zero-allocation when no recorder attached, redactable via `emitPatterns` |
225
- | **Detach** *(new in 4.17)* | `scope.$detachAndForget(driver, child, input)` and `scope.$detachAndJoinLater(driver, child, input)` &mdash; fire-and-forget child flowcharts via the `footprintjs/detach` subpath. Six built-in drivers (microtask / immediate / setImmediate / setTimeout / sendBeacon / workerThread) + custom-driver protocol. Builder-native composition (`addDetachAndForget` / `addDetachAndJoinLater`) makes detach a labeled chart stage. `flushAllDetached()` for graceful shutdown. [Guide →](https://footprintjs.github.io/footPrint/guides/patterns/detach/) |
226
- | **Recorder storage primitives** | `BoundaryStateStore<TState>` &mdash; one of three composable storage shelves alongside `SequenceStore<T>` (durable ordered, with `getEntryRanges()`) and `KeyedStore<T>` (durable 1:1). `BoundaryStateStore` tracks live transient state DURING a `[start, stop]` event interval (LLM stream partial, tool args streaming, agent turn state) and clears on stop. O(1) reads via `get` / `hasActive` / `activeCount`. Mental model: recorder *interfaces* (`ScopeRecorder` / `FlowRecorder` / `EmitRecorder`) are observers; stores are *bookkeeping shelves*. A real recorder picks ONE observer interface and OWNS the store as a field (composition &mdash; "one purpose per recorder"). The `Store` classes are exported from `footprintjs/trace` and are the only recorder-storage model &mdash; there are no abstract base classes to extend. [Guide →](https://footprintjs.github.io/footPrint/guides/features/recorder-storage-primitives/) |
227
-
228
- ---
229
-
230
- ## Tree-shakeable & ESM-first
125
+ **The rejection is connected to the decision; the decision is connected to the value's producer.** `RejectExport` writes a constant status without reading `width`, so data dependencies alone would miss the governing decision. The `controlDeps` lookup supplies that connection.
231
126
 
232
- Import one thing, ship one thing. footprintjs is built so your bundle grows only with what you actually use:
127
+ The next question might be: **“Did `LoadImage` load a thumbnail instead of the original?”** That remains a hypothesis to investigate. The record establishes the observed path, not whether 1280 is the right requirement or whether the correct source was loaded.
233
128
 
234
- - **Dual build, true ESM.** Ships CommonJS (`require`) **and** real ECMAScript Modules (`import`) with TypeScript types. The ESM build is marked `type:module` and every internal import carries an explicit `.js` extension, so it loads as true ESM under Node, Vite, Next, Deno, and Bun — no compatibility shims.
235
- - **Per-file modules + `sideEffects:false`.** The dist is emitted file-by-file (never pre-bundled) and declares zero side effects, so bundlers can drop every export you don't touch.
236
- - **Package doors.** Read execution records with `foottrace`, write them with `foottrace/write`, and handle record paths with `foottrace/paths`. Recorder stores and topology belong to `footprintjs/trace`, fire-and-forget children to `footprintjs/detach`, and engine internals to `footprintjs/advanced`. Each door is independently tree-shakeable.
129
+ ## Two ways to work with AI
237
130
 
238
- **Proven, not promised.** A CI smoke test bundles a minimal `import { flowChart } from 'footprintjs'` and asserts the recorder, detach, and trace layers are pruned — your flowchart core doesn't drag them in. See [`test/esm-packaging.test.ts`](test/esm-packaging.test.ts).
131
+ ### An agent building your application
239
132
 
240
- ```ts
241
- // Only flowChart? The recorder/detach/trace layers are tree-shaken away.
242
- import { flowChart } from 'footprintjs';
243
- ```
244
-
245
- ---
246
-
247
- ## Dev Mode
133
+ Give the coding agent a workflow it can investigate:
248
134
 
249
- footprintjs ships with developer-only diagnostics that are OFF by default. Turn them on during development to catch mistakes early. Pass your application's environment setting to this helper (for example, `process.env.NODE_ENV` in Node.js):
135
+ > Build this workflow with FootPrint. Track relevant state, use explicit decision helpers, and attach the required recorders before execution. When an outcome is wrong, inspect its recorded producer, inputs, and governing decisions. Separate evidence from hypotheses, then verify the repair with regression tests.
250
136
 
251
- ```ts
252
- import { enableDevMode } from 'footprintjs';
137
+ The application does **not** need an LLM at runtime. Start with the [AI instruction files](https://github.com/footprintjs/footPrint/tree/main/ai-instructions) and [AGENTS.md](https://github.com/footprintjs/footPrint/blob/main/AGENTS.md).
253
138
 
254
- function configureDiagnostics(environment: string | undefined) {
255
- if (environment !== 'production') {
256
- enableDevMode();
257
- }
258
- }
259
- ```
139
+ ### An agent inside your application
260
140
 
261
- One flag gates every library dev-only check:
141
+ A running agent can consume workflow results and their evidence to investigate or explain an outcome. [AgentFootprint](https://github.com/footprintjs/agentfootprint) applies this approach to agent workflows, including context and tool activity. In both uses, the model reads evidence; it does not create the execution history.
262
142
 
263
- | Check | What it warns about |
264
- |---|---|
265
- | Circular refs | `scope.setValue(...)` called with an object that references itself |
266
- | Empty recorders | `attachCombinedRecorder(r)` with `r` that has no `on*` handler (likely mistake) |
267
- | Suspicious predicates | `decide()` / `select()` rules with shapes that probably won't match |
268
- | Snapshot integrity | `getSubtreeSnapshot()` asked for a path that doesn't exist |
143
+ ## Workflows and libraries—not only backends
269
144
 
270
- All dev warnings are `console.warn`. Use `disableDevMode()` to silence them at runtime.
145
+ Use the pattern at meaningful workflow boundaries, not necessarily around every helper function.
271
146
 
272
- ---
147
+ | Project | Focus |
148
+ | --- | --- |
149
+ | [AgentFootprint](https://github.com/footprintjs/agentfootprint) | Agent execution, context, and tool-call evidence. |
150
+ | [HCI Footprint](https://github.com/footprintjs/hcifootprint) | Explicit application actions and journeys for human–agent interaction. |
151
+ | [VizFootprint](https://github.com/footprintjs/vizfootprint) | Analysis workflows and recorded exploration. |
152
+ | [StoryDeck](https://github.com/footprintjs/storydeck) | One content model with article, scroll, and presentation views. |
153
+ | [StoryReel](https://github.com/footprintjs/storyreel) | A film-making pipeline with FootPrint stages and a making-of record. |
273
154
 
274
- ## AI Coding Tool Support
155
+ These projects have different dependencies and maturity; they are not identical wrappers. StoryReel's [pipeline](https://github.com/footprintjs/storyreel/blob/main/src/pipeline.mjs) is a concrete example beyond agent applications.
275
156
 
276
- FootPrint ships with built-in instructions for every major AI coding assistant. Your AI tool understands the API, patterns, and anti-patterns out of the box.
157
+ ## Two packages, separate responsibilities
277
158
 
278
- ```bash
279
- # Download and run the setup script from GitHub
280
- npx degit footprintjs/footPrint/ai-instructions footprint-ai && bash footprint-ai/setup.sh && rm -rf footprint-ai
281
- ```
159
+ | Package | Responsibility |
160
+ | --- | --- |
161
+ | `footprintjs` | Executes flowcharts: stages, tracked scope, decisions, and runtime recorders. |
162
+ | `foottrace` | Owns execution-record primitives and readers for replay, time travel, and dependency queries. |
282
163
 
283
- | Tool | What gets installed |
284
- |------|-------------------|
285
- | **Claude Code** | `.claude/skills/footprint/SKILL.md` + `CLAUDE.md` |
286
- | **OpenAI Codex** | `AGENTS.md` |
287
- | **GitHub Copilot** | `.github/copilot-instructions.md` |
288
- | **Cursor** | `.cursor/rules/footprint.md` |
289
- | **Windsurf** | `.windsurfrules` |
290
- | **Cline** | `.clinerules` |
291
- | **Kiro** | `.kiro/rules/footprint.md` |
164
+ Foottrace reads supported saved records without the original flowchart engine or an AI provider. Its `foottrace/write` entry also owns record-writing primitives. Import it directly when using its queries.
292
165
 
293
- ---
166
+ For offline investigation, persist the evidence each reader needs—not just the final result. This example queries one live run; storage, retention, access control, and preservation of control relationships across recording boundaries require application design.
294
167
 
295
- ## Roadmap — community extension points
168
+ ## A retry that needs reconciliation
296
169
 
297
- These are deliberately deferred ideas where footprintjs aims to be a *true
298
- developer's friend*: ship a great zero-config default, but let teams who need it
299
- **bring their own** implementation. Contributions welcome — open an issue to
300
- discuss before a PR.
170
+ Use `addRetryLoop` when an outside operation may happen even though its response is lost. It puts the attempt, reconciliation, decision and wait into ordinary chart nodes. Each logical execution keeps one operation key; another send requires an authoritative `none` result. An uncertain reconciliation stops by default.
301
171
 
302
- - **Pluggable performance primitives (bring-your-own).** Hot-path internals
303
- (`deepEqual` for change-only commits, `deepSmartMerge`, deep clones) are
304
- built-in today. A future opt-in would let extreme-throughput consumers inject
305
- their own (e.g. a SIMD fast-deep-equal or structural-sharing clone) while
306
- everyone else keeps the default. Must honour the existing structural-equality
307
- contract (a wrong comparator could drop real changes), so it ships with a
308
- documented contract + dev-mode validation. See
309
- [Commit change semantics](./docs/design/commit-change-semantics.md).
172
+ See the [builder rule and in-memory example](src/lib/builder/README.md#explicit-retries-that-reconcile-an-outside-operation) and the [runnable keyed-retry example](examples/runtime-features/retry/06-explicit-reconciliation.ts). Physical call outcomes remain unchanged; separate `retryLoop` metadata records the workflow pass and decision.
310
173
 
311
- ## FAQ
174
+ ## What the record cannot prove
312
175
 
313
- **Are recorders blocking? Do observers slow my chart down?**
314
- Inline (default) recorders run synchronously inside the producing statement.
315
- If an observer is heavy, opt it into the deferred tier:
316
- `executor.attachScopeRecorder(rec, { delivery: 'deferred' })` — events are
317
- captured into one bounded, totally-ordered queue and delivered at the next
318
- microtask checkpoint ("one beat behind"), fully drained before `run()`
319
- returns. Same record, same order; the engine stops paying for observation.
320
- Full model + FAQ: [Deferred observers guide](./docs/guides/observers-deferred.md).
176
+ - **Correctness or real-world cause.** Recorded program dependencies do not prove the requirement is right, the result is correct, or a model's interpretation is sound.
177
+ - **A complete or repeatable outside world.** Untracked inputs, capture settings, and query limits can leave gaps. Replaying recorded state does not guarantee identical external-service or model responses.
178
+ - **Integrity or compliance by itself.** An in-memory record is not a tamper-evident archive or a compliance assessment. Protect retained evidence and test failed-run persistence too.
321
179
 
322
- How it stays fast, as patterns with numbers and the tests that pin them: [Performance patterns](./docs/guides/performance-patterns.md).
180
+ For provenance, European governance terminology, disclosure controls, OpenTelemetry, vocabulary, and recording boundaries, read **[Provenance, governance and limits](docs/provenance-governance-and-limits.md)**.
323
181
 
324
- The record is the interface — write its shape from any runtime and get time travel, the fold and the Lens: [The record contract](./docs/guides/record-contract.md).
182
+ ## Explore
325
183
 
326
- ---
184
+ [API and guides](https://footprintjs.github.io/footPrint/) · [Examples](https://footprintjs.github.io/footprint-playground/) · [Contributing](https://github.com/footprintjs/footPrint/blob/main/CONTRIBUTING.md) · [MIT license](https://github.com/footprintjs/footPrint/blob/main/LICENSE)
327
185
 
328
- ## Documentation
329
-
330
- | Resource | Link |
331
- |----------|------|
332
- | **Getting Started** | [Quick Start](https://footprintjs.github.io/footPrint/getting-started/quick-start/) &middot; [Key Concepts](https://footprintjs.github.io/footPrint/getting-started/key-concepts/) &middot; [Why footprintjs?](https://footprintjs.github.io/footPrint/getting-started/why/) |
333
- | **Guides** | [Building](https://footprintjs.github.io/footPrint/guides/building/) &middot; [Decision branching](https://footprintjs.github.io/footPrint/guides/decision-branching/) &middot; [Recorders](https://footprintjs.github.io/footPrint/guides/recording/) &middot; [Subflows](https://footprintjs.github.io/footPrint/guides/subflows/) &middot; [Self-describing APIs](https://footprintjs.github.io/footPrint/guides/self-describing/) &middot; [Execution model & limits](./docs/guides/execution-model.md) |
334
- | **API Reference** | [flowChart() / Builder](https://footprintjs.github.io/footPrint/api/flowchart/) &middot; [decide() / select()](https://footprintjs.github.io/footPrint/api/decide/) &middot; [FlowChartExecutor](https://footprintjs.github.io/footPrint/api/executor/) &middot; [Recorders](https://footprintjs.github.io/footPrint/api/recorders/) &middot; [Contract & Self-describing](https://footprintjs.github.io/footPrint/api/contract/) |
335
- | **Try it** | [Interactive Playground](https://footprintjs.github.io/footprint-playground/) &middot; [Try with your LLM](https://footprintjs.github.io/footprint-playground/try-with-ai) &middot; [Live Demo](https://footprintjs.github.io/footprint-demo/) |
336
-
337
- ---
338
-
339
- ## The footprintjs ecosystem
340
-
341
- The self-explaining stack — from backend pipelines to AI agents. → **[overview](https://footprintjs.github.io/)**
342
-
343
- | Project | Role |
344
- |---|---|
345
- | **footprintjs** ← you are here | the flowchart pattern (core engine) |
346
- | [agentfootprint](https://footprintjs.github.io/agentfootprint/) | build self-explaining AI agents |
347
- | [Explainable UI](https://footprintjs.github.io/explainable-ui/) | visualize a footprintjs run |
348
- | [Lens](https://github.com/footprintjs/agentfootprint-lens) | debug an agentfootprint run |
349
- | [Thinking UI](https://footprintjs.github.io/agentThinkingUI/) | replay an agent run for non-devs |
350
-
351
- ---
352
-
353
- ## Citing
354
-
355
- footprintjs is part of a research program on making software systems explain themselves — every run records *why* it did what it did, as a causal trace. Researching agent transparency, observability, or explainable AI? The [ecosystem map](https://footprintjs.github.io/) is a good starting point.
356
-
357
- If you use footprintjs in academic work, please cite it (or use the "Cite this repository" button on GitHub):
358
-
359
- ```bibtex
360
- @software{anbalagan_footprintjs,
361
- author = {Anbalagan, Sanjay Krishna},
362
- title = {footprintjs: the self-explaining flowchart engine},
363
- url = {https://github.com/footprintjs/footPrint},
364
- license = {MIT},
365
- year = {2024}
366
- }
367
- ```
186
+ **Capture the connections during execution. Let people and agents investigate the evidence.**
368
187
 
369
- ---
188
+ ### Attempt metrics and evidence references
370
189
 
371
- [MIT](./LICENSE) &copy; [Sanjay Krishna Anbalagan](https://github.com/sanjay1909)
190
+ `attempts()` from `footprintjs/recorders` collects payload-free attempt facts during traversal. Use `byTarget()`,
191
+ `byRun()`, bounded `slowest()` exemplars and `series()` to follow native calls and explicit retry decisions; optional
192
+ `AttemptStore` adapters support cross-run queries. Row/exemplar/I/O limits disclose omitted or pending evidence.
193
+ `toOTel()` returns histogram/sum JSON without sending it anywhere. Durations are summed work time; orchestration
194
+ completion is not provider confirmation. See [the metric guide](docs/guides/attempt-metrics.md) and
195
+ [the stored-trace navigation example](examples/runtime-features/retry/07-attempt-metrics-and-trace.ts).