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.
- package/AGENTS.md +2 -1
- package/CLAUDE.md +61 -7
- package/README.md +136 -312
- package/dist/esm/index.d.ts +62 -2
- package/dist/esm/index.js +13 -6
- package/dist/esm/lib/attempt/anySignal.d.ts +19 -0
- package/dist/esm/lib/attempt/anySignal.js +39 -0
- package/dist/esm/lib/attempt/call.d.ts +88 -0
- package/dist/esm/lib/attempt/call.js +129 -0
- package/dist/esm/lib/attempt/category.d.ts +37 -0
- package/dist/esm/lib/attempt/category.js +131 -0
- package/dist/esm/lib/attempt/correlation.d.ts +95 -0
- package/dist/esm/lib/attempt/correlation.js +178 -0
- package/dist/esm/lib/attempt/deadline.d.ts +44 -0
- package/dist/esm/lib/attempt/deadline.js +101 -0
- package/dist/esm/lib/attempt/decision.d.ts +52 -0
- package/dist/esm/lib/attempt/decision.js +134 -0
- package/dist/esm/lib/attempt/effect.d.ts +76 -0
- package/dist/esm/lib/attempt/effect.js +160 -0
- package/dist/esm/lib/attempt/errors.d.ts +41 -0
- package/dist/esm/lib/attempt/errors.js +44 -0
- package/dist/esm/lib/attempt/index.d.ts +18 -0
- package/dist/esm/lib/attempt/index.js +15 -0
- package/dist/esm/lib/attempt/name.d.ts +21 -0
- package/dist/esm/lib/attempt/name.js +43 -0
- package/dist/esm/lib/attempt/observed.d.ts +66 -0
- package/dist/esm/lib/attempt/observed.js +171 -0
- package/dist/esm/lib/attempt/policy.d.ts +45 -0
- package/dist/esm/lib/attempt/policy.js +83 -0
- package/dist/esm/lib/attempt/record.d.ts +11 -0
- package/dist/esm/lib/attempt/record.js +24 -0
- package/dist/esm/lib/attempt/retryLoopContext.d.ts +18 -0
- package/dist/esm/lib/attempt/retryLoopContext.js +24 -0
- package/dist/esm/lib/attempt/retryLoopTypes.d.ts +18 -0
- package/dist/esm/lib/attempt/retryLoopTypes.js +2 -0
- package/dist/esm/lib/attempt/runner.d.ts +157 -0
- package/dist/esm/lib/attempt/runner.js +523 -0
- package/dist/esm/lib/attempt/standalone.d.ts +47 -0
- package/dist/esm/lib/attempt/standalone.js +126 -0
- package/dist/esm/lib/attempt/types.d.ts +453 -0
- package/dist/esm/lib/attempt/types.js +16 -0
- package/dist/esm/lib/budget/index.d.ts +9 -0
- package/dist/esm/lib/budget/index.js +9 -0
- package/dist/esm/lib/budget/timeBudget.d.ts +136 -0
- package/dist/esm/lib/budget/timeBudget.js +666 -0
- package/dist/esm/lib/builder/FlowChartBuilder.d.ts +88 -3
- package/dist/esm/lib/builder/FlowChartBuilder.js +199 -9
- package/dist/esm/lib/builder/retryLoop.d.ts +56 -0
- package/dist/esm/lib/builder/retryLoop.js +283 -0
- package/dist/esm/lib/builder/types.d.ts +35 -1
- package/dist/esm/lib/builder/types.js +1 -1
- package/dist/esm/lib/decide/decide.js +2 -2
- package/dist/esm/lib/decide/index.d.ts +1 -1
- package/dist/esm/lib/decide/index.js +2 -2
- package/dist/esm/lib/decide/types.d.ts +3 -0
- package/dist/esm/lib/decide/types.js +1 -8
- package/dist/esm/lib/engine/graph/StageNode.d.ts +11 -1
- package/dist/esm/lib/engine/graph/StageNode.js +1 -1
- package/dist/esm/lib/engine/graph/prefixNodeTree.js +5 -1
- package/dist/esm/lib/engine/handlers/ChildrenExecutor.js +36 -6
- package/dist/esm/lib/engine/handlers/DeciderHandler.js +9 -5
- package/dist/esm/lib/engine/handlers/ResumeEntry.js +3 -1
- package/dist/esm/lib/engine/handlers/SelectorHandler.js +6 -5
- package/dist/esm/lib/engine/handlers/StageRunner.d.ts +8 -1
- package/dist/esm/lib/engine/handlers/StageRunner.js +36 -9
- package/dist/esm/lib/engine/handlers/SubflowExecutor.js +24 -5
- package/dist/esm/lib/engine/handlers/commitStage.d.ts +7 -0
- package/dist/esm/lib/engine/handlers/commitStage.js +22 -4
- package/dist/esm/lib/engine/handlers/stageError.d.ts +9 -0
- package/dist/esm/lib/engine/handlers/stageError.js +23 -1
- package/dist/esm/lib/engine/index.d.ts +2 -2
- package/dist/esm/lib/engine/index.js +1 -1
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +27 -13
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +68 -40
- package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.d.ts +4 -1
- package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.js +19 -2
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.d.ts +22 -3
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.js +61 -9
- package/dist/esm/lib/engine/narrative/NullControlFlowNarrativeGenerator.d.ts +1 -0
- package/dist/esm/lib/engine/narrative/NullControlFlowNarrativeGenerator.js +2 -1
- package/dist/esm/lib/engine/narrative/formatting/sentences.d.ts +23 -0
- package/dist/esm/lib/engine/narrative/formatting/sentences.js +127 -1
- package/dist/esm/lib/engine/narrative/index.d.ts +2 -2
- package/dist/esm/lib/engine/narrative/index.js +1 -1
- package/dist/esm/lib/engine/narrative/narrativeTypes.d.ts +27 -21
- package/dist/esm/lib/engine/narrative/narrativeTypes.js +1 -1
- package/dist/esm/lib/engine/narrative/recorders/ManifestFlowRecorder.d.ts +45 -2
- package/dist/esm/lib/engine/narrative/recorders/ManifestFlowRecorder.js +55 -2
- package/dist/esm/lib/engine/narrative/recorders/index.d.ts +1 -1
- package/dist/esm/lib/engine/narrative/recorders/index.js +1 -1
- package/dist/esm/lib/engine/narrative/types.d.ts +74 -5
- package/dist/esm/lib/engine/narrative/types.js +1 -1
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.d.ts +59 -19
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +194 -118
- package/dist/esm/lib/engine/traversalContext.d.ts +7 -2
- package/dist/esm/lib/engine/traversalContext.js +6 -3
- package/dist/esm/lib/engine/types.d.ts +52 -57
- package/dist/esm/lib/engine/types.js +1 -1
- package/dist/esm/lib/errors/terminalFailure.d.ts +29 -0
- package/dist/esm/lib/errors/terminalFailure.js +60 -0
- package/dist/esm/lib/{decide → filter}/evaluator.d.ts +7 -2
- package/dist/esm/lib/filter/evaluator.js +135 -0
- package/dist/esm/lib/ids/idempotencyKey.d.ts +14 -0
- package/dist/esm/lib/ids/idempotencyKey.js +24 -0
- package/dist/esm/lib/memory/StageContext.d.ts +123 -3
- package/dist/esm/lib/memory/StageContext.js +245 -4
- package/dist/esm/lib/memory/attention.d.ts +26 -0
- package/dist/esm/lib/memory/attention.js +171 -0
- package/dist/esm/lib/memory/borrowedMutation.d.ts +8 -0
- package/dist/esm/lib/memory/borrowedMutation.js +14 -1
- package/dist/esm/lib/memory/frameTypes.d.ts +38 -0
- package/dist/esm/lib/memory/frameTypes.js +3 -1
- package/dist/esm/lib/memory/redaction.d.ts +12 -0
- package/dist/esm/lib/memory/redaction.js +54 -5
- package/dist/esm/lib/pause/record.js +10 -1
- package/dist/esm/lib/pause/types.d.ts +19 -0
- package/dist/esm/lib/pause/types.js +17 -1
- package/dist/esm/lib/reactive/createTypedScope.js +3 -1
- package/dist/esm/lib/reactive/types.d.ts +36 -4
- package/dist/esm/lib/reactive/types.js +3 -1
- package/dist/esm/lib/recorder/AttemptRecorder.d.ts +141 -0
- package/dist/esm/lib/recorder/AttemptRecorder.js +412 -0
- package/dist/esm/lib/recorder/ControlDepRecorder.d.ts +36 -2
- package/dist/esm/lib/recorder/ControlDepRecorder.js +50 -2
- package/dist/esm/lib/recorder/EmitRecorder.d.ts +3 -0
- package/dist/esm/lib/recorder/EmitRecorder.js +1 -1
- package/dist/esm/lib/recorder/InOutRecorder.d.ts +37 -1
- package/dist/esm/lib/recorder/InOutRecorder.js +75 -6
- package/dist/esm/lib/recorder/QualityRecorder.d.ts +32 -5
- package/dist/esm/lib/recorder/QualityRecorder.js +87 -29
- package/dist/esm/lib/recorder/TopologyRecorder.d.ts +35 -5
- package/dist/esm/lib/recorder/TopologyRecorder.js +76 -2
- package/dist/esm/lib/recorder/attemptMetricRows.d.ts +11 -0
- package/dist/esm/lib/recorder/attemptMetricRows.js +202 -0
- package/dist/esm/lib/recorder/attemptMetrics.d.ts +7 -0
- package/dist/esm/lib/recorder/attemptMetrics.js +165 -0
- package/dist/esm/lib/recorder/attemptMetricsTypes.d.ts +114 -0
- package/dist/esm/lib/recorder/attemptMetricsTypes.js +2 -0
- package/dist/esm/lib/recorder/attemptOTel.d.ts +78 -0
- package/dist/esm/lib/recorder/attemptOTel.js +107 -0
- package/dist/esm/lib/recorder/attemptSeries.d.ts +81 -0
- package/dist/esm/lib/recorder/attemptSeries.js +103 -0
- package/dist/esm/lib/recorder/hooks.d.ts +9 -0
- package/dist/esm/lib/recorder/hooks.js +4 -1
- package/dist/esm/lib/runner/DeferredObserverTier.js +13 -1
- package/dist/esm/lib/runner/ExecutionRuntime.d.ts +54 -6
- package/dist/esm/lib/runner/ExecutionRuntime.js +57 -5
- package/dist/esm/lib/runner/FlowChartExecutor.d.ts +46 -2
- package/dist/esm/lib/runner/FlowChartExecutor.js +330 -101
- package/dist/esm/lib/runner/RunnableChart.d.ts +6 -0
- package/dist/esm/lib/runner/RunnableChart.js +5 -1
- package/dist/esm/lib/runner/attach.d.ts +2 -1
- package/dist/esm/lib/runner/attach.js +8 -2
- package/dist/esm/lib/runner/checkpoint.js +3 -1
- package/dist/esm/lib/runner/deadline.d.ts +42 -0
- package/dist/esm/lib/runner/deadline.js +90 -0
- package/dist/esm/lib/runner/index.d.ts +3 -1
- package/dist/esm/lib/runner/index.js +2 -1
- package/dist/esm/lib/runner/options.d.ts +17 -0
- package/dist/esm/lib/runner/options.js +3 -1
- package/dist/esm/lib/runner/recordSink.d.ts +128 -0
- package/dist/esm/lib/runner/recordSink.js +296 -0
- package/dist/esm/lib/runner/resume.d.ts +3 -0
- package/dist/esm/lib/runner/resume.js +22 -2
- package/dist/esm/lib/runner/snapshot.d.ts +2 -2
- package/dist/esm/lib/runner/snapshot.js +6 -2
- package/dist/esm/lib/scope/ScopeFacade.d.ts +118 -4
- package/dist/esm/lib/scope/ScopeFacade.js +304 -7
- package/dist/esm/lib/scope/recorders/DebugRecorder.d.ts +17 -3
- package/dist/esm/lib/scope/recorders/DebugRecorder.js +79 -13
- package/dist/esm/lib/scope/recorders/MetricRecorder.d.ts +10 -0
- package/dist/esm/lib/scope/recorders/MetricRecorder.js +15 -2
- package/dist/esm/lib/scope/runtime.d.ts +3 -0
- package/dist/esm/lib/scope/runtime.js +1 -1
- package/dist/esm/lib/scope/types.d.ts +6 -0
- package/dist/esm/lib/scope/types.js +1 -1
- package/dist/esm/lib/sinks/fileSink.d.ts +135 -0
- package/dist/esm/lib/sinks/fileSink.js +387 -0
- package/dist/esm/recorders.d.ts +8 -2
- package/dist/esm/recorders.js +7 -1
- package/dist/esm/sinks.d.ts +23 -0
- package/dist/esm/sinks.js +23 -0
- package/dist/esm/trace.d.ts +2 -2
- package/dist/esm/trace.js +1 -1
- package/dist/index.js +77 -60
- package/dist/lib/attempt/anySignal.js +43 -0
- package/dist/lib/attempt/call.js +134 -0
- package/dist/lib/attempt/category.js +136 -0
- package/dist/lib/attempt/correlation.js +186 -0
- package/dist/lib/attempt/deadline.js +112 -0
- package/dist/lib/attempt/decision.js +139 -0
- package/dist/lib/attempt/effect.js +174 -0
- package/dist/lib/attempt/errors.js +49 -0
- package/dist/lib/attempt/index.js +26 -0
- package/dist/lib/attempt/name.js +48 -0
- package/dist/lib/attempt/observed.js +177 -0
- package/dist/lib/attempt/policy.js +92 -0
- package/dist/lib/attempt/record.js +29 -0
- package/dist/lib/attempt/retryLoopContext.js +31 -0
- package/dist/lib/attempt/retryLoopTypes.js +3 -0
- package/dist/lib/attempt/runner.js +530 -0
- package/dist/lib/attempt/standalone.js +130 -0
- package/dist/lib/attempt/types.js +17 -0
- package/dist/lib/budget/index.js +17 -0
- package/dist/lib/budget/timeBudget.js +674 -0
- package/dist/lib/builder/FlowChartBuilder.js +199 -9
- package/dist/lib/builder/retryLoop.js +287 -0
- package/dist/lib/builder/types.js +1 -1
- package/dist/lib/decide/decide.js +2 -2
- package/dist/lib/decide/index.js +2 -2
- package/dist/lib/decide/types.js +1 -8
- package/dist/lib/engine/graph/StageNode.js +1 -1
- package/dist/lib/engine/graph/prefixNodeTree.js +5 -1
- package/dist/lib/engine/handlers/ChildrenExecutor.js +36 -6
- package/dist/lib/engine/handlers/DeciderHandler.js +7 -3
- package/dist/lib/engine/handlers/ResumeEntry.js +3 -1
- package/dist/lib/engine/handlers/SelectorHandler.js +4 -3
- package/dist/lib/engine/handlers/StageRunner.js +36 -9
- package/dist/lib/engine/handlers/SubflowExecutor.js +24 -5
- package/dist/lib/engine/handlers/commitStage.js +24 -5
- package/dist/lib/engine/handlers/stageError.js +26 -2
- package/dist/lib/engine/index.js +1 -1
- package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +67 -39
- package/dist/lib/engine/narrative/FlowRecorderDispatcher.js +19 -2
- package/dist/lib/engine/narrative/NarrativeFlowRecorder.js +60 -8
- package/dist/lib/engine/narrative/NullControlFlowNarrativeGenerator.js +2 -1
- package/dist/lib/engine/narrative/formatting/sentences.js +131 -2
- package/dist/lib/engine/narrative/index.js +1 -1
- package/dist/lib/engine/narrative/narrativeTypes.js +1 -1
- package/dist/lib/engine/narrative/recorders/ManifestFlowRecorder.js +55 -2
- package/dist/lib/engine/narrative/recorders/index.js +1 -1
- package/dist/lib/engine/narrative/types.js +1 -1
- package/dist/lib/engine/traversal/FlowchartTraverser.js +192 -116
- package/dist/lib/engine/traversalContext.js +6 -3
- package/dist/lib/engine/types.js +1 -1
- package/dist/lib/errors/terminalFailure.js +64 -0
- package/dist/lib/filter/evaluator.js +139 -0
- package/dist/lib/ids/idempotencyKey.js +28 -0
- package/dist/lib/memory/StageContext.js +246 -5
- package/dist/lib/memory/attention.js +175 -0
- package/dist/lib/memory/borrowedMutation.js +16 -2
- package/dist/lib/memory/frameTypes.js +3 -1
- package/dist/lib/memory/redaction.js +54 -5
- package/dist/lib/pause/record.js +10 -1
- package/dist/lib/pause/types.js +17 -1
- package/dist/lib/reactive/createTypedScope.js +3 -1
- package/dist/lib/reactive/types.js +3 -1
- package/dist/lib/recorder/AttemptRecorder.js +417 -0
- package/dist/lib/recorder/ControlDepRecorder.js +50 -2
- package/dist/lib/recorder/EmitRecorder.js +1 -1
- package/dist/lib/recorder/InOutRecorder.js +75 -6
- package/dist/lib/recorder/QualityRecorder.js +87 -29
- package/dist/lib/recorder/TopologyRecorder.js +76 -2
- package/dist/lib/recorder/attemptMetricRows.js +209 -0
- package/dist/lib/recorder/attemptMetrics.js +174 -0
- package/dist/lib/recorder/attemptMetricsTypes.js +3 -0
- package/dist/lib/recorder/attemptOTel.js +111 -0
- package/dist/lib/recorder/attemptSeries.js +113 -0
- package/dist/lib/recorder/hooks.js +4 -1
- package/dist/lib/runner/DeferredObserverTier.js +13 -1
- package/dist/lib/runner/ExecutionRuntime.js +57 -5
- package/dist/lib/runner/FlowChartExecutor.js +330 -101
- package/dist/lib/runner/RunnableChart.js +5 -1
- package/dist/lib/runner/attach.js +8 -2
- package/dist/lib/runner/checkpoint.js +3 -1
- package/dist/lib/runner/deadline.js +94 -0
- package/dist/lib/runner/index.js +4 -2
- package/dist/lib/runner/options.js +3 -1
- package/dist/lib/runner/recordSink.js +302 -0
- package/dist/lib/runner/resume.js +22 -2
- package/dist/lib/runner/snapshot.js +6 -2
- package/dist/lib/scope/ScopeFacade.js +303 -6
- package/dist/lib/scope/recorders/DebugRecorder.js +79 -13
- package/dist/lib/scope/recorders/MetricRecorder.js +15 -2
- package/dist/lib/scope/runtime.js +1 -1
- package/dist/lib/scope/types.js +1 -1
- package/dist/lib/sinks/fileSink.js +392 -0
- package/dist/recorders.js +10 -2
- package/dist/sinks.js +32 -0
- package/dist/trace.js +1 -1
- package/dist/types/index.d.ts +62 -2
- package/dist/types/lib/attempt/anySignal.d.ts +19 -0
- package/dist/types/lib/attempt/call.d.ts +88 -0
- package/dist/types/lib/attempt/category.d.ts +37 -0
- package/dist/types/lib/attempt/correlation.d.ts +95 -0
- package/dist/types/lib/attempt/deadline.d.ts +44 -0
- package/dist/types/lib/attempt/decision.d.ts +52 -0
- package/dist/types/lib/attempt/effect.d.ts +76 -0
- package/dist/types/lib/attempt/errors.d.ts +41 -0
- package/dist/types/lib/attempt/index.d.ts +18 -0
- package/dist/types/lib/attempt/name.d.ts +21 -0
- package/dist/types/lib/attempt/observed.d.ts +66 -0
- package/dist/types/lib/attempt/policy.d.ts +45 -0
- package/dist/types/lib/attempt/record.d.ts +11 -0
- package/dist/types/lib/attempt/retryLoopContext.d.ts +18 -0
- package/dist/types/lib/attempt/retryLoopTypes.d.ts +18 -0
- package/dist/types/lib/attempt/runner.d.ts +157 -0
- package/dist/types/lib/attempt/standalone.d.ts +47 -0
- package/dist/types/lib/attempt/types.d.ts +453 -0
- package/dist/types/lib/budget/index.d.ts +9 -0
- package/dist/types/lib/budget/timeBudget.d.ts +136 -0
- package/dist/types/lib/builder/FlowChartBuilder.d.ts +88 -3
- package/dist/types/lib/builder/retryLoop.d.ts +56 -0
- package/dist/types/lib/builder/types.d.ts +35 -1
- package/dist/types/lib/decide/index.d.ts +1 -1
- package/dist/types/lib/decide/types.d.ts +3 -0
- package/dist/types/lib/engine/graph/StageNode.d.ts +11 -1
- package/dist/types/lib/engine/handlers/StageRunner.d.ts +8 -1
- package/dist/types/lib/engine/handlers/commitStage.d.ts +7 -0
- package/dist/types/lib/engine/handlers/stageError.d.ts +9 -0
- package/dist/types/lib/engine/index.d.ts +2 -2
- package/dist/types/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +27 -13
- package/dist/types/lib/engine/narrative/FlowRecorderDispatcher.d.ts +4 -1
- package/dist/types/lib/engine/narrative/NarrativeFlowRecorder.d.ts +22 -3
- package/dist/types/lib/engine/narrative/NullControlFlowNarrativeGenerator.d.ts +1 -0
- package/dist/types/lib/engine/narrative/formatting/sentences.d.ts +23 -0
- package/dist/types/lib/engine/narrative/index.d.ts +2 -2
- package/dist/types/lib/engine/narrative/narrativeTypes.d.ts +27 -21
- package/dist/types/lib/engine/narrative/recorders/ManifestFlowRecorder.d.ts +45 -2
- package/dist/types/lib/engine/narrative/recorders/index.d.ts +1 -1
- package/dist/types/lib/engine/narrative/types.d.ts +74 -5
- package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +59 -19
- package/dist/types/lib/engine/traversalContext.d.ts +7 -2
- package/dist/types/lib/engine/types.d.ts +52 -57
- package/dist/types/lib/errors/terminalFailure.d.ts +29 -0
- package/dist/types/lib/{decide → filter}/evaluator.d.ts +7 -2
- package/dist/types/lib/ids/idempotencyKey.d.ts +14 -0
- package/dist/types/lib/memory/StageContext.d.ts +123 -3
- package/dist/types/lib/memory/attention.d.ts +26 -0
- package/dist/types/lib/memory/borrowedMutation.d.ts +8 -0
- package/dist/types/lib/memory/frameTypes.d.ts +38 -0
- package/dist/types/lib/memory/redaction.d.ts +12 -0
- package/dist/types/lib/pause/types.d.ts +19 -0
- package/dist/types/lib/reactive/types.d.ts +36 -4
- package/dist/types/lib/recorder/AttemptRecorder.d.ts +141 -0
- package/dist/types/lib/recorder/ControlDepRecorder.d.ts +36 -2
- package/dist/types/lib/recorder/EmitRecorder.d.ts +3 -0
- package/dist/types/lib/recorder/InOutRecorder.d.ts +37 -1
- package/dist/types/lib/recorder/QualityRecorder.d.ts +32 -5
- package/dist/types/lib/recorder/TopologyRecorder.d.ts +35 -5
- package/dist/types/lib/recorder/attemptMetricRows.d.ts +11 -0
- package/dist/types/lib/recorder/attemptMetrics.d.ts +7 -0
- package/dist/types/lib/recorder/attemptMetricsTypes.d.ts +114 -0
- package/dist/types/lib/recorder/attemptOTel.d.ts +78 -0
- package/dist/types/lib/recorder/attemptSeries.d.ts +81 -0
- package/dist/types/lib/recorder/hooks.d.ts +9 -0
- package/dist/types/lib/runner/ExecutionRuntime.d.ts +54 -6
- package/dist/types/lib/runner/FlowChartExecutor.d.ts +46 -2
- package/dist/types/lib/runner/RunnableChart.d.ts +6 -0
- package/dist/types/lib/runner/attach.d.ts +2 -1
- package/dist/types/lib/runner/deadline.d.ts +42 -0
- package/dist/types/lib/runner/index.d.ts +3 -1
- package/dist/types/lib/runner/options.d.ts +17 -0
- package/dist/types/lib/runner/recordSink.d.ts +128 -0
- package/dist/types/lib/runner/resume.d.ts +3 -0
- package/dist/types/lib/runner/snapshot.d.ts +2 -2
- package/dist/types/lib/scope/ScopeFacade.d.ts +118 -4
- package/dist/types/lib/scope/recorders/DebugRecorder.d.ts +17 -3
- package/dist/types/lib/scope/recorders/MetricRecorder.d.ts +10 -0
- package/dist/types/lib/scope/runtime.d.ts +3 -0
- package/dist/types/lib/scope/types.d.ts +6 -0
- package/dist/types/lib/sinks/fileSink.d.ts +135 -0
- package/dist/types/recorders.d.ts +8 -2
- package/dist/types/sinks.d.ts +23 -0
- package/dist/types/trace.d.ts +2 -2
- package/package.json +20 -6
- package/dist/esm/lib/decide/evaluator.js +0 -130
- package/dist/lib/decide/evaluator.js +0 -134
package/README.md
CHANGED
|
@@ -1,371 +1,195 @@
|
|
|
1
|
-
|
|
2
|
-
<h1 align="center">FootPrint</h1>
|
|
3
|
-
<p align="center">
|
|
4
|
-
<strong>The flowchart pattern for backend code — 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> — 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** — the flowchart pattern — 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 — no hallucination.
|
|
1
|
+
# FootPrint
|
|
30
2
|
|
|
31
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
15
|
+
An image export is rejected. The application did not crash. It produced an outcome somebody needs to investigate.
|
|
53
16
|
|
|
54
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
25
|
+
Requires Node.js 22 or newer. To use the same library versions:
|
|
75
26
|
|
|
76
|
-
|
|
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
|
-
|
|
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,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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('
|
|
108
|
-
scope.
|
|
57
|
+
.addFunctionBranch('reject', 'RejectExport', (scope) => {
|
|
58
|
+
scope.status = 'rejected';
|
|
109
59
|
})
|
|
110
|
-
.setDefault('
|
|
60
|
+
.setDefault('reject')
|
|
111
61
|
.end()
|
|
112
62
|
.build();
|
|
113
63
|
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
//
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
133
|
-
>
|
|
134
|
-
> **[Browse 37+ examples](https://footprintjs.github.io/footprint-playground/)** — 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 — 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) — 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** — 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** — powers time-travel replay |
|
|
151
|
-
|
|
152
|
-
---
|
|
101
|
+
### What the run recorded
|
|
153
102
|
|
|
154
|
-
|
|
103
|
+
Narrative excerpt from the reviewed run:
|
|
155
104
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
|
167
|
-
|
|
168
|
-
> **[Live demo: Claude calls a credit-decision flowchart as an MCP tool](https://footprintjs.github.io/footprint-playground/samples/llm-agent-tool)** — 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 — 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
|
-
|
|
190
|
-
}, 'assess').build();
|
|
117
|
+
The dependency query prints:
|
|
191
118
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
-
|
|
203
|
-
|
|
204
|
-
---
|
|
205
|
-
|
|
206
|
-
## Features
|
|
207
|
-
|
|
208
|
-
| Feature | Description |
|
|
209
|
-
|---------|-------------|
|
|
210
|
-
| **Causal Traces** | Every read/write captured — LLMs backtrack through variables to find causes |
|
|
211
|
-
| **Decision Evidence** | `decide()` / `select()` auto-capture WHY a branch was chosen — operators, thresholds, pass/fail |
|
|
212
|
-
| **TypedScope<T>** | Typed property access — `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 — `executor.attachCombinedRecorder(r)` |
|
|
219
|
-
| **Deferred observers** *(new in 9.6)* | `attach*Recorder(rec, { delivery: 'deferred' })` — 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 — 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 →](./docs/guides/error-handling.md#declarative-retry) |
|
|
223
|
-
| **Subflow break propagation** | Mount a subflow with `propagateBreak: true` — inner `$break` terminates the parent loop, with drill-down preserved |
|
|
224
|
-
| **Emit channel** | `scope.$emit(name, payload)` — 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)` — 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>` — 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 — "one purpose per recorder"). The `Store` classes are exported from `footprintjs/trace` and are the only recorder-storage model — 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
131
|
+
### An agent building your application
|
|
239
132
|
|
|
240
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
255
|
-
if (environment !== 'production') {
|
|
256
|
-
enableDevMode();
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
```
|
|
139
|
+
### An agent inside your application
|
|
260
140
|
|
|
261
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
157
|
+
## Two packages, separate responsibilities
|
|
277
158
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
168
|
+
## A retry that needs reconciliation
|
|
296
169
|
|
|
297
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
174
|
+
## What the record cannot prove
|
|
312
175
|
|
|
313
|
-
**
|
|
314
|
-
|
|
315
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
329
|
-
|
|
330
|
-
| Resource | Link |
|
|
331
|
-
|----------|------|
|
|
332
|
-
| **Getting Started** | [Quick Start](https://footprintjs.github.io/footPrint/getting-started/quick-start/) · [Key Concepts](https://footprintjs.github.io/footPrint/getting-started/key-concepts/) · [Why footprintjs?](https://footprintjs.github.io/footPrint/getting-started/why/) |
|
|
333
|
-
| **Guides** | [Building](https://footprintjs.github.io/footPrint/guides/building/) · [Decision branching](https://footprintjs.github.io/footPrint/guides/decision-branching/) · [Recorders](https://footprintjs.github.io/footPrint/guides/recording/) · [Subflows](https://footprintjs.github.io/footPrint/guides/subflows/) · [Self-describing APIs](https://footprintjs.github.io/footPrint/guides/self-describing/) · [Execution model & limits](./docs/guides/execution-model.md) |
|
|
334
|
-
| **API Reference** | [flowChart() / Builder](https://footprintjs.github.io/footPrint/api/flowchart/) · [decide() / select()](https://footprintjs.github.io/footPrint/api/decide/) · [FlowChartExecutor](https://footprintjs.github.io/footPrint/api/executor/) · [Recorders](https://footprintjs.github.io/footPrint/api/recorders/) · [Contract & Self-describing](https://footprintjs.github.io/footPrint/api/contract/) |
|
|
335
|
-
| **Try it** | [Interactive Playground](https://footprintjs.github.io/footprint-playground/) · [Try with your LLM](https://footprintjs.github.io/footprint-playground/try-with-ai) · [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
|
-
|
|
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).
|