footprintjs 3.0.21 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CLAUDE.md +2 -0
  2. package/dist/esm/lib/builder/FlowChartBuilder.js +3 -3
  3. package/dist/esm/lib/builder/typedFlowChart.js +16 -5
  4. package/dist/esm/lib/builder/types.js +1 -1
  5. package/dist/esm/lib/contract/defineContract.js +33 -7
  6. package/dist/esm/lib/contract/openapi.js +12 -33
  7. package/dist/esm/lib/contract/types.js +1 -1
  8. package/dist/esm/lib/decide/decide.js +33 -3
  9. package/dist/esm/lib/decide/types.js +1 -1
  10. package/dist/esm/lib/engine/handlers/RuntimeStructureManager.js +19 -7
  11. package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +4 -2
  12. package/dist/esm/lib/engine/narrative/ControlFlowNarrativeGenerator.js +4 -2
  13. package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +325 -266
  14. package/dist/esm/lib/engine/types.js +1 -1
  15. package/dist/esm/lib/memory/StageContext.js +15 -3
  16. package/dist/esm/lib/memory/pathOps.js +31 -3
  17. package/dist/esm/lib/memory/utils.js +30 -10
  18. package/dist/esm/lib/runner/FlowChartExecutor.js +79 -6
  19. package/dist/esm/lib/runner/index.js +1 -1
  20. package/dist/esm/lib/scope/ScopeFacade.js +36 -7
  21. package/dist/esm/lib/scope/providers/baseStateCompatible.js +2 -2
  22. package/dist/esm/lib/scope/providers/types.js +1 -1
  23. package/dist/esm/lib/scope/types.js +1 -1
  24. package/dist/lib/builder/FlowChartBuilder.js +3 -3
  25. package/dist/lib/builder/typedFlowChart.js +16 -5
  26. package/dist/lib/builder/types.js +1 -1
  27. package/dist/lib/contract/defineContract.js +33 -7
  28. package/dist/lib/contract/openapi.js +12 -33
  29. package/dist/lib/contract/types.js +1 -1
  30. package/dist/lib/decide/decide.js +33 -3
  31. package/dist/lib/decide/types.js +1 -1
  32. package/dist/lib/engine/handlers/RuntimeStructureManager.js +19 -7
  33. package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +4 -2
  34. package/dist/lib/engine/narrative/ControlFlowNarrativeGenerator.js +4 -2
  35. package/dist/lib/engine/traversal/FlowchartTraverser.js +325 -266
  36. package/dist/lib/engine/types.js +1 -1
  37. package/dist/lib/memory/StageContext.js +15 -3
  38. package/dist/lib/memory/pathOps.js +31 -3
  39. package/dist/lib/memory/utils.js +30 -10
  40. package/dist/lib/runner/FlowChartExecutor.js +79 -6
  41. package/dist/lib/runner/index.js +1 -1
  42. package/dist/lib/scope/ScopeFacade.js +36 -7
  43. package/dist/lib/scope/providers/baseStateCompatible.js +2 -2
  44. package/dist/lib/scope/providers/types.js +1 -1
  45. package/dist/lib/scope/types.js +1 -1
  46. package/dist/types/lib/builder/typedFlowChart.d.ts +15 -4
  47. package/dist/types/lib/builder/types.d.ts +10 -1
  48. package/dist/types/lib/contract/openapi.d.ts +9 -3
  49. package/dist/types/lib/contract/types.d.ts +13 -2
  50. package/dist/types/lib/decide/decide.d.ts +10 -0
  51. package/dist/types/lib/decide/types.d.ts +20 -0
  52. package/dist/types/lib/engine/handlers/RuntimeStructureManager.d.ts +2 -1
  53. package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +47 -0
  54. package/dist/types/lib/engine/types.d.ts +9 -2
  55. package/dist/types/lib/memory/StageContext.d.ts +12 -0
  56. package/dist/types/lib/memory/pathOps.d.ts +26 -2
  57. package/dist/types/lib/memory/utils.d.ts +16 -3
  58. package/dist/types/lib/runner/FlowChartExecutor.d.ts +98 -3
  59. package/dist/types/lib/runner/index.d.ts +1 -0
  60. package/dist/types/lib/scope/ScopeFacade.d.ts +18 -1
  61. package/dist/types/lib/scope/providers/types.d.ts +6 -0
  62. package/dist/types/lib/scope/types.d.ts +7 -1
  63. package/package.json +1 -1
