agentfootprint 9.87.1 → 9.89.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 (143) hide show
  1. package/CHANGELOG.md +946 -0
  2. package/dist/core/Agent.js +32 -0
  3. package/dist/core/Agent.js.map +1 -1
  4. package/dist/core/LLMCall.js +7 -10
  5. package/dist/core/LLMCall.js.map +1 -1
  6. package/dist/core/agent/buildAgentMessageApiChart.js +2 -4
  7. package/dist/core/agent/buildAgentMessageApiChart.js.map +1 -1
  8. package/dist/core/agent/buildDynamicAgentChart.js +10 -0
  9. package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
  10. package/dist/core/agent/buildMessageApiChart.js +2 -4
  11. package/dist/core/agent/buildMessageApiChart.js.map +1 -1
  12. package/dist/core/agent/composeRequest.js +134 -0
  13. package/dist/core/agent/composeRequest.js.map +1 -0
  14. package/dist/core/agent/stages/callLLM.js +62 -25
  15. package/dist/core/agent/stages/callLLM.js.map +1 -1
  16. package/dist/core/agent/stages/seed.js +12 -0
  17. package/dist/core/agent/stages/seed.js.map +1 -1
  18. package/dist/core/agent/stages/toolCalls.js +2 -4
  19. package/dist/core/agent/stages/toolCalls.js.map +1 -1
  20. package/dist/core/flowchartAsTool.js.map +1 -1
  21. package/dist/esm/core/Agent.d.ts +3 -0
  22. package/dist/esm/core/Agent.js +32 -0
  23. package/dist/esm/core/Agent.js.map +1 -1
  24. package/dist/esm/core/LLMCall.js +7 -10
  25. package/dist/esm/core/LLMCall.js.map +1 -1
  26. package/dist/esm/core/agent/buildAgentMessageApiChart.js +2 -4
  27. package/dist/esm/core/agent/buildAgentMessageApiChart.js.map +1 -1
  28. package/dist/esm/core/agent/buildDynamicAgentChart.js +10 -0
  29. package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
  30. package/dist/esm/core/agent/buildMessageApiChart.js +2 -4
  31. package/dist/esm/core/agent/buildMessageApiChart.js.map +1 -1
  32. package/dist/esm/core/agent/composeRequest.d.ts +121 -0
  33. package/dist/esm/core/agent/composeRequest.js +127 -0
  34. package/dist/esm/core/agent/composeRequest.js.map +1 -0
  35. package/dist/esm/core/agent/stages/callLLM.d.ts +28 -0
  36. package/dist/esm/core/agent/stages/callLLM.js +61 -24
  37. package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
  38. package/dist/esm/core/agent/stages/seed.d.ts +26 -0
  39. package/dist/esm/core/agent/stages/seed.js +12 -0
  40. package/dist/esm/core/agent/stages/seed.js.map +1 -1
  41. package/dist/esm/core/agent/stages/toolCalls.js +2 -4
  42. package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
  43. package/dist/esm/core/agent/types.d.ts +64 -0
  44. package/dist/esm/core/flowchartAsTool.d.ts +15 -7
  45. package/dist/esm/core/flowchartAsTool.js.map +1 -1
  46. package/dist/esm/index.d.ts +1 -0
  47. package/dist/esm/index.js +9 -0
  48. package/dist/esm/index.js.map +1 -1
  49. package/dist/esm/lib/context-bisect/llmEdgeWeigher.d.ts +8 -0
  50. package/dist/esm/lib/context-bisect/llmEdgeWeigher.js +0 -0
  51. package/dist/esm/lib/context-bisect/llmEdgeWeigher.js.map +1 -1
  52. package/dist/esm/lib/context-bisect/trajectory.js +3 -7
  53. package/dist/esm/lib/context-bisect/trajectory.js.map +1 -1
  54. package/dist/esm/lib/context-ledger/contextLedger.js +5 -12
  55. package/dist/esm/lib/context-ledger/contextLedger.js.map +1 -1
  56. package/dist/esm/lib/time-travel/epochs.d.ts +210 -0
  57. package/dist/esm/lib/time-travel/epochs.js +274 -0
  58. package/dist/esm/lib/time-travel/epochs.js.map +1 -0
  59. package/dist/esm/lib/time-travel/index.d.ts +10 -4
  60. package/dist/esm/lib/time-travel/index.js +10 -4
  61. package/dist/esm/lib/time-travel/index.js.map +1 -1
  62. package/dist/esm/lib/time-travel/keyedFold.d.ts +112 -0
  63. package/dist/esm/lib/time-travel/keyedFold.js +286 -0
  64. package/dist/esm/lib/time-travel/keyedFold.js.map +1 -0
  65. package/dist/esm/lib/time-travel/milestoneStops.d.ts +57 -36
  66. package/dist/esm/lib/time-travel/milestoneStops.js +75 -82
  67. package/dist/esm/lib/time-travel/milestoneStops.js.map +1 -1
  68. package/dist/esm/lib/time-travel/receipt.d.ts +496 -0
  69. package/dist/esm/lib/time-travel/receipt.js +434 -0
  70. package/dist/esm/lib/time-travel/receipt.js.map +1 -0
  71. package/dist/esm/lib/time-travel/servedView.d.ts +525 -0
  72. package/dist/esm/lib/time-travel/servedView.js +820 -0
  73. package/dist/esm/lib/time-travel/servedView.js.map +1 -0
  74. package/dist/esm/lib/time-travel/sha256.d.ts +24 -0
  75. package/dist/esm/lib/time-travel/sha256.js +103 -0
  76. package/dist/esm/lib/time-travel/sha256.js.map +1 -0
  77. package/dist/esm/recorders/observability/BoundaryRecorder.d.ts +21 -0
  78. package/dist/esm/recorders/observability/BoundaryRecorder.js +6 -0
  79. package/dist/esm/recorders/observability/BoundaryRecorder.js.map +1 -1
  80. package/dist/index.js +124 -103
  81. package/dist/index.js.map +1 -1
  82. package/dist/lib/context-bisect/llmEdgeWeigher.js +0 -0
  83. package/dist/lib/context-bisect/llmEdgeWeigher.js.map +1 -1
  84. package/dist/lib/context-bisect/trajectory.js +3 -7
  85. package/dist/lib/context-bisect/trajectory.js.map +1 -1
  86. package/dist/lib/context-ledger/contextLedger.js +5 -12
  87. package/dist/lib/context-ledger/contextLedger.js.map +1 -1
  88. package/dist/lib/time-travel/epochs.js +284 -0
  89. package/dist/lib/time-travel/epochs.js.map +1 -0
  90. package/dist/lib/time-travel/index.js +35 -5
  91. package/dist/lib/time-travel/index.js.map +1 -1
  92. package/dist/lib/time-travel/keyedFold.js +290 -0
  93. package/dist/lib/time-travel/keyedFold.js.map +1 -0
  94. package/dist/lib/time-travel/milestoneStops.js +74 -81
  95. package/dist/lib/time-travel/milestoneStops.js.map +1 -1
  96. package/dist/lib/time-travel/receipt.js +442 -0
  97. package/dist/lib/time-travel/receipt.js.map +1 -0
  98. package/dist/lib/time-travel/servedView.js +826 -0
  99. package/dist/lib/time-travel/servedView.js.map +1 -0
  100. package/dist/lib/time-travel/sha256.js +107 -0
  101. package/dist/lib/time-travel/sha256.js.map +1 -0
  102. package/dist/recorders/observability/BoundaryRecorder.js +6 -0
  103. package/dist/recorders/observability/BoundaryRecorder.js.map +1 -1
  104. package/dist/types/core/Agent.d.ts +3 -0
  105. package/dist/types/core/Agent.d.ts.map +1 -1
  106. package/dist/types/core/LLMCall.d.ts.map +1 -1
  107. package/dist/types/core/agent/buildAgentMessageApiChart.d.ts.map +1 -1
  108. package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
  109. package/dist/types/core/agent/buildMessageApiChart.d.ts.map +1 -1
  110. package/dist/types/core/agent/composeRequest.d.ts +122 -0
  111. package/dist/types/core/agent/composeRequest.d.ts.map +1 -0
  112. package/dist/types/core/agent/stages/callLLM.d.ts +28 -0
  113. package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
  114. package/dist/types/core/agent/stages/seed.d.ts +26 -0
  115. package/dist/types/core/agent/stages/seed.d.ts.map +1 -1
  116. package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
  117. package/dist/types/core/agent/types.d.ts +64 -0
  118. package/dist/types/core/agent/types.d.ts.map +1 -1
  119. package/dist/types/core/flowchartAsTool.d.ts +15 -7
  120. package/dist/types/core/flowchartAsTool.d.ts.map +1 -1
  121. package/dist/types/index.d.ts +1 -0
  122. package/dist/types/index.d.ts.map +1 -1
  123. package/dist/types/lib/context-bisect/llmEdgeWeigher.d.ts +8 -0
  124. package/dist/types/lib/context-bisect/llmEdgeWeigher.d.ts.map +1 -1
  125. package/dist/types/lib/context-bisect/trajectory.d.ts.map +1 -1
  126. package/dist/types/lib/context-ledger/contextLedger.d.ts.map +1 -1
  127. package/dist/types/lib/time-travel/epochs.d.ts +211 -0
  128. package/dist/types/lib/time-travel/epochs.d.ts.map +1 -0
  129. package/dist/types/lib/time-travel/index.d.ts +10 -4
  130. package/dist/types/lib/time-travel/index.d.ts.map +1 -1
  131. package/dist/types/lib/time-travel/keyedFold.d.ts +113 -0
  132. package/dist/types/lib/time-travel/keyedFold.d.ts.map +1 -0
  133. package/dist/types/lib/time-travel/milestoneStops.d.ts +57 -36
  134. package/dist/types/lib/time-travel/milestoneStops.d.ts.map +1 -1
  135. package/dist/types/lib/time-travel/receipt.d.ts +497 -0
  136. package/dist/types/lib/time-travel/receipt.d.ts.map +1 -0
  137. package/dist/types/lib/time-travel/servedView.d.ts +526 -0
  138. package/dist/types/lib/time-travel/servedView.d.ts.map +1 -0
  139. package/dist/types/lib/time-travel/sha256.d.ts +25 -0
  140. package/dist/types/lib/time-travel/sha256.d.ts.map +1 -0
  141. package/dist/types/recorders/observability/BoundaryRecorder.d.ts +21 -0
  142. package/dist/types/recorders/observability/BoundaryRecorder.d.ts.map +1 -1
  143. package/package.json +3 -3
