footprintjs 9.9.0 → 9.10.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 (227) hide show
  1. package/AGENTS.md +9 -9
  2. package/CLAUDE.md +82 -753
  3. package/README.md +51 -20
  4. package/dist/esm/advanced.d.ts +52 -0
  5. package/dist/esm/detach.d.ts +59 -0
  6. package/dist/esm/index.d.ts +202 -0
  7. package/dist/esm/lib/builder/FlowChartBuilder.d.ts +475 -0
  8. package/dist/esm/lib/builder/FlowChartBuilder.js +4 -3
  9. package/dist/esm/lib/builder/index.d.ts +11 -0
  10. package/dist/esm/lib/builder/structure/StructureRecorder.d.ts +349 -0
  11. package/dist/esm/lib/builder/structure/StructureRecorderDispatcher.d.ts +77 -0
  12. package/dist/esm/lib/builder/typedFlowChart.d.ts +25 -0
  13. package/dist/esm/lib/builder/types.d.ts +154 -0
  14. package/dist/esm/lib/capture/envelope.d.ts +169 -0
  15. package/dist/esm/lib/capture/index.d.ts +16 -0
  16. package/dist/esm/lib/capture/policies.d.ts +42 -0
  17. package/dist/esm/lib/capture/summarize.d.ts +65 -0
  18. package/dist/esm/lib/contract/defineContract.d.ts +18 -0
  19. package/dist/esm/lib/contract/index.d.ts +14 -0
  20. package/dist/esm/lib/contract/openapi.d.ts +18 -0
  21. package/dist/esm/lib/contract/schema.d.ts +13 -0
  22. package/dist/esm/lib/contract/types.d.ts +105 -0
  23. package/dist/esm/lib/decide/decide.d.ts +47 -0
  24. package/dist/esm/lib/decide/evaluator.d.ts +39 -0
  25. package/dist/esm/lib/decide/evidence.d.ts +22 -0
  26. package/dist/esm/lib/decide/index.d.ts +12 -0
  27. package/dist/esm/lib/decide/types.d.ts +111 -0
  28. package/dist/esm/lib/detach/drivers/immediate.d.ts +39 -0
  29. package/dist/esm/lib/detach/drivers/microtaskBatch.d.ts +57 -0
  30. package/dist/esm/lib/detach/drivers/sendBeacon.d.ts +38 -0
  31. package/dist/esm/lib/detach/drivers/setImmediate.d.ts +32 -0
  32. package/dist/esm/lib/detach/drivers/setTimeout.d.ts +34 -0
  33. package/dist/esm/lib/detach/drivers/workerThread.d.ts +50 -0
  34. package/dist/esm/lib/detach/flush.d.ts +62 -0
  35. package/dist/esm/lib/detach/handle.d.ts +83 -0
  36. package/dist/esm/lib/detach/registry.d.ts +82 -0
  37. package/dist/esm/lib/detach/runChild.d.ts +41 -0
  38. package/dist/esm/lib/detach/spawn.d.ts +64 -0
  39. package/dist/esm/lib/detach/types.d.ts +200 -0
  40. package/dist/esm/lib/engine/errors/errorInfo.d.ts +46 -0
  41. package/dist/esm/lib/engine/errors/index.d.ts +2 -0
  42. package/dist/esm/lib/engine/graph/StageNode.d.ts +108 -0
  43. package/dist/esm/lib/engine/graph/index.d.ts +2 -0
  44. package/dist/esm/lib/engine/handlers/ChildrenExecutor.d.ts +32 -0
  45. package/dist/esm/lib/engine/handlers/ContinuationResolver.d.ts +95 -0
  46. package/dist/esm/lib/engine/handlers/DeciderHandler.d.ts +56 -0
  47. package/dist/esm/lib/engine/handlers/NodeResolver.d.ts +41 -0
  48. package/dist/esm/lib/engine/handlers/RuntimeStructureManager.d.ts +37 -0
  49. package/dist/esm/lib/engine/handlers/SelectorHandler.d.ts +27 -0
  50. package/dist/esm/lib/engine/handlers/StageRunner.d.ts +17 -0
  51. package/dist/esm/lib/engine/handlers/SubflowExecutor.d.ts +34 -0
  52. package/dist/esm/lib/engine/handlers/SubflowExecutor.js +8 -1
  53. package/dist/esm/lib/engine/handlers/SubflowInputMapper.d.ts +40 -0
  54. package/dist/esm/lib/engine/handlers/index.d.ts +13 -0
  55. package/dist/esm/lib/engine/handlers/types.d.ts +32 -0
  56. package/dist/esm/lib/engine/index.d.ts +28 -0
  57. package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +139 -0
  58. package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.d.ts +47 -0
  59. package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.d.ts +34 -0
  60. package/dist/esm/lib/engine/narrative/NullControlFlowNarrativeGenerator.d.ts +27 -0
  61. package/dist/esm/lib/engine/narrative/index.d.ts +15 -0
  62. package/dist/esm/lib/engine/narrative/narrativeTypes.d.ts +196 -0
  63. package/dist/esm/lib/engine/narrative/recorders/AdaptiveNarrativeFlowRecorder.d.ts +25 -0
  64. package/dist/esm/lib/engine/narrative/recorders/ManifestFlowRecorder.d.ts +69 -0
  65. package/dist/esm/lib/engine/narrative/recorders/MilestoneNarrativeFlowRecorder.d.ts +24 -0
  66. package/dist/esm/lib/engine/narrative/recorders/ProgressiveNarrativeFlowRecorder.d.ts +30 -0
  67. package/dist/esm/lib/engine/narrative/recorders/RLENarrativeFlowRecorder.d.ts +25 -0
  68. package/dist/esm/lib/engine/narrative/recorders/SeparateNarrativeFlowRecorder.d.ts +32 -0
  69. package/dist/esm/lib/engine/narrative/recorders/SilentNarrativeFlowRecorder.d.ts +25 -0
  70. package/dist/esm/lib/engine/narrative/recorders/WindowedNarrativeFlowRecorder.d.ts +29 -0
  71. package/dist/esm/lib/engine/narrative/recorders/index.d.ts +9 -0
  72. package/dist/esm/lib/engine/narrative/types.d.ts +384 -0
  73. package/dist/esm/lib/engine/runtimeStageId.d.ts +103 -0
  74. package/dist/esm/lib/engine/traversal/FlowchartTraverser.d.ts +376 -0
  75. package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +1 -1
  76. package/dist/esm/lib/engine/traversal/index.d.ts +2 -0
  77. package/dist/esm/lib/engine/types.d.ts +417 -0
  78. package/dist/esm/lib/engine/walkSubflowSpec.d.ts +95 -0
  79. package/dist/esm/lib/memory/DiagnosticCollector.d.ts +33 -0
  80. package/dist/esm/lib/memory/EventLog.d.ts +27 -0
  81. package/dist/esm/lib/memory/SharedMemory.d.ts +31 -0
  82. package/dist/esm/lib/memory/StageContext.d.ts +368 -0
  83. package/dist/esm/lib/memory/StageContext.js +44 -2
  84. package/dist/esm/lib/memory/TransactionBuffer.d.ts +183 -0
  85. package/dist/esm/lib/memory/TransactionBuffer.js +35 -13
  86. package/dist/esm/lib/memory/backtrack.d.ts +252 -0
  87. package/dist/esm/lib/memory/backtrack.js +79 -8
  88. package/dist/esm/lib/memory/commitLogUtils.d.ts +41 -0
  89. package/dist/esm/lib/memory/index.d.ts +14 -0
  90. package/dist/esm/lib/memory/pathOps.d.ts +54 -0
  91. package/dist/esm/lib/memory/types.d.ts +230 -0
  92. package/dist/esm/lib/memory/types.js +1 -1
  93. package/dist/esm/lib/memory/utils.d.ts +124 -0
  94. package/dist/esm/lib/observer-queue/deferredDispatcher.d.ts +169 -0
  95. package/dist/esm/lib/observer-queue/flushDriver.d.ts +124 -0
  96. package/dist/esm/lib/observer-queue/index.d.ts +25 -0
  97. package/dist/esm/lib/observer-queue/mergedQueue.d.ts +85 -0
  98. package/dist/esm/lib/observer-queue/ring.d.ts +99 -0
  99. package/dist/esm/lib/pause/index.d.ts +2 -0
  100. package/dist/esm/lib/pause/types.d.ts +238 -0
  101. package/dist/esm/lib/pause/types.js +2 -2
  102. package/dist/esm/lib/reactive/allowlist.d.ts +30 -0
  103. package/dist/esm/lib/reactive/arrayTraps.d.ts +23 -0
  104. package/dist/esm/lib/reactive/createTypedScope.d.ts +24 -0
  105. package/dist/esm/lib/reactive/index.d.ts +14 -0
  106. package/dist/esm/lib/reactive/pathBuilder.d.ts +31 -0
  107. package/dist/esm/lib/reactive/types.d.ts +159 -0
  108. package/dist/esm/lib/reactive/types.js +1 -1
  109. package/dist/esm/lib/recorder/BoundaryStateStore.d.ts +115 -0
  110. package/dist/esm/lib/recorder/CombinedRecorder.d.ts +215 -0
  111. package/dist/esm/lib/recorder/CombinedRecorder.js +2 -2
  112. package/dist/esm/lib/recorder/CommitRangeIndex.d.ts +147 -0
  113. package/dist/esm/lib/recorder/CompositeRecorder.d.ts +95 -0
  114. package/dist/esm/lib/recorder/ControlDepRecorder.d.ts +133 -0
  115. package/dist/esm/lib/recorder/EmitRecorder.d.ts +135 -0
  116. package/dist/esm/lib/recorder/InOutRecorder.d.ts +176 -0
  117. package/dist/esm/lib/recorder/KeyedStore.d.ts +70 -0
  118. package/dist/esm/lib/recorder/QualityRecorder.d.ts +122 -0
  119. package/dist/esm/lib/recorder/RecorderOperation.d.ts +35 -0
  120. package/dist/esm/lib/recorder/SequenceStore.d.ts +120 -0
  121. package/dist/esm/lib/recorder/TopologyRecorder.d.ts +165 -0
  122. package/dist/esm/lib/recorder/TopologyRecorder.js +1 -1
  123. package/dist/esm/lib/recorder/index.d.ts +9 -0
  124. package/dist/esm/lib/recorder/invokeHook.d.ts +32 -0
  125. package/dist/esm/lib/recorder/qualityTrace.d.ts +54 -0
  126. package/dist/esm/lib/runner/ComposableRunner.d.ts +33 -0
  127. package/dist/esm/lib/runner/DeferredObserverTier.d.ts +204 -0
  128. package/dist/esm/lib/runner/ExecutionRuntime.d.ts +162 -0
  129. package/dist/esm/lib/runner/ExecutionRuntime.js +16 -1
  130. package/dist/esm/lib/runner/FlowChartExecutor.d.ts +660 -0
  131. package/dist/esm/lib/runner/FlowChartExecutor.js +35 -3
  132. package/dist/esm/lib/runner/RunContext.d.ts +42 -0
  133. package/dist/esm/lib/runner/RunnableChart.d.ts +57 -0
  134. package/dist/esm/lib/runner/checkpointSanitize.d.ts +44 -0
  135. package/dist/esm/lib/runner/getSubtreeSnapshot.d.ts +70 -0
  136. package/dist/esm/lib/runner/index.d.ts +11 -0
  137. package/dist/esm/lib/runner/runId.d.ts +45 -0
  138. package/dist/esm/lib/runner/validateInput.d.ts +11 -0
  139. package/dist/esm/lib/schema/detect.d.ts +32 -0
  140. package/dist/esm/lib/schema/errors.d.ts +36 -0
  141. package/dist/esm/lib/schema/index.d.ts +14 -0
  142. package/dist/esm/lib/schema/validate.d.ts +33 -0
  143. package/dist/esm/lib/scope/ScopeFacade.d.ts +250 -0
  144. package/dist/esm/lib/scope/detectCircular.d.ts +47 -0
  145. package/dist/esm/lib/scope/index.d.ts +16 -0
  146. package/dist/esm/lib/scope/protection/createProtectedScope.d.ts +9 -0
  147. package/dist/esm/lib/scope/protection/index.d.ts +2 -0
  148. package/dist/esm/lib/scope/protection/readonlyInput.d.ts +26 -0
  149. package/dist/esm/lib/scope/protection/types.d.ts +13 -0
  150. package/dist/esm/lib/scope/providers/baseStateCompatible.d.ts +24 -0
  151. package/dist/esm/lib/scope/providers/guards.d.ts +14 -0
  152. package/dist/esm/lib/scope/providers/index.d.ts +6 -0
  153. package/dist/esm/lib/scope/providers/providers.d.ts +8 -0
  154. package/dist/esm/lib/scope/providers/registry.d.ts +11 -0
  155. package/dist/esm/lib/scope/providers/resolve.d.ts +8 -0
  156. package/dist/esm/lib/scope/providers/types.d.ts +40 -0
  157. package/dist/esm/lib/scope/recorders/DebugRecorder.d.ts +63 -0
  158. package/dist/esm/lib/scope/recorders/MetricRecorder.d.ts +125 -0
  159. package/dist/esm/lib/scope/recorders/index.d.ts +5 -0
  160. package/dist/esm/lib/scope/recorders/summarizeValue.d.ts +7 -0
  161. package/dist/esm/lib/scope/recorders/summarizeValue.js +3 -3
  162. package/dist/esm/lib/scope/state/installResolvers.d.ts +4 -0
  163. package/dist/esm/lib/scope/state/zod/defineScopeFromZod.d.ts +9 -0
  164. package/dist/esm/lib/scope/state/zod/index.d.ts +5 -0
  165. package/dist/esm/lib/scope/state/zod/resolver.d.ts +5 -0
  166. package/dist/esm/lib/scope/state/zod/schema/builder.d.ts +12 -0
  167. package/dist/esm/lib/scope/state/zod/scopeFactory.d.ts +9 -0
  168. package/dist/esm/lib/scope/state/zod/utils/validateHelper.d.ts +25 -0
  169. package/dist/esm/lib/scope/types.d.ts +142 -0
  170. package/dist/esm/lib/slice/elementProvenance.d.ts +74 -0
  171. package/dist/esm/lib/slice/elementProvenance.js +181 -0
  172. package/dist/esm/lib/slice/index.d.ts +16 -0
  173. package/dist/esm/lib/slice/index.js +16 -0
  174. package/dist/esm/lib/slice/keysReadSources.d.ts +51 -0
  175. package/dist/esm/lib/slice/keysReadSources.js +96 -0
  176. package/dist/esm/lib/slice/serialize.d.ts +40 -0
  177. package/dist/esm/lib/slice/serialize.js +97 -0
  178. package/dist/esm/lib/slice/sliceForKey.d.ts +47 -0
  179. package/dist/esm/lib/slice/sliceForKey.js +72 -0
  180. package/dist/esm/lib/slice/types.d.ts +240 -0
  181. package/dist/esm/lib/slice/types.js +20 -0
  182. package/dist/esm/recorders.d.ts +70 -0
  183. package/dist/esm/trace.d.ts +57 -0
  184. package/dist/esm/trace.js +2 -1
  185. package/dist/esm/zod.d.ts +18 -0
  186. package/dist/lib/builder/FlowChartBuilder.js +4 -3
  187. package/dist/lib/engine/handlers/SubflowExecutor.js +8 -1
  188. package/dist/lib/engine/traversal/FlowchartTraverser.js +1 -1
  189. package/dist/lib/memory/StageContext.js +44 -2
  190. package/dist/lib/memory/TransactionBuffer.js +35 -13
  191. package/dist/lib/memory/backtrack.js +79 -8
  192. package/dist/lib/memory/types.js +1 -1
  193. package/dist/lib/pause/types.js +2 -2
  194. package/dist/lib/reactive/types.js +1 -1
  195. package/dist/lib/recorder/CombinedRecorder.js +2 -2
  196. package/dist/lib/recorder/TopologyRecorder.js +1 -1
  197. package/dist/lib/runner/ExecutionRuntime.js +16 -1
  198. package/dist/lib/runner/FlowChartExecutor.js +35 -3
  199. package/dist/lib/scope/recorders/summarizeValue.js +3 -3
  200. package/dist/lib/slice/elementProvenance.js +186 -0
  201. package/dist/lib/slice/index.js +28 -0
  202. package/dist/lib/slice/keysReadSources.js +102 -0
  203. package/dist/lib/slice/serialize.js +102 -0
  204. package/dist/lib/slice/sliceForKey.js +77 -0
  205. package/dist/lib/slice/types.js +21 -0
  206. package/dist/trace.js +12 -2
  207. package/dist/types/lib/builder/FlowChartBuilder.d.ts +25 -2
  208. package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +1 -1
  209. package/dist/types/lib/memory/StageContext.d.ts +28 -1
  210. package/dist/types/lib/memory/TransactionBuffer.d.ts +10 -1
  211. package/dist/types/lib/memory/backtrack.d.ts +26 -0
  212. package/dist/types/lib/memory/types.d.ts +26 -0
  213. package/dist/types/lib/pause/types.d.ts +4 -3
  214. package/dist/types/lib/reactive/types.d.ts +1 -1
  215. package/dist/types/lib/recorder/CombinedRecorder.d.ts +1 -1
  216. package/dist/types/lib/recorder/TopologyRecorder.d.ts +1 -1
  217. package/dist/types/lib/runner/ExecutionRuntime.d.ts +15 -1
  218. package/dist/types/lib/runner/FlowChartExecutor.d.ts +34 -3
  219. package/dist/types/lib/scope/recorders/summarizeValue.d.ts +2 -2
  220. package/dist/types/lib/slice/elementProvenance.d.ts +74 -0
  221. package/dist/types/lib/slice/index.d.ts +16 -0
  222. package/dist/types/lib/slice/keysReadSources.d.ts +51 -0
  223. package/dist/types/lib/slice/serialize.d.ts +40 -0
  224. package/dist/types/lib/slice/sliceForKey.d.ts +47 -0
  225. package/dist/types/lib/slice/types.d.ts +240 -0
  226. package/dist/types/trace.d.ts +3 -0
  227. package/package.json +75 -21