@@ -6,4 +6,4 @@
6
6
  * StageContextLike is the minimal surface from StageContext to avoid tight coupling.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Njb3BlL3Byb3ZpZGVycy90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7O0dBS0ciLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFByb3ZpZGVyIFN5c3RlbSBUeXBlc1xuICpcbiAqIERlZmluZXMgY29udHJhY3RzIGJldHdlZW4gdGhlIHJlZ2lzdHJ5LCByZXNvbHZlcnMsIGFuZCBwcm92aWRlcnMuXG4gKiBTdGFnZUNvbnRleHRMaWtlIGlzIHRoZSBtaW5pbWFsIHN1cmZhY2UgZnJvbSBTdGFnZUNvbnRleHQgdG8gYXZvaWQgdGlnaHQgY291cGxpbmcuXG4gKi9cblxuLyoqIE1pbmltYWwgc3VyZmFjZSBmcm9tIFN0YWdlQ29udGV4dCAocGF0Y2gtYmFzZWQpICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YWdlQ29udGV4dExpa2Uge1xuICBnZXRWYWx1ZShwYXRoOiBzdHJpbmdbXSwga2V5Pzogc3RyaW5nKTogdW5rbm93bjtcbiAgc2V0T2JqZWN0KHBhdGg6IHN0cmluZ1tdLCBrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24sIHNob3VsZFJlZGFjdD86IGJvb2xlYW4sIGRlc2NyaXB0aW9uPzogc3RyaW5nKTogdm9pZDtcbiAgdXBkYXRlT2JqZWN0KHBhdGg6IHN0cmluZ1tdLCBrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24sIGRlc2NyaXB0aW9uPzogc3RyaW5nKTogdm9pZDtcblxuICBhZGRMb2c/KGtleTogc3RyaW5nLCB2YWw6IHVua25vd24pOiB2b2lkO1xuICBhZGRFcnJvcj8oa2V5OiBzdHJpbmcsIHZhbDogdW5rbm93bik6IHZvaWQ7XG5cbiAgZ2V0RnJvbUdsb2JhbENvbnRleHQ/KGtleTogc3RyaW5nKTogdW5rbm93bjtcbiAgc2V0Um9vdD8oa2V5OiBzdHJpbmcsIHZhbHVlOiB1bmtub3duKTogdm9pZDtcbiAgc2V0R2xvYmFsPyhrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24sIGRlc2NyaXB0aW9uPzogc3RyaW5nKTogdm9pZDtcblxuICBwaXBlbGluZUlkPzogc3RyaW5nO1xuICBydW5JZD86IHN0cmluZztcbn1cblxuLyoqIEZhY3RvcnkgdHlwZSB0aGUgcGlwZWxpbmUgZXhwZWN0cyAqL1xuZXhwb3J0IHR5cGUgU2NvcGVGYWN0b3J5PFRTY29wZT4gPSAoY3R4OiBTdGFnZUNvbnRleHRMaWtlLCBzdGFnZU5hbWU6IHN0cmluZywgcmVhZE9ubHk/OiB1bmtub3duKSA9PiBUU2NvcGU7XG5cbi8qKiBTdHJhdGVneSBvYmplY3QgdGhhdCBjcmVhdGVzIGEgc2NvcGUgKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NvcGVQcm92aWRlcjxUU2NvcGU+IHtcbiAgcmVhZG9ubHkga2luZDogc3RyaW5nO1xuICBjcmVhdGUoY3R4OiBTdGFnZUNvbnRleHRMaWtlLCBzdGFnZU5hbWU6IHN0cmluZywgcmVhZE9ubHk/OiB1bmtub3duKTogVFNjb3BlO1xufVxuXG4vKiogUmVzb2x2ZXIgdGhhdCBjYW4gdHVybiBhbiBhcmJpdHJhcnkgaW5wdXQgaW50byBhIFNjb3BlUHJvdmlkZXIgKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJvdmlkZXJSZXNvbHZlcjxUU2NvcGUgPSBhbnk+IHtcbiAgbmFtZTogc3RyaW5nO1xuICBjYW5IYW5kbGUoaW5wdXQ6IHVua25vd24pOiBib29sZWFuO1xuICBtYWtlUHJvdmlkZXIoaW5wdXQ6IHVua25vd24sIG9wdGlvbnM/OiB1bmtub3duKTogU2NvcGVQcm92aWRlcjxUU2NvcGU+O1xufVxuXG4vKiogT3B0aW9uYWwgc3RyaWN0bmVzcyBmb3Igc2NoZW1hLWJhY2tlZCBwcm92aWRlcnMgKi9cbmV4cG9ydCB0eXBlIFN0cmljdE1vZGUgPSAnb2ZmJyB8ICd3YXJuJyB8ICdkZW55JztcblxuLyoqIE9wdGlvbnMgYmFnIHBhc3NlZCB0byByZXNvbHZlKCkgKi9cbmV4cG9ydCB0eXBlIFJlc29sdmVPcHRpb25zID0ge1xuICB6b2Q/OiB7IHN0cmljdD86IFN0cmljdE1vZGUgfTtcbn07XG4iXX0=
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Njb3BlL3Byb3ZpZGVycy90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7O0dBS0ciLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFByb3ZpZGVyIFN5c3RlbSBUeXBlc1xuICpcbiAqIERlZmluZXMgY29udHJhY3RzIGJldHdlZW4gdGhlIHJlZ2lzdHJ5LCByZXNvbHZlcnMsIGFuZCBwcm92aWRlcnMuXG4gKiBTdGFnZUNvbnRleHRMaWtlIGlzIHRoZSBtaW5pbWFsIHN1cmZhY2UgZnJvbSBTdGFnZUNvbnRleHQgdG8gYXZvaWQgdGlnaHQgY291cGxpbmcuXG4gKi9cblxuLyoqIE1pbmltYWwgc3VyZmFjZSBmcm9tIFN0YWdlQ29udGV4dCAocGF0Y2gtYmFzZWQpICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YWdlQ29udGV4dExpa2Uge1xuICBnZXRWYWx1ZShwYXRoOiBzdHJpbmdbXSwga2V5Pzogc3RyaW5nKTogdW5rbm93bjtcbiAgc2V0T2JqZWN0KHBhdGg6IHN0cmluZ1tdLCBrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24sIHNob3VsZFJlZGFjdD86IGJvb2xlYW4sIGRlc2NyaXB0aW9uPzogc3RyaW5nKTogdm9pZDtcbiAgdXBkYXRlT2JqZWN0KHBhdGg6IHN0cmluZ1tdLCBrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24sIGRlc2NyaXB0aW9uPzogc3RyaW5nKTogdm9pZDtcblxuICBhZGRMb2c/KGtleTogc3RyaW5nLCB2YWw6IHVua25vd24pOiB2b2lkO1xuICBhZGRFcnJvcj8oa2V5OiBzdHJpbmcsIHZhbDogdW5rbm93bik6IHZvaWQ7XG5cbiAgZ2V0R2xvYmFsPyhrZXk6IHN0cmluZyk6IHVua25vd247XG4gIC8qKlxuICAgKiBAZGVwcmVjYXRlZCBzaW5jZSB2My4xLjAg4oCUIHVzZSB7QGxpbmsgZ2V0R2xvYmFsfSBpbnN0ZWFkLiBXaWxsIGJlIHJlbW92ZWQgaW4gdjQuMC4wLlxuICAgKiBJbnRlcm5hbCBjYWxsZXJzIG5vIGxvbmdlciBpbnZva2UgdGhpcyBtZXRob2Qg4oCUIGltcGxlbWVudG9ycyBvZiBgU3RhZ2VDb250ZXh0TGlrZWBcbiAgICogbXVzdCBwcm92aWRlIGBnZXRHbG9iYWw/YCAobm90IGp1c3QgYGdldEZyb21HbG9iYWxDb250ZXh0P2ApIGZvciBgZ2V0SW5pdGlhbFZhbHVlRm9yYCB0byB3b3JrLlxuICAgKi9cbiAgZ2V0RnJvbUdsb2JhbENvbnRleHQ/KGtleTogc3RyaW5nKTogdW5rbm93bjtcbiAgc2V0Um9vdD8oa2V5OiBzdHJpbmcsIHZhbHVlOiB1bmtub3duKTogdm9pZDtcbiAgc2V0R2xvYmFsPyhrZXk6IHN0cmluZywgdmFsdWU6IHVua25vd24sIGRlc2NyaXB0aW9uPzogc3RyaW5nKTogdm9pZDtcblxuICBwaXBlbGluZUlkPzogc3RyaW5nO1xuICBydW5JZD86IHN0cmluZztcbn1cblxuLyoqIEZhY3RvcnkgdHlwZSB0aGUgcGlwZWxpbmUgZXhwZWN0cyAqL1xuZXhwb3J0IHR5cGUgU2NvcGVGYWN0b3J5PFRTY29wZT4gPSAoY3R4OiBTdGFnZUNvbnRleHRMaWtlLCBzdGFnZU5hbWU6IHN0cmluZywgcmVhZE9ubHk/OiB1bmtub3duKSA9PiBUU2NvcGU7XG5cbi8qKiBTdHJhdGVneSBvYmplY3QgdGhhdCBjcmVhdGVzIGEgc2NvcGUgKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NvcGVQcm92aWRlcjxUU2NvcGU+IHtcbiAgcmVhZG9ubHkga2luZDogc3RyaW5nO1xuICBjcmVhdGUoY3R4OiBTdGFnZUNvbnRleHRMaWtlLCBzdGFnZU5hbWU6IHN0cmluZywgcmVhZE9ubHk/OiB1bmtub3duKTogVFNjb3BlO1xufVxuXG4vKiogUmVzb2x2ZXIgdGhhdCBjYW4gdHVybiBhbiBhcmJpdHJhcnkgaW5wdXQgaW50byBhIFNjb3BlUHJvdmlkZXIgKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJvdmlkZXJSZXNvbHZlcjxUU2NvcGUgPSBhbnk+IHtcbiAgbmFtZTogc3RyaW5nO1xuICBjYW5IYW5kbGUoaW5wdXQ6IHVua25vd24pOiBib29sZWFuO1xuICBtYWtlUHJvdmlkZXIoaW5wdXQ6IHVua25vd24sIG9wdGlvbnM/OiB1bmtub3duKTogU2NvcGVQcm92aWRlcjxUU2NvcGU+O1xufVxuXG4vKiogT3B0aW9uYWwgc3RyaWN0bmVzcyBmb3Igc2NoZW1hLWJhY2tlZCBwcm92aWRlcnMgKi9cbmV4cG9ydCB0eXBlIFN0cmljdE1vZGUgPSAnb2ZmJyB8ICd3YXJuJyB8ICdkZW55JztcblxuLyoqIE9wdGlvbnMgYmFnIHBhc3NlZCB0byByZXNvbHZlKCkgKi9cbmV4cG9ydCB0eXBlIFJlc29sdmVPcHRpb25zID0ge1xuICB6b2Q/OiB7IHN0cmljdD86IFN0cmljdE1vZGUgfTtcbn07XG4iXX0=
@@ -7,4 +7,4 @@
7
7
  * attached to Scope instances to observe read/write/commit operations.
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3Njb3BlL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUciLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNjb3BlIFR5cGUgRGVmaW5pdGlvbnNcbiAqXG4gKiBDb3JlIHR5cGVzIGZvciB0aGUgY29tcG9zYWJsZSBTY29wZSBzeXN0ZW0gd2l0aCBwbHVnZ2FibGUgUmVjb3JkZXJzLlxuICogQXJjaGl0ZWN0dXJlIGZvbGxvd3MgY29tcG9zaXRpb24tb3Zlci1pbmhlcml0YW5jZTogUmVjb3JkZXJzIGFyZVxuICogYXR0YWNoZWQgdG8gU2NvcGUgaW5zdGFuY2VzIHRvIG9ic2VydmUgcmVhZC93cml0ZS9jb21taXQgb3BlcmF0aW9ucy5cbiAqL1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBFdmVudCBUeXBlc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlY29yZGVyQ29udGV4dCB7XG4gIHN0YWdlTmFtZTogc3RyaW5nO1xuICBwaXBlbGluZUlkOiBzdHJpbmc7XG4gIHRpbWVzdGFtcDogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlYWRFdmVudCBleHRlbmRzIFJlY29yZGVyQ29udGV4dCB7XG4gIGtleT86IHN0cmluZztcbiAgdmFsdWU6IHVua25vd247XG4gIC8qKiBUcnVlIHdoZW4gdGhlIHZhbHVlIGhhcyBiZWVuIHJlZGFjdGVkIGZvciBQSUkgcHJvdGVjdGlvbi4gKi9cbiAgcmVkYWN0ZWQ/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFdyaXRlRXZlbnQgZXh0ZW5kcyBSZWNvcmRlckNvbnRleHQge1xuICBrZXk6IHN0cmluZztcbiAgdmFsdWU6IHVua25vd247XG4gIG9wZXJhdGlvbjogJ3NldCcgfCAndXBkYXRlJyB8ICdkZWxldGUnO1xuICAvKiogVHJ1ZSB3aGVuIHRoZSB2YWx1ZSBoYXMgYmVlbiByZWRhY3RlZCBmb3IgUElJIHByb3RlY3Rpb24uICovXG4gIHJlZGFjdGVkPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb21taXRFdmVudCBleHRlbmRzIFJlY29yZGVyQ29udGV4dCB7XG4gIG11dGF0aW9uczogQXJyYXk8e1xuICAgIGtleTogc3RyaW5nO1xuICAgIHZhbHVlOiB1bmtub3duO1xuICAgIG9wZXJhdGlvbjogJ3NldCcgfCAndXBkYXRlJyB8ICdkZWxldGUnO1xuICB9Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFcnJvckV2ZW50IGV4dGVuZHMgUmVjb3JkZXJDb250ZXh0IHtcbiAgZXJyb3I6IEVycm9yO1xuICBvcGVyYXRpb246ICdyZWFkJyB8ICd3cml0ZScgfCAnY29tbWl0JztcbiAga2V5Pzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0YWdlRXZlbnQgZXh0ZW5kcyBSZWNvcmRlckNvbnRleHQge1xuICBkdXJhdGlvbj86IG51bWJlcjtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gUmVkYWN0aW9uIFBvbGljeVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIERlY2xhcmF0aXZlIHJlZGFjdGlvbiBjb25maWd1cmF0aW9uIOKAlCBkZWZpbmUgb25jZSwgYXBwbGllZCBldmVyeXdoZXJlLlxuICpcbiAqIENvbmZpZ3VyZSBhdCB0aGUgc2NvcGUgY2xhc3MgbGV2ZWwgKHN0YXRpYyBwcm9wZXJ0eSkgb3IgcGFzcyB0b1xuICogRmxvd0NoYXJ0RXhlY3V0b3IgdG8gYXBwbHkgYWNyb3NzIGFsbCBzdGFnZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVkYWN0aW9uUG9saWN5IHtcbiAgLyoqIEV4YWN0IGtleSBuYW1lcyB0byBhbHdheXMgcmVkYWN0IChlLmcuIFsnc3NuJywgJ2NyZWRpdENhcmQnXSkuICovXG4gIGtleXM/OiBzdHJpbmdbXTtcbiAgLyoqIFJlZ2V4IHBhdHRlcm5zIOKAlCBhbnkga2V5IG1hdGNoaW5nIGEgcGF0dGVybiBpcyBhdXRvLXJlZGFjdGVkLiAqL1xuICBwYXR0ZXJucz86IFJlZ0V4cFtdO1xuICAvKiogRmllbGQtbGV2ZWwgcmVkYWN0aW9uIHdpdGhpbiBvYmplY3RzIOKAlCBrZXkg4oaSIGFycmF5IG9mIGZpZWxkcyB0byBzY3J1Yi5cbiAgICogIFN1cHBvcnRzIGRvdC1ub3RhdGlvbiBmb3IgbmVzdGVkIHBhdGhzIChlLmcuICdhZGRyZXNzLnppcCcpLiAqL1xuICBmaWVsZHM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT47XG59XG5cbi8qKlxuICogQ29tcGxpYW5jZS1mcmllbmRseSByZXBvcnQgb2Ygd2hhdCB3YXMgcmVkYWN0ZWQuIE5ldmVyIGluY2x1ZGVzIHZhbHVlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWRhY3Rpb25SZXBvcnQge1xuICAvKiogS2V5cyBmdWxseSByZWRhY3RlZCAoZXhhY3QgbWF0Y2ggb3IgcGF0dGVybiBtYXRjaCkuICovXG4gIHJlZGFjdGVkS2V5czogc3RyaW5nW107XG4gIC8qKiBLZXlzIHdpdGggZmllbGQtbGV2ZWwgcmVkYWN0aW9uIOKGkiB3aGljaCBmaWVsZHMgd2VyZSBzY3J1YmJlZC4gKi9cbiAgZmllbGRSZWRhY3Rpb25zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT47XG4gIC8qKiBTb3VyY2Ugc3RyaW5ncyBvZiByZWdpc3RlcmVkIHBhdHRlcm5zLiAqL1xuICBwYXR0ZXJuczogc3RyaW5nW107XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFJlY29yZGVyIEludGVyZmFjZVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFBsdWdnYWJsZSBvYnNlcnZlciBmb3Igc2NvcGUgb3BlcmF0aW9ucy5cbiAqXG4gKiBBbGwgbWV0aG9kcyBhcmUgb3B0aW9uYWwg4oCUIGltcGxlbWVudCBvbmx5IHRoZSBob29rcyB5b3UgbmVlZC5cbiAqIFJlY29yZGVycyBhcmUgaW52b2tlZCBzeW5jaHJvbm91c2x5IGluIGF0dGFjaG1lbnQgb3JkZXIuXG4gKiBJZiBhIHJlY29yZGVyIHRocm93cywgdGhlIGVycm9yIGlzIGNhdWdodCBhbmQgcGFzc2VkIHRvIG9uRXJyb3JcbiAqIGhvb2tzIG9mIG90aGVyIHJlY29yZGVyczsgdGhlIHNjb3BlIG9wZXJhdGlvbiBjb250aW51ZXMgbm9ybWFsbHkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVjb3JkZXIge1xuICByZWFkb25seSBpZDogc3RyaW5nO1xuICBvblJlYWQ/KGV2ZW50OiBSZWFkRXZlbnQpOiB2b2lkO1xuICBvbldyaXRlPyhldmVudDogV3JpdGVFdmVudCk6IHZvaWQ7XG4gIG9uQ29tbWl0PyhldmVudDogQ29tbWl0RXZlbnQpOiB2b2lkO1xuICBvbkVycm9yPyhldmVudDogRXJyb3JFdmVudCk6IHZvaWQ7XG4gIG9uU3RhZ2VTdGFydD8oZXZlbnQ6IFN0YWdlRXZlbnQpOiB2b2lkO1xuICBvblN0YWdlRW5kPyhldmVudDogU3RhZ2VFdmVudCk6IHZvaWQ7XG4gIC8qKiBSZXNldCBzdGF0ZSBiZWZvcmUgZWFjaCBleGVjdXRvci5ydW4oKSDigJQgcHJldmVudHMgY3Jvc3MtcnVuIGFjY3VtdWxhdGlvbi4gKi9cbiAgY2xlYXI/KCk6IHZvaWQ7XG4gIC8qKiBFeHBvc2UgY29sbGVjdGVkIGRhdGEgZm9yIGluY2x1c2lvbiBpbiBleGVjdXRvci5nZXRTbmFwc2hvdCgpLnJlY29yZGVycy4gKi9cbiAgdG9TbmFwc2hvdD8oKTogeyBuYW1lOiBzdHJpbmc7IGRhdGE6IHVua25vd24gfTtcbn1cbiJdfQ==
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3Njb3BlL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUciLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNjb3BlIFR5cGUgRGVmaW5pdGlvbnNcbiAqXG4gKiBDb3JlIHR5cGVzIGZvciB0aGUgY29tcG9zYWJsZSBTY29wZSBzeXN0ZW0gd2l0aCBwbHVnZ2FibGUgUmVjb3JkZXJzLlxuICogQXJjaGl0ZWN0dXJlIGZvbGxvd3MgY29tcG9zaXRpb24tb3Zlci1pbmhlcml0YW5jZTogUmVjb3JkZXJzIGFyZVxuICogYXR0YWNoZWQgdG8gU2NvcGUgaW5zdGFuY2VzIHRvIG9ic2VydmUgcmVhZC93cml0ZS9jb21taXQgb3BlcmF0aW9ucy5cbiAqL1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBFdmVudCBUeXBlc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlY29yZGVyQ29udGV4dCB7XG4gIHN0YWdlTmFtZTogc3RyaW5nO1xuICBwaXBlbGluZUlkOiBzdHJpbmc7XG4gIHRpbWVzdGFtcDogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlYWRFdmVudCBleHRlbmRzIFJlY29yZGVyQ29udGV4dCB7XG4gIGtleT86IHN0cmluZztcbiAgdmFsdWU6IHVua25vd247XG4gIC8qKiBUcnVlIHdoZW4gdGhlIHZhbHVlIGhhcyBiZWVuIHJlZGFjdGVkIGZvciBQSUkgcHJvdGVjdGlvbi4gKi9cbiAgcmVkYWN0ZWQ/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFdyaXRlRXZlbnQgZXh0ZW5kcyBSZWNvcmRlckNvbnRleHQge1xuICBrZXk6IHN0cmluZztcbiAgdmFsdWU6IHVua25vd247XG4gIG9wZXJhdGlvbjogJ3NldCcgfCAndXBkYXRlJyB8ICdkZWxldGUnO1xuICAvKiogVHJ1ZSB3aGVuIHRoZSB2YWx1ZSBoYXMgYmVlbiByZWRhY3RlZCBmb3IgUElJIHByb3RlY3Rpb24uICovXG4gIHJlZGFjdGVkPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb21taXRFdmVudCBleHRlbmRzIFJlY29yZGVyQ29udGV4dCB7XG4gIG11dGF0aW9uczogQXJyYXk8e1xuICAgIGtleTogc3RyaW5nO1xuICAgIHZhbHVlOiB1bmtub3duO1xuICAgIG9wZXJhdGlvbjogJ3NldCcgfCAndXBkYXRlJyB8ICdkZWxldGUnO1xuICB9Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFcnJvckV2ZW50IGV4dGVuZHMgUmVjb3JkZXJDb250ZXh0IHtcbiAgZXJyb3I6IEVycm9yO1xuICBvcGVyYXRpb246ICdyZWFkJyB8ICd3cml0ZScgfCAnY29tbWl0JztcbiAga2V5Pzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0YWdlRXZlbnQgZXh0ZW5kcyBSZWNvcmRlckNvbnRleHQge1xuICBkdXJhdGlvbj86IG51bWJlcjtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gUmVkYWN0aW9uIFBvbGljeVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIERlY2xhcmF0aXZlIHJlZGFjdGlvbiBjb25maWd1cmF0aW9uIOKAlCBkZWZpbmUgb25jZSwgYXBwbGllZCBldmVyeXdoZXJlLlxuICpcbiAqIENvbmZpZ3VyZSBhdCB0aGUgc2NvcGUgY2xhc3MgbGV2ZWwgKHN0YXRpYyBwcm9wZXJ0eSkgb3IgcGFzcyB0b1xuICogRmxvd0NoYXJ0RXhlY3V0b3IgdG8gYXBwbHkgYWNyb3NzIGFsbCBzdGFnZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVkYWN0aW9uUG9saWN5IHtcbiAgLyoqIEV4YWN0IGtleSBuYW1lcyB0byBhbHdheXMgcmVkYWN0IChlLmcuIFsnc3NuJywgJ2NyZWRpdENhcmQnXSkuICovXG4gIGtleXM/OiBzdHJpbmdbXTtcbiAgLyoqXG4gICAqIFJlZ2V4IHBhdHRlcm5zIOKAlCBhbnkga2V5IG1hdGNoaW5nIGEgcGF0dGVybiBpcyBhdXRvLXJlZGFjdGVkLlxuICAgKlxuICAgKiBQYXR0ZXJuIG1hdGNoaW5nIGlzIHNraXBwZWQgZm9yIGtleXMgdGhhdCBleGNlZWQgYW4gaW50ZXJuYWwgbGVuZ3RoIGNhcFxuICAgKiAoZGVzaWduZWQgdG8gcHJldmVudCBSZURvUyBvbiBwYXRob2xvZ2ljYWwgcGF0dGVybnMpLiBGb3IgdmVyeSBsb25nIGtleVxuICAgKiBuYW1lcywgdXNlIGBrZXlzYCAoZXhhY3QgbWF0Y2gpIGluc3RlYWQgb2YgcGF0dGVybnMuXG4gICAqL1xuICBwYXR0ZXJucz86IFJlZ0V4cFtdO1xuICAvKiogRmllbGQtbGV2ZWwgcmVkYWN0aW9uIHdpdGhpbiBvYmplY3RzIOKAlCBrZXkg4oaSIGFycmF5IG9mIGZpZWxkcyB0byBzY3J1Yi5cbiAgICogIFN1cHBvcnRzIGRvdC1ub3RhdGlvbiBmb3IgbmVzdGVkIHBhdGhzIChlLmcuICdhZGRyZXNzLnppcCcpLiAqL1xuICBmaWVsZHM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT47XG59XG5cbi8qKlxuICogQ29tcGxpYW5jZS1mcmllbmRseSByZXBvcnQgb2Ygd2hhdCB3YXMgcmVkYWN0ZWQuIE5ldmVyIGluY2x1ZGVzIHZhbHVlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWRhY3Rpb25SZXBvcnQge1xuICAvKiogS2V5cyBmdWxseSByZWRhY3RlZCAoZXhhY3QgbWF0Y2ggb3IgcGF0dGVybiBtYXRjaCkuICovXG4gIHJlZGFjdGVkS2V5czogc3RyaW5nW107XG4gIC8qKiBLZXlzIHdpdGggZmllbGQtbGV2ZWwgcmVkYWN0aW9uIOKGkiB3aGljaCBmaWVsZHMgd2VyZSBzY3J1YmJlZC4gKi9cbiAgZmllbGRSZWRhY3Rpb25zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT47XG4gIC8qKiBTb3VyY2Ugc3RyaW5ncyBvZiByZWdpc3RlcmVkIHBhdHRlcm5zLiAqL1xuICBwYXR0ZXJuczogc3RyaW5nW107XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFJlY29yZGVyIEludGVyZmFjZVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIFBsdWdnYWJsZSBvYnNlcnZlciBmb3Igc2NvcGUgb3BlcmF0aW9ucy5cbiAqXG4gKiBBbGwgbWV0aG9kcyBhcmUgb3B0aW9uYWwg4oCUIGltcGxlbWVudCBvbmx5IHRoZSBob29rcyB5b3UgbmVlZC5cbiAqIFJlY29yZGVycyBhcmUgaW52b2tlZCBzeW5jaHJvbm91c2x5IGluIGF0dGFjaG1lbnQgb3JkZXIuXG4gKiBJZiBhIHJlY29yZGVyIHRocm93cywgdGhlIGVycm9yIGlzIGNhdWdodCBhbmQgcGFzc2VkIHRvIG9uRXJyb3JcbiAqIGhvb2tzIG9mIG90aGVyIHJlY29yZGVyczsgdGhlIHNjb3BlIG9wZXJhdGlvbiBjb250aW51ZXMgbm9ybWFsbHkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVjb3JkZXIge1xuICByZWFkb25seSBpZDogc3RyaW5nO1xuICBvblJlYWQ/KGV2ZW50OiBSZWFkRXZlbnQpOiB2b2lkO1xuICBvbldyaXRlPyhldmVudDogV3JpdGVFdmVudCk6IHZvaWQ7XG4gIG9uQ29tbWl0PyhldmVudDogQ29tbWl0RXZlbnQpOiB2b2lkO1xuICBvbkVycm9yPyhldmVudDogRXJyb3JFdmVudCk6IHZvaWQ7XG4gIG9uU3RhZ2VTdGFydD8oZXZlbnQ6IFN0YWdlRXZlbnQpOiB2b2lkO1xuICBvblN0YWdlRW5kPyhldmVudDogU3RhZ2VFdmVudCk6IHZvaWQ7XG4gIC8qKiBSZXNldCBzdGF0ZSBiZWZvcmUgZWFjaCBleGVjdXRvci5ydW4oKSDigJQgcHJldmVudHMgY3Jvc3MtcnVuIGFjY3VtdWxhdGlvbi4gKi9cbiAgY2xlYXI/KCk6IHZvaWQ7XG4gIC8qKiBFeHBvc2UgY29sbGVjdGVkIGRhdGEgZm9yIGluY2x1c2lvbiBpbiBleGVjdXRvci5nZXRTbmFwc2hvdCgpLnJlY29yZGVycy4gKi9cbiAgdG9TbmFwc2hvdD8oKTogeyBuYW1lOiBzdHJpbmc7IGRhdGE6IHVua25vd24gfTtcbn1cbiJdfQ==
@@ -26,9 +26,20 @@ export declare function createTypedScopeFactory<T extends object>(): ScopeFactor
26
26
  /**
27
27
  * Convenience builder for typed pipelines.
28
28
  *
29
- * Usage:
30
- * const chart = typedFlowChart<LoanState>('Intake', intakeFn, 'intake')
31
- * .addFunction('Process', processFn, 'process')
32
- * .build();
29
+ * @deprecated Use {@link flowChart} instead. `flowChart<T>(name, fn, id)` is identical
30
+ * to `typedFlowChart<T>(name, fn, id)` and auto-embeds the TypedScope factory at build time.
31
+ * `typedFlowChart` will be removed in a future major version.
32
+ * No changes to executor construction are required — `build()` now embeds the scope factory automatically.
33
+ *
34
+ * Migration:
35
+ * ```typescript
36
+ * // Before:
37
+ * import { typedFlowChart } from 'footprintjs/advanced';
38
+ * const chart = typedFlowChart<LoanState>('Intake', fn, 'intake').build();
39
+ *
40
+ * // After:
41
+ * import { flowChart } from 'footprintjs';
42
+ * const chart = flowChart<LoanState>('Intake', fn, 'intake').build();
43
+ * ```
33
44
  */