@@ -0,0 +1,113 @@
1
+ /**
2
+ * keyedFold — the value of ONE state key at one commit, folded from the run's
3
+ * own fold base.
4
+ *
5
+ * Role: Fold. It reads a finished run's commit log plus the base that log
6
+ * was recorded against, and answers "what was `key` at commit `idx`?"
7
+ * It executes nothing, records nothing and stores nothing beside the
8
+ * log. Its answers are DETACHED — deep-frozen before they are cached,
9
+ * because a memo that hands out live references is a fold that lets a
10
+ * reader rewrite the run (`keyedFold.ts` · `freezeDeep`).
11
+ * Reads: a `FoldSource` — a snapshot (`commitLog` + `initialState`) or a
12
+ * subflow subtree (`history` + `initialState`), through footprintjs's
13
+ * own `stateAt` (for the base) and `applySmartMerge` (for the replay).
14
+ * Emits: N/A.
15
+ *
16
+ * ── WHY THIS FILE EXISTS ───────────────────────────────────────────────────
17
+ * A commit log stores DIFFS. `commitValueAt` folds them for one key and says
18
+ * so in its own docstring: a value that came from the run's INITIAL state and
19
+ * was never `set` again folds to ABSENT, because the log alone cannot see the
20
+ * pre-run base.
21
+ *
22
+ * That is not an edge case here. A RESUMED agent run is a fresh executor
23
+ * seeded from `checkpoint.sharedState`, so the entire pre-pause world —
24
+ * `systemPromptInjections`, `history`, `dynamicToolSchemas`, every build-time
25
+ * constant `seed` wrote before the pause — is base, not log. Folding the
26
+ * resumed run with `commitValueAt` returns an empty system prompt and a
27
+ * truncated conversation and declares no gap: a confident falsehood about the
28
+ * one question this family exists to answer. footprintjs 9.17 shipped
29
+ * `RuntimeSnapshot.initialState` and `stateAt` for exactly this, and every
30
+ * read in `epochs.ts` goes through here so it lands on that base.
31
+ *
32
+ * ── WHY NOT JUST CALL `stateAt` PER READ ───────────────────────────────────
33
+ * `stateAt` folds the WHOLE state, and it clones that state once per bundle
34
+ * (`applySmartMerge` opens with a `structuredClone` of its base). One fold is
35
+ * therefore O(commits × state size) — measured on a real 100-turn agent
36
+ * (1,719 commits, 101 epochs): 323 ms for a single fold, and 11.7 s to fold
37
+ * once per epoch, against 78 ms for the whole per-epoch scrub before this
38
+ * release. A per-epoch reader cannot pay that.
39
+ *
40
+ * So `stateAt` is used for the ONE thing only it can give — the fold base and
41
+ * the honest `basis` verdict, at `commitIdx: -1`, where it folds nothing and
42
+ * clones the base once — and the forward replay is done per key, through
43
+ * footprintjs's own `applySmartMerge`. There is deliberately no second
44
+ * implementation of the trace verbs here: every `set` / `append` / `merge` /
45
+ * `delete` is applied by the same function the live commit uses.
46
+ * `keyed-fold-equivalence.test.ts` pins the result against `stateAt` itself on
47
+ * real runs, including a resumed one and a merge with no `set` anchor — the
48
+ * one shape that cannot be folded at all without the base.
49
+ */
50
+ import type { CommitBundle } from 'footprintjs/advanced';
51
+ /**
52
+ * How a fold was derived — footprintjs's own two answers, restated here so a
53
+ * caller of this module does not have to import the engine's trace barrel to
54
+ * name them.
55
+ *
56
+ * - `'initial+log'` — the recording carried its fold base, so a value seeded
57
+ * before the run (or before a resume) folds correctly.
58
+ * - `'log-only'` — it did not. Anything the log never `set` reads as absent,
59
+ * and a reader must say so rather than present the hole as a proof.
60
+ */
61
+ export type FoldBasis = 'initial+log' | 'log-only';
62
+ /**
63
+ * Anything that carries a commit log and, ideally, the base it was recorded
64
+ * against — the two field spellings footprintjs already has: `commitLog` on a
65
+ * run snapshot, `history` on a subflow subtree.
66
+ */
67
+ export interface FoldSourceLike {
68
+ readonly commitLog?: readonly CommitBundle[];
69
+ readonly history?: readonly unknown[];
70
+ readonly initialState?: Record<string, unknown>;
71
+ }
72
+ /**
73
+ * One key's value at one commit — the question, and the answers already
74
+ * computed for it.
75
+ */
76
+ export interface KeyedFold {
77
+ /** How this fold was derived — see {@link FoldBasis}. */
78
+ readonly basis: FoldBasis;
79
+ /** How many bundles the log holds. */
80
+ readonly length: number;
81
+ /**
82
+ * The value of `key` folded through commit ARRAY INDEX `idx`, inclusive.
83
+ * `-1` (or lower) folds nothing and returns the base's value — the state
84
+ * before the log's first commit.
85
+ *
86
+ * DEEP-FROZEN, and the same object on every call for the same question. It
87
+ * is detached from the engine's own bundles AND unmutable, so a caller
88
+ * cannot rewrite what a later index folds to — `keyedFold.ts` · `freezeDeep`
89
+ * says why that is a law here rather than a courtesy. Copy it
90
+ * (`structuredClone`, a spread) if you need something to edit.
91
+ */
92
+ valueAt(key: string, idx: number): unknown;
93
+ }
94
+ /**
95
+ * The keyed fold for one source, memoized on the source object.
96
+ *
97
+ * Memoized because a per-epoch reader asks the same source for the same keys
98
+ * at many different commits, and the index is the expensive half: building it
99
+ * is one pass over the log, and answering a read afterwards is a binary search
100
+ * plus a replay from the nearest full-value write (normally exactly one).
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * import { keyedFold } from 'agentfootprint';
105
+ *
106
+ * const fold = keyedFold(agent.getSnapshot());
107
+ * fold.basis; // 'initial+log' — the base travelled
108
+ * fold.valueAt('history', 12); // the conversation after the 13th commit
109
+ * fold.valueAt('history', -1); // …and what the run STARTED from
110
+ * ```
111
+ */
112
+ export declare function keyedFold(source: FoldSourceLike | undefined): KeyedFold;
113
+ //# sourceMappingURL=keyedFold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyedFold.d.ts","sourceRoot":"","sources":["../../../../src/lib/time-travel/keyedFold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD;;;;;;;;;GASG;AACH,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,UAAU,CAAC;AAEnD;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjD;AAmCD;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,yDAAyD;IACzD,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,sCAAsC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5C;AAqGD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,GAAG,SAAS,CAmGvE"}
@@ -8,16 +8,26 @@
8
8
  * it), and `conventions.ts` · `milestoneFor` for the domain vocabulary.
