foottrace 0.0.0-stage → 1.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.
Files changed (196) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +73 -2
  3. package/dist/esm/index.d.ts +27 -0
  4. package/dist/esm/index.js +12 -0
  5. package/dist/esm/lib/capture/freeze.d.ts +91 -0
  6. package/dist/esm/lib/capture/freeze.js +313 -0
  7. package/dist/esm/lib/capture/ownData.d.ts +18 -0
  8. package/dist/esm/lib/capture/ownData.js +35 -0
  9. package/dist/esm/lib/capture/valueKinds.d.ts +57 -0
  10. package/dist/esm/lib/capture/valueKinds.js +141 -0
  11. package/dist/esm/lib/ids/runtimeStageId.d.ts +173 -0
  12. package/dist/esm/lib/ids/runtimeStageId.js +193 -0
  13. package/dist/esm/lib/memory/EventLog.d.ts +105 -0
  14. package/dist/esm/lib/memory/EventLog.js +147 -0
  15. package/dist/esm/lib/memory/RecordFrame.d.ts +232 -0
  16. package/dist/esm/lib/memory/RecordFrame.js +295 -0
  17. package/dist/esm/lib/memory/SharedMemory.d.ts +46 -0
  18. package/dist/esm/lib/memory/SharedMemory.js +87 -0
  19. package/dist/esm/lib/memory/TransactionBuffer.d.ts +521 -0
  20. package/dist/esm/lib/memory/TransactionBuffer.js +946 -0
  21. package/dist/esm/lib/memory/admission.d.ts +81 -0
  22. package/dist/esm/lib/memory/admission.js +152 -0
  23. package/dist/esm/lib/memory/backtrack.d.ts +286 -0
  24. package/dist/esm/lib/memory/backtrack.js +456 -0
  25. package/dist/esm/lib/memory/commitLogUtils.d.ts +217 -0
  26. package/dist/esm/lib/memory/commitLogUtils.js +383 -0
  27. package/dist/esm/lib/memory/deltaEncoding.d.ts +66 -0
  28. package/dist/esm/lib/memory/deltaEncoding.js +121 -0
  29. package/dist/esm/lib/memory/equality.d.ts +93 -0
  30. package/dist/esm/lib/memory/equality.js +261 -0
  31. package/dist/esm/lib/memory/eventPosition.d.ts +18 -0
  32. package/dist/esm/lib/memory/eventPosition.js +1 -0
  33. package/dist/esm/lib/memory/honesty.d.ts +93 -0
  34. package/dist/esm/lib/memory/honesty.js +91 -0
  35. package/dist/esm/lib/memory/keyPaths.d.ts +125 -0
  36. package/dist/esm/lib/memory/keyPaths.js +226 -0
  37. package/dist/esm/lib/memory/logModel.d.ts +76 -0
  38. package/dist/esm/lib/memory/logModel.js +363 -0
  39. package/dist/esm/lib/memory/merge.d.ts +26 -0
  40. package/dist/esm/lib/memory/merge.js +51 -0
  41. package/dist/esm/lib/memory/pathOps.d.ts +118 -0
  42. package/dist/esm/lib/memory/pathOps.js +292 -0
  43. package/dist/esm/lib/memory/paths.d.ts +56 -0
  44. package/dist/esm/lib/memory/paths.js +60 -0
  45. package/dist/esm/lib/memory/placeholders.d.ts +39 -0
  46. package/dist/esm/lib/memory/placeholders.js +39 -0
  47. package/dist/esm/lib/memory/recordCommit.d.ts +45 -0
  48. package/dist/esm/lib/memory/recordCommit.js +60 -0
  49. package/dist/esm/lib/memory/scrub.d.ts +52 -0
  50. package/dist/esm/lib/memory/scrub.js +72 -0
  51. package/dist/esm/lib/memory/types.d.ts +209 -0
  52. package/dist/esm/lib/memory/types.js +9 -0
  53. package/dist/esm/lib/memory/utils.d.ts +73 -0
  54. package/dist/esm/lib/memory/utils.js +150 -0
  55. package/dist/esm/lib/memory/verbs.d.ts +333 -0
  56. package/dist/esm/lib/memory/verbs.js +426 -0
  57. package/dist/esm/lib/recorder/CommitRangeIndex.d.ts +147 -0
  58. package/dist/esm/lib/recorder/CommitRangeIndex.js +206 -0
  59. package/dist/esm/lib/slice/elementProvenance.d.ts +81 -0
  60. package/dist/esm/lib/slice/elementProvenance.js +189 -0
  61. package/dist/esm/lib/slice/forwardSliceForKey.d.ts +88 -0
  62. package/dist/esm/lib/slice/forwardSliceForKey.js +242 -0
  63. package/dist/esm/lib/slice/index.d.ts +26 -0
  64. package/dist/esm/lib/slice/index.js +25 -0
  65. package/dist/esm/lib/slice/keyIndex.d.ts +137 -0
  66. package/dist/esm/lib/slice/keyIndex.js +292 -0
  67. package/dist/esm/lib/slice/keyTimeline.d.ts +49 -0
  68. package/dist/esm/lib/slice/keyTimeline.js +112 -0
  69. package/dist/esm/lib/slice/keysReadSources.d.ts +51 -0
  70. package/dist/esm/lib/slice/keysReadSources.js +94 -0
  71. package/dist/esm/lib/slice/serialize.d.ts +78 -0
  72. package/dist/esm/lib/slice/serialize.js +277 -0
  73. package/dist/esm/lib/slice/sliceForKey.d.ts +40 -0
  74. package/dist/esm/lib/slice/sliceForKey.js +78 -0
  75. package/dist/esm/lib/slice/types.d.ts +567 -0
  76. package/dist/esm/lib/slice/types.js +24 -0
  77. package/dist/esm/lib/time-travel/axis.d.ts +119 -0
  78. package/dist/esm/lib/time-travel/axis.js +178 -0
  79. package/dist/esm/lib/time-travel/bundles.d.ts +77 -0
  80. package/dist/esm/lib/time-travel/bundles.js +135 -0
  81. package/dist/esm/lib/time-travel/chain.d.ts +93 -0
  82. package/dist/esm/lib/time-travel/chain.js +187 -0
  83. package/dist/esm/lib/time-travel/commitStops.d.ts +55 -0
  84. package/dist/esm/lib/time-travel/commitStops.js +201 -0
  85. package/dist/esm/lib/time-travel/index.d.ts +22 -0
  86. package/dist/esm/lib/time-travel/index.js +20 -0
  87. package/dist/esm/lib/time-travel/stateAt.d.ts +102 -0
  88. package/dist/esm/lib/time-travel/stateAt.js +152 -0
  89. package/dist/esm/lib/time-travel/tagStops.d.ts +72 -0
  90. package/dist/esm/lib/time-travel/tagStops.js +101 -0
  91. package/dist/esm/lib/time-travel/timeTravel.d.ts +70 -0
  92. package/dist/esm/lib/time-travel/timeTravel.js +359 -0
  93. package/dist/esm/lib/time-travel/types.d.ts +470 -0
  94. package/dist/esm/lib/time-travel/types.js +22 -0
  95. package/dist/esm/package.json +1 -0
  96. package/dist/esm/paths.d.ts +4 -0
  97. package/dist/esm/paths.js +4 -0
  98. package/dist/esm/write.d.ts +49 -0
  99. package/dist/esm/write.js +47 -0
  100. package/dist/index.js +67 -0
  101. package/dist/lib/capture/freeze.js +319 -0
  102. package/dist/lib/capture/ownData.js +40 -0
  103. package/dist/lib/capture/valueKinds.js +145 -0
  104. package/dist/lib/ids/runtimeStageId.js +209 -0
  105. package/dist/lib/memory/EventLog.js +151 -0
  106. package/dist/lib/memory/RecordFrame.js +299 -0
  107. package/dist/lib/memory/SharedMemory.js +91 -0
  108. package/dist/lib/memory/TransactionBuffer.js +950 -0
  109. package/dist/lib/memory/admission.js +158 -0
  110. package/dist/lib/memory/backtrack.js +462 -0
  111. package/dist/lib/memory/commitLogUtils.js +398 -0
  112. package/dist/lib/memory/deltaEncoding.js +127 -0
  113. package/dist/lib/memory/equality.js +265 -0
  114. package/dist/lib/memory/eventPosition.js +2 -0
  115. package/dist/lib/memory/honesty.js +94 -0
  116. package/dist/lib/memory/keyPaths.js +242 -0
  117. package/dist/lib/memory/logModel.js +371 -0
  118. package/dist/lib/memory/merge.js +55 -0
  119. package/dist/lib/memory/pathOps.js +308 -0
  120. package/dist/lib/memory/paths.js +66 -0
  121. package/dist/lib/memory/placeholders.js +42 -0
  122. package/dist/lib/memory/recordCommit.js +64 -0
  123. package/dist/lib/memory/scrub.js +77 -0
  124. package/dist/lib/memory/types.js +10 -0
  125. package/dist/lib/memory/utils.js +169 -0
  126. package/dist/lib/memory/verbs.js +443 -0
  127. package/dist/lib/recorder/CommitRangeIndex.js +210 -0
  128. package/dist/lib/slice/elementProvenance.js +194 -0
  129. package/dist/lib/slice/forwardSliceForKey.js +246 -0
  130. package/dist/lib/slice/index.js +42 -0
  131. package/dist/lib/slice/keyIndex.js +312 -0
  132. package/dist/lib/slice/keyTimeline.js +116 -0
  133. package/dist/lib/slice/keysReadSources.js +100 -0
  134. package/dist/lib/slice/serialize.js +285 -0
  135. package/dist/lib/slice/sliceForKey.js +82 -0
  136. package/dist/lib/slice/types.js +25 -0
  137. package/dist/lib/time-travel/axis.js +183 -0
  138. package/dist/lib/time-travel/bundles.js +143 -0
  139. package/dist/lib/time-travel/chain.js +192 -0
  140. package/dist/lib/time-travel/commitStops.js +205 -0
  141. package/dist/lib/time-travel/index.js +31 -0
  142. package/dist/lib/time-travel/stateAt.js +159 -0
  143. package/dist/lib/time-travel/tagStops.js +105 -0
  144. package/dist/lib/time-travel/timeTravel.js +363 -0
  145. package/dist/lib/time-travel/types.js +23 -0
  146. package/dist/paths.js +14 -0
  147. package/dist/types/index.d.ts +27 -0
  148. package/dist/types/lib/capture/freeze.d.ts +91 -0
  149. package/dist/types/lib/capture/ownData.d.ts +18 -0
  150. package/dist/types/lib/capture/valueKinds.d.ts +57 -0
  151. package/dist/types/lib/ids/runtimeStageId.d.ts +173 -0
  152. package/dist/types/lib/memory/EventLog.d.ts +105 -0
  153. package/dist/types/lib/memory/RecordFrame.d.ts +232 -0
  154. package/dist/types/lib/memory/SharedMemory.d.ts +46 -0
  155. package/dist/types/lib/memory/TransactionBuffer.d.ts +521 -0
  156. package/dist/types/lib/memory/admission.d.ts +81 -0
  157. package/dist/types/lib/memory/backtrack.d.ts +286 -0
  158. package/dist/types/lib/memory/commitLogUtils.d.ts +217 -0
  159. package/dist/types/lib/memory/deltaEncoding.d.ts +66 -0
  160. package/dist/types/lib/memory/equality.d.ts +93 -0
  161. package/dist/types/lib/memory/eventPosition.d.ts +18 -0
  162. package/dist/types/lib/memory/honesty.d.ts +93 -0
  163. package/dist/types/lib/memory/keyPaths.d.ts +125 -0
  164. package/dist/types/lib/memory/logModel.d.ts +76 -0
  165. package/dist/types/lib/memory/merge.d.ts +26 -0
  166. package/dist/types/lib/memory/pathOps.d.ts +118 -0
  167. package/dist/types/lib/memory/paths.d.ts +56 -0
  168. package/dist/types/lib/memory/placeholders.d.ts +39 -0
  169. package/dist/types/lib/memory/recordCommit.d.ts +45 -0
  170. package/dist/types/lib/memory/scrub.d.ts +52 -0
  171. package/dist/types/lib/memory/types.d.ts +209 -0
  172. package/dist/types/lib/memory/utils.d.ts +73 -0
  173. package/dist/types/lib/memory/verbs.d.ts +333 -0
  174. package/dist/types/lib/recorder/CommitRangeIndex.d.ts +147 -0
  175. package/dist/types/lib/slice/elementProvenance.d.ts +81 -0
  176. package/dist/types/lib/slice/forwardSliceForKey.d.ts +88 -0
  177. package/dist/types/lib/slice/index.d.ts +26 -0
  178. package/dist/types/lib/slice/keyIndex.d.ts +137 -0
  179. package/dist/types/lib/slice/keyTimeline.d.ts +49 -0
  180. package/dist/types/lib/slice/keysReadSources.d.ts +51 -0
  181. package/dist/types/lib/slice/serialize.d.ts +78 -0
  182. package/dist/types/lib/slice/sliceForKey.d.ts +40 -0
  183. package/dist/types/lib/slice/types.d.ts +567 -0
  184. package/dist/types/lib/time-travel/axis.d.ts +119 -0
  185. package/dist/types/lib/time-travel/bundles.d.ts +77 -0
  186. package/dist/types/lib/time-travel/chain.d.ts +93 -0
  187. package/dist/types/lib/time-travel/commitStops.d.ts +55 -0
  188. package/dist/types/lib/time-travel/index.d.ts +22 -0
  189. package/dist/types/lib/time-travel/stateAt.d.ts +102 -0
  190. package/dist/types/lib/time-travel/tagStops.d.ts +72 -0
  191. package/dist/types/lib/time-travel/timeTravel.d.ts +70 -0
  192. package/dist/types/lib/time-travel/types.d.ts +470 -0
  193. package/dist/types/paths.d.ts +4 -0
  194. package/dist/types/write.d.ts +49 -0
  195. package/dist/write.js +56 -0
  196. package/package.json +48 -4
