footprintjs 5.0.0 → 6.0.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/CLAUDE.md +32 -8
- package/dist/advanced.js +2 -3
- package/dist/esm/advanced.js +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/lib/builder/FlowChartBuilder.js +364 -100
- package/dist/esm/lib/builder/index.js +1 -1
- package/dist/esm/lib/builder/structure/StructureRecorder.js +158 -0
- package/dist/esm/lib/builder/structure/StructureRecorderDispatcher.js +171 -0
- package/dist/esm/lib/builder/types.js +1 -1
- package/dist/esm/lib/engine/errors/errorInfo.js +4 -3
- package/dist/esm/lib/engine/handlers/ChildrenExecutor.js +11 -2
- package/dist/esm/lib/engine/handlers/DeciderHandler.js +5 -7
- package/dist/esm/lib/engine/handlers/RuntimeStructureManager.js +2 -2
- package/dist/esm/lib/engine/handlers/SelectorHandler.js +9 -7
- package/dist/esm/lib/engine/handlers/SubflowExecutor.js +7 -1
- package/dist/esm/lib/engine/handlers/index.js +1 -3
- package/dist/esm/lib/engine/handlers/types.js +2 -2
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +12 -2
- package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.js +3 -3
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.js +8 -1
- package/dist/esm/lib/engine/narrative/types.js +1 -1
- package/dist/esm/lib/engine/runtimeStageId.js +64 -2
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +11 -54
- package/dist/esm/lib/engine/types.js +1 -1
- package/dist/esm/lib/engine/walkSubflowSpec.js +144 -0
- package/dist/esm/lib/runner/FlowChartExecutor.js +4 -17
- package/dist/esm/lib/runner/getSubtreeSnapshot.js +3 -2
- package/dist/esm/trace.js +3 -2
- package/dist/index.js +1 -1
- package/dist/lib/builder/FlowChartBuilder.js +364 -100
- package/dist/lib/builder/index.js +1 -1
- package/dist/lib/builder/structure/StructureRecorder.js +159 -0
- package/dist/lib/builder/structure/StructureRecorderDispatcher.js +175 -0
- package/dist/lib/builder/types.js +1 -1
- package/dist/lib/engine/errors/errorInfo.js +4 -3
- package/dist/lib/engine/handlers/ChildrenExecutor.js +11 -2
- package/dist/lib/engine/handlers/DeciderHandler.js +5 -7
- package/dist/lib/engine/handlers/RuntimeStructureManager.js +2 -2
- package/dist/lib/engine/handlers/SelectorHandler.js +9 -7
- package/dist/lib/engine/handlers/SubflowExecutor.js +7 -1
- package/dist/lib/engine/handlers/index.js +2 -5
- package/dist/lib/engine/handlers/types.js +2 -2
- package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +12 -2
- package/dist/lib/engine/narrative/FlowRecorderDispatcher.js +3 -3
- package/dist/lib/engine/narrative/NarrativeFlowRecorder.js +8 -1
- package/dist/lib/engine/narrative/types.js +1 -1
- package/dist/lib/engine/runtimeStageId.js +66 -3
- package/dist/lib/engine/traversal/FlowchartTraverser.js +11 -54
- package/dist/lib/engine/types.js +1 -1
- package/dist/lib/engine/walkSubflowSpec.js +148 -0
- package/dist/lib/runner/FlowChartExecutor.js +4 -17
- package/dist/lib/runner/getSubtreeSnapshot.js +3 -2
- package/dist/trace.js +5 -2
- package/dist/types/advanced.d.ts +4 -4
- package/dist/types/index.d.ts +2 -0
- package/dist/types/lib/builder/FlowChartBuilder.d.ts +110 -14
- package/dist/types/lib/builder/index.d.ts +2 -1
- package/dist/types/lib/builder/structure/StructureRecorder.d.ts +349 -0
- package/dist/types/lib/builder/structure/StructureRecorderDispatcher.d.ts +77 -0
- package/dist/types/lib/builder/types.d.ts +20 -6
- package/dist/types/lib/engine/errors/errorInfo.d.ts +3 -2
- package/dist/types/lib/engine/handlers/DeciderHandler.d.ts +3 -3
- package/dist/types/lib/engine/handlers/RuntimeStructureManager.d.ts +1 -1
- package/dist/types/lib/engine/handlers/SelectorHandler.d.ts +2 -2
- package/dist/types/lib/engine/handlers/index.d.ts +1 -2
- package/dist/types/lib/engine/handlers/types.d.ts +2 -9
- package/dist/types/lib/engine/narrative/FlowRecorderDispatcher.d.ts +2 -2
- package/dist/types/lib/engine/narrative/types.d.ts +24 -2
- package/dist/types/lib/engine/runtimeStageId.d.ts +57 -1
- package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +1 -6
- package/dist/types/lib/engine/types.d.ts +0 -26
- package/dist/types/lib/engine/walkSubflowSpec.d.ts +95 -0
- package/dist/types/lib/runner/FlowChartExecutor.d.ts +4 -16
- package/dist/types/trace.d.ts +3 -1
- package/package.json +1 -1
- package/dist/esm/lib/engine/handlers/ExtractorRunner.js +0 -122
- package/dist/lib/engine/handlers/ExtractorRunner.js +0 -126
- package/dist/types/lib/engine/handlers/ExtractorRunner.d.ts +0 -41
package/dist/trace.js
CHANGED
|
@@ -22,11 +22,14 @@
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.qualityTrace = exports.formatQualityTrace = exports.QualityRecorder = exports.ROOT_SUBFLOW_ID = exports.ROOT_RUNTIME_STAGE_ID = exports.inOutRecorder = exports.InOutRecorder = exports.topologyRecorder = exports.TopologyRecorder = exports.BoundaryStateTracker = exports.SequenceRecorder = exports.KeyedRecorder = exports.CommitRangeIndex = exports.SequenceStore = exports.KeyedStore = exports.BoundaryStateStore = exports.formatCausalChain = exports.flattenCausalDAG = exports.causalChain = exports.findLastWriter = exports.findCommits = exports.findCommit = exports.parseRuntimeStageId = exports.createExecutionCounter = exports.buildRuntimeStageId = void 0;
|
|
25
|
+
exports.qualityTrace = exports.formatQualityTrace = exports.QualityRecorder = exports.ROOT_SUBFLOW_ID = exports.ROOT_RUNTIME_STAGE_ID = exports.inOutRecorder = exports.InOutRecorder = exports.topologyRecorder = exports.TopologyRecorder = exports.BoundaryStateTracker = exports.SequenceRecorder = exports.KeyedRecorder = exports.CommitRangeIndex = exports.SequenceStore = exports.KeyedStore = exports.BoundaryStateStore = exports.formatCausalChain = exports.flattenCausalDAG = exports.causalChain = exports.findLastWriter = exports.findCommits = exports.findCommit = exports.walkSubflowSpec = exports.splitStageId = exports.parseRuntimeStageId = exports.createExecutionCounter = exports.buildRuntimeStageId = void 0;
|
|
26
26
|
var runtimeStageId_js_1 = require("./lib/engine/runtimeStageId.js");
|
|
27
27
|
Object.defineProperty(exports, "buildRuntimeStageId", { enumerable: true, get: function () { return runtimeStageId_js_1.buildRuntimeStageId; } });
|
|
28
28
|
Object.defineProperty(exports, "createExecutionCounter", { enumerable: true, get: function () { return runtimeStageId_js_1.createExecutionCounter; } });
|
|
29
29
|
Object.defineProperty(exports, "parseRuntimeStageId", { enumerable: true, get: function () { return runtimeStageId_js_1.parseRuntimeStageId; } });
|
|
30
|
+
Object.defineProperty(exports, "splitStageId", { enumerable: true, get: function () { return runtimeStageId_js_1.splitStageId; } });
|
|
31
|
+
var walkSubflowSpec_js_1 = require("./lib/engine/walkSubflowSpec.js");
|
|
32
|
+
Object.defineProperty(exports, "walkSubflowSpec", { enumerable: true, get: function () { return walkSubflowSpec_js_1.walkSubflowSpec; } });
|
|
30
33
|
// Commit log queries — typed utilities for backtracking
|
|
31
34
|
var commitLogUtils_js_1 = require("./lib/memory/commitLogUtils.js");
|
|
32
35
|
Object.defineProperty(exports, "findCommit", { enumerable: true, get: function () { return commitLogUtils_js_1.findCommit; } });
|
|
@@ -75,4 +78,4 @@ Object.defineProperty(exports, "QualityRecorder", { enumerable: true, get: funct
|
|
|
75
78
|
var qualityTrace_js_1 = require("./lib/recorder/qualityTrace.js");
|
|
76
79
|
Object.defineProperty(exports, "formatQualityTrace", { enumerable: true, get: function () { return qualityTrace_js_1.formatQualityTrace; } });
|
|
77
80
|
Object.defineProperty(exports, "qualityTrace", { enumerable: true, get: function () { return qualityTrace_js_1.qualityTrace; } });
|
|
78
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
81
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHJhY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7OztBQUlILG9FQUt3QztBQUp0Qyx3SEFBQSxtQkFBbUIsT0FBQTtBQUNuQiwySEFBQSxzQkFBc0IsT0FBQTtBQUN0Qix3SEFBQSxtQkFBbUIsT0FBQTtBQUNuQixpSEFBQSxZQUFZLE9BQUE7QUFNZCxzRUFBa0U7QUFBekQscUhBQUEsZUFBZSxPQUFBO0FBRXhCLHdEQUF3RDtBQUN4RCxvRUFBeUY7QUFBaEYsK0dBQUEsVUFBVSxPQUFBO0FBQUUsZ0hBQUEsV0FBVyxPQUFBO0FBQUUsbUhBQUEsY0FBYyxPQUFBO0FBSWhELDBEQUE2RjtBQUFwRiwyR0FBQSxXQUFXLE9BQUE7QUFBRSxnSEFBQSxnQkFBZ0IsT0FBQTtBQUFFLGlIQUFBLGlCQUFpQixPQUFBO0FBRXpELG1FQUFtRTtBQUNuRSxpRUFBaUU7QUFDakUsaUVBQWlFO0FBQ2pFLDRDQUE0QztBQUM1Qyw4RUFBMEU7QUFBakUsMkhBQUEsa0JBQWtCLE9BQUE7QUFDM0IsOERBQTBEO0FBQWpELDJHQUFBLFVBQVUsT0FBQTtBQUNuQixvRUFBZ0U7QUFBdkQsaUhBQUEsYUFBYSxPQUFBO0FBU3RCLDBFQUFzRTtBQUE3RCx1SEFBQSxnQkFBZ0IsT0FBQTtBQUV6QixvRUFBb0U7QUFDcEUsK0RBQStEO0FBQy9ELGdFQUFnRTtBQUNoRSx3REFBd0Q7QUFDeEQseURBQXlEO0FBQ3pELG9FQUFnRTtBQUF2RCxpSEFBQSxhQUFhLE9BQUE7QUFFdEIsb0ZBQW9GO0FBQ3BGLDBFQUFzRTtBQUE3RCx1SEFBQSxnQkFBZ0IsT0FBQTtBQUV6Qix1RUFBdUU7QUFDdkUsNkVBQTZFO0FBQzdFLGtGQUE4RTtBQUFyRSwrSEFBQSxvQkFBb0IsT0FBQTtBQVU3QiwwRUFBd0Y7QUFBL0UsdUhBQUEsZ0JBQWdCLE9BQUE7QUFBRSx1SEFBQSxnQkFBZ0IsT0FBQTtBQUszQyxvRUFBdUg7QUFBOUcsaUhBQUEsYUFBYSxPQUFBO0FBQUUsaUhBQUEsYUFBYSxPQUFBO0FBQUUseUhBQUEscUJBQXFCLE9BQUE7QUFBRSxtSEFBQSxlQUFlLE9BQUE7QUFJN0Usd0VBQW9FO0FBQTNELHFIQUFBLGVBQWUsT0FBQTtBQUl4QixrRUFBa0Y7QUFBekUscUhBQUEsa0JBQWtCLE9BQUE7QUFBRSwrR0FBQSxZQUFZLE9BQUEiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGZvb3RwcmludGpzL3RyYWNlIOKAlCBFeGVjdXRpb24gdHJhY2luZywgZGVidWdnaW5nLCBhbmQgYmFja3RyYWNraW5nIHV0aWxpdGllcy5cbiAqXG4gKiBSdW50aW1lIHN0YWdlIElEcywgY29tbWl0IGxvZyBxdWVyaWVzLCBhbmQgcmVjb3JkZXIgYmFzZSBjbGFzc2VzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBwYXJzZVJ1bnRpbWVTdGFnZUlkLCBmaW5kTGFzdFdyaXRlciwgS2V5ZWRSZWNvcmRlciwgU2VxdWVuY2VSZWNvcmRlciB9IGZyb20gJ2Zvb3RwcmludGpzL3RyYWNlJztcbiAqXG4gKiAvLyBQYXJzZSBhIHJ1bnRpbWVTdGFnZUlkXG4gKiBjb25zdCB7IHN0YWdlSWQsIGV4ZWN1dGlvbkluZGV4IH0gPSBwYXJzZVJ1bnRpbWVTdGFnZUlkKCdjYWxsLWxsbSM1Jyk7XG4gKlxuICogLy8gQmFja3RyYWNrOiB3aG8gd3JvdGUgJ3N5c3RlbVByb21wdCcgYmVmb3JlIHN0YWdlIGF0IGlkeCA4P1xuICogY29uc3Qgd3JpdGVyID0gZmluZExhc3RXcml0ZXIoY29tbWl0TG9nLCAnc3lzdGVtUHJvbXB0JywgOCk7XG4gKlxuICogLy8gQnVpbGQgYSBrZXllZCByZWNvcmRlciAoMToxIOKAlCBvbmUgZW50cnkgcGVyIHN0ZXApXG4gKiBjbGFzcyBNeVJlY29yZGVyIGV4dGVuZHMgS2V5ZWRSZWNvcmRlcjxNeUVudHJ5PiB7IC4uLiB9XG4gKlxuICogLy8gQnVpbGQgYSBzZXF1ZW5jZSByZWNvcmRlciAoMTpOIOKAlCBtdWx0aXBsZSBlbnRyaWVzIHBlciBzdGVwLCBvcmRlcmluZyBtYXR0ZXJzKVxuICogY2xhc3MgQXVkaXRSZWNvcmRlciBleHRlbmRzIFNlcXVlbmNlUmVjb3JkZXI8QXVkaXRFbnRyeT4geyAuLi4gfVxuICogYGBgXG4gKi9cblxuLy8gUnVudGltZSBzdGFnZSBJRCDigJQgdW5pcXVlIGV4ZWN1dGlvbiBzdGVwIGlkZW50aWZpZXJzXG5leHBvcnQgdHlwZSB7IEV4ZWN1dGlvbkNvdW50ZXIgfSBmcm9tICcuL2xpYi9lbmdpbmUvcnVudGltZVN0YWdlSWQuanMnO1xuZXhwb3J0IHtcbiAgYnVpbGRSdW50aW1lU3RhZ2VJZCxcbiAgY3JlYXRlRXhlY3V0aW9uQ291bnRlcixcbiAgcGFyc2VSdW50aW1lU3RhZ2VJZCxcbiAgc3BsaXRTdGFnZUlkLFxufSBmcm9tICcuL2xpYi9lbmdpbmUvcnVudGltZVN0YWdlSWQuanMnO1xuXG4vLyB3YWxrU3ViZmxvd1NwZWMg4oCUIGZsYXQgb3JkZXJlZCB0cmF2ZXJzYWwgb2YgYSBzdWJmbG93J3Mgc3RydWN0dXJlXG4vLyAoY29uc3VtZSB2aWEgU3RydWN0dXJlUmVjb3JkZXIub25TdWJmbG93TW91bnRlZCdzIHN1YmZsb3dTcGVjIHBheWxvYWQpXG5leHBvcnQgdHlwZSB7IFdhbGtlckl0ZW0sIFdhbGtlck9wdGlvbnMgfSBmcm9tICcuL2xpYi9lbmdpbmUvd2Fsa1N1YmZsb3dTcGVjLmpzJztcbmV4cG9ydCB7IHdhbGtTdWJmbG93U3BlYyB9IGZyb20gJy4vbGliL2VuZ2luZS93YWxrU3ViZmxvd1NwZWMuanMnO1xuXG4vLyBDb21taXQgbG9nIHF1ZXJpZXMg4oCUIHR5cGVkIHV0aWxpdGllcyBmb3IgYmFja3RyYWNraW5nXG5leHBvcnQgeyBmaW5kQ29tbWl0LCBmaW5kQ29tbWl0cywgZmluZExhc3RXcml0ZXIgfSBmcm9tICcuL2xpYi9tZW1vcnkvY29tbWl0TG9nVXRpbHMuanMnO1xuXG4vLyBDYXVzYWwgY2hhaW4g4oCUIGJhY2t3YXJkIHByb2dyYW0gc2xpY2luZyBvbiBjb21taXQgbG9nIChEQUcpXG5leHBvcnQgdHlwZSB7IENhdXNhbENoYWluT3B0aW9ucywgQ2F1c2FsTm9kZSwgS2V5c1JlYWRMb29rdXAgfSBmcm9tICcuL2xpYi9tZW1vcnkvYmFja3RyYWNrLmpzJztcbmV4cG9ydCB7IGNhdXNhbENoYWluLCBmbGF0dGVuQ2F1c2FsREFHLCBmb3JtYXRDYXVzYWxDaGFpbiB9IGZyb20gJy4vbGliL21lbW9yeS9iYWNrdHJhY2suanMnO1xuXG4vLyDilIDilIAgdjUgU3RvcmVzIChjb25jcmV0ZSwgY29tcG9zYWJsZSDigJQgcHJpbWFyeSByZWNvcmRlciBBUEkpIOKUgOKUgOKUgOKUgOKUgFxuLy8gQ29tcG9zZSB0aGVzZSB2aWEgYG5ldyBTdG9yZTxUPigpYCBhcyBhIGZpZWxkIG9uIHlvdXIgcmVjb3JkZXJcbi8vIGNsYXNzLiBPbmUgcHVycG9zZSBwZXIgcmVjb3JkZXI6IHN0b3JlcyBhcmUgc3RvcmFnZTsgcmVjb3JkZXJzXG4vLyBhcmUgZXZlbnQtaG9vayBpbnRlcmZhY2UgaW1wbGVtZW50YXRpb25zLlxuZXhwb3J0IHsgQm91bmRhcnlTdGF0ZVN0b3JlIH0gZnJvbSAnLi9saWIvcmVjb3JkZXIvQm91bmRhcnlTdGF0ZVN0b3JlLmpzJztcbmV4cG9ydCB7IEtleWVkU3RvcmUgfSBmcm9tICcuL2xpYi9yZWNvcmRlci9LZXllZFN0b3JlLmpzJztcbmV4cG9ydCB7IFNlcXVlbmNlU3RvcmUgfSBmcm9tICcuL2xpYi9yZWNvcmRlci9TZXF1ZW5jZVN0b3JlLmpzJztcblxuLy8g4pSA4pSAIHY1LjEgQ29tbWl0IGdyb3VwaW5nIHByaW1pdGl2ZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbi8vIEludGVydmFsIGluZGV4IG92ZXIgY29tbWl0IGluZGljZXMuIEJ1aWx0IGluY3JlbWVudGFsbHkgZHVyaW5nXG4vLyB0cmF2ZXJzYWw6IG9wZW4oKSBvbiBib3VuZGFyeSBlbnRyeSwgY2xvc2UoKSBvbiBleGl0LiBRdWVyeSBhdCBhbnlcbi8vIGNvbW1pdCBwb3NpdGlvbiB3aXRoIGVuY2xvc2luZygpL292ZXJsYXBwaW5nKCkuIEdlbmVyaWMgb3ZlciBUTGFiZWxcbi8vIOKAlCBmb290cHJpbnRqcyBvd25zIFpFUk8ga25vd2xlZGdlIG9mIHdoYXQgY29uc3VtZXJzIHVzZSBhcyBsYWJlbHMuXG4vLyBTZWUgZG9jcy9kZXNpZ24vY29tbWl0LXJhbmdlLWluZGV4Lm1kIGZvciB0aGUgZnVsbCBjb250cmFjdC5cbmV4cG9ydCB0eXBlIHsgUmFuZ2VFbnRyeSwgUmFuZ2VUb2tlbiB9IGZyb20gJy4vbGliL3JlY29yZGVyL0NvbW1pdFJhbmdlSW5kZXguanMnO1xuZXhwb3J0IHsgQ29tbWl0UmFuZ2VJbmRleCB9IGZyb20gJy4vbGliL3JlY29yZGVyL0NvbW1pdFJhbmdlSW5kZXguanMnO1xuXG4vLyDilIDilIAgQWJzdHJhY3QgYmFzZXMgKERFUFJFQ0FURUQgaW4gdjUg4oCUIHNsYXRlZCBmb3IgcmVtb3ZhbCkg4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4vLyBLZXB0IGR1cmluZyB0aGUgdjUgbWlncmF0aW9uIHdpbmRvdyBmb3IgZG93bnN0cmVhbSBjb25zdW1lcnNcbi8vIChhZ2VudGZvb3RwcmludCwgYWdlbnRmb290cHJpbnQtbGVucywgZXRjLikgdGhhdCBzdGlsbCBleHRlbmRcbi8vIHRoZW0uIE1pZ3JhdGUgdG8gdGhlIGNvcnJlc3BvbmRpbmcgU3RvcmUgY2xhc3MgYWJvdmUuXG4vLyBLZXllZFJlY29yZGVyIOKAlCBiYXNlIGNsYXNzIGZvciAxOjEgTWFwLWJhc2VkIHJlY29yZGVyc1xuZXhwb3J0IHsgS2V5ZWRSZWNvcmRlciB9IGZyb20gJy4vbGliL3JlY29yZGVyL0tleWVkUmVjb3JkZXIuanMnO1xuXG4vLyBTZXF1ZW5jZVJlY29yZGVyIOKAlCBiYXNlIGNsYXNzIGZvciAxOk4gb3JkZXJlZCBzZXF1ZW5jZSByZWNvcmRlcnMgd2l0aCBrZXllZCBpbmRleFxuZXhwb3J0IHsgU2VxdWVuY2VSZWNvcmRlciB9IGZyb20gJy4vbGliL3JlY29yZGVyL1NlcXVlbmNlUmVjb3JkZXIuanMnO1xuXG4vLyBCb3VuZGFyeVN0YXRlVHJhY2tlciDigJQgYmFzZSBjbGFzcyBmb3IgdHJhbnNpZW50IGJyYWNrZXQtc2NvcGVkIHN0YXRlXG4vLyAobGl2ZSBzdGF0ZSBEVVJJTkcgYSBtYXRjaGVkIFtzdGFydCwgc3RvcF0gZXZlbnQgaW50ZXJ2YWw7IGNsZWFycyBvbiBzdG9wKVxuZXhwb3J0IHsgQm91bmRhcnlTdGF0ZVRyYWNrZXIgfSBmcm9tICcuL2xpYi9yZWNvcmRlci9Cb3VuZGFyeVN0YXRlVHJhY2tlci5qcyc7XG5cbi8vIFRvcG9sb2d5UmVjb3JkZXIg4oCUIGNvbXBvc2l0aW9uIGdyYXBoIGFjY3VtdWxhdG9yIChzdWJmbG93cyArIGNvbnRyb2wtZmxvdyBlZGdlcylcbmV4cG9ydCB0eXBlIHtcbiAgVG9wb2xvZ3ksXG4gIFRvcG9sb2d5RWRnZSxcbiAgVG9wb2xvZ3lJbmNvbWluZ0tpbmQsXG4gIFRvcG9sb2d5Tm9kZSxcbiAgVG9wb2xvZ3lSZWNvcmRlck9wdGlvbnMsXG59IGZyb20gJy4vbGliL3JlY29yZGVyL1RvcG9sb2d5UmVjb3JkZXIuanMnO1xuZXhwb3J0IHsgVG9wb2xvZ3lSZWNvcmRlciwgdG9wb2xvZ3lSZWNvcmRlciB9IGZyb20gJy4vbGliL3JlY29yZGVyL1RvcG9sb2d5UmVjb3JkZXIuanMnO1xuXG4vLyBJbk91dFJlY29yZGVyIOKAlCBjaGFydCBpbi9vdXQgc3RyZWFtIChlbnRyeS9leGl0IHBhaXJzIGF0IGV2ZXJ5IGNoYXJ0IGJvdW5kYXJ5LFxuLy8gaW5jbHVkaW5nIHRoZSB0b3AtbGV2ZWwgcnVuIGFuZCBldmVyeSBzdWJmbG93KVxuZXhwb3J0IHR5cGUgeyBJbk91dEVudHJ5LCBJbk91dFBoYXNlLCBJbk91dFJlY29yZGVyT3B0aW9ucyB9IGZyb20gJy4vbGliL3JlY29yZGVyL0luT3V0UmVjb3JkZXIuanMnO1xuZXhwb3J0IHsgSW5PdXRSZWNvcmRlciwgaW5PdXRSZWNvcmRlciwgUk9PVF9SVU5USU1FX1NUQUdFX0lELCBST09UX1NVQkZMT1dfSUQgfSBmcm9tICcuL2xpYi9yZWNvcmRlci9Jbk91dFJlY29yZGVyLmpzJztcblxuLy8gUXVhbGl0eVJlY29yZGVyIOKAlCBwZXItc3RlcCBxdWFsaXR5IHNjb3Jpbmcgd2l0aCBiYWNrdHJhY2tpbmdcbmV4cG9ydCB0eXBlIHsgUXVhbGl0eUVudHJ5LCBRdWFsaXR5UmVjb3JkZXJPcHRpb25zLCBRdWFsaXR5U2NvcmluZ0ZuIH0gZnJvbSAnLi9saWIvcmVjb3JkZXIvUXVhbGl0eVJlY29yZGVyLmpzJztcbmV4cG9ydCB7IFF1YWxpdHlSZWNvcmRlciB9IGZyb20gJy4vbGliL3JlY29yZGVyL1F1YWxpdHlSZWNvcmRlci5qcyc7XG5cbi8vIHF1YWxpdHlUcmFjZSDigJQgUXVhbGl0eSBTdGFjayBUcmFjZSAoYmFja3RyYWNrIGZyb20gbG93LXNjb3Jpbmcgc3RlcHMpXG5leHBvcnQgdHlwZSB7IFF1YWxpdHlGcmFtZSwgUXVhbGl0eVN0YWNrVHJhY2UgfSBmcm9tICcuL2xpYi9yZWNvcmRlci9xdWFsaXR5VHJhY2UuanMnO1xuZXhwb3J0IHsgZm9ybWF0UXVhbGl0eVRyYWNlLCBxdWFsaXR5VHJhY2UgfSBmcm9tICcuL2xpYi9yZWNvcmRlci9xdWFsaXR5VHJhY2UuanMnO1xuIl19
|
package/dist/types/advanced.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export { EventLog } from './lib/memory/index.js';
|
|
|
26
26
|
export { TransactionBuffer } from './lib/memory/index.js';
|
|
27
27
|
export { DiagnosticCollector } from './lib/memory/index.js';
|
|
28
28
|
export { applySmartMerge, deepSmartMerge, getNestedValue, getRunAndGlobalPaths, normalisePath, redactPatch, setNestedValue, updateNestedValue, updateValue, } from './lib/memory/index.js';
|
|
29
|
-
export type {
|
|
29
|
+
export type { ExecOptions, FlowChartOptions, FlowChartSpec, ILogger, ScopeProtectionMode, SerializedPipelineStructure, SimplifiedParallelSpec, StageFn, StageNode, StreamCallback, StreamLifecycleHandler, StreamTokenHandler, SubflowMountOptions, SubflowRef, } from './lib/builder/index.js';
|
|
30
30
|
export { ArrayMergeMode, DeciderList, SelectorFnList, specToStageNode } from './lib/builder/index.js';
|
|
31
31
|
export { createTypedScopeFactory } from './lib/builder/typedFlowChart.js';
|
|
32
32
|
export type { ProviderResolver, ResolveOptions, ScopeProvider, StageContextLike, StrictMode, } from './lib/scope/index.js';
|
|
@@ -44,10 +44,10 @@ export { FlowchartTraverser } from './lib/engine/index.js';
|
|
|
44
44
|
export { isStageNodeReturn } from './lib/engine/index.js';
|
|
45
45
|
export type { IControlFlowNarrative } from './lib/engine/index.js';
|
|
46
46
|
export type { CombinedNarrativeEntry, CombinedNarrativeOptions } from './lib/engine/index.js';
|
|
47
|
-
export type { BranchResult, BranchResults, SerializedPipelineStructure as EngineSerializedPipelineStructure,
|
|
47
|
+
export type { BranchResult, BranchResults, SerializedPipelineStructure as EngineSerializedPipelineStructure, HandlerDeps, IExecutionRuntime, NodeResultType, RuntimeStructureMetadata, ScopeFactory, SerializedPipelineNode, StageFunction, SubflowResult, TraversalResult, } from './lib/engine/index.js';
|
|
48
48
|
export { NullControlFlowNarrativeGenerator } from './lib/engine/index.js';
|
|
49
|
-
export type {
|
|
50
|
-
export { applyOutputMapping, ChildrenExecutor, computeNodeType, ContinuationResolver, createSubflowHandlerDeps, DeciderHandler, DEFAULT_MAX_ITERATIONS,
|
|
49
|
+
export type { ExecuteNodeFn, RunStageFn } from './lib/engine/index.js';
|
|
50
|
+
export { applyOutputMapping, ChildrenExecutor, computeNodeType, ContinuationResolver, createSubflowHandlerDeps, DeciderHandler, DEFAULT_MAX_ITERATIONS, extractParentScopeValues, getInitialScopeValues, NodeResolver, RuntimeStructureManager, seedSubflowGlobalStore, SelectorHandler, StageRunner, SubflowExecutor, } from './lib/engine/index.js';
|
|
51
51
|
export type { ExecutionCounter } from './lib/engine/runtimeStageId.js';
|
|
52
52
|
export { buildRuntimeStageId, createExecutionCounter, parseRuntimeStageId } from './lib/engine/runtimeStageId.js';
|
|
53
53
|
export { findCommit, findCommits, findLastWriter } from './lib/memory/commitLogUtils.js';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
export type { FlowChart, StageFunction as StageHandler, StreamHandlers } from './lib/builder/index.js';
|
|
18
18
|
/** @category Quick Start */
|
|
19
19
|
export { flowChart, FlowChartBuilder } 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';
|
|
20
22
|
/** @category Quick Start */
|
|
21
23
|
export type { TypedStageFunction } from './lib/builder/typedFlowChart.js';
|
|
22
24
|
/** @category Quick Start */
|
|
@@ -15,8 +15,10 @@ import type { ScopeFactory } from '../engine/types.js';
|
|
|
15
15
|
import type { PausableHandler } from '../pause/types.js';
|
|
16
16
|
import type { TypedScope } from '../reactive/types.js';
|
|
17
17
|
import { type RunnableFlowChart } from '../runner/RunnableChart.js';
|
|
18
|
+
import type { StructureEdgeKind, StructureRecorder } from './structure/StructureRecorder.js';
|
|
19
|
+
import { StructureRecorderDispatcher } from './structure/StructureRecorderDispatcher.js';
|
|
18
20
|
import { type TypedStageFunction } from './typedFlowChart.js';
|
|
19
|
-
import type {
|
|
21
|
+
import type { FlowChart, FlowChartOptions, FlowChartSpec, ILogger, SerializedPipelineStructure, SimplifiedParallelSpec, StageFunction, StageNode, StreamLifecycleHandler, StreamTokenHandler, SubflowMountOptions } from './types.js';
|
|
20
22
|
/**
|
|
21
23
|
* Fluent helper returned by addDeciderFunction to add branches.
|
|
22
24
|
* `end()` sets `deciderFn = true` — the fn IS the decider.
|
|
@@ -92,9 +94,22 @@ export declare class FlowChartBuilder<TOut = any, TScope = any> {
|
|
|
92
94
|
root: StageNode<TOut, TScope>;
|
|
93
95
|
}>;
|
|
94
96
|
private _streamHandlers;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
/**
|
|
98
|
+
* L7.3 — Build-time observer fan-out. Owned by the builder so every
|
|
99
|
+
* `addX()` method can fire `StructureRecorder` events at the natural
|
|
100
|
+
* moment of the corresponding mutation. Dispatcher is allocated
|
|
101
|
+
* lazily on first attach to keep the zero-recorder path allocation-
|
|
102
|
+
* free.
|
|
103
|
+
*/
|
|
104
|
+
private _structureDispatcher?;
|
|
105
|
+
/**
|
|
106
|
+
* L7.3 — Sealed-after-build flag (Panel 2 phase invariant). Flips
|
|
107
|
+
* to `true` when `.build()` returns; subsequent `attachStructureRecorder`
|
|
108
|
+
* throws. Prevents the footgun where a consumer attaches a recorder
|
|
109
|
+
* mid-execution and gets partial structure data (missed every event
|
|
110
|
+
* already fired during construction).
|
|
111
|
+
*/
|
|
112
|
+
private _sealed;
|
|
98
113
|
private _enableNarrative;
|
|
99
114
|
private _logger?;
|
|
100
115
|
private _descriptionParts;
|
|
@@ -106,7 +121,90 @@ export declare class FlowChartBuilder<TOut = any, TScope = any> {
|
|
|
106
121
|
private _outputSchema?;
|
|
107
122
|
private _outputMapper?;
|
|
108
123
|
private _scopeFactory?;
|
|
109
|
-
|
|
124
|
+
/**
|
|
125
|
+
* Attach a `StructureRecorder` for build-phase observation. Multiple
|
|
126
|
+
* recorders coexist (same id allowed; iteration order = attach
|
|
127
|
+
* order). Throws if called after `.build()` — the chart is sealed at
|
|
128
|
+
* that point and any recorder attached late would miss every event
|
|
129
|
+
* fired during construction.
|
|
130
|
+
*
|
|
131
|
+
* **Seed replay**: when this is called AFTER `start()` has already
|
|
132
|
+
* fired (i.e., after the `flowChart()` factory returns), the
|
|
133
|
+
* just-attached recorder receives a one-time `onStageAdded` for the
|
|
134
|
+
* root stage so it observes the seed. Only the new recorder sees
|
|
135
|
+
* the replay; already-attached recorders are not re-fired.
|
|
136
|
+
*
|
|
137
|
+
* **Mid-chain attach caveat**: a recorder attached AFTER one or more
|
|
138
|
+
* `addX()` calls receives the seed replay but MISSES every
|
|
139
|
+
* intermediate event. Attach BEFORE the first `addX()` for complete
|
|
140
|
+
* capture.
|
|
141
|
+
*
|
|
142
|
+
* Public for now to enable direct attach in tests + early consumers.
|
|
143
|
+
* L7.4 will wire `flowChart(..., { structureRecorders: [...] })` as
|
|
144
|
+
* an additional registration site; this method will remain.
|
|
145
|
+
*/
|
|
146
|
+
attachStructureRecorder(recorder: StructureRecorder): this;
|
|
147
|
+
/**
|
|
148
|
+
* Inspect accumulated `StructureBuildError`s. Returns empty array
|
|
149
|
+
* when no recorders attached OR no errors occurred. Returns a
|
|
150
|
+
* defensive copy — caller mutations do not affect subsequent calls.
|
|
151
|
+
*
|
|
152
|
+
* **Call on the BUILDER, not the chart returned by `.build()`.**
|
|
153
|
+
* Capture the builder reference before `.build()` if you need
|
|
154
|
+
* post-build access:
|
|
155
|
+
* ```ts
|
|
156
|
+
* const builder = flowChart(...).attachStructureRecorder(rec);
|
|
157
|
+
* const chart = builder.build();
|
|
158
|
+
* const errors = builder.getStructureBuildErrors();
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
getStructureBuildErrors(): ReturnType<StructureRecorderDispatcher['getErrors']>;
|
|
162
|
+
private _fireStageAdded;
|
|
163
|
+
private _fireEdgeAdded;
|
|
164
|
+
private _fireLoopEdgeAdded;
|
|
165
|
+
/**
|
|
166
|
+
* Fire the `next` edge(s) from a parent spec to a freshly-added
|
|
167
|
+
* node — with convergence expansion when the parent is a
|
|
168
|
+
* fork / decider / selector with branches.
|
|
169
|
+
*
|
|
170
|
+
* A fork at `parent` is semantically `parent ──fork-branch──► child[i]`
|
|
171
|
+
* for each child, and the chained `.addFunction(X)` continues
|
|
172
|
+
* AFTER the fork converges. The runtime semantics are that each
|
|
173
|
+
* child INDEPENDENTLY feeds `X` (parallel completion → join). The
|
|
174
|
+
* literal "edge from parent to X" would misrepresent this —
|
|
175
|
+
* visualizers and topological algorithms would see one edge where
|
|
176
|
+
* there should be N convergence edges.
|
|
177
|
+
*
|
|
178
|
+
* Fix: when `parentSpec` has branch children (fork or branched
|
|
179
|
+
* decider/selector), fire one `next` edge from EACH child to the
|
|
180
|
+
* target. Otherwise fire the single edge from `parentSpec` itself.
|
|
181
|
+
*
|
|
182
|
+
* Loop-reference children (synthetic spec nodes created by
|
|
183
|
+
* `.loopTo()`) are excluded — they're back-edge markers, not
|
|
184
|
+
* convergence sources.
|
|
185
|
+
*
|
|
186
|
+
* Call ORDER constraint: must be called BEFORE the cursor advances
|
|
187
|
+
* to the new target. The caller passes the PRE-ADVANCE parent spec.
|
|
188
|
+
*/
|
|
189
|
+
private _fireNextEdgeFromParent;
|
|
190
|
+
private _fireDeciderComplete;
|
|
191
|
+
private _fireSubflowMounted;
|
|
192
|
+
/** Sub-builder access (`.b._fireXxx`) is needed by DeciderList /
|
|
193
|
+
* SelectorFnList; expose the dispatcher through internal helpers
|
|
194
|
+
* that go through the same no-op-when-absent guard.
|
|
195
|
+
*
|
|
196
|
+
* @internal — these methods are exposed because TypeScript `private`
|
|
197
|
+
* doesn't traverse class boundaries. Consumer code MUST NOT call
|
|
198
|
+
* them; calling them post-construction lets a hostile caller
|
|
199
|
+
* fabricate structure events and corrupt downstream visualizations
|
|
200
|
+
* or audit trails. The `_` prefix is intentional convention. */
|
|
201
|
+
_fireEdgeAddedFromSubBuilder(from: string, to: string, kind: StructureEdgeKind, label?: string): void;
|
|
202
|
+
/** @internal — see `_fireEdgeAddedFromSubBuilder`. */
|
|
203
|
+
_fireStageAddedFromSubBuilder(spec: SerializedPipelineStructure): void;
|
|
204
|
+
/** @internal — see `_fireEdgeAddedFromSubBuilder`. */
|
|
205
|
+
_fireDeciderCompleteFromSubBuilder(decider: string, type: 'decider' | 'selector', branchIds: string[], defaultBranch?: string): void;
|
|
206
|
+
/** @internal — see `_fireEdgeAddedFromSubBuilder`. */
|
|
207
|
+
_fireSubflowMountedFromSubBuilder(subflowId: string, subflowName: string, rootStageId: string, isLazy?: boolean, subflowSpec?: SerializedPipelineStructure, subflowPath?: string): void;
|
|
110
208
|
private _appendDescriptionLine;
|
|
111
209
|
private _appendSubflowDescription;
|
|
112
210
|
setLogger(logger: ILogger): this;
|
|
@@ -240,12 +338,6 @@ export declare class FlowChartBuilder<TOut = any, TScope = any> {
|
|
|
240
338
|
onStream(handler: StreamTokenHandler): this;
|
|
241
339
|
onStreamStart(handler: StreamLifecycleHandler): this;
|
|
242
340
|
onStreamEnd(handler: StreamLifecycleHandler): this;
|
|
243
|
-
addTraversalExtractor<TResult = unknown>(extractor: TraversalExtractor<TResult>): this;
|
|
244
|
-
addBuildTimeExtractor<TResult = FlowChartSpec>(extractor: BuildTimeExtractor<TResult>): this;
|
|
245
|
-
getBuildTimeExtractorErrors(): Array<{
|
|
246
|
-
message: string;
|
|
247
|
-
error: unknown;
|
|
248
|
-
}>;
|
|
249
341
|
build(): RunnableFlowChart<TOut, TScope>;
|
|
250
342
|
/** Override the scope factory. Rarely needed — auto-embeds TypedScope by default. */
|
|
251
343
|
setScopeFactory(factory: ScopeFactory<TScope>): this;
|
|
@@ -253,7 +345,11 @@ export declare class FlowChartBuilder<TOut = any, TScope = any> {
|
|
|
253
345
|
toMermaid(): string;
|
|
254
346
|
private _needCursor;
|
|
255
347
|
private _needCursorSpec;
|
|
256
|
-
|
|
348
|
+
/**
|
|
349
|
+
* Advance the spec cursor. Retained as a method so call sites stay
|
|
350
|
+
* one-liners and future cursor-related side effects have a hook.
|
|
351
|
+
*/
|
|
352
|
+
private _advanceCursorSpec;
|
|
257
353
|
_stageMapHas(key: string): boolean;
|
|
258
354
|
_addToMap(id: string, fn: StageFunction<TOut, TScope>): void;
|
|
259
355
|
_mergeStageMap(other: Map<string, StageFunction<TOut, TScope>>, prefix?: string): void;
|
|
@@ -262,6 +358,6 @@ export declare class FlowChartBuilder<TOut = any, TScope = any> {
|
|
|
262
358
|
root: StageNode<TOut, TScope>;
|
|
263
359
|
}> | undefined, prefix: string): void;
|
|
264
360
|
}
|
|
265
|
-
export declare function flowChart<TState extends object>(name: string, fn: TypedStageFunction<TState> | PausableHandler<TypedScope<TState>>, id: string,
|
|
266
|
-
export declare function flowChart<TOut = any, TScope = any>(name: string, fn: StageFunction<TOut, TScope> | PausableHandler<TScope>, id: string,
|
|
361
|
+
export declare function flowChart<TState extends object>(name: string, fn: TypedStageFunction<TState> | PausableHandler<TypedScope<TState>>, id: string, options?: FlowChartOptions): FlowChartBuilder<any, TypedScope<TState>>;
|
|
362
|
+
export declare function flowChart<TOut = any, TScope = any>(name: string, fn: StageFunction<TOut, TScope> | PausableHandler<TScope>, id: string, options?: FlowChartOptions): FlowChartBuilder<TOut, TScope>;
|
|
267
363
|
export declare function specToStageNode(spec: FlowChartSpec): StageNode<any, any>;
|
|
@@ -6,5 +6,6 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { DeciderList, FlowChartBuilder, SelectorFnList } from './FlowChartBuilder.js';
|
|
8
8
|
export { flowChart, specToStageNode } from './FlowChartBuilder.js';
|
|
9
|
-
export type {
|
|
9
|
+
export type { ExecOptions, FlowChart, FlowChartOptions, FlowChartSpec, ILogger, ScopeProtectionMode, SerializedPipelineStructure, SimplifiedParallelSpec, StageFn, StageFunction, StageNode, StreamCallback, StreamHandlers, StreamLifecycleHandler, StreamTokenHandler, SubflowMountOptions, SubflowRef, } from './types.js';
|
|
10
10
|
export { ArrayMergeMode } from './types.js';
|
|
11
|
+
export type { StructureDeciderCompleteEvent, StructureEdgeAddedEvent, StructureEdgeKind, StructureLoopEdgeAddedEvent, StructureRecorder, StructureStageAddedEvent, StructureSubflowMountedEvent, } from './structure/StructureRecorder.js';
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StructureRecorder — passive observer of BUILD-TIME chart construction events.
|
|
3
|
+
*
|
|
4
|
+
* The build-time twin of `FlowRecorder`. Where `FlowRecorder` observes
|
|
5
|
+
* RUNTIME control-flow transitions (per-execution `runtimeStageId`,
|
|
6
|
+
* iteration counts, errors, pauses), `StructureRecorder` observes
|
|
7
|
+
* STATIC chart shape as it's assembled by the builder — every spec
|
|
8
|
+
* node added, every outgoing edge wired, every decider closed.
|
|
9
|
+
*
|
|
10
|
+
* Why two interfaces, not one
|
|
11
|
+
* ───────────────────────────
|
|
12
|
+
* Build and runtime events have different INVARIANTS, not just
|
|
13
|
+
* different timing:
|
|
14
|
+
*
|
|
15
|
+
* - Runtime events carry `runtimeStageId` (`[subflowPath/]stageId#N`),
|
|
16
|
+
* `iteration`, `traversalContext` — load-bearing for time-travel
|
|
17
|
+
* UIs, commit-log indices, and `SequenceRecorder<T>` consumers.
|
|
18
|
+
* NONE of these exist at build time.
|
|
19
|
+
*
|
|
20
|
+
* - Build events carry only `stageId` + structural fields. No
|
|
21
|
+
* execution index, no iteration, no snapshot.
|
|
22
|
+
*
|
|
23
|
+
* - Some events have no analog across phases: `onPause` /
|
|
24
|
+
* `onResume` / `onError` / `onRunStart` are runtime-only;
|
|
25
|
+
* `onDeciderComplete` / `onStageAdded` are build-only.
|
|
26
|
+
*
|
|
27
|
+
* A single `FlowRecorder` with `phase: 'static' | 'dynamic'`
|
|
28
|
+
* discriminator would force every consumer to write
|
|
29
|
+
* `if (e.phase === 'static') ...` branches and would erase the
|
|
30
|
+
* least-privilege boundary (a static-only consumer should NOT
|
|
31
|
+
* accidentally observe runtime data — e.g., a public docs site
|
|
32
|
+
* rendering chart topology must not see scope values).
|
|
33
|
+
*
|
|
34
|
+
* Two interfaces, same mental model, clean separation. Two
|
|
35
|
+
* registration sites ship today (pick whichever fits your call
|
|
36
|
+
* site):
|
|
37
|
+
*
|
|
38
|
+
* 1. **Options-bag** (preferred when the recorder set is known
|
|
39
|
+
* at construction time — registers BEFORE `start()` so even
|
|
40
|
+
* the seed event fires through the normal dispatcher fan-out):
|
|
41
|
+
* ```ts
|
|
42
|
+
* flowChart('seed', fn, 'seed', { structureRecorders: [rec] })
|
|
43
|
+
* .addFunction('a', fnA, 'a').build();
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* 2. **Fluent** (preferred when attach is conditional, late, or
|
|
47
|
+
* in a chain builder — the just-attached recorder gets a
|
|
48
|
+
* one-time seed replay so it observes the root stage):
|
|
49
|
+
* ```ts
|
|
50
|
+
* flowChart('seed', fn, 'seed')
|
|
51
|
+
* .attachStructureRecorder(rec)
|
|
52
|
+
* .addFunction('a', fnA, 'a').build();
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* Both deliver the same event stream to the same recorder. See the
|
|
56
|
+
* `@example` block below for a fully-fleshed-out implementation.
|
|
57
|
+
*
|
|
58
|
+
* Lifecycle + ordering invariants
|
|
59
|
+
* ───────────────────────────────
|
|
60
|
+
* - Fires SYNCHRONOUSLY during builder chain calls (and during
|
|
61
|
+
* `.build()` for the terminal node) at the natural moment each
|
|
62
|
+
* spec mutation completes.
|
|
63
|
+
* - `onStageAdded(A)` and `onStageAdded(B)` fire BEFORE any
|
|
64
|
+
* `onEdgeAdded({from: A, to: B})` — endpoint registration
|
|
65
|
+
* happens before edge wiring.
|
|
66
|
+
* - `onDeciderComplete(D)` fires at sub-builder `.end()` time, AFTER
|
|
67
|
+
* every child's `onStageAdded` and every `onEdgeAdded({from: D,
|
|
68
|
+
* to: child})`. Marks the decider as no-further-mutation.
|
|
69
|
+
* - `onSubflowMounted({subflowId})` fires once per mount.
|
|
70
|
+
* **MOUNT-ONLY**: parent recorders do NOT receive a replay of
|
|
71
|
+
* the subflow's own internal structure events (those fired
|
|
72
|
+
* during the subflow's own `.build()`). Matches the runtime
|
|
73
|
+
* `onSubflowEntry` semantics — composition over replay.
|
|
74
|
+
*
|
|
75
|
+
* Error isolation (matches FlowRecorder contract)
|
|
76
|
+
* ───────────────────────────────────────────────
|
|
77
|
+
* - A throwing handler is caught, logged via `isDevMode()` warning,
|
|
78
|
+
* and accumulated on `builder.getStructureBuildErrors()` for
|
|
79
|
+
* post-hoc inspection.
|
|
80
|
+
* - Subsequent recorders + subsequent events fire normally; one
|
|
81
|
+
* misbehaving recorder cannot THROW its way into blocking
|
|
82
|
+
* construction.
|
|
83
|
+
* - The errors[] accumulator is soft-capped (~100 entries) with a
|
|
84
|
+
* `__truncated__` sentinel record once the cap is hit, to prevent
|
|
85
|
+
* unbounded growth on chatty broken recorders.
|
|
86
|
+
* - Note: throw isolation does NOT defend against a handler that
|
|
87
|
+
* succeeds at runtime but mutates `event.spec` to corrupt the
|
|
88
|
+
* chart. See "Spec mutation" below.
|
|
89
|
+
*
|
|
90
|
+
* Spec mutation — readonly-by-contract (NOT runtime-enforced)
|
|
91
|
+
* ────────────────────────────────────────────────────────────
|
|
92
|
+
* - Event payloads pass spec references where useful (e.g., `spec`
|
|
93
|
+
* on `onStageAdded`). Every field on every event payload is
|
|
94
|
+
* marked `readonly` in TypeScript — the type system signals
|
|
95
|
+
* consumer intent at author time.
|
|
96
|
+
* - There is NO runtime freeze. The builder fires `onStageAdded`
|
|
97
|
+
* IMMEDIATELY when a spec node is added, BEFORE the builder
|
|
98
|
+
* wires that node's `.next`/`.children`/`.loopTarget` in the
|
|
99
|
+
* subsequent `addX` call. Freezing here would break the
|
|
100
|
+
* builder's own subsequent mutation.
|
|
101
|
+
* - Handler mutation of `event.spec` is DOCUMENTED UNDEFINED
|
|
102
|
+
* BEHAVIOR — it will succeed at runtime, but is not supported
|
|
103
|
+
* and downstream consumers may break. Specifically, mutating
|
|
104
|
+
* `event.spec.fn`, `event.spec.id`, or `event.spec.children`
|
|
105
|
+
* can corrupt subsequent runtime behavior of the chart.
|
|
106
|
+
* - **Trust model**: attach ONLY recorders from trusted code paths.
|
|
107
|
+
* A hostile or buggy recorder can effectively substitute stage
|
|
108
|
+
* functions or rewire the chart structure. The `readonly`
|
|
109
|
+
* markers cannot defend against intentional mutation.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```ts
|
|
113
|
+
* class TraceStructureRecorder implements StructureRecorder {
|
|
114
|
+
* readonly id = 'trace-static';
|
|
115
|
+
* nodes: XyflowNode[] = [];
|
|
116
|
+
* edges: XyflowEdge[] = [];
|
|
117
|
+
*
|
|
118
|
+
* onStageAdded(e) {
|
|
119
|
+
* // Node role: 'stage' is the initial type. If outgoing edges
|
|
120
|
+
* // arrive with kind 'fork-branch' / 'decision-branch' the node
|
|
121
|
+
* // is functioning as a fork/decider — derive the visual style
|
|
122
|
+
* // from those edges, not from `e.type` alone.
|
|
123
|
+
* this.nodes.push({ id: e.stageId, type: 'lensStage', data: { label: e.name } });
|
|
124
|
+
* }
|
|
125
|
+
* onEdgeAdded(e) {
|
|
126
|
+
* this.edges.push({ id: `${e.from}->${e.to}`, source: e.from, target: e.to });
|
|
127
|
+
* }
|
|
128
|
+
* onSubflowMounted(e) {
|
|
129
|
+
* this.nodes.push({ id: e.subflowId, type: 'subflow', data: { label: e.subflowName } });
|
|
130
|
+
* }
|
|
131
|
+
* onDeciderComplete(e) {
|
|
132
|
+
* // Optional: finalize node styling now that branch list is sealed.
|
|
133
|
+
* }
|
|
134
|
+
* }
|
|
135
|
+
*
|
|
136
|
+
* // Registration option A — options-bag (preferred when recorders
|
|
137
|
+
* // are known up front; attaches BEFORE the seed event fires):
|
|
138
|
+
* const rec = new TraceStructureRecorder();
|
|
139
|
+
* const builder = flowChart('seed', fn, 'seed', {
|
|
140
|
+
* structureRecorders: [rec],
|
|
141
|
+
* }).addFunction('a', fnA, 'a');
|
|
142
|
+
* const chart = builder.build();
|
|
143
|
+
*
|
|
144
|
+
* // Registration option B — fluent chain (preferred for conditional
|
|
145
|
+
* // or late attach; the just-attached recorder gets a seed replay):
|
|
146
|
+
* const rec2 = new TraceStructureRecorder();
|
|
147
|
+
* const builder2 = flowChart('seed', fn, 'seed')
|
|
148
|
+
* .attachStructureRecorder(rec2)
|
|
149
|
+
* .addFunction('a', fnA, 'a');
|
|
150
|
+
*
|
|
151
|
+
* // Inspect any recorder errors (call on the BUILDER, not the chart):
|
|
152
|
+
* const errors = builder.getStructureBuildErrors();
|
|
153
|
+
*
|
|
154
|
+
* <ReactFlow nodes={rec.nodes} edges={rec.edges} />
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
import type { FlowChartSpec, SerializedPipelineStructure } from '../types.js';
|
|
158
|
+
/**
|
|
159
|
+
* Event payload for `StructureRecorder.onStageAdded`. Fires for every
|
|
160
|
+
* spec node added to the chart, including the seed (added via
|
|
161
|
+
* `flowChart()` factory) and subflow mount nodes. Excludes synthetic
|
|
162
|
+
* loop-reference nodes (those carry `isLoopReference: true` on the
|
|
163
|
+
* spec; consumers see them via the separate `onLoopEdgeAdded` event
|
|
164
|
+
* instead of as fresh stages).
|
|
165
|
+
*/
|
|
166
|
+
export interface StructureStageAddedEvent {
|
|
167
|
+
/**
|
|
168
|
+
* Stable identifier for this node. AT EVENT FIRE TIME this is the
|
|
169
|
+
* builder's LOCAL form (no subflow prefix — the prefix is applied
|
|
170
|
+
* later by `_prefixNodeTree` when this builder is mounted as a
|
|
171
|
+
* subflow into a parent).
|
|
172
|
+
*
|
|
173
|
+
* Note: `spec.id` is a LIVE reference. If you read it AFTER this
|
|
174
|
+
* chart has been mounted as a subflow, it may have been rewritten
|
|
175
|
+
* to the FULL prefixed form. Use `splitStageId(spec.id)` from
|
|
176
|
+
* `footprintjs/trace` to decompose it back into local + subflowPath.
|
|
177
|
+
*
|
|
178
|
+
* Correlating with runtime events:
|
|
179
|
+
* - Same builder (no mount) →
|
|
180
|
+
* `event.stageId === parseRuntimeStageId(runtime).stageId`
|
|
181
|
+
* - This builder mounted as subflow → use `splitStageId` on the
|
|
182
|
+
* prefixed form (or `parseRuntimeStageId` on the full
|
|
183
|
+
* runtimeStageId) before comparing.
|
|
184
|
+
*/
|
|
185
|
+
readonly stageId: string;
|
|
186
|
+
/** Human-readable label for the node. */
|
|
187
|
+
readonly name: string;
|
|
188
|
+
/** Spec node `type`. Lets recorders branch on stage vs decider vs
|
|
189
|
+
* fork vs subflow without re-deriving from other fields. */
|
|
190
|
+
readonly type: NonNullable<FlowChartSpec['type']>;
|
|
191
|
+
/** True for nodes added via `addPausableFunction()` — useful for
|
|
192
|
+
* visualisers that want to mark stages that can pause execution. */
|
|
193
|
+
readonly isPausable?: boolean;
|
|
194
|
+
/** Live reference to the full spec node, for handlers that want
|
|
195
|
+
* details beyond the discriminator fields above. MUST NOT be
|
|
196
|
+
* mutated by the handler — readonly is type-level intent; no
|
|
197
|
+
* runtime freeze. See "Spec mutation" in the file header for the
|
|
198
|
+
* trust-model caveats. */
|
|
199
|
+
readonly spec: FlowChartSpec;
|
|
200
|
+
}
|
|
201
|
+
/** Edge kinds the builder produces at structural time. Matches the
|
|
202
|
+
* footprintjs control-flow vocabulary used at runtime.
|
|
203
|
+
*
|
|
204
|
+
* Why no `subflow-entry` here: subflow mounts use the lifecycle
|
|
205
|
+
* event `onSubflowMounted` (not an edge event). If a future use case
|
|
206
|
+
* needs the parent→subflow-root edge as a distinct kind, it'll be
|
|
207
|
+
* added then — YAGNI now (Panel 3, L7.2 review). */
|
|
208
|
+
export type StructureEdgeKind = 'next' | 'fork-branch' | 'decision-branch';
|
|
209
|
+
/**
|
|
210
|
+
* Event payload for `StructureRecorder.onEdgeAdded`. Fires whenever
|
|
211
|
+
* the builder wires an outgoing edge from one node to another. Both
|
|
212
|
+
* endpoints have already been announced via `onStageAdded` by the
|
|
213
|
+
* time this fires.
|
|
214
|
+
*
|
|
215
|
+
* Loop back-edges have their OWN event (`onLoopEdgeAdded`) so
|
|
216
|
+
* consumers can theme them distinctly and so build-time events stay
|
|
217
|
+
* free of the runtime-only `iteration` field.
|
|
218
|
+
*/
|
|
219
|
+
export interface StructureEdgeAddedEvent {
|
|
220
|
+
readonly from: string;
|
|
221
|
+
readonly to: string;
|
|
222
|
+
readonly kind: StructureEdgeKind;
|
|
223
|
+
/** Optional human-readable label — used today for decider branch
|
|
224
|
+
* keys (e.g., `'low'`, `'high'`, `'high (default)'`) and parallel
|
|
225
|
+
* branch ids. */
|
|
226
|
+
readonly label?: string;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Event payload for `StructureRecorder.onLoopEdgeAdded`. Fires when
|
|
230
|
+
* `.loopTo(target)` installs a back-edge. Distinct from
|
|
231
|
+
* `onEdgeAdded` so consumers can theme back-edges differently and
|
|
232
|
+
* because runtime `onLoop` carries `iteration: number` which has no
|
|
233
|
+
* build-time meaning — keeping the events separated avoids forcing
|
|
234
|
+
* an `iteration?: number` lie into the structural shape.
|
|
235
|
+
*/
|
|
236
|
+
export interface StructureLoopEdgeAddedEvent {
|
|
237
|
+
readonly from: string;
|
|
238
|
+
readonly to: string;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Event payload for `StructureRecorder.onDeciderComplete`. Fires
|
|
242
|
+
* when a decider / selector sub-builder closes via `.end()`. By the
|
|
243
|
+
* time this fires every branch has been announced and the
|
|
244
|
+
* `defaultBranch` (if set via `.setDefault()`) is final. Lets
|
|
245
|
+
* recorders treat the decider as no-further-mutation and snapshot
|
|
246
|
+
* its branch list as final.
|
|
247
|
+
*/
|
|
248
|
+
export interface StructureDeciderCompleteEvent {
|
|
249
|
+
/** Decider / selector stage id. */
|
|
250
|
+
readonly decider: string;
|
|
251
|
+
/** Spec type (`'decider'` vs `'selector'`) — exposed so consumers
|
|
252
|
+
* don't need to look up the original `onStageAdded` event. */
|
|
253
|
+
readonly type: 'decider' | 'selector';
|
|
254
|
+
/** Branch member ids in declaration order. */
|
|
255
|
+
readonly branchIds: readonly string[];
|
|
256
|
+
/** Default branch id when set via `.setDefault()`; undefined when
|
|
257
|
+
* no default is configured (e.g., selectors). */
|
|
258
|
+
readonly defaultBranch?: string;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Event payload for `StructureRecorder.onSubflowMounted`. Fires once
|
|
262
|
+
* per subflow mount (`addSubFlowChart` / `addSubFlowChartNext` and
|
|
263
|
+
* their lazy variants).
|
|
264
|
+
*
|
|
265
|
+
* **MOUNT-ONLY semantics** — the subflow's OWN structure events
|
|
266
|
+
* (every `onStageAdded` / `onEdgeAdded` inside the subflow) fired
|
|
267
|
+
* during the subflow's own `.build()`, before the mount. Parent
|
|
268
|
+
* recorders do NOT receive a replay. Instead, this event delivers
|
|
269
|
+
* the subflow's full structure via `subflowSpec`, and consumers can
|
|
270
|
+
* walk it via `walkSubflowSpec` from `footprintjs/trace`.
|
|
271
|
+
*
|
|
272
|
+
* This matches `FlowRecorder.onSubflowEntry` semantics at runtime
|
|
273
|
+
* (parents see the boundary, not a replay of internals) and
|
|
274
|
+
* preserves the "one purpose per recorder" convention.
|
|
275
|
+
*/
|
|
276
|
+
export interface StructureSubflowMountedEvent {
|
|
277
|
+
/** Subflow identifier the parent assigned at mount. */
|
|
278
|
+
readonly subflowId: string;
|
|
279
|
+
/** Human-readable subflow name. */
|
|
280
|
+
readonly subflowName: string;
|
|
281
|
+
/** Mount node id in the parent's chart. */
|
|
282
|
+
readonly rootStageId: string;
|
|
283
|
+
/** True when the mount uses lazy resolution (deferred subflow
|
|
284
|
+
* resolution until execution). */
|
|
285
|
+
readonly isLazy?: boolean;
|
|
286
|
+
/**
|
|
287
|
+
* The mounted subflow's complete spec — the SAME OBJECT
|
|
288
|
+
* (=== reference equality) reachable via `subflow.buildTimeStructure`
|
|
289
|
+
* for the FlowChart the consumer passed to `addSubFlowChartBranch` /
|
|
290
|
+
* `addSubFlowChart` / `addSubFlowChartNext`.
|
|
291
|
+
*
|
|
292
|
+
* UNDEFINED for lazy mounts at build time (`isLazy: true`) — the
|
|
293
|
+
* subflow's structure hasn't been resolved yet. Consumers waiting on
|
|
294
|
+
* lazy subflows handle the runtime `onSubflowEntry` event instead.
|
|
295
|
+
*
|
|
296
|
+
* Immutable post-build; consumers MUST NOT mutate.
|
|
297
|
+
*
|
|
298
|
+
* @internal `SerializedPipelineStructure` is library-internal.
|
|
299
|
+
* Use `walkSubflowSpec` from `footprintjs/trace` for the
|
|
300
|
+
* stable public contract.
|
|
301
|
+
*/
|
|
302
|
+
readonly subflowSpec?: SerializedPipelineStructure;
|
|
303
|
+
/**
|
|
304
|
+
* Local mount id of this subflow within its parent — equal to
|
|
305
|
+
* `subflowId` for top-level mounts (e.g. `'auth'`), composed
|
|
306
|
+
* (`'auth/verify'`) for nested mounts whose recorder is attached
|
|
307
|
+
* to the grandparent. Matches runtime `traversalContext.subflowPath`
|
|
308
|
+
* semantics — NEVER prefixed with `__root__/`.
|
|
309
|
+
*/
|
|
310
|
+
readonly subflowPath: string;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Pluggable observer for BUILD-TIME chart construction events.
|
|
314
|
+
*
|
|
315
|
+
* All methods are optional — implement only the hooks you need.
|
|
316
|
+
* Handlers fire SYNCHRONOUSLY during builder operations and `.build()`.
|
|
317
|
+
* A throwing handler is caught (see "Error isolation" in the file
|
|
318
|
+
* header); subsequent dispatch continues.
|
|
319
|
+
*
|
|
320
|
+
* Lifecycle: each `StructureRecorder` instance is registered via
|
|
321
|
+
* EITHER the `flowChart()` options bag (`{ structureRecorders: [rec] }`)
|
|
322
|
+
* OR the fluent `.attachStructureRecorder(rec)` chain — see the file
|
|
323
|
+
* header for the trade-offs. Registration after `.build()` is
|
|
324
|
+
* rejected (chart is sealed).
|
|
325
|
+
*/
|
|
326
|
+
export interface StructureRecorder {
|
|
327
|
+
/**
|
|
328
|
+
* Stable identifier — used by the dispatcher to scope error
|
|
329
|
+
* messages and to support `detach(id)` lookup.
|
|
330
|
+
*
|
|
331
|
+
* Convention (matches `FlowRecorder.id` from CLAUDE.md):
|
|
332
|
+
* - domain-prefixed kebab-case (`'lens-structure'`,
|
|
333
|
+
* `'agentfootprint-composition'`, `'trace-explainable'`)
|
|
334
|
+
* - same id → multiple recorders coexist (NOT deduplicated by
|
|
335
|
+
* id; the dispatcher fires every attached recorder regardless)
|
|
336
|
+
* - `detach(id)` removes EVERY recorder with that id — be
|
|
337
|
+
* intentional about reuse if you rely on selective detach
|
|
338
|
+
*
|
|
339
|
+
* Choose a stable id at module load and don't randomise it across
|
|
340
|
+
* runs — it lands in `StructureBuildError.recorderId` so debug
|
|
341
|
+
* output is greppable.
|
|
342
|
+
*/
|
|
343
|
+
readonly id: string;
|
|
344
|
+
onStageAdded?(event: StructureStageAddedEvent): void;
|
|
345
|
+
onEdgeAdded?(event: StructureEdgeAddedEvent): void;
|
|
346
|
+
onLoopEdgeAdded?(event: StructureLoopEdgeAddedEvent): void;
|
|
347
|
+
onDeciderComplete?(event: StructureDeciderCompleteEvent): void;
|
|
348
|
+
onSubflowMounted?(event: StructureSubflowMountedEvent): void;
|
|
349
|
+
}
|