package/README.md CHANGED
@@ -5,6 +5,8 @@
5
5
  </p>
6
6
  </p>
7
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
+
8
10
  <p align="center">
9
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>
10
12
  <!-- coverage-badge --><img src="https://img.shields.io/badge/coverage-93%25-brightgreen.svg" alt="coverage: 93%"><!-- /coverage-badge -->
@@ -65,7 +67,7 @@ Stage 4: Next step: Generate rejection.
65
67
  Step 1: Write decision = "REJECTED — below-average credit; DTI exceeds 43%; Self-employed < 2yr"
66
68
  ```
67
69
 
68
- The LLM backtracks: `riskTier="high"` &larr; `dtiStatus="excessive"` &larr; `dtiRatio=0.6` &larr; `app.monthlyDebts=2100`. Every variable links to its cause:
70
+ 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:
69
71
 
70
72
  > **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."
71
73
 
@@ -107,23 +109,22 @@ const chart = flowChart<State>('FetchUser', async (scope) => {
107
109
  .end()
108
110
  .build();
109
111
 
110
- // 3. Run — state + self-generated trace included
111
- const result = await chart.recorder(narrative()).run();
112
-
113
- console.log(result.state.lane); // "VIP express"
114
- console.log(result.narrative);
115
- // [
116
- // "Stage 1: The process began with FetchUser.",
117
- // " Step 1: Write user = {name, tier}",
118
- // "Stage 2: Next, it moved on to ApplyDiscount.",
119
- // " Step 1: Read user = {name, tier}",
120
- // " Step 2: Write discount = 0.2",
121
- // "Stage 3: Next step: Route by discount tier.",
122
- // " Step 1: Read discount = 0.2",
123
- // "[Condition]: It evaluated Rule 0 \"High discount\": discount 0.2 gt 0.1 ✓, and chose VIPCheckout.",
124
- // "Stage 4: Next, it moved on to VIPCheckout.",
125
- // " Step 1: Write lane = \"VIP express\"",
126
- // ]
112
+ // 3. Run — capture the narrative recorder so you can read the trace back
113
+ const trace = narrative();
114
+ const result = await chart.recorder(trace).run();
115
+
116
+ console.log(result.state.lane); // "VIP express"
117
+ console.log(trace.getEntries().map((e) => e.text).join('\n'));
118
+ // Stage 1: The process began with FetchUser.
119
+ // Step 1: Write user = {name, tier}
120
+ // Stage 2: Next, it moved on to ApplyDiscount.
121
+ // Step 1: Read user = {name, tier}
122
+ // Step 2: Write discount = 0.2
123
+ // Stage 3: Next step: Route by discount tier.
124
+ // Step 1: Read discount = 0.2
125
+ // [Condition]: It evaluated Rule 0 "High discount": discount 0.2 gt 0.1 ✓, and chose VIPCheckout.
126
+ // Stage 4: Next, it moved on to VIPCheckout.
127
+ // Step 1: Write lane = "VIP express"
127
128
  ```