9
9
  * Emits: N/A.
10
10
  *
11
- * WHY THIS FILE EXISTS. footprintjs 9.17 ships the reader's cursor
12
- * (`timeTravel`) and one stop grammar — `commitStops`, one stop per executed
13
- * stage — because that is the only grammar the substrate itself knows. It does
14
- * NOT know what an LLM turn is. agentfootprint does: `milestoneFor` has
15
- * classified a local stage id into an iteration / slot / llm-turn / tool-call /
16
- * decision since 9.x, and until now every consumer that wanted a milestone
17
- * slider mapped that classifier onto commits by hand. The Why Lens did it one
18
- * way; anyone else with a recording had to write it again. This is that
19
- * mapping, once, on the strategy seam the port opened — so the agent SUPPLIES
20
- * the stops for its own runs and every reader gets the same axis.
11
+ * WHY THIS FILE EXISTS. footprintjs ships the reader's cursor (`timeTravel`)
12
+ * and one stop grammar — `commitStops`, one stop per executed stage — because
13
+ * that is the only grammar the substrate itself knows. It does NOT know what an
14
+ * LLM turn is. agentfootprint does: `milestoneFor` has classified a local stage
15
+ * id into an iteration / slot / llm-turn / tool-call / decision since 9.x, and
16
+ * until 9.87 every consumer that wanted a milestone slider mapped that
17
+ * classifier onto commits by hand. This is that mapping, once, on the strategy
18
+ * seam the port opened — so the agent SUPPLIES the stops for its own runs and
19
+ * every reader gets the same axis.
20
+ *
21
+ * WHAT IT IS (9.89.0). A FILTER over the port's own axis. footprintjs 9.18
22
+ * shipped `filterStops(stops, keep)` — the bookend guard, the re-partition and
23
+ * a `meta` slot on the stop — because two consumers had each re-derived all
24
+ * three by hand against 9.17, this file among them. The hand-rolled copies are
25
+ * gone: the one owner of the `[start, …stages, end]` contract is the library
26
+ * that returns it, and this strategy is one expression over it. The axis is
27
+ * byte-for-byte the 9.88.0 axis (`test/lib/time-travel/milestone-stops-equivalence.test.ts` pins
28
+ * that against a verbatim copy of the 9.88.0 implementation); what is new is that the milestone now RIDES on the
29
+ * stop as `meta`, and that a start which absorbed pre-milestone stages says so
30
+ * with `prologue: true`.
21
31
  *