34
45
  export declare function typedFlowChart<T extends object>(name: string, fn: TypedStageFunction<T>, id: string, buildTimeExtractor?: BuildTimeExtractor<any>, description?: string): FlowChartBuilder<any, TypedScope<T>>;
@@ -19,7 +19,7 @@ export type { ScopeProtectionMode };
19
19
  export interface SerializedPipelineStructure {
20
20
  name: string;
21
21
  id?: string;
22
- type: 'stage' | 'decider' | 'fork' | 'streaming';
22
+ type: 'stage' | 'decider' | 'selector' | 'fork' | 'streaming';
23
23
  /** Semantic icon hint for visualization (e.g., "llm", "tool", "rag", "agent", "start") */
24
24
  icon?: string;
25
25
  description?: string;
@@ -36,6 +36,13 @@ export interface SerializedPipelineStructure {
36
36
  isSubflowRoot?: boolean;
37
37
  subflowId?: string;
38
38
  subflowName?: string;
39
+ /**
40
+ * Nested pipeline structure for a subflow node.
41
+ * WARNING: Any future walker that traverses this field recursively must apply its own
42
+ * depth guard (see MAX_WALK_DEPTH in contract/openapi.ts). The current `buildDescription`
43
+ * walk in openapi.ts does NOT traverse subflowStructure — if it ever does, the depth
44
+ * guard must cover both the `next` chain and this nested structure.
45
+ */
39
46
  subflowStructure?: SerializedPipelineStructure;
40
47
  iterationCount?: number;
41
48
  /** True when this subflow uses lazy resolution (deferred until execution). */
@@ -44,6 +51,8 @@ export interface SerializedPipelineStructure {
44
51
  export interface FlowChartSpec {
45
52
  name: string;
46
53
  id?: string;
54
+ /** Node type — matches `SerializedPipelineStructure.type` for visualization alignment. */
55
+ type?: 'stage' | 'decider' | 'selector' | 'fork' | 'streaming';
47
56
  /** Semantic icon hint for visualization (e.g., "llm", "tool", "rag", "agent", "start") */
48
57
  icon?: string;
49
58
  description?: string;
@@ -2,11 +2,17 @@
2
2
  * contract/openapi.ts — OpenAPI 3.1 spec generator.
3
3
  *
4
4
  * Generates an OpenAPI spec from a FlowChartContract by combining:
5
- * - chart.description → operation description
6
- * - chart.stageDescriptions → step-by-step detail
5
+ * - chart.description → operation description (built incrementally during FlowChartBuilder.build())
7
6
  * - inputSchema → requestBody
8
7
  * - outputSchema → response
9
- * - chart.buildTimeStructure → operation metadata (branches, forks, etc.)
8
+ *
9
+ * chart.description is assembled by FlowChartBuilder as each stage is added —
10
+ * no post-processing walk of buildTimeStructure is needed or performed here.
10
11
  */
11
12
  import type { FlowChartContract, OpenAPIOptions, OpenAPISpec } from './types.js';
13
+ /**
14
+ * Generates an OpenAPI 3.1 spec from a FlowChartContract.
15
+ * Uses `chart.description` which FlowChartBuilder assembles at build time —
16
+ * no post-processing walk of buildTimeStructure is performed here.
17
+ */
12
18
  export declare function generateOpenAPI(contract: FlowChartContract, options?: OpenAPIOptions): OpenAPISpec;
@@ -36,7 +36,18 @@ export interface FlowChartContractOptions<_TInput = unknown, TOutput = unknown>
36
36
  outputMapper?: (finalScope: Record<string, unknown>) => TOutput;
37
37
  }
38
38
  export interface FlowChartContract<_TInput = unknown, TOutput = unknown> {
39
- /** The compiled flowchart. */
39
+ /**
40
+ * Prototype-linked view of the original compiled FlowChart.
41
+ *
42
+ * Own properties (inputSchema, outputSchema, outputMapper) are shadowed here
43
+ * so that the contract's values take precedence over builder-set values.
44
+ * All other fields (root, stageMap, methods) are inherited via the prototype
45
+ * chain with zero copying. The original chart is never mutated.
46
+ *
47
+ * ⚠️ Do NOT use Object.keys(), spread ({...chart}), or JSON.stringify() on
48
+ * this object — it will only see own (shadowed) properties. Use named
49
+ * property access or chart.toSpec() instead.
50
+ */
40
51
  chart: FlowChart;
41
52
  /** JSON Schema for the input (normalized from Zod or raw). */
42
53
  inputSchema?: JsonSchema;
@@ -44,7 +55,7 @@ export interface FlowChartContract<_TInput = unknown, TOutput = unknown> {
44
55
  outputSchema?: JsonSchema;
45
56
  /** Maps the final scope state into the response shape. */
46
57
  outputMapper?: (finalScope: Record<string, unknown>) => TOutput;
47
- /** Auto-generated OpenAPI spec. */
58
+ /** Auto-generated OpenAPI spec. Description is read from `chart.description` (pre-built at build time). */
48
59
  toOpenAPI(options?: OpenAPIOptions): OpenAPISpec;
49
60
  }
50
61
  export interface OpenAPIOptions {
@@ -15,6 +15,11 @@ import type { DecideRule, DecisionResult, SelectionResult } from './types.js';
15
15
  * @param scope - TypedScope or ScopeFacade
16
16
  * @param rules - Array of DecideRule (function or filter when clauses)
17
17
  * @param defaultBranch - Branch ID if no rule matches
18
+ *
19
+ * **Error behavior:** If a `when` function throws during evaluation, the rule is
20
+ * treated as non-matching (`matched: false`) and the error message is captured in
21
+ * `matchError` on that rule's `RuleEvidence` entry. Execution continues with
22
+ * subsequent rules; errors do not propagate to the caller.
18
23
  */
19
24
  export declare function decide<S extends object>(scope: S, rules: DecideRule<S>[], defaultBranch: string): DecisionResult;
20
25
  /**
@@ -22,5 +27,10 @@ export declare function decide<S extends object>(scope: S, rules: DecideRule<S>[
22
27
  *
23
28
  * @param scope - TypedScope or ScopeFacade
24
29
  * @param rules - Array of DecideRule (function or filter when clauses)
30
+ *
31
+ * **Error behavior:** If a `when` function throws during evaluation, the rule is
32
+ * treated as non-matching (`matched: false`) and the error message is captured in
33
+ * `matchError` on that rule's `RuleEvidence` entry. Evaluation continues with
34
+ * remaining rules; errors do not propagate to the caller.
25
35
  */
26
36
  export declare function select<S extends object>(scope: S, rules: DecideRule<S>[]): SelectionResult;
@@ -53,6 +53,16 @@ export interface FunctionRuleEvidence {
53
53
  matched: boolean;
54
54
  label?: string;
55
55
  inputs: ReadInput[];
56
+ /**
57
+ * Error message if the `when` function threw during evaluation.
58
+ * Present only when an exception occurred; `matched` is `false` in that case.
59
+ * Surfaces the error for debugging rather than swallowing it silently.
60
+ *
61
+ * **Security note:** Error messages from user-provided `when` functions are captured
62
+ * as-is and are NOT filtered through the redaction policy. Avoid including sensitive
63
+ * scope values in thrown error messages.
64
+ */
65
+ matchError?: string;
56
66
  }
57
67
  export interface FilterRuleEvidence {
58
68
  type: 'filter';
@@ -62,6 +72,16 @@ export interface FilterRuleEvidence {
62
72
  matched: boolean;
63
73
  label?: string;
64
74
  conditions: FilterCondition[];
75
+ /**
76
+ * Error message if the filter evaluator threw during evaluation.
77
+ * Present only when an exception occurred; `matched` is `false` in that case.
78
+ * Surfaces the error for debugging rather than swallowing it silently.
79
+ *
80
+ * **Security note:** Error messages from user-provided `when` functions are captured
81
+ * as-is and are NOT filtered through the redaction policy. Avoid including sensitive
82
+ * scope values in thrown error messages.
83
+ */
84
+ matchError?: string;
65
85
  }
66
86
  export type RuleEvidence = FunctionRuleEvidence | FilterRuleEvidence;
67
87
  export interface ReadInput {
@@ -13,7 +13,7 @@ import type { SerializedPipelineStructure } from '../types.js';
13
13
  * Compute the node type from node properties.
14
14
  * Shared by RuntimeStructureManager (serialization) and ExtractorRunner (metadata).
15
15
  */
16
- export declare function computeNodeType(node: StageNode): 'stage' | 'decider' | 'fork' | 'streaming';
16
+ export declare function computeNodeType(node: StageNode): 'stage' | 'decider' | 'selector' | 'fork' | 'streaming';
17
17
  export declare class RuntimeStructureManager {
18
18
  private runtimePipelineStructure?;
19
19
  private structureNodeMap;
@@ -21,6 +21,7 @@ export declare class RuntimeStructureManager {
21
21
  init(buildTimeStructure?: SerializedPipelineStructure): void;
22
22
  /** Returns the current runtime structure (mutated during execution). */
23
23
  getStructure(): SerializedPipelineStructure | undefined;
24
+ private static readonly MAX_NODE_MAP_DEPTH;
24
25
  /** Recursively registers all nodes in the O(1) lookup map. */
25
26
  private buildNodeMap;
26
27
  /** Convert a runtime StageNode into a SerializedPipelineStructure node. */
@@ -45,6 +45,11 @@ export interface TraverserOptions<TOut = any, TScope = any> {
45
45
  signal?: AbortSignal;
46
46
  /** Pre-configured FlowRecorders to attach when narrative is enabled. */
47
47
  flowRecorders?: FlowRecorder[];
48
+ /**
49
+ * Maximum recursive executeNode depth. Defaults to FlowchartTraverser.MAX_EXECUTE_DEPTH (500).
50
+ * Override in tests or unusually deep pipelines.
51
+ */
52
+ maxDepth?: number;
48
53
  }
49
54
  export declare class FlowchartTraverser<TOut = any, TScope = any> {
50
55
  private readonly root;
@@ -65,6 +70,42 @@ export declare class FlowchartTraverser<TOut = any, TScope = any> {
65
70
  private readonly narrativeGenerator;
66
71
  private readonly flowRecorderDispatcher;
67
72
  private subflowResults;
73
+ /**
74
+ * Per-traverser set of lazy subflow IDs that have been resolved by THIS run.
75
+ * Used instead of writing `node.subflowResolver = undefined` back to the shared
76
+ * StageNode graph — avoids a race where a concurrent traverser clears the shared
77
+ * resolver before another traverser has finished using it.
78
+ */
79
+ private readonly resolvedLazySubflows;
80
+ /**
81
+ * Recursion depth counter for executeNode.
82
+ * Each recursive executeNode call increments this; decrements on exit (try/finally).
83
+ * Prevents call-stack overflow on infinite loops or excessively deep stage chains.
84
+ */
85
+ private _executeDepth;
86
+ /**
87
+ * Per-instance maximum depth (set from TraverserOptions.maxDepth or the class default).
88
+ */
89
+ private readonly _maxDepth;
90
+ /**
91
+ * Default maximum recursive executeNode depth before an error is thrown.
92
+ * 500 comfortably covers any realistic pipeline depth (including deeply nested
93
+ * subflows) while preventing call-stack overflow (~10 000 frames in V8).
94
+ *
95
+ * **Note on counting:** the counter increments once per `executeNode` call, not once per
96
+ * logical user stage. Subflow root entry and subflow continuation after return each cost
97
+ * one tick. For pipelines with many nested subflows, budget roughly 2 × (avg stages per
98
+ * subflow) of headroom when computing a custom `maxDepth` via `RunOptions.maxDepth`.
99
+ *
100
+ * **Note on loops:** for `loopTo()` pipelines, this depth guard and `ContinuationResolver`'s
101
+ * iteration limit are independent — the lower one fires first. The default depth guard (500)
102
+ * fires before the default iteration limit (1000) for loop-heavy pipelines.
103
+ *
104
+ * @remarks Not safe for concurrent `.execute()` calls on the same instance — concurrent
105
+ * executions race on `_executeDepth`. Use a separate `FlowchartTraverser` per concurrent
106
+ * execution. `FlowChartExecutor.run()` always creates a fresh traverser per call.
107
+ */
108
+ static readonly MAX_EXECUTE_DEPTH = 500;
68
109
  constructor(opts: TraverserOptions<TOut, TScope>);
69
110
  private createDeps;
70
111
  execute(): Promise<TraversalResult>;
@@ -76,6 +117,12 @@ export declare class FlowchartTraverser<TOut = any, TScope = any> {
76
117
  subflowResults?: Record<string, unknown> | undefined;
77
118
  recorders?: {
78
119
  id: string;
120
+ /**
121
+ * Per-traverser set of lazy subflow IDs that have been resolved by THIS run.
122
+ * Used instead of writing `node.subflowResolver = undefined` back to the shared
123
+ * StageNode graph — avoids a race where a concurrent traverser clears the shared
124
+ * resolver before another traverser has finished using it.
125
+ */
79
126
  name: string;
80
127
  data: unknown;
81
128
  }[] | undefined;
@@ -144,10 +144,17 @@ export interface RunOptions {
144
144
  * Accessible via `scope.getEnv()`. Inherited by subflows automatically.
145
145
  */
146
146
  env?: ExecutionEnv;
147
+ /**
148
+ * Override the maximum recursive `executeNode` depth for this run.
149
+ * Defaults to `FlowchartTraverser.MAX_EXECUTE_DEPTH` (500).
150
+ * Useful when deeply nested subflows or long chains need more headroom.
151
+ * Must be >= 1.
152
+ */
153
+ maxDepth?: number;
147
154
  }
148
155
  export type { FlowControlType, FlowMessage };
149
156
  export interface RuntimeStructureMetadata {
150
- type: 'stage' | 'decider' | 'fork' | 'streaming';
157
+ type: 'stage' | 'decider' | 'selector' | 'fork' | 'streaming';
151
158
  subflowId?: string;
152
159
  isSubflowRoot?: boolean;
153
160
  subflowName?: string;
@@ -200,7 +207,7 @@ export type TraversalResult = BranchResults | string | Error;
200
207
  export interface SerializedPipelineNode {
201
208
  name: string;
202
209
  id?: string;
203
- type?: 'stage' | 'decider' | 'fork' | 'streaming' | 'loop' | 'user' | 'tool' | 'function' | 'sequence';
210
+ type?: 'stage' | 'decider' | 'selector' | 'fork' | 'streaming' | 'loop' | 'user' | 'tool' | 'function' | 'sequence';
204
211
  description?: string;
205
212
  children?: SerializedPipelineNode[];
206
213
  next?: SerializedPipelineNode;
@@ -53,10 +53,22 @@ export declare class StageContext {
53
53
  appendToArray(path: string[], key: string, items: unknown[], description?: string): void;
54
54
  mergeObject(path: string[], key: string, obj: Record<string, unknown>, description?: string): void;
55
55
  getValue(path: string[], key?: string, description?: string): any;
56
+ /**
57
+ * @deprecated since v3.1.0 — use {@link getValue} instead. Will be removed in v4.0.0.
58
+ * This alias exists for backward compatibility only.
59
+ */
56
60
  get(path: string[], key?: string): any;
57
61
  getRoot(key: string): any;
58
62
  getGlobal(key: string): any;
63
+ /**
64
+ * @deprecated since v3.1.0 — use {@link getRoot} instead. Will be removed in v4.0.0.
65
+ * This alias exists for backward compatibility only.
66
+ */
59
67
  getFromRoot(key: string): any;
68
+ /**
69
+ * @deprecated since v3.1.0 — use {@link getGlobal} instead. Will be removed in v4.0.0.
70
+ * This alias exists for backward compatibility only.
71
+ */
60
72
  getFromGlobalContext(key: string): any;
61
73
  getScope(): Record<string, unknown>;
62
74
  getRunId(): string;
@@ -1,10 +1,34 @@
1
1
  /**
2
2
  * pathOps.ts — Native nested-path helpers (replaces lodash.get/set/has/mergewith)
3
3
  *
4
- * All functions guard against prototype-pollution attacks.
4
+ * Security contract: all functions guard against prototype-pollution and
5
+ * prototype-chain-read attacks. The DENIED set blocks the three canonical
6
+ * pollution vectors (__proto__, constructor, prototype) on every function.
7
+ *
8
+ * Intentional asymmetry:
9
+ * - nativeSet — DENIED check only at each segment. No hasOwnProperty
10
+ * check is needed because writing always creates an OWN property on `curr`,
11
+ * which cannot pollute the prototype chain.
12
+ * - nativeGet / nativeHas — DENIED check + hasOwnProperty at every step.
13
+ * Reads follow the prototype chain by default (bracket notation), so the
14
+ * hasOwnProperty guard is required to prevent leaking inherited values
15
+ * (e.g. Object.prototype, Object constructor, toString).
16
+ * - mergeContextWins — DENIED check only; Object.keys() is own-enumerable-only
17
+ * by spec so prototype keys never appear in the iteration.
18
+ *
19
+ * Do NOT "fix" the nativeSet asymmetry by adding hasOwnProperty — it is
20
+ * intentional and would break path creation for new intermediate nodes.
21
+ *
5
22
  * Paths may be dot-notation strings or pre-split (string|number)[] arrays.
6
23
  */
7
- /** Get the value at `path` in `obj`, returning `defaultValue` if absent. */
24
+ /**
25
+ * Get the value at `path` in `obj`, returning `defaultValue` if absent.
26
+ *
27
+ * Security: each path segment is checked against the DENIED list and requires
28
+ * an own property at every step, preventing prototype-chain reads.
29
+ * e.g. nativeGet({}, '__proto__') and nativeGet({}, 'constructor') both return
30
+ * `defaultValue` instead of leaking Object.prototype / the Object constructor.
31
+ */
8
32
  export declare function nativeGet(obj: any, path: string | (string | number)[], defaultValue?: any): any;
9
33
  /** Mutate `obj`, setting `value` at `path` (creates intermediate objects). Returns `obj`. */
10
34
  export declare function nativeSet(obj: any, path: string | (string | number)[], value: any): any;
@@ -31,9 +31,18 @@ export declare function setNestedValue<T>(obj: NestedObject, runId: string, _pat
31
31
  export declare function updateNestedValue<T>(obj: any, runId: string | undefined, _path: (string | number)[], field: string | number, value: T, defaultValues?: unknown): any;
32
32
  /**
33
33
  * In-place value update with merge semantics.
34
- * - Arrays: concatenate
35
- * - Objects: shallow merge (spread)
34
+ * - Arrays (non-empty): concatenate onto existing
35
+ * - Arrays (empty): direct replace writing `[]` clears the field
36
+ * - Objects (non-empty): shallow merge (spread)
37
+ * - Objects (empty): direct replace — writing `{}` clears the field
36
38
  * - Primitives: direct assignment
39
+ *
40
+ * Note on empty arrays: both `value && Array.isArray(value)` and
41
+ * `Array.isArray(value)` evaluate the same for arrays — `[]` is truthy in
42
+ * JavaScript, so the `&&` guard was never the issue. The actual bug was the
43
+ * concat path: `[...cur, ...[]]` silently returned `cur` unchanged when `value`
44
+ * was `[]`, making `updateValue(obj, 'tags', [])` a no-op instead of a clear.
45
+ * The fix is the explicit `value.length === 0` early-return branch.
37
46
  */
38
47
  export declare function updateValue(object: any, key: string | number, value: any): void;
39
48
  /**
@@ -50,7 +59,11 @@ export declare function redactPatch(patch: MemoryPatch, redactedSet: Set<string>
50
59
  export declare function normalisePath(path: (string | number)[]): string;
51
60
  /**
52
61
  * Deep union merge helper.
53
- * - Arrays: union without duplicates (encounter order preserved)
62
+ * - Arrays (non-empty): union without duplicates (encounter order preserved)
63
+ * - Arrays (empty): replace — src `[]` clears the destination array.
64
+ * Rationale: writing `scope.tags = []` means "clear tags", not "append nothing".
65
+ * Without this rule, an empty-array write silently becomes a no-op which is
66
+ * impossible to distinguish from a bug.
54
67
  * - Objects: recursive merge
55
68
  * - Primitives: source wins
56
69
  */
@@ -3,8 +3,14 @@
3
3
  *
4
4
  * Wraps FlowchartTraverser. Pairs with FlowChartBuilder:
5
5
  * const chart = flowChart('entry', entryFn).addFunction('process', processFn).build();
6
- * const executor = new FlowChartExecutor(chart); // uses default ScopeFacade
7
- * const executor = new FlowChartExecutor(chart, myFactory); // custom scope factory
6
+ *
7
+ * // Recommended options object form:
8
+ * const executor = new FlowChartExecutor(chart);
9
+ * const executor = new FlowChartExecutor(chart, { scopeFactory: myFactory, enrichSnapshots: true });
10
+ *
11
+ * // Legacy — positional params 3-9 are deprecated; pass an options object instead:
12
+ * const executor = new FlowChartExecutor(chart, myFactory); // still supported
13
+ *
8
14
  * const result = await executor.run();
9
15
  */
10
16
  import type { CombinedNarrativeEntry } from '../engine/narrative/CombinedNarrativeBuilder.js';
@@ -14,6 +20,54 @@ import { type ExtractorError, type FlowChart, type RunOptions, type ScopeFactory
14
20
  import type { ScopeProtectionMode } from '../scope/protection/types.js';
15
21
  import type { Recorder, RedactionPolicy, RedactionReport } from '../scope/types.js';
16
22
  import { type RuntimeSnapshot } from './ExecutionRuntime.js';
23
+ /**
24
+ * Options object for `FlowChartExecutor` — preferred over positional params.
25
+ *
26
+ * ```typescript
27
+ * const ex = new FlowChartExecutor(chart, {
28
+ * scopeFactory: myFactory,
29
+ * enrichSnapshots: true,
30
+ * });
31
+ * ```
32
+ *
33
+ * **Sync note for maintainers:** Every field added here must also appear in the
34
+ * `flowChartArgs` private field type and in the constructor's options-resolution
35
+ * block (the `else if` branch that reads from `opts`). Missing any one of the
36
+ * three causes silent omission — the option is accepted but never applied.
37
+ *
38
+ * **TScope inference note:** When using the options-object form with a custom scope,
39
+ * TypeScript cannot infer `TScope` through the options object. Pass the type
40
+ * explicitly: `new FlowChartExecutor<TOut, MyScope>(chart, { scopeFactory })`.
41
+ */
42
+ export interface FlowChartExecutorOptions<TScope = any> {
43
+ /** Custom scope factory. Defaults to TypedScope or ScopeFacade auto-detection. */
44
+ scopeFactory?: ScopeFactory<TScope>;
45
+ /** Whether to enrich snapshots with scope state (enables `getSnapshot()`). */
46
+ enrichSnapshots?: boolean;
47
+ /**
48
+ * Default values pre-populated into the shared context before **each** stage
49
+ * (re-applied every stage, acting as baseline defaults).
50
+ */
51
+ defaultValuesForContext?: unknown;
52
+ /**
53
+ * Initial context values merged into the shared context **once** at startup
54
+ * (applied before the first stage, not repeated on subsequent stages).
55
+ * Distinct from `defaultValuesForContext`, which is re-applied every stage.
56
+ */
57
+ initialContext?: unknown;
58
+ /** Read-only input accessible via `scope.getArgs()` — never tracked or written. */
59
+ readOnlyContext?: unknown;
60
+ /**
61
+ * Custom error classifier for throttling detection. Return `true` if the
62
+ * error represents a rate-limit or backpressure condition (the executor will
63
+ * treat it differently from hard failures). Defaults to no throttling classification.
64
+ */
65
+ throttlingErrorChecker?: (error: unknown) => boolean;
66
+ /** Handlers for streaming stage lifecycle events (see `addStreamingFunction`). */
67
+ streamHandlers?: StreamHandlers;
68
+ /** Scope protection mode for TypedScope direct-assignment detection. */
69
+ scopeProtectionMode?: ScopeProtectionMode;
70
+ }
17
71
  export declare class FlowChartExecutor<TOut = any, TScope = any> {
18
72
  private traverser;
19
73
  private narrativeEnabled;
@@ -24,7 +78,48 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
24
78
  private sharedRedactedKeys;
25
79
  private sharedRedactedFieldsByKey;
26
80
  private readonly flowChartArgs;
27
- constructor(flowChart: FlowChart<TOut, TScope>, scopeFactory?: ScopeFactory<TScope>, defaultValuesForContext?: unknown, initialContext?: unknown, readOnlyContext?: unknown, throttlingErrorChecker?: (error: unknown) => boolean, streamHandlers?: StreamHandlers, scopeProtectionMode?: ScopeProtectionMode, enrichSnapshots?: boolean);
81
+ /**
82
+ * Create a FlowChartExecutor.
83
+ *
84
+ * **Preferred form** (options object — avoids positional parameter confusion):
85
+ * ```typescript
86
+ * new FlowChartExecutor(chart, { scopeFactory, enrichSnapshots: true })
87
+ * ```
88
+ *
89
+ * **Backward-compatible positional form** (params 3–9 deprecated — use options object):
90
+ * ```typescript
91
+ * new FlowChartExecutor(chart, scopeFactory) // fine — 2 params
92
+ * new FlowChartExecutor(chart, factory, defaultValues, ...) // deprecated: use options object
93
+ * ```
94
+ *
95
+ * @param flowChart - The compiled FlowChart returned by `flowChart(...).build()`
96
+ * @param factoryOrOptions - A `ScopeFactory<TScope>` (still supported — NOT deprecated) OR a
97
+ * `FlowChartExecutorOptions<TScope>` options object (preferred for 3+ settings).
98
+ * Passing `(chart, scopeFactory)` — the 2-param form — is fine and will not be removed.
99
+ * Only params 3–9 are deprecated.
100
+ * @param defaultValuesForContext - @deprecated Pass via `options.defaultValuesForContext` instead.
101
+ * @param initialContext - @deprecated Pass via `options.initialContext` instead.
102
+ * @param readOnlyContext - @deprecated Pass via `options.readOnlyContext` instead.
103
+ * @param throttlingErrorChecker - @deprecated Pass via `options.throttlingErrorChecker` instead.
104
+ * @param streamHandlers - @deprecated Pass via `options.streamHandlers` instead.
105
+ * @param scopeProtectionMode - @deprecated Pass via `options.scopeProtectionMode` instead.
106
+ * @param enrichSnapshots - @deprecated Pass via `options.enrichSnapshots` instead.
107
+ */
108
+ constructor(flowChart: FlowChart<TOut, TScope>, factoryOrOptions?: ScopeFactory<TScope> | FlowChartExecutorOptions<TScope>,
109
+ /** @deprecated Use {@link FlowChartExecutorOptions} instead. */
110
+ defaultValuesForContext?: unknown,
111
+ /** @deprecated Use {@link FlowChartExecutorOptions} instead. */
112
+ initialContext?: unknown,
113
+ /** @deprecated Use {@link FlowChartExecutorOptions} instead. */
114
+ readOnlyContext?: unknown,
115
+ /** @deprecated Use {@link FlowChartExecutorOptions} instead. */
116
+ throttlingErrorChecker?: (error: unknown) => boolean,
117
+ /** @deprecated Use {@link FlowChartExecutorOptions} instead. */
118
+ streamHandlers?: StreamHandlers,
119
+ /** @deprecated Use {@link FlowChartExecutorOptions} instead. */
120
+ scopeProtectionMode?: ScopeProtectionMode,
121
+ /** @deprecated Use {@link FlowChartExecutorOptions} instead. */
122
+ enrichSnapshots?: boolean);
28
123
  private createTraverser;
29
124
  enableNarrative(): void;
30
125
  /**
@@ -1,6 +1,7 @@
1
1
  export type { ComposableRunner } from './ComposableRunner.js';
2
2
  export type { NarrativeEntry, RecorderSnapshot, RuntimeSnapshot } from './ExecutionRuntime.js';
3
3
  export { ExecutionRuntime } from './ExecutionRuntime.js';
4
+ export type { FlowChartExecutorOptions } from './FlowChartExecutor.js';
4
5
  export { FlowChartExecutor } from './FlowChartExecutor.js';
5
6
  export type { SubtreeSnapshot } from './getSubtreeSnapshot.js';
6
7
  export { getSubtreeSnapshot, listSubflowPaths } from './getSubtreeSnapshot.js';
@@ -111,8 +111,25 @@ export declare class ScopeFacade {
111
111
  getPipelineId(): string;
112
112
  /** Checks if a key is redacted (explicit _redactedKeys set). */
113
113
  private _isKeyRedacted;
114
- /** Checks if a key should be auto-redacted by the policy (exact keys + patterns). */
114
+ /**
115
+ * Checks if a key should be auto-redacted by the policy (exact keys + patterns).
116
+ *
117
+ * ReDoS guard: pattern testing is capped at MAX_PATTERN_KEY_LEN characters.
118
+ * Scope state keys are always short identifiers; any key exceeding the cap
119
+ * is almost certainly not a legitimate scope key, so skipping pattern matching
120
+ * for it does not risk leaking PII. Exact-key matching (Array.includes) is
121
+ * still applied regardless of length and is not vulnerable to ReDoS.
122
+ */
115
123
  private _isPolicyRedacted;
124
+ /**
125
+ * Maximum key length (characters) that will be tested against regex redaction
126
+ * patterns. Keys longer than this are skipped for pattern matching to prevent
127
+ * ReDoS: a pathological regex tested against an unboundedly long key string
128
+ * can cause catastrophic backtracking.
129
+ *
130
+ * 256 characters comfortably exceeds any realistic scope-state key name.
131
+ */
132
+ private static readonly _MAX_PATTERN_KEY_LEN;
116
133
  /**
117
134
  * Returns a deep-cloned copy with specified fields replaced by '[REDACTED]'.
118
135
  * Supports dot-notation paths (e.g. 'address.zip') for nested objects.
@@ -11,6 +11,12 @@ export interface StageContextLike {
11
11
  updateObject(path: string[], key: string, value: unknown, description?: string): void;
12
12
  addLog?(key: string, val: unknown): void;
13
13
  addError?(key: string, val: unknown): void;
14
+ getGlobal?(key: string): unknown;
15
+ /**
16
+ * @deprecated since v3.1.0 — use {@link getGlobal} instead. Will be removed in v4.0.0.
17
+ * Internal callers no longer invoke this method — implementors of `StageContextLike`
18
+ * must provide `getGlobal?` (not just `getFromGlobalContext?`) for `getInitialValueFor` to work.
19
+ */
14
20
  getFromGlobalContext?(key: string): unknown;
15
21
  setRoot?(key: string, value: unknown): void;
16
22
  setGlobal?(key: string, value: unknown, description?: string): void;
@@ -47,7 +47,13 @@ export interface StageEvent extends RecorderContext {
47
47
  export interface RedactionPolicy {
48
48
  /** Exact key names to always redact (e.g. ['ssn', 'creditCard']). */
49
49
  keys?: string[];
50
- /** Regex patterns — any key matching a pattern is auto-redacted. */
50
+ /**
51
+ * Regex patterns — any key matching a pattern is auto-redacted.
52
+ *
53
+ * Pattern matching is skipped for keys that exceed an internal length cap
54
+ * (designed to prevent ReDoS on pathological patterns). For very long key
55
+ * names, use `keys` (exact match) instead of patterns.
56
+ */
51
57
  patterns?: RegExp[];
52
58
  /** Field-level redaction within objects — key → array of fields to scrub.
53
59
  * Supports dot-notation for nested paths (e.g. 'address.zip'). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "footprintjs",
3
- "version": "3.0.21",
3
+ "version": "3.1.0",
4
4
  "description": "Explainable backend flows — automatic causal traces, decision evidence, and MCP tool generation for AI agents",
5
5
  "license": "MIT",
6
6
  "author": "Sanjay Krishna Anbalagan",