128
129
 
129
130
  > **[Try it in the browser](https://footprintjs.github.io/footprint-playground/)** &mdash; no install needed
@@ -132,13 +133,29 @@ console.log(result.narrative);
132
133
 
133
134
  ---
134
135
 
136
+ ## Vocabulary
137
+
138
+ If you know agent or backend systems, you already know these &mdash; here's footprint's name for each:
139
+
140
+ | footprint term | = the thing you already know |
141
+ |---|---|
142
+ | **scope** | the run's shared **state** (an agent's working memory) &mdash; but every read/write is tracked |
143
+ | **stage** | a **step** / node in the flowchart |
144
+ | **decider** / **selector** | a **router** (picks one branch) / **parallel fan-out** (picks many) |
145
+ | **subflow** | a nested flowchart you compose like a **function** |
146
+ | **recorder** | an **observer** &mdash; called on each read, write, and decision |
147
+ | **narrative** | the execution **trace** rendered as plain-English sentences (the LLM-readable form) |
148
+ | **commit log** | the ordered record of **what each step wrote** &mdash; powers time-travel replay |
149
+
150
+ ---
151
+
135
152
  ## Try With Your LLM
136
153
 
137
154
  Expose any flowchart as an MCP tool in one line &mdash; the description, input schema, and step list are auto-generated from the graph.