22
32
  * WHAT IT IS NOT. Not a second cursor. A strategy only says where the one
23
33
  * cursor may rest; `timeTravel` still owns the position, the folds and the
@@ -32,15 +42,14 @@ import { type Milestone } from '../../conventions.js';
32
42
  * The milestone a stop stands for, or `null` when it stands for none (the
33
43
  * `'start'` / `'end'` bookends).
34
44
  *
35
- * WHY A FUNCTION AND NOT A FIELD. footprintjs's `Stop` is a closed shape —
36
- * `step`, `runtimeStageId`, `commitIdx`, `lastCommitIdx`, `stageId`,
37
- * `subflowPath`, `label`, `kind` — with no extension slot a strategy may write
38
- * its own vocabulary into, and `kind` is the port's own `StopKind`
39
- * (`'commit' | 'mount' | 'start' | 'end'`), not ours to overload. So the
40
- * milestone kind travels the only way it honestly can: re-derived from the
41
- * stop's `runtimeStageId`, by the same classifier that put the stop on the
42
- * axis. Same input, same function, same answer — there is no second source of
43
- * truth here, only a second reading of the one there is.
45
+ * A stop that {@link milestoneStops} made carries its milestone as
46
+ * `stop.meta`, and that is what is read — the classification the strategy
47
+ * made when it put the stop on the axis, not a second run of the classifier.
48
+ * A stop from ANOTHER strategy — the port's own `commitStops`, or a consumer's
49
+ * filter that kept the stop without a milestone meta — has none, so the answer
50
+ * falls back to where it always came from: `milestoneFor` over the stop's
51
+ * `runtimeStageId`. Same classifier, same answer; a `meta` of some other
52
+ * vocabulary is not mistaken for ours.
44
53
  *