@@ -0,0 +1,27 @@
1
+ /** Read a recorded execution: replay, time travel, slicing and attribution. */
2
+ export type { CommitIdx, ExecutionCounter, ExecutionIndex, RuntimeStageId } from './lib/ids/runtimeStageId.js';
3
+ export { buildRuntimeStageId, createExecutionCounter, parseRuntimeStageId, splitStageId, } from './lib/ids/runtimeStageId.js';
4
+ export { UnknownVerbError } from './lib/memory/verbs.js';
5
+ export type { CommitBundle, MemoryPatch, TraceEntry } from './lib/memory/types.js';
6
+ export type { ExecutionTree } from './lib/memory/types.js';
7
+ export { applySmartMerge } from './lib/memory/verbs.js';
8
+ export type { ValueBasis, ValueBasisOptions, ValueWithBasis, WriterBasis, WriterWithBasis, } from './lib/memory/commitLogUtils.js';
9
+ export { buildCommitIndex, commitIndexOf, commitValueAt, commitValueAtWithBasis, findCommit, findCommits, findLastWriter, findLastWriterWithBasis, inferLegacyPhases, recordsPhases, } from './lib/memory/commitLogUtils.js';
10
+ export type { CommitPhase } from './lib/memory/types.js';
11
+ export type { AxisRefusal, AxisSplit, BookendedAxis, FoldBasis, FoldedState, FoldSource, LogGap, Mark, Move, MoveRefusal, Stop, StopFilter, StopKind, TimeTravel, TimeTravelOptions, TimeTravelSource, TimeTravelStrategy, } from './lib/time-travel/index.js';
12
+ export { commitStops, commitStopsStrategy, filterStops, isCommitBundle, splitAxis, stateAt, tagStops, timeTravel, } from './lib/time-travel/index.js';
13
+ export type { CausalChainOptions, CausalEdge, CausalNode, ControlDependency, ControlDepLookup, EdgeWeigher, KeysReadLookup, } from './lib/memory/backtrack.js';
14
+ export { causalChain, flattenCausalDAG, formatCausalChain } from './lib/memory/backtrack.js';
15
+ export type { UntrackedSource } from './lib/memory/types.js';
16
+ export type { ArrayProvenance, AttributionBasis, ElementBirth, FedBasis, ForwardEdge, ForwardNode, ForwardRead, ForwardSlice, ForwardSliceJSON, HonestyNote, HonestyNoteCode, KeyMoment, KeysReadSource, KeyTimeline, MissingProvenanceReason, MissingSliceReason, ReadsCoverage, SliceJSON, StateKey, VariableSlice, } from './lib/slice/index.js';
17
+ export type { ForwardSliceForKeyOptions, KeyTimelineOptions, SliceForKeyOptions } from './lib/slice/index.js';
18
+ export { arrayProvenance, elementProvenance, formatForwardSlice, formatSlice, formatTimeline, forwardSliceForKey, forwardSliceToJSON, keysReadFromExecutionTree, keysReadFromMap, keyTimeline, resolveKeysReadSource, sliceForKey, sliceToJSON, } from './lib/slice/index.js';
19
+ export type { HonestyCode } from './lib/memory/honesty.js';
20
+ export { HONESTY_CODES } from './lib/memory/honesty.js';
21
+ export type { RangeEntry, RangeToken } from './lib/recorder/CommitRangeIndex.js';
22
+ export { CommitRangeIndex } from './lib/recorder/CommitRangeIndex.js';
23
+ export type { CommitValuesMode } from './lib/memory/types.js';
24
+ export type { EmitSourcePosition, LogAddress } from './lib/memory/eventPosition.js';
25
+ export { EXECUTION_DELIMITER, PATH_DELIMITER, isExecutionKey, joinPath, pathSegments as idPathSegments, stageIdOf, subflowSegmentsOf, } from './lib/ids/runtimeStageId.js';
26
+ export { deepEqual } from './lib/memory/equality.js';
27
+ export { serveRecord } from './lib/capture/freeze.js';
@@ -0,0 +1,91 @@
1
+ /**
2
+ * freeze.ts — the ONE deep-freeze walk (moved here from `scope/protection/readonlyInput.ts` in F3),
3
+ * and the serve-time law for the commit log (9.44.2).
4
+ *
5
+ * WHY HERE. Saved trees freeze through this walk: the fold base served as
6
+ * `initialState` (`ExecutionRuntime · getFoldBase`), the
7
+ * dev-mode snapshot (`runner/snapshot.ts · servedSnapshot`), every state `stateAt` hands out
8
+ * (`time-travel/stateAt.ts`) and, since F3, every commit bundle (`EventLog · record`). `memory/` must
9
+ * not import `scope/` (that edge closed the memory ⇄ scope ⇄ recorder module cycle F0 removed), so the
10
+ * walk lives in this leaf folder, which imports nothing outside itself. Args use an ownership snapshot
11
+ * instead (`scope/protection/readonlyInput.ts · createFrozenArgs`): never freeze borrowed caller values.
12
+ *
13
+ * FREEZE WHAT CAN BE FROZEN, COPY WHAT CAN'T (9.44.2). `Object.freeze` cannot seal a Date's time, a
14
+ * Map's or Set's entries, a buffer's bytes, a RegExp (`compile()` rewrites a frozen one) or an Error
15
+ * (V8's own `stack` accessor writes through a frozen one). A fresh tree handed to one caller (a `stateAt`
16
+ * state, the dev-mode snapshot) is that caller's own, so freezing it is a guard and nothing more. The
17
+ * COMMIT LOG — each bundle, and the fold base — is served to every reader, so {@link freezeRecord}
18
+ * remembers that a record holds such a value, its first serve maps the containers on the way to each
19
+ * one (its open PATHS), and {@link serveRecord} hands a reader a copy of those paths only: a fresh copy
20
+ * of each such value, fresh frozen containers on the way to it, and every other part shared, frozen, as
21
+ * it is. Until 9.44.2 `snapshot.commitLog[i].overwrite.when.setTime(0)` rewrote every later snapshot,
22
+ * `stateAt`, `commitValueAt`, slice and cursor answer.
23
+ *
24
+ * Every walk here is ITERATIVE (an explicit stack): a record's depth is not bounded by the call stack.
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * import { deepFreeze, freezeRecord, serveRecord } from './freeze.js';
29
+ *
30
+ * const args = deepFreeze({ order: { lines: [{ sku: 'A' }] }, bytes: new Uint8Array([1]) });
31
+ * Object.isFrozen(args.order.lines[0]); // true
32
+ * Object.isFrozen(args.bytes); // false — a typed array cannot be frozen; it is skipped
33
+ *
34
+ * const record = freezeRecord({ when: new Date(0), tags: ['a'] });
35
+ * const served = serveRecord(record);
36
+ * served.when.setTime(5); // changes the reader's copy
37
+ * serveRecord(record).when.getTime(); // 0 — every serve is the record as recorded
38
+ * served.tags === record.tags; // true — the sealed part is shared, not copied
39
+ * serveRecord(freezeRecord({ n: 1 })); // a record freezing sealed whole: served as itself
40
+ * ```
41
+ */
42
+ /**
43
+ * How {@link deepFreeze} walks an ARRAY.
44
+ *
45
+ * - `'every-key'` (the default) — every own property, as for any other object: the index elements
46
+ * AND any expando (`arr.note = { … }`). The dev-mode snapshot relies on this contract.
47
+ * - `'indices'` — the index elements only, so no key string is allocated per element; this is what
48
+ * keeps freezing a 10,000-element commit inside its budget (`bench/element-writes.ts`). An object
49
+ * hung on an array EXPANDO is then left unfrozen, and unseen by {@link serveRecord} — the commit
50
+ * log's named hole (`EventLog · record`; an array expando is out of contract for state).
51
+ */
52
+ export type ArrayWalk = 'every-key' | 'indices';
53
+ /**
54
+ * Freezes `obj` and every object reachable through its own properties, and returns `obj`.
55
+ *
56
+ * - An object that is ALREADY frozen is left as it is, and not descended — 9.32.0's contract, kept:
57
+ * args may hold a caller's frozen object with live parts inside (a class instance a stage calls),
58
+ * and freezing past it would break them. It is also what ends a cycle. The commit log never meets
59
+ * one: its payloads are fresh `structuredClone`s.
60
+ * - ArrayBuffer views (typed arrays, `DataView`) are skipped: `Object.freeze` throws on a non-empty
61
+ * typed array, so a `Uint8Array` in state, args or the fold base used to fail the run or the
62
+ * snapshot here.
63
+ * - What `Object.freeze` cannot reach stays mutable — Map and Set contents, a Date's time, the
64
+ * bytes behind a buffer. A frozen RegExp's `lastIndex` is read-only, so a `/g` or `/y` regex
65
+ * taken from a frozen tree throws when `exec` or `replace` advance it. The commit log goes through
66
+ * {@link freezeRecord} and {@link serveRecord} instead.
67
+ * - Functions are not descended (they are not values the engine stores).
68
+ */
69
+ export declare function deepFreeze<T>(obj: T, arrays?: ArrayWalk): T;
70
+ /**
71
+ * {@link deepFreeze} for a record many readers are SERVED (a commit bundle, the fold base), and two more
72
+ * things on the same walk:
73
+ *
74
+ * - it remembers THAT the record holds a value freezing cannot seal — one flag; the record's first
75
+ * serve maps WHERE (the containers on the way to each such value, its open paths), so the run pays
76
+ * nothing more and {@link serveRecord} copies those paths and nothing else;
77
+ * - a typed array or `DataView` that views a SLICE of a bigger buffer (a Node `Buffer` views its
78
+ * shared pool) is replaced, in the record, by a copy of the bytes it views — the record keeps the
79
+ * view's bytes, never the rest of the buffer (a resizable or shared buffer is kept as it is).
80
+ *
81
+ * A part frozen before is not frozen past (deepFreeze's contract) but is looked through, so a value
82
+ * freezing cannot seal inside it still opens the record. Returns `record`.
83
+ */
84
+ export declare function freezeRecord<T extends object>(record: T, arrays?: ArrayWalk): T;
85
+ /**
86
+ * The record as a reader may hold it — THE serve-time law: a record freezing sealed whole is served as
87
+ * itself (shared, no cost); any other as a copy of its open paths ({@link freezeRecord}): fresh frozen
88
+ * containers down to each value freezing cannot seal, a fresh copy of that value, and every other part
89
+ * shared, frozen, as it is. A copy is served the same way again.
90
+ */
91
+ export declare function serveRecord<T>(record: T): T;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The private L0 owner of own-slot writes. Selector validation belongs to
3
+ * pathOps: payload names (including `__proto__`) are ordinary data here.
4
+ * Neither operation flattens an existing own accessor or changes its flags.
5
+ */
6
+ /**
7
+ * `target[name] = value`, preserving existing own-slot behavior while making
8
+ * a missing inherited name an OWN data property. Payload names such as
9
+ * `__proto__` are data, not setters or selector instructions. Shared by the
10
+ * record-serving and copy-on-write copies; this is not a public helper.
11
+ */
12
+ export declare function putOwn(target: Record<string, unknown>, name: string | number, value: unknown): void;
13
+ /**
14
+ * Nested diagnostic writers require a missing slot to be CREATED, not merely
15
+ * assigned. Keep that contract separate from putOwn: an out-of-range typed
16
+ * array index is an assignment no-op, but cannot be defined as an own slot.
17
+ */
18
+ export declare function setOwnValue(target: Record<string, unknown>, name: string | number, value: unknown): void;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * valueKinds.ts — what KIND of value a record holds: the one classifier.
3
+ *
4
+ * WHY. Committed state is what survives `structuredClone` (an engine invariant), so the values a
5
+ * record holds are the kinds the clone keeps. Two laws need the kind, and both ask here:
6
+ *
7
+ * - what counts as a CHANGE (`memory/equality.ts · deepEqual`): two values are equal when a record
8
+ * holds the same thing for both, compared kind by kind. Until 9.44.2 only Date, Map and Set had a
9
+ * kind; a RegExp, an Error, a boxed number, a buffer, a DataView or a Blob was compared as an
10
+ * object with no own keys — equal to any other of its kind — so replacing one committed no row
11
+ * and live state kept the old value;
12
+ * - what a served record must COPY (`capture/freeze.ts · freezeRecord` / `serveRecord`):
13
+ * `Object.freeze` seals only the kinds whose content is their own properties ({@link SEALABLE}).
14
+ *
15
+ * A leaf: imports nothing (`capture/` is L0, below `memory/`).
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * kindOf(new Date(0)); // 'date'
20
+ * kindOf(new (class Point { x = 1 })()); // 'plain' — its clone is a plain object
21
+ * kindOf(new Blob(['a'])); // 'opaque' — its clone keeps content this library cannot read
22
+ * SEALABLE.date; // false — setTime writes a slot Object.freeze cannot reach
23
+ * ```
24
+ */
25
+ /** Every kind a record can hold. */
26
+ export type ValueKind =
27
+ /** An object the clone keeps as its own enumerable keys — a class instance included. */
28
+ 'plain' | 'array' | 'date' | 'regexp' | 'map' | 'set' | 'error'
29
+ /** A boxed primitive: `new Number(1)`, `new String('a')`, `new Boolean(true)`, `Object(1n)`. */
30
+ | 'boxed'
31
+ /** An `ArrayBuffer` (a `SharedArrayBuffer` too: shared memory is out of contract for state). */
32
+ | 'buffer'
33
+ /** A typed array or a `DataView`. */
34
+ | 'view'
35
+ /** Any other object the clone keeps as itself (a Blob, a File, a `DOMException`): content unread here. */
36
+ | 'opaque';
37
+ /**
38
+ * Does `Object.freeze` seal every part of a value of this kind? True only where the content is the
39
+ * value's own properties (or a slot nothing can write). A `Record`, so a new kind does not compile
40
+ * until it is decided here.
41
+ */
42
+ export declare const SEALABLE: {
43
+ readonly [K in ValueKind]: boolean;
44
+ };
45
+ /**
46
+ * The kind of an object, as a record holds it. A plain object or an array — the bulk of state —
47
+ * costs one `Array.isArray` and one `getPrototypeOf`; a built-in a tag and one brand-checked read.
48
+ * The brand is the value's own slot, so a subclass (a `Map` subclass is a `'map'`, Node's `Buffer` a
49
+ * `'view'`) and a value from another realm land on their kind.
50
+ *
51
+ * Any other object is classified by WHAT ITS CLONE IS, once per prototype: a class instance comes
52
+ * back a plain object (`'plain'`), a fake built-in (`Object.create(Date.prototype)`, or a class whose
53
+ * `Symbol.toStringTag` says `'Date'`) comes back `{}` (`'plain'`), and a host object comes back as
54
+ * itself (`'opaque'`). A prototype whose instance the clone refuses is `'opaque'` — remembered too:
55
+ * it cannot be held, and its commit will refuse it.
56
+ */
57
+ export declare function kindOf(value: object): ValueKind;
@@ -0,0 +1,173 @@
1
+ /**
2
+ * runtimeStageId — unique identifier for each execution step during traversal.
3
+ *
4
+ * Format: [subflowPath/]stageId#executionIndex
5
+ *
6
+ * Components:
7
+ * stageId — stable node ID from the builder ('call-llm', 'seed')
8
+ * executionIndex — monotonic counter incremented per stage execution (0, 1, 2...)
9
+ * subflowPath — optional path for subflow stages ('sf-tools', 'sf-outer/sf-inner')
10
+ *
11
+ * Properties:
12
+ * - Unique within a run (executionIndex never repeats)
13
+ * - Execution-ordered (sort by executionIndex = execution order)
14
+ * - Human-readable ('sf-tools/execute-tool-calls#8')
15
+ * - Parseable (split on '#' for stageId and index, split stageId on '/' for subflow path)
16
+ *
17
+ * Naming-collision warning
18
+ * ────────────────────────
19
+ * The parsed-output `.stageId` field below is the LOCAL form (segment
20
+ * after the last '/'). This is NOT the same as `spec.id` / `node.id`
21
+ * for subflow-nested stages, which carry the FULL prefixed form
22
+ * (`'sf-tools/execute-tool-calls'`). To compare safely, use
23
+ * `splitStageId(spec.id)` to decompose the prefixed form the same
24
+ * way `parseRuntimeStageId` decomposes a runtimeStageId.
25
+ *
26
+ * @example
27
+ * ```
28
+ * buildRuntimeStageId('call-llm', 5) // 'call-llm#5'
29
+ * buildRuntimeStageId('execute-tool-calls', 8, 'sf-tools') // 'sf-tools/execute-tool-calls#8'
30
+ * buildRuntimeStageId('validate', 3, 'sf-outer/sf-inner') // 'sf-outer/sf-inner/validate#3'
31
+ * ```
32
+ *
33
+ * ## The one owner (F7, 9.37.0)
34
+ *
35
+ * This module is the ONE place the grammar is spelled. Every reader asks it —
36
+ * `isExecutionKey`, `stageIdOf`, `subflowPathOf`, `subflowSegmentsOf`,
37
+ * `lastSegmentOf`, `isWithinSubflow` — and every composer joins through
38
+ * `joinPath` / `buildRuntimeStageId`; no other file splits on `#` or `/`.
39
+ * It builds, parses and reads ids, and imports nothing: it is the record's
40
+ * (C6). The delimiters are RESERVED (RFC 3986 §2.2 style): the engine's id
41
+ * doors refuse them in user-authored ids through ONE function,
42
+ * `reservedIds.ts · refuseReservedId`, which reads them here — so
43
+ * last-delimiter parsing is sound by construction rather than by hope. Stores
44
+ * and the prefixer never refuse — they hold runtime ids and prefixed ids,
45
+ * which carry the delimiters on purpose.
46
+ */
47
+ /** Separates subflow path segments from each other and from the stage id. */
48
+ export declare const PATH_DELIMITER = "/";
49
+ /** Separates the (prefixed) stage id from the execution index. */
50
+ export declare const EXECUTION_DELIMITER = "#";
51
+ declare const RUNTIME_STAGE_ID: unique symbol;
52
+ declare const EXECUTION_INDEX: unique symbol;
53
+ declare const COMMIT_IDX: unique symbol;
54
+ /** A `[subflowPath/]stageId#executionIndex` string the grammar produced. Assignable to `string`. */
55
+ export type RuntimeStageId = string & {
56
+ readonly [RUNTIME_STAGE_ID]: true;
57
+ };
58
+ /** The run-global, monotonic position of one stage execution (the `#N`). Assignable to `number`. */
59
+ export type ExecutionIndex = number & {
60
+ readonly [EXECUTION_INDEX]: true;
61
+ };
62
+ /** A bundle's position in a commit log (`bundle.idx`). Assignable to `number`. */
63
+ export type CommitIdx = number & {
64
+ readonly [COMMIT_IDX]: true;
65
+ };
66
+ /**
67
+ * Build a runtimeStageId from its components.
68
+ *
69
+ * Note: The traverser does NOT use the subflowPath parameter — node.id already
70
+ * includes the subflow prefix from the builder. This parameter exists for external
71
+ * consumers constructing IDs from parsed components (round-trip via parseRuntimeStageId).
72
+ */
73
+ export declare function buildRuntimeStageId(stageId: string, executionIndex: number, subflowPath?: string): RuntimeStageId;
74
+ /**
75
+ * Parse a runtimeStageId into its components.
76
+ *
77
+ * IMPORTANT — naming collision: the returned `stageId` is the LOCAL
78
+ * form (the segment between the last '/' and the '#'). This is NOT
79
+ * the same as `spec.id` or `node.id` for subflow-nested stages,
80
+ * which contain the FULL prefixed form.
81
+ *
82
+ * parseRuntimeStageId('sf-tools/execute-tool-calls#8').stageId
83
+ * // → 'execute-tool-calls' (LOCAL)
84
+ *
85
+ * node.id // (post-mount, in a spec that contains subflows)
86
+ * // → 'sf-tools/execute-tool-calls' (FULL prefixed)
87
+ *
88
+ * To compare these two safely, use `splitStageId(node.id)` to get
89
+ * the local form, OR reconstruct the full form via
90
+ * `(subflowPath ? subflowPath + '/' : '') + stageId`.
91
+ */
92
+ export declare function parseRuntimeStageId(runtimeStageId: string): {
93
+ stageId: string;
94
+ executionIndex: ExecutionIndex;
95
+ subflowPath: string | undefined;
96
+ };
97
+ /**
98
+ * Decompose a (possibly prefixed) stage id into its components.
99
+ *
100
+ * Use this when you have an id WITHOUT the `#N` execution suffix and
101
+ * need the local stage name and/or the subflow path. Common sources
102
+ * of such ids:
103
+ * - `spec.id` (post-mount the id includes any subflow prefix)
104
+ * - `CommitBundle.stageId` (post-mount id)
105
+ * - `node.id` from xyflow nodes built off the spec
106
+ * - the segment of `runtimeStageId` BEFORE the `#` (use
107
+ * `parseRuntimeStageId` directly for full runtimeStageId strings)
108
+ *
109
+ * Mirrors the decomposition `parseRuntimeStageId` performs on the
110
+ * stageId portion of a runtimeStageId, so the two helpers stay in
111
+ * lockstep on naming and behavior.
112
+ *
113
+ * @example
114
+ * splitStageId('sf-tools/execute-tool-calls')
115
+ * // → { localStageId: 'execute-tool-calls', subflowPath: 'sf-tools' }
116
+ *
117
+ * splitStageId('execute-tool-calls')
118
+ * // → { localStageId: 'execute-tool-calls', subflowPath: undefined }
119
+ *
120
+ * splitStageId('sf-outer/sf-inner/validate')
121
+ * // → { localStageId: 'validate', subflowPath: 'sf-outer/sf-inner' }
122
+ */
123
+ export declare function splitStageId(prefixedStageId: string): {
124
+ localStageId: string;
125
+ subflowPath: string | undefined;
126
+ };
127
+ /**
128
+ * True when `key` names one EXECUTION (`…#N`) rather than a stage or a subflow
129
+ * path. Its presence alone decides: the delimiter is reserved in every
130
+ * user-authored id (`reservedIds.ts · refuseReservedId`), so only the grammar
131
+ * puts it there.
132
+ *
133
+ * Asked where a map is keyed by both — `subflowResults` is dual-keyed by
134
+ * subflow path AND by mount runtimeStageId.
135
+ */
136
+ export declare function isExecutionKey(key: string): boolean;
137
+ /**
138
+ * The FULL (subflow-prefixed) stage id of a runtimeStageId — everything before
139
+ * the last `#`, i.e. what `node.id` / `CommitBundle.stageId` hold. A string
140
+ * with no `#` is returned whole.
141
+ *
142
+ * @example stageIdOf('sf-tools/execute#8') // 'sf-tools/execute'
143
+ */
144
+ export declare function stageIdOf(runtimeStageId: string): string;
145
+ /** The execution index of a runtimeStageId, or `NaN` when it carries none. */
146
+ export declare function executionIndexOf(runtimeStageId: string): number;
147
+ /**
148
+ * The subflow path a runtimeStageId executes in (`'sf-a/sf-b'`), or
149
+ * `undefined` at the top level. Reads the stage-id part, so it agrees with
150
+ * `splitStageId(stageIdOf(rid)).subflowPath`.
151
+ */
152
+ export declare function subflowPathOf(runtimeStageId: string): string | undefined;
153
+ /** The subflow path of a runtimeStageId as segments (`['sf-a', 'sf-b']`); `[]` at the top level. */
154
+ export declare function subflowSegmentsOf(runtimeStageId: string): string[];
155
+ /** The non-empty segments of a subflow path or prefixed id (`'a//b/'` → `['a', 'b']`). */
156
+ export declare function pathSegments(path: string): string[];
157
+ /** The last segment of a path or prefixed id (`'sf-a/sf-b'` → `'sf-b'`); the whole string when it has none. */
158
+ export declare function lastSegmentOf(path: string): string;
159
+ /** Join path segments with the grammar's delimiter (`joinPath('sf', 'stage')` → `'sf/stage'`). */
160
+ export declare function joinPath(...segments: readonly string[]): string;
161
+ /** True when the (prefixed) id `id` sits INSIDE the subflow at `path` — at any depth below it. */
162
+ export declare function isWithinSubflow(id: string, path: string): boolean;
163
+ /**
164
+ * Shared mutable counter for execution index.
165
+ * Passed by reference to child traversers (subflows) so they
166
+ * continue the global numbering instead of restarting at 0.
167
+ */
168
+ export interface ExecutionCounter {
169
+ value: number;
170
+ }
171
+ /** Create a new execution counter starting at 0. */
172
+ export declare function createExecutionCounter(): ExecutionCounter;
173
+ export {};
@@ -0,0 +1,105 @@
1
+ /**
2
+ * EventLog — Time-travel snapshot storage for flowchart execution
3
+ *
4
+ * Like git history: stores commit bundles (diffs), not full snapshots.
5
+ *
6
+ * THE RECORD IS IMMUTABLE FROM `record` (F3, ruling R3). Every bundle is deep-frozen as it is
7
+ * recorded — the bundle, `overwrite` and `updates` at every depth, the trace and each row, the
8
+ * row's `readKeys`, `redactedPaths`, `tags`, `untrackedSources` — so a holder of a snapshot can no
9
+ * longer rewrite the history every later answer is folded from: an assignment into a bundle throws
10
+ * a `TypeError` in strict code. Safe because nothing outside the log holds a bundle's containers:
11
+ * the log's payload is the commit's own copy (`recordCommit` hands it the output of
12
+ * `scrubPatch`), and live state, the redacted mirror and write retention each take their own copy
13
+ * (`verbs.ts · foldRows` detaches, `StageContext · retainedForm` clones) — pinned by
14
+ * test/lib/memory/property/record-reachability.property.test.ts.
15
+ *
16
+ * What `Object.freeze` cannot seal — a Date's time, a Map's or Set's entries, a buffer's bytes, a
17
+ * RegExp, an Error's stack — is never handed out to a reader (9.44.2): `record` remembers that a
18
+ * bundle holds such a value (`capture/freeze.ts · freezeRecord`), and `list()` — like the public
19
+ * snapshot, `runner/snapshot.ts · servedSnapshot` — serves that bundle as a copy of its open paths
20
+ * (`serveRecord`, mapped at its first serve): fresh frozen containers down to each such value, a
21
+ * fresh copy of it, every other part the log's own. A reader edits only its own copy; every later
22
+ * serve reads the record as recorded. `recorded()` is the engine's own, unserved read. Named holes: an object hung on an array EXPANDO (arrays are walked
23
+ * by index — the `'indices'` walk, which keeps the freeze inside its budget; an expando is out of
24
+ * contract for state) and a `SharedArrayBuffer` (every copy shares its memory). A frozen RegExp's
25
+ * `lastIndex` is read-only, so a `/g` or `/y` regex read from a bundle throws when `exec` or
26
+ * `replace` advance it.
27
+ */
28
+ import type { EmitSourcePosition, LogAddress } from './eventPosition.js';
29
+ import type { CommitBundle } from './types.js';
30
+ export declare class EventLog {
31
+ /** Base snapshot BEFORE the first stage mutates anything. */
32
+ private base;
33
+ /** Ordered list of commit bundles. */
34
+ private steps;
35
+ private sourceAddress?;
36
+ private sourceAddressRetired;
37
+ constructor(initialMemory: any);
38
+ /**
39
+ * The fold BASE — the state as it stood before the first commit.
40
+ *
41
+ * This is the other half of the commit log: bundles are DIFFS, so a log
42
+ * alone cannot reconstruct state that was seeded before the run (an
43
+ * executor `initialContext`, `defaultValuesForContext`, a resume's
44
+ * `checkpoint.sharedState`, a subflow's `inputMapper` seed). Travelling
45
+ * with the log — `RuntimeSnapshot.initialState` — is what lets an OFFLINE
46
+ * consumer fold; without it the honest answer is a partial one
47
+ * (`stateAt`'s `basis: 'log-only'`).
48
+ *
49
+ * Returns a fresh detached clone on every call — the caller owns it.
50
+ */
51
+ getInitialState(): any;
52
+ /**
53
+ * Reconstructs the full state at any given step.
54
+ * Replays commits from the beginning — O(n) but low memory footprint.
55
+ *
56
+ * INDEX CONVENTION — `stepIdx` is EXCLUSIVE: `materialise(3)` folds commits
57
+ * 0, 1 and 2. `stateAt(source, commitIdx)` (foottrace) folds the
58
+ * same log but its `commitIdx` is INCLUSIVE, because a reader's cursor asks
59
+ * "the state AT this stop", which must include that stop's own commit. Two
60
+ * folds over one log with opposite conventions: check which one you hold.
61
+ *
62
+ * One clone of the base per call, then every bundle replayed INTO that
63
+ * private copy (`applySmartMergeInto` — the live commit's copy-on-write law
64
+ * below the root, 9.29.0, so the fold and the live state agree at every
65
+ * path). The result is the caller's: it shares nothing with the base or
66
+ * the log.
67
+ *
68
+ * @deprecated Since 9.33.0 — use `stateAt` from `foottrace`, which folds the same log
69
+ * from the same base (`RuntimeSnapshot.initialState`) and says how it was derived (`basis`).
70
+ * Nothing in the library calls this; it stays for one minor and is then removed. Mind the
71
+ * index: `materialise(n)` folds commits `0..n-1`, `stateAt(source, n - 1)` the same commits.
72
+ */
73
+ materialise(stepIdx?: number): any;
74
+ /**
75
+ * Persists a commit bundle for a finished stage, and FREEZES it (see the module doc): the bundle
76
+ * is stamped with its position, then deep-frozen, then appended. The engine hands it a bundle
77
+ * built for the log alone; a caller of this class (`foottrace/write`) hands over a bundle it
78
+ * will no longer edit — its own object is the one frozen.
79
+ */
80
+ record(bundle: CommitBundle): void;
81
+ /**
82
+ * Every recorded commit bundle, AS SERVED (9.44.2): a new array each call; a bundle freezing sealed
83
+ * whole is the log's own (frozen) object, one holding a Date, Map, buffer … is a copy of its open
84
+ * paths (`capture/freeze.ts · serveRecord`) — the reader's own, so no edit reaches the log.
85
+ */
86
+ list(): CommitBundle[];
87
+ /**
88
+ * @internal The bundles as the log holds them — each frozen, NOT served — in a new array, so a holder's
89
+ * `splice` reaches only its own. For the engine's own snapshot (`ExecutionRuntime · getSnapshot`, which
90
+ * a subflow mount takes once per mount), so the run serves nothing; a reader is served by `list()` and
91
+ * `getSnapshot().commitLog`. A known open door (CHANGELOG 9.44.2): a holder of these bundles can still
92
+ * edit a Date, Map or buffer inside them.
93
+ */
94
+ recorded(): CommitBundle[];
95
+ /** Number of recorded commits. */
96
+ get length(): number;
97
+ /** Immutable identity of this log, absent until the engine binds it. */
98
+ get address(): LogAddress | undefined;
99
+ /** @internal Bind once; resuming the same log must not rename its earlier positions. */
100
+ bindAddress(logRunId: string, drillPath: readonly string[]): void;
101
+ /** O(1) source-time capture. No counter, observer bookkeeping, or future commit prediction. */
102
+ capturePosition(runId: string): EmitSourcePosition | undefined;
103
+ /** Wipes history (useful for test resets). */
104
+ clear(): void;
105
+ }