138
155
 
139
156
  ```typescript
140
157
  const tool = chart.toMCPTool();
141
- // { name: 'assesscredit', description: '1. AssessCredit\n2. ...', inputSchema: { ... } }
158
+ // { name: 'AssessCredit', description: 'FlowChart: AssessCredit\nSteps:\n1. AssessCredit\n2. ...', inputSchema: { type: 'object', properties: {} } }
142
159
 
143
160
  // Register with any MCP server or pass directly to the Anthropic SDK:
144
161
  const anthropicTool = { name: tool.name, description: tool.description, input_schema: tool.inputSchema };
@@ -161,7 +178,7 @@ The LLM calls the tool, gets back the decision and causal trace, and explains th
161
178
  | **7 Patterns** | Linear, parallel fork, conditional, multi-select, subflow, streaming, loops |
162
179
  | **Transactional State** | Per-stage staged commits, safe merges, time-travel replay |
163
180
  | **PII Redaction** | Per-key or declarative `RedactionPolicy` with audit trail |
164
- | **Flow Recorders** | 8 narrative strategies for loop compression |
181
+ | **Flow Recorders** | 7 loop-compression strategies (+ a subflow Manifest recorder) |
165
182
  | **Combined Recorders** | Single-hook observers that span data-flow + control-flow &mdash; `executor.attachCombinedRecorder(r)` |
166
183
  | **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) |
167
184
  | **Contracts** | I/O schemas (Zod/JSON Schema) + OpenAPI 3.1 + MCP tool generation |
@@ -276,4 +293,18 @@ Full model + FAQ: [Deferred observers guide](./docs/guides/observers-deferred.md
276
293
 
277
294
  ---
278
295
 
296
+ ## The footprintjs ecosystem
297
+
298
+ The self-explaining stack — from backend pipelines to AI agents. → **[overview](https://footprintjs.github.io/)**
299
+
300
+ | Project | Role |
301
+ |---|---|
302
+ | **footprintjs** ← you are here | the flowchart pattern (core engine) |
303
+ | [agentfootprint](https://footprintjs.github.io/agentfootprint/) | build self-explaining AI agents |
304
+ | [Explainable UI](https://footprintjs.github.io/explainable-ui/) | visualize a footprintjs run |
305
+ | [Lens](https://github.com/footprintjs/agentfootprint-lens) | debug an agentfootprint run |
306
+ | [Thinking UI](https://footprintjs.github.io/agentThinkingUI/) | replay an agent run for non-devs |
307
+
308
+ ---
309
+
279
310
  [MIT](./LICENSE) &copy; [Sanjay Krishna Anbalagan](https://github.com/sanjay1909)
@@ -0,0 +1,52 @@
1
+ /**
2
+ * footprintjs/advanced — Low-level internals for custom execution engines and testing.
3
+ *
4
+ * Most users never need this. Use `footprintjs` (main) instead.
5
+ * This entry point exposes `SharedMemory`, `StageContext`, `FlowchartTraverser`,
6
+ * and other primitives that power the engine.
7
+ *
8
+ * ```ts
9
+ * import { SharedMemory, StageContext } from 'footprintjs/advanced';
10
+ * ```
11
+ *
12
+ * @module advanced
13
+ */
14
+ /**
15
+ * FootPrint — Advanced / Internal API
16
+ *
17
+ * These exports are for advanced use cases, testing, and building
18
+ * custom execution engines. Most users should use the main 'footprint' entry point.
19
+ *
20
+ * Import via: import { ... } from 'footprint/advanced'
21
+ */
22
+ export type { CommitBundle, FlowControlType, FlowMessage, MemoryPatch, ReadSummaryMarker, ReadTrackingMode, RetentionPolicy, StageSnapshot, TraceEntry, UntrackedSource, WriteSummaryMarker, WriteTrackingMode, } from './lib/memory/index.js';
23
+ export { SharedMemory } from './lib/memory/index.js';
24
+ export { StageContext } from './lib/memory/index.js';
25
+ export { EventLog } from './lib/memory/index.js';
26
+ export { TransactionBuffer } from './lib/memory/index.js';
27
+ export { DiagnosticCollector } from './lib/memory/index.js';
28
+ export { applySmartMerge, deepSmartMerge, getNestedValue, getRunAndGlobalPaths, normalisePath, redactPatch, setNestedValue, updateNestedValue, updateValue, } from './lib/memory/index.js';
29
+ export type { ExecOptions, FlowChartOptions, FlowChartSpec, ILogger, ScopeProtectionMode, SerializedPipelineStructure, SimplifiedParallelSpec, StageFn, StageNode, StreamCallback, StreamLifecycleHandler, StreamTokenHandler, SubflowMountOptions, SubflowRef, } from './lib/builder/index.js';
30
+ export { ArrayMergeMode, DeciderList, SelectorFnList, specToStageNode } from './lib/builder/index.js';
31
+ export { createTypedScopeFactory } from './lib/builder/typedFlowChart.js';
32
+ export type { ProviderResolver, ResolveOptions, ScopeProvider, StageContextLike, StrictMode, } from './lib/scope/index.js';
33
+ export { createErrorMessage, createProtectedScope, ScopeFacade } from './lib/scope/index.js';
34
+ export { attachScopeMethods, isSubclassOfScopeFacade, looksLikeClassCtor, looksLikeFactory, makeClassProvider, makeFactoryProvider, registerScopeResolver, resolveScopeProvider, toScopeFactory, } from './lib/scope/index.js';
35
+ export type { AggregatedMetrics, DebugEntry, DebugRecorderOptions, DebugVerbosity, RecorderContext, StageEvent, StageMetrics, } from './lib/scope/index.js';
36
+ export type { RuntimeSnapshot } from './lib/runner/index.js';
37
+ export { ExecutionRuntime } from './lib/runner/index.js';
38
+ export type { ReactiveOptions, ReactiveTarget } from './lib/reactive/index.js';
39
+ export { BREAK_SETTER, buildNestedPatch, createArrayProxy, joinPath, SCOPE_METHOD_NAMES, shouldWrapWithProxy, } from './lib/reactive/index.js';
40
+ export type { TraverserOptions } from './lib/engine/index.js';
41
+ export type { Decider } from './lib/engine/index.js';
42
+ export { FlowchartTraverser } from './lib/engine/index.js';
43
+ export { isStageNodeReturn } from './lib/engine/index.js';
44
+ export type { IControlFlowNarrative } from './lib/engine/index.js';
45
+ export type { CombinedNarrativeEntry, CombinedNarrativeOptions } from './lib/engine/index.js';
46
+ export type { BranchResult, BranchResults, SerializedPipelineStructure as EngineSerializedPipelineStructure, HandlerDeps, IExecutionRuntime, NodeResultType, RuntimeStructureMetadata, ScopeFactory, SerializedPipelineNode, StageFunction, SubflowResult, TraversalResult, } from './lib/engine/index.js';
47
+ export { NullControlFlowNarrativeGenerator } from './lib/engine/index.js';
48
+ export type { ExecuteNodeFn, RunStageFn } from './lib/engine/index.js';
49
+ export { applyOutputMapping, ChildrenExecutor, computeNodeType, ContinuationResolver, createSubflowHandlerDeps, DeciderHandler, DEFAULT_MAX_ITERATIONS, extractParentScopeValues, getInitialScopeValues, NodeResolver, RuntimeStructureManager, seedSubflowGlobalStore, SelectorHandler, StageRunner, SubflowExecutor, } from './lib/engine/index.js';
50
+ export type { ExecutionCounter } from './lib/engine/runtimeStageId.js';
51
+ export { buildRuntimeStageId, createExecutionCounter, parseRuntimeStageId } from './lib/engine/runtimeStageId.js';
52
+ export { findCommit, findCommits, findLastWriter } from './lib/memory/commitLogUtils.js';
@@ -0,0 +1,59 @@
1
+ /**
2
+ * footprintjs/detach — Fire-and-forget child flowchart execution.
3
+ *
4
+ * A library of scheduling drivers that lets you detach work from the
5
+ * parent stage's hot path. The parent stage returns immediately; the
6
+ * child runs on whichever driver you pick (microtask, immediate, plus
7
+ * setImmediate / setTimeout / sendBeacon / worker-thread in v4.17.1+).
8
+ *
9
+ * Two shapes:
10
+ *
11
+ * - `detachAndJoinLater(driver, child, input)` — returns a `DetachHandle`
12
+ * you can `wait()` on (Promise) or read `.status` from (sync).
13
+ * - `detachAndForget(driver, child, input)` — discards the handle.
14
+ * Use for fire-and-forget telemetry where the caller never needs to
15
+ * know how the child finished.
16
+ *
17
+ * Two entry points:
18
+ *
19
+ * - `scope.$detachAndJoinLater(driver, child, input)` — from inside a
20
+ * stage. refIds are minted from the calling stage's runtimeStageId
21
+ * for diagnostic correlation.
22
+ * - `executor.detachAndJoinLater(driver, child, input)` — from outside
23
+ * any chart (consumer code). refIds use the synthetic `__executor__`
24
+ * prefix.
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * import { microtaskBatchDriver } from 'footprintjs/detach';
29
+ * import { flowChart, FlowChartExecutor } from 'footprintjs';
30
+ *
31
+ * const telemetry = flowChart('telemetry', async (scope) => {
32
+ * await fetch('/log', { method: 'POST', body: JSON.stringify(scope.$getArgs()) });
33
+ * }, 'telemetry').build();
34
+ *
35
+ * const main = flowChart('process', async (scope) => {
36
+ * scope.result = await heavyWork();
37
+ * // Fire telemetry without blocking the parent.
38
+ * scope.$detachAndForget(microtaskBatchDriver, telemetry, { event: 'processed' });
39
+ * }, 'process').build();
40
+ *
41
+ * await new FlowChartExecutor(main).run();
42
+ * ```
43
+ */
44
+ export type { DetachDriver, DetachHandle, DetachPollResult, DetachWaitResult, DriverCapabilities, } from './lib/detach/types.js';
45
+ export { createImmediateDriver, immediateDriver } from './lib/detach/drivers/immediate.js';
46
+ export { createMicrotaskBatchDriver, microtaskBatchDriver } from './lib/detach/drivers/microtaskBatch.js';
47
+ export type { SendBeaconDriverOptions } from './lib/detach/drivers/sendBeacon.js';
48
+ export { createSendBeaconDriver } from './lib/detach/drivers/sendBeacon.js';
49
+ export { createSetImmediateDriver, setImmediateDriver } from './lib/detach/drivers/setImmediate.js';
50
+ export type { SetTimeoutDriverOptions } from './lib/detach/drivers/setTimeout.js';
51
+ export { createSetTimeoutDriver, setTimeoutDriver } from './lib/detach/drivers/setTimeout.js';
52
+ export type { WorkerThreadDriverOptions } from './lib/detach/drivers/workerThread.js';
53
+ export { createWorkerThreadDriver } from './lib/detach/drivers/workerThread.js';
54
+ export { asImpl, createHandle, HandleImpl } from './lib/detach/handle.js';
55
+ export type { ChildRunner } from './lib/detach/runChild.js';
56
+ export { defaultRunChild } from './lib/detach/runChild.js';
57
+ export { size as detachedCount, ids as listDetachedIds, lookup as lookupDetachedHandle, } from './lib/detach/registry.js';
58
+ export type { FlushOptions, FlushResult } from './lib/detach/flush.js';
59
+ export { flushAllDetached } from './lib/detach/flush.js';
@@ -0,0 +1,202 @@
1
+ /**
2
+ * FootPrint — Public API (v3)
3
+ *
4
+ * The flowchart pattern for backend code.
5
+ * Build → Run → Observe.
6
+ *
7
+ * **Three import paths:**
8
+ * ```ts
9
+ * import { flowChart, decide, narrative } from 'footprintjs'; // main — start here
10
+ * import { metrics, debug, manifest } from 'footprintjs/recorders'; // recorder factories
11
+ * import { SharedMemory, StageContext } from 'footprintjs/advanced'; // internals
12
+ * ```
13
+ *
14
+ * @module
15
+ */
16
+ /** @category Quick Start */
17
+ export type { FlowChart, StageFunction as StageHandler, StreamHandlers } from './lib/builder/index.js';
18
+ /** @category Quick Start */
19
+ export { flowChart, FlowChartBuilder, flowChartSelector } from './lib/builder/index.js';
20
+ /** @category Quick Start — build-time observer (twin of FlowRecorder) */
21
+ export type { StructureDeciderCompleteEvent, StructureEdgeAddedEvent, StructureEdgeKind, StructureLoopEdgeAddedEvent, StructureRecorder, StructureStageAddedEvent, StructureSubflowMountedEvent, } from './lib/builder/index.js';
22
+ /** @category Quick Start */
23
+ export type { TypedStageFunction } from './lib/builder/typedFlowChart.js';
24
+ /** @category Quick Start */
25
+ export type { ScopeMethods, TypedScope } from './lib/reactive/index.js';
26
+ /** @category Quick Start */
27
+ export { narrative } from './recorders.js';
28
+ /** @category Decision Branching */
29
+ export type { DecideRule, DecisionEvidence, DecisionResult, FilterOps, RuleEvidence, SelectionEvidence, SelectionResult, WhenClause, WhereFilter, } from './lib/decide/index.js';
30
+ /** @category Decision Branching */
31
+ export { decide, select } from './lib/decide/index.js';
32
+ /** @category Run */
33
+ export type { RunResult } from './lib/runner/index.js';
34
+ /** @category Run */
35
+ export type { FlowChartExecutorOptions } from './lib/runner/index.js';
36
+ /** @category Run */
37
+ export { FlowChartExecutor } from './lib/runner/index.js';
38
+ /** @category Run */
39
+ export { RunContext } from './lib/runner/index.js';
40
+ /** @category Run */
41
+ export type { ChartOpenAPIOptions, MCPToolDescription, RunnableFlowChart } from './lib/runner/RunnableChart.js';
42
+ /** @category Observe — Data */
43
+ export type { CommitEvent, ErrorEvent, ReadEvent, RedactionPolicy, RedactionReport, ScopeRecorder, StageEvent, WriteEvent, } from './lib/scope/index.js';
44
+ /** @category Observe — Data */
45
+ export { MetricRecorder } from './lib/scope/index.js';
46
+ /** @category Observe — Data */
47
+ export { DebugRecorder } from './lib/scope/index.js';
48
+ /** @category Observe — Operation */
49
+ export { RecorderOperation } from './lib/recorder/index.js';
50
+ /**
51
+ * @category Observe — Delivery tier (RFC-001 deferred observers)
52
+ *
53
+ * Every `attach*Recorder` call accepts an options bag:
54
+ * `executor.attachScopeRecorder(rec, { delivery: 'deferred' })` takes the
55
+ * recorder OUT of the engine's hot path — events are captured into one
56
+ * bounded, totally-ordered queue and delivered at the next microtask
57
+ * checkpoint ("one beat behind"). Omit `delivery` for the historical
58
+ * synchronous call (byte-identical to previous releases). Accounting
59
+ * surfaces on `snapshot.observerStats`; `executor.drainObservers()` settles
60
+ * async listeners before shutdown. See `docs/guides/observers-deferred.md`.
61
+ */
62
+ export type { AttachRecorderOptions, ObserverDelivery, ObserverDrainResult, ObserverStats, } from './lib/runner/index.js';
63
+ /**
64
+ * @category Observe — Delivery tier (RFC-001 deferred observers)
65
+ *
66
+ * `CapturePolicy` — how a deferred event's payload is materialized at
67
+ * capture time (`'summary'` default / `'clone'` / `'ref'`). `OverflowPolicy`
68
+ * — what a saturated queue does (`'drop-oldest'` default / `'sample'` /
69
+ * `'block'`). `DispatcherStats` / `ListenerStats` — the accounting shapes
70
+ * embedded in `ObserverStats`. Types only — the observer-queue module
71
+ * itself is internal; consumers use the attach options.
72
+ */
73
+ export type { CapturePolicy, DispatcherStats, ListenerStats, OverflowPolicy } from './lib/observer-queue/index.js';
74
+ /** @category Observe — Combined (both data-flow and control-flow) */
75
+ export type { CombinedRecorder } from './lib/recorder/index.js';
76
+ /** @category Observe — Combined (both data-flow and control-flow) */
77
+ export { hasEmitRecorderMethods, hasFlowRecorderMethods, hasRecorderMethods, isFlowEvent, } from './lib/recorder/index.js';
78
+ /**
79
+ * @category Observe — Emit (user-authored structured events)
80
+ *
81
+ * Third observer channel (alongside `ScopeRecorder` and `FlowRecorder`). Consumer
82
+ * code calls `scope.$emit(name, payload)` from inside a stage; every attached
83
+ * `EmitRecorder.onEmit(event)` fires synchronously with stage-context
84
+ * enrichment. Pass-through — no buffering, zero allocation when no recorder
85
+ * is attached.
86
+ */
87
+ export type { EmitEvent, EmitRecorder } from './lib/recorder/index.js';
88
+ /** @category Observe — Flow */
89
+ export type { FlowBreakEvent, FlowDecisionEvent, FlowErrorEvent, FlowForkEvent, FlowLoopEvent, FlowNextEvent, FlowRecorder, FlowRunEvent, FlowRunFailedEvent, FlowSelectedEvent, FlowStageEvent, FlowSubflowEvent, FlowSubflowRegisteredEvent, TraversalContext, } from './lib/engine/index.js';
90
+ /** @category Observe — Flow */
91
+ export type { CombinedNarrativeEntry } from './lib/engine/index.js';
92
+ /**
93
+ * @category Observe — Flow
94
+ *
95
+ * `NarrativeFormatter` — pluggable formatter that converts event context
96
+ * objects into the text lines of the narrative. Prefer this name in new
97
+ * code; `NarrativeRenderer` is a deprecated alias that will be removed in
98
+ * the next major release.
99
+ */
100
+ export type { NarrativeFormatter, NarrativeRenderer } from './lib/engine/index.js';
101
+ /** @category Observe — Flow */
102
+ export { NarrativeFlowRecorder } from './lib/engine/index.js';
103
+ /** @category Observe — Flow */
104
+ export type { ManifestEntry } from './lib/engine/index.js';
105
+ /** @category Observe — Flow */
106
+ export { ManifestFlowRecorder } from './lib/engine/index.js';
107
+ /** @category Observe — Flow */
108
+ export { AdaptiveNarrativeFlowRecorder } from './lib/engine/index.js';
109
+ /** @category Observe — Flow */
110
+ export { MilestoneNarrativeFlowRecorder } from './lib/engine/index.js';
111
+ /** @category Observe — Flow */
112
+ export { ProgressiveNarrativeFlowRecorder } from './lib/engine/index.js';
113
+ /** @category Observe — Flow */
114
+ export { RLENarrativeFlowRecorder } from './lib/engine/index.js';
115
+ /** @category Observe — Flow */
116
+ export { SeparateNarrativeFlowRecorder } from './lib/engine/index.js';
117
+ /** @category Observe — Flow */
118
+ export { SilentNarrativeFlowRecorder } from './lib/engine/index.js';
119
+ /** @category Observe — Flow */
120
+ export { WindowedNarrativeFlowRecorder } from './lib/engine/index.js';
121
+ /** @category Self-Describing */
122
+ export type { FlowChartContract, FlowChartContractOptions, JsonSchema, OpenAPIOptions, OpenAPISpec, } from './lib/contract/index.js';
123
+ /** @category Snapshot & Composition */
124
+ export type { ComposableRunner } from './lib/runner/index.js';
125
+ /** @category Snapshot & Composition */
126
+ export type { RecorderSnapshot, RuntimeSnapshot, SubtreeSnapshot } from './lib/runner/index.js';
127
+ /** @category Snapshot & Composition */
128
+ export { getSubtreeSnapshot, listSubflowPaths } from './lib/runner/index.js';
129
+ /** @category ScopeRecorder */
130
+ export { CompositeRecorder } from './lib/recorder/index.js';
131
+ /** @category Pause/Resume */
132
+ /** @category Pause/Resume */
133
+ export type { FlowchartCheckpoint, PausableHandler } from './lib/pause/index.js';
134
+ /** @category ScopeRecorder */
135
+ export type { CompositeSnapshot } from './lib/recorder/index.js';
136
+ /** @category Configuration */
137
+ export type { ExecutionEnv, ExecutorResult, PausedResult, RunOptions } from './lib/engine/index.js';
138
+ /** @category Configuration */
139
+ export type { ScopeFactory } from './lib/engine/index.js';
140
+ /**
141
+ * @category Configuration
142
+ *
143
+ * Read-tracking policy for `StageSnapshot.stageReads` (#14):
144
+ * `'full'` (default — per-read value clone, historical behavior) /
145
+ * `'summary'` (cheap `ReadSummaryMarker` per read) / `'off'` (no tracking,
146
+ * zero per-read clone). Pass as `new FlowChartExecutor(chart, { readTracking })`
147
+ * or call `executor.setReadTracking(mode)` before `run()`.
148
+ */
149
+ export type { ReadSummaryMarker, ReadTrackingMode } from './lib/memory/index.js';
150
+ /**
151
+ * @category Configuration
152
+ *
153
+ * Write-tracking policy for `StageSnapshot.stageWrites` (#13c-A) — the
154
+ * sibling of `ReadTrackingMode`; both alias the shared `RetentionPolicy`
155
+ * family from `lib/capture`. `'full'` (default — per-write value clone,
156
+ * historical behavior) / `'summary'` (cheap `WriteSummaryMarker` per write)
157
+ * / `'off'` (no tracking; `stageWrites` absent and the `onCommit` mutations
158
+ * payload is empty — writes themselves still commit, and the commit log is
159
+ * unaffected). Pass as `new FlowChartExecutor(chart, { writeTracking })` or
160
+ * call `executor.setWriteTracking(mode)` before `run()`.
161
+ */
162
+ export type { RetentionPolicy, WriteSummaryMarker, WriteTrackingMode } from './lib/memory/index.js';
163
+ /**
164
+ * @category Configuration
165
+ *
166
+ * Commit-values encoding for the COMMIT LOG (#13c-B) — the third dial of
167
+ * the family, and the only LOSSLESS one (it changes the log's encoding,
168
+ * never its information). `'full'` (default — every surviving `set` stores
169
+ * the full final value, byte-identical to history) / `'delta'` (array
170
+ * net-changes that are "base plus a tail" commit as an `append` verb
171
+ * storing only the tail; `deleteValue()` commits as a real `delete` verb;
172
+ * one trace entry per surviving path). Replay reconstructs every step's
173
+ * full state exactly. Consumers reading `bundle.overwrite[key]` as the full
174
+ * value must use `commitValueAt` from `footprintjs/trace`. Pass as
175
+ * `new FlowChartExecutor(chart, { commitValues })` or call
176
+ * `executor.setCommitValues(mode)` before `run()`; the active mode is the
177
+ * snapshot discriminant `getSnapshot().commitValues`.
178
+ */
179
+ export type { CommitValuesMode } from './lib/memory/index.js';
180
+ /** @category Contract & Validation */
181
+ export type { SchemaKind, ValidationIssue, ValidationResult } from './lib/schema/index.js';
182
+ /** @category Contract & Validation */
183
+ export { detectSchema, isValidatable, isZod } from './lib/schema/index.js';
184
+ /** @category Contract & Validation */
185
+ export { InputValidationError, validateAgainstSchema, validateOrThrow } from './lib/schema/index.js';
186
+ /** @category Error Utilities */
187
+ export type { StructuredErrorInfo } from './lib/engine/index.js';
188
+ /** @category Error Utilities */
189
+ export { extractErrorInfo, formatErrorInfo } from './lib/engine/index.js';
190
+ /**
191
+ * @category Dev Tools
192
+ *
193
+ * Global dev-mode flag. Call `enableDevMode()` at application startup to
194
+ * turn on developer-only diagnostics across the library — circular-reference
195
+ * detection in scope writes, warnings when a recorder has no observer
196
+ * methods, suspicious-predicate warnings in decide/select, structural
197
+ * checks in `getSubtreeSnapshot`, and any future dev-only diagnostic.
198
+ *
199
+ * Production leaves it OFF by default (zero overhead). See the JSDoc on
200
+ * `enableDevMode` for the full list and usage example.
201
+ */
202
+ export { disableDevMode, enableDevMode, isDevMode } from './lib/scope/detectCircular.js';