45
54
  * @example
46
55
  * ```ts
@@ -48,7 +57,7 @@ import { type Milestone } from '../../conventions.js';
48
57
  * milestoneOf(stop)?.kind; // 'llm-turn'
49
58
  * ```
50
59
  */
51
- export declare function milestoneOf(stop: Stop): Milestone | null;
60
+ export declare function milestoneOf(stop: Stop<unknown>): Milestone | null;
52
61
  /**
53
62
  * Derive one stop per committed MILESTONE from a recorded commit log.
54
63
  *
@@ -61,9 +70,11 @@ export declare function milestoneOf(stop: Stop): Milestone | null;
61
70
  * parallel fork child commits twice and siblings interleave — every repeat is
62
71
  * an empty bundle), the authoritative mount set read off the execution tree,
63
72
  * the `'start'` / `'end'` bookends, and the id-less leading commit that carries
64
- * a subflow's `inputMapper` seed. This function calls `commitStops` and filters
65
- * its result. A second implementation of that collapsing would be a second
66
- * chance to disagree with the library about what a stage is.
73
+ * a subflow's `inputMapper` seed. And since 9.89.0 the COMPOSITION itself is
74
+ * the port's too: `filterStops` checks the `[start, …stages, end]` shape,
75
+ * keeps what `keep` keeps, and re-partitions the log. A second implementation
76
+ * of any of that would be a second chance to disagree with the library about
77
+ * what a stage is.
67
78
  *
68
79
  * **The survivors re-partition the log.** A stage that classifies `null` is not
69
80
  * a stop, but its commits still happened, so they are folded into the stop that
@@ -74,14 +85,21 @@ export declare function milestoneOf(stop: Stop): Milestone | null;
74
85
  * so on a drilled cursor `'start'` reads as "what this subflow began with,
75
86
  * after its plumbing ran".
76
87
  *
77
- * **What that costs `'start'`.** On footprintjs's own axis `'start'` is the fold
78
- * base: the state before ANY stage ran. Here it absorbs every stage that ran
79
- * before the first milestone, so `stateAt(start)` is the state the first
80
- * milestone READ, not the run's raw base — a real agent seeds a couple of dozen
81
- * keys in `seed` before anything a reader would scrub to. That is the right
82
- * answer for this axis (the stops must still partition the log) and the wrong
83
- * one to assume from `kind: 'start'` alone, so it is said out loud here, in the
84
- * folder README, on the docs page and in a test.
88
+ * **What that costs `'start'`, and the flag that says so.** On footprintjs's
89
+ * own axis `'start'` is the fold base: the state before ANY stage ran. Here it
90
+ * absorbs every stage that ran before the first milestone, so `stateAt(start)`
91
+ * is the state the first milestone READ, not the run's raw base — a real agent
92
+ * seeds a couple of dozen keys in `seed` before anything a reader would scrub
93
+ * to. That is the right answer for this axis (the stops must still partition
94
+ * the log), and since 9.18 the port marks it: the returned start carries
95
+ * `prologue: true` whenever it absorbed a stage, so a renderer that means
96
+ * "before anything ran" checks `kind === 'start' && !prologue` instead of
97
+ * assuming it from the kind.
98
+ *
99
+ * **The milestone rides on the stop.** Every kept stop carries its
100
+ * classification as `meta` — `Stop<Milestone>` — so a reader asks
101
+ * `stop.meta?.kind` (or {@link milestoneOf}, which reads the same slot) rather
102
+ * than re-running the classifier over the id. The bookends carry none.
85
103
  *
86
104
  * **A log with no milestones in it at all.** A non-empty log the classifier
87
105
  * recognises nothing in — a non-agent chart handed this strategy — yields the
@@ -109,21 +127,24 @@ export declare function milestoneOf(stop: Stop): Milestone | null;
109
127
  * @example
110
128
  * ```ts
111
129
  * import { timeTravel } from 'footprintjs/trace';
112
- * import { milestoneStopsStrategy, milestoneOf } from 'agentfootprint';
130
+ * import { milestoneStopsStrategy } from 'agentfootprint';
113
131
  *
114
132
  * const cursor = timeTravel(agent.getSnapshot()!, { strategy: milestoneStopsStrategy });
115
- * cursor.stops.map((s) => [s.label, milestoneOf(s)?.kind]);
133
+ * cursor.stops.map((s) => [s.label, s.meta?.kind]);
116
134
  * // measured on a two-turn `dynamic` run — 42 commits, 15 stops:
117
135
  * // [['Run start', undefined], ['Iteration', 'iteration'],
118
136
  * // ['System prompt', 'slot'], ['Messages', 'slot'], ['Tools', 'slot'],
119
137
  * // ['LLM turn', 'llm-turn'], ['Route', 'decision'], ['Tool call', 'tool-call'],
120
138
  * // … the second turn …, ['Run end', undefined]]
139
+ * cursor.stops[0].prologue; // true — `seed` and the plumbing ran before the first Iteration
121
140
  * ```
122
141
  */
123
- export declare function milestoneStops(commitLog: readonly CommitBundle[], executionTree?: StageSnapshot): Stop[];
142
+ export declare function milestoneStops(commitLog: readonly CommitBundle[], executionTree?: StageSnapshot): Stop<Milestone>[];
124
143
  /**
125
144
  * `milestoneStops` as a footprintjs `TimeTravelStrategy` — what you hand
126
- * `timeTravel(snapshot, { strategy })`.
145
+ * `timeTravel(snapshot, { strategy })`. Typed over {@link Milestone}, so the
146
+ * cursor's stops are `Stop<Milestone>` and `cursor.at()?.meta?.kind` is typed;
147
+ * it is still assignable wherever a bare `TimeTravelStrategy` is expected.
127
148
  */
128
- export declare const milestoneStopsStrategy: TimeTravelStrategy;
149
+ export declare const milestoneStopsStrategy: TimeTravelStrategy<Milestone>;
129
150
  //# sourceMappingURL=milestoneStops.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"milestoneStops.d.ts","sourceRoot":"","sources":["../../../../src/lib/time-travel/milestoneStops.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAExE,OAAO,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAExD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsEG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,SAAS,YAAY,EAAE,EAClC,aAAa,CAAC,EAAE,aAAa,GAC5B,IAAI,EAAE,CAuDR;AAED;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,kBAAiD,CAAC"}
1
+ {"version":3,"file":"milestoneStops.d.ts","sourceRoot":"","sources":["../../../../src/lib/time-travel/milestoneStops.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAExE,OAAO,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAgB,KAAK,SAAS,EAAsB,MAAM,sBAAsB,CAAC;AAiBxF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAGjE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,SAAS,YAAY,EAAE,EAClC,aAAa,CAAC,EAAE,aAAa,GAC5B,IAAI,CAAC,SAAS,CAAC,EAAE,CAKnB;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,kBAAkB,CAAC,SAAS,CAAgC,CAAC"}