agentfootprint 9.89.3 → 9.91.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 (78) hide show
  1. package/CHANGELOG.md +164 -0
  2. package/dist/conventions.js +146 -46
  3. package/dist/conventions.js.map +1 -1
  4. package/dist/core/LLMCall.js +75 -10
  5. package/dist/core/LLMCall.js.map +1 -1
  6. package/dist/core/agent/buildAgentChart.js +25 -8
  7. package/dist/core/agent/buildAgentChart.js.map +1 -1
  8. package/dist/core/agent/buildAgentMessageApiChart.js +38 -5
  9. package/dist/core/agent/buildAgentMessageApiChart.js.map +1 -1
  10. package/dist/core/agent/buildDynamicAgentChart.js +27 -9
  11. package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
  12. package/dist/core/agent/buildMessageApiChart.js +32 -4
  13. package/dist/core/agent/buildMessageApiChart.js.map +1 -1
  14. package/dist/core/agent/messageApiReceipt.js +77 -0
  15. package/dist/core/agent/messageApiReceipt.js.map +1 -0
  16. package/dist/core/agent/stages/callLLM.js +1 -5
  17. package/dist/core/agent/stages/callLLM.js.map +1 -1
  18. package/dist/esm/conventions.d.ts +54 -0
  19. package/dist/esm/conventions.js +140 -44
  20. package/dist/esm/conventions.js.map +1 -1
  21. package/dist/esm/core/LLMCall.d.ts +18 -0
  22. package/dist/esm/core/LLMCall.js +77 -12
  23. package/dist/esm/core/LLMCall.js.map +1 -1
  24. package/dist/esm/core/agent/buildAgentChart.js +26 -9
  25. package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
  26. package/dist/esm/core/agent/buildAgentMessageApiChart.d.ts +22 -0
  27. package/dist/esm/core/agent/buildAgentMessageApiChart.js +40 -7
  28. package/dist/esm/core/agent/buildAgentMessageApiChart.js.map +1 -1
  29. package/dist/esm/core/agent/buildDynamicAgentChart.js +28 -10
  30. package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
  31. package/dist/esm/core/agent/buildMessageApiChart.d.ts +32 -0
  32. package/dist/esm/core/agent/buildMessageApiChart.js +34 -6
  33. package/dist/esm/core/agent/buildMessageApiChart.js.map +1 -1
  34. package/dist/esm/core/agent/messageApiReceipt.d.ts +82 -0
  35. package/dist/esm/core/agent/messageApiReceipt.js +73 -0
  36. package/dist/esm/core/agent/messageApiReceipt.js.map +1 -0
  37. package/dist/esm/core/agent/stages/callLLM.js +3 -7
  38. package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
  39. package/dist/esm/index.d.ts +1 -1
  40. package/dist/esm/index.js +5 -0
  41. package/dist/esm/index.js.map +1 -1
  42. package/dist/esm/lib/time-travel/milestoneStops.js +29 -9
  43. package/dist/esm/lib/time-travel/milestoneStops.js.map +1 -1
  44. package/dist/esm/lib/time-travel/receipt.d.ts +45 -13
  45. package/dist/esm/lib/time-travel/receipt.js +41 -10
  46. package/dist/esm/lib/time-travel/receipt.js.map +1 -1
  47. package/dist/esm/lib/time-travel/servedView.d.ts +36 -35
  48. package/dist/esm/lib/time-travel/servedView.js +64 -43
  49. package/dist/esm/lib/time-travel/servedView.js.map +1 -1
  50. package/dist/index.js +16 -5
  51. package/dist/index.js.map +1 -1
  52. package/dist/lib/time-travel/milestoneStops.js +29 -9
  53. package/dist/lib/time-travel/milestoneStops.js.map +1 -1
  54. package/dist/lib/time-travel/receipt.js +43 -11
  55. package/dist/lib/time-travel/receipt.js.map +1 -1
  56. package/dist/lib/time-travel/servedView.js +64 -43
  57. package/dist/lib/time-travel/servedView.js.map +1 -1
  58. package/dist/types/conventions.d.ts +54 -0
  59. package/dist/types/conventions.d.ts.map +1 -1
  60. package/dist/types/core/LLMCall.d.ts +18 -0
  61. package/dist/types/core/LLMCall.d.ts.map +1 -1
  62. package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
  63. package/dist/types/core/agent/buildAgentMessageApiChart.d.ts +22 -0
  64. package/dist/types/core/agent/buildAgentMessageApiChart.d.ts.map +1 -1
  65. package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
  66. package/dist/types/core/agent/buildMessageApiChart.d.ts +32 -0
  67. package/dist/types/core/agent/buildMessageApiChart.d.ts.map +1 -1
  68. package/dist/types/core/agent/messageApiReceipt.d.ts +83 -0
  69. package/dist/types/core/agent/messageApiReceipt.d.ts.map +1 -0
  70. package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
  71. package/dist/types/index.d.ts +1 -1
  72. package/dist/types/index.d.ts.map +1 -1
  73. package/dist/types/lib/time-travel/milestoneStops.d.ts.map +1 -1
  74. package/dist/types/lib/time-travel/receipt.d.ts +45 -13
  75. package/dist/types/lib/time-travel/receipt.d.ts.map +1 -1
  76. package/dist/types/lib/time-travel/servedView.d.ts +36 -35
  77. package/dist/types/lib/time-travel/servedView.d.ts.map +1 -1
  78. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -7,6 +7,170 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [9.91.0] - 2026-09-10
11
+
12
+ **Every chart that serves a model now mints a receipt.** A receipt is the proof
13
+ of what the model was actually handed, minted at the call and committed in the
14
+ bundle the call already writes — and until this release exactly ONE stage minted
15
+ one. Three other charts in this library handed a model a request and left
16
+ `no-receipt-on-chart` on every view they produced, so a reader of an `LLMCall`
17
+ or messageAPI recording could only ever see Reconstructed, never Verified.
18
+
19
+ Two reasons were on the record for that. **Neither survived.** The first — that
20
+ `Receipt.cache.transform` has no honest value on a chart running no cache
21
+ strategy — was already refuted in 9.88.0 and left refuted in the source: an
22
+ `Agent` with a pass-through strategy records `'unchanged'` today, and the value
23
+ is true for the same reason where no strategy exists at all, because *the
24
+ request that went out IS the request that was assembled*. **No fourth enum value
25
+ was added.** The second — the salt — never applied to `LLMCall`, which owns its
26
+ executor and mints a run id exactly as `Agent` does. It DOES apply to the two
27
+ messageAPI charts, and that was verified rather than assumed: footprintjs stamps
28
+ `TraversalContext.runId` on recorder events, not on a stage's scope; there is no
29
+ `$runId` on `ScopeFacade`; `ExecutionEnv` is a fixed type carrying `traceId` and
30
+ no run id. A chart builder run on somebody else's executor genuinely cannot
31
+ invent the value — so it is a dep, and a chart given none mints NOTHING rather
32
+ than salting every hash with an empty string.
33
+
34
+ ### Added
35
+
36
+ - **`LLMCall` mints a receipt** (`LLMCall.ts` · `callLLM`), salted with the run
37
+ id `createExecutor` already mints per run — read at CALL time, not closed over
38
+ at build time, so the second run of the same `LLMCall` is not salted with the
39
+ first run's value. `servedAt` on an `LLMCall` recording now carries
40
+ `basis.model`, `params` and the cache verdict, and stops raising
41
+ `no-receipt-on-chart`.
42
+ - **`LLMCallOptions.recordReceipt`** — the twin of `AgentOptions.recordReceipt`,
43
+ same field, same contract, default ON. `false` declines the mint (one
44
+ commit-log value and a SHA-256 per piece, per message, per tool schema);
45
+ `servedAt` still rebuilds the view and declares the missing witness.
46
+ - **`MessageApiChartDeps.getRunId` / `AgentMessageApiChartDeps.getRunId`** —
47
+ supply the run id and the chart mints on every turn; omit it and it mints
48
+ none. `src/core/agent/messageApiReceipt.ts` owns that rule for both charts,
49
+ because the two are deliberate twins and a mint written out in each is two
50
+ chances to disagree about what the model was handed.
51
+ - **`receipt.ts` · `receiptPieces`** — the injection-record → receipt-piece map,
52
+ which was about to have four copies. One owner, calling the same
53
+ `contributingPieces` the system-prompt join calls, so a piece cannot be on the
54
+ receipt and absent from the string.
55
+
56
+ ### Fixed
57
+
58
+ - **`servedAt` reported an EMPTY tool list on a call that served tools.**
59
+ `servedView.ts` · `viewOf` read the served list from `dynamicToolSchemas`
60
+ alone. The agent charts map the tools slot's output onto that key at the mount
61
+ boundary; the messageAPI charts carry it out under the slot's own name — so a
62
+ `buildAgentMessageApiChart` view said `tools.names: []` about a call that
63
+ served one. An empty list is not an omission, it is a DENIAL, and it went
64
+ unnoticed for as long as no receipt existed to contradict it. The read is now
65
+ a fallback chain (the agent key first, so no agent recording changes), the
66
+ same shape the conversation has had since 9.88.0. Red before, on
67
+ `test/lib/time-travel/receipt-conformance.test.ts` · *the tool the model was
68
+ served is hashed by the receipt AND rebuilt from the log*.
69
+
70
+ ### Changed
71
+
72
+ - **`SERVED_GAPS['no-receipt-on-chart']` is unchanged, and still true.** Its
73
+ printed sentence never named a chart, so nothing in it went false; the
74
+ MECHANISM comment beside it now names the shapes that still reach it — a
75
+ messageAPI chart handed no run id, a run that declined with `recordReceipt:
76
+ false`, a recording made before 9.88.0, and a consumer's own `call-llm` stage,
77
+ which this library does not mint for. The cause `'no-receipt-committed'` is
78
+ still driven by a REAL run in both walks; the driver moved from an `LLMCall`
79
+ (which now mints) to a messageAPI chart with no run id.
80
+ - **The composed request is assembled once per chart.** Each of the three
81
+ charts now builds ONE `LLMRequest` object and both sends it and fingerprints
82
+ it, and each routes its conversation through `stripFrameworkFields` — the
83
+ third rule of the one assembly — so the mint and the rebuild cannot drift.
84
+ Every other byte those charts commit is unchanged: measured by dumping each
85
+ chart's commit log, its per-bundle keys and its final state before and after,
86
+ and diffing (identical apart from the new `receipt` key).
87
+
88
+ ### Docs
89
+
90
+ - `src/lib/time-travel/README.md` — a "Which charts mint a receipt" table (chart
91
+ → mints? → the salt) with the builder example, and every measurement that
92
+ named an `LLMCall` view as receipt-less retaken on the shape that still is.
93
+ - `docs-next` `debug/time-travel.mdx` — the same section for the site. No new
94
+ route.
95
+ - `docs/design/2026-09-recorded-not-built.md` — entry 8's reproduction retaken
96
+ (it still stands; only its driver moved) and an appendix marking the standing
97
+ no-mint fact BUILT in 9.91.0, with the reasons that died and the one that
98
+ survives.
99
+
100
+ ## [9.90.0] - 2026-09-10
101
+
102
+ **The recording carries its own milestones.** Until now a stored run could not
103
+ say which of its stops were an LLM turn, a tool call or a decision: every reader
104
+ re-derived that from the stage id — `milestoneFor(runtimeStageId)`, a switch
105
+ that parses `#` and `/`, lives outside the recording, and goes stale the day a
106
+ stage is renamed. footprintjs 9.21 gave a chart a way to DECLARE a stage's
107
+ names at build time and stamp them on its first commit bundle
108
+ (`CommitBundle.tags`). This release puts the agent's milestones there — law 3
109
+ of footprintjs's declared-tags design: **the tag is the fact; the derivation is
110
+ the fallback.**
111
+
112
+ ### Added
113
+
114
+ - **Declared milestones, one vocabulary, one owner.** `conventions.ts` now
115
+ holds ONE table (local stage id → `Milestone`) that both `milestoneFor(id)`
116
+ and the new `milestoneTagsFor(localStageId)` read, so the fact on the bundle
117
+ and the fallback from the id can never disagree. Every milestone site in
118
+ `buildAgentChart`, `buildDynamicAgentChart`, `LLMCall` and the two messageAPI
119
+ charts declares `milestoneTagsFor(<its id>)` — never a literal. The wire
120
+ form: `milestone:<kind>` (what a reader filters on) and
121
+ `milestone-label:<label>` (the human word). Exported: `MILESTONE_KINDS`,
122
+ `MILESTONE_TAG_PREFIX`, `MILESTONE_LABEL_TAG_PREFIX`, `milestoneTag(kind)`,
123
+ `milestoneTags(milestone)`, `milestoneTagsFor(localStageId)` (throws for an
124
+ id the table does not classify — a wiring mistake is loud), and
125
+ `milestoneFromTags(tags, labelWhenUndeclared?)` (reads a bundle's tags back;
126
+ non-strings ignored; a `milestone:` tag with an unknown kind is `null`).
127
+ - **The Map advertises the vocabulary.** `buildTimeStructure` lists the tags
128
+ each stage CAN produce before any run — a lens draws its legend first.
129
+ - `examples/observability/25-declared-vs-derived-stops.ts` — one real run
130
+ scrubbed two ways: `tagStops(['milestone:llm-turn'])` (footprintjs's own
131
+ strategy, no agent id conventions) and a DERIVED mark (a write-set predicate:
132
+ stops where `currentSkillId` was written), with the measured cost of each on
133
+ 42 commits — declared 0.016 ms, write-set 0.020 ms, `milestoneStops`
134
+ 0.018 ms, and a `stateAt` fold per candidate stop 11.7 ms (≈ 750×). That
135
+ ratio is why the declaration is the fact and the derivation is the fallback.
136
+
137
+ ### Changed
138
+
139
+ - **`milestoneStops` reads the bundle first.** A stop's first bundle
140
+ (`log[stop.commitIdx]`, where footprintjs stamps the tags) decides: tags
141
+ present → they are the milestone, and a bundle tagged as something ELSE is
142
+ not a stop however recognisable its id; no tags at all → `milestoneFor(id)`,
143
+ exactly as before. A recording made before 9.90.0 therefore yields the same
144
+ axis it always did; `milestoneOf(stop)`, `Stop<Milestone>` and the labels
145
+ are unchanged in shape. `test/lib/time-travel/milestone-stops-equivalence.test.ts`
146
+ now also pins the TAG-ONLY axis against the id axis on every fixture (both
147
+ chart shapes, every drill, a paused-then-resumed run, an `LLMCall`) — the
148
+ forgotten-tag catch: a declaration site without its tag goes red — plus a
149
+ stripped-tags recording (the fallback), a mixed log, and the Map.
150
+ - **footprintjs `^9.21.1` (was `^9.20.0`)** — dev and peer. 9.21.1 is the
151
+ release that lets a subflow mounted as a decider / selector BRANCH carry
152
+ declared tags (`SubflowMountOptions.tags`, landing on the mount's FIRST
153
+ bundle), which is how the three context slots — `sf-system-prompt` /
154
+ `sf-messages` / `sf-tools`, selector branches in every Agent chart — declare
155
+ `milestone:slot`. **Every milestone stage is declared.** On a 9.90.0
156
+ recording the id fallback runs zero times, and the equivalence test counts
157
+ it on every fixture, so a future undeclared site is caught even where the
158
+ fallback would have hidden it on the axis.
159
+
160
+ ```ts
161
+ import { tagStops, timeTravel } from 'footprintjs/trace';
162
+ import { milestoneTag, milestoneStopsStrategy } from 'agentfootprint';
163
+
164
+ // A reader with NO agent id conventions — footprintjs's own strategy, our word:
165
+ const turns = timeTravel(agent.getSnapshot()!, { strategy: tagStops([milestoneTag('llm-turn')]) });
166
+ turns.stops.map((s) => s.label); // ['Run start', 'CallLLM', 'CallLLM', 'Run end']
167
+ turns.stops[1].meta; // ['milestone:llm-turn', 'milestone-label:LLM turn']
168
+
169
+ // The agent's own axis, unchanged in shape — tag first, id fallback:
170
+ const all = timeTravel(agent.getSnapshot()!, { strategy: milestoneStopsStrategy });
171
+ all.stops[5].meta; // { kind: 'llm-turn', label: 'LLM turn' } — read off the bundle
172
+ ```
173
+
10
174
  ## [9.89.3] - 2026-09-10
11
175
 
12
176
  **One owner of a subflow's served state.** A patch: no signature changes; a
@@ -11,7 +11,7 @@
11
11
  * Rename any ID here → both builders and recorders stay in sync.
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.isInjectionKey = exports.injectionKeyForSlot = exports.INJECTION_KEYS = exports.milestoneFor = exports.stageRole = exports.isKnownStage = exports.isKnownSubflow = exports.slotFromRuntimeStageId = exports.slotFromSubflowId = exports.isSlotSubflow = exports.STAGE_IDS = exports.assertUnreservedSubflowSegment = exports.isReservedSubflowSegment = exports.RESERVED_SUBFLOW_PREFIX = exports.SUBFLOW_IDS = void 0;
14
+ exports.isInjectionKey = exports.injectionKeyForSlot = exports.INJECTION_KEYS = exports.milestoneFromTags = exports.milestoneTagsFor = exports.milestoneTags = exports.milestoneTag = exports.MILESTONE_LABEL_TAG_PREFIX = exports.MILESTONE_TAG_PREFIX = exports.milestoneFor = exports.MILESTONE_KINDS = exports.stageRole = exports.isKnownStage = exports.isKnownSubflow = exports.slotFromRuntimeStageId = exports.slotFromSubflowId = exports.isSlotSubflow = exports.STAGE_IDS = exports.assertUnreservedSubflowSegment = exports.isReservedSubflowSegment = exports.RESERVED_SUBFLOW_PREFIX = exports.SUBFLOW_IDS = void 0;
15
15
  const trace_1 = require("footprintjs/trace");
16
16
  /** Subflow IDs — mounted by builders, observed by recorders. */
17
17
  exports.SUBFLOW_IDS = {
@@ -328,6 +328,54 @@ function stageRole(id) {
328
328
  return 'boundary'; // unknown → neutral (never silently muted)
329
329
  }
330
330
  exports.stageRole = stageRole;
331
+ /** Every {@link MilestoneKind}, for validating a kind read off a recording. */
332
+ exports.MILESTONE_KINDS = Object.freeze([
333
+ 'iteration',
334
+ 'slot',
335
+ 'llm-turn',
336
+ 'tool-call',
337
+ 'decision',
338
+ ]);
339
+ const milestone = (kind, label) => Object.freeze({ kind, label });
340
+ /**
341
+ * THE milestone table — local stage id → {@link Milestone}. One owner, two
342
+ * readers: {@link milestoneFor} classifies an id from a recording made BEFORE
343
+ * the chart declared tags (9.90.0), and {@link milestoneTagsFor} is what every
344
+ * chart-building site declares from, so the fact stamped on the commit bundle
345
+ * and the fallback derived from the id can never disagree.
346
+ */
347
+ const MILESTONES = new Map([
348
+ // Loop entry — one per ReAct iteration. INJECTION_ENGINE is the flat loop
349
+ // target; LLM_CALL is the subflow-shape loop target.
350
+ [exports.SUBFLOW_IDS.INJECTION_ENGINE, milestone('iteration', 'Iteration')],
351
+ [exports.SUBFLOW_IDS.LLM_CALL, milestone('iteration', 'Iteration')],
352
+ // Context slots — one stop per slot that was engineered THIS iteration. In
353
+ // dynamic mode all three appear every turn; in classic mode only the slot
354
+ // that actually re-ran (Messages) appears after turn 1 — so scrubbing shows
355
+ // exactly "which slot got updated."
356
+ [exports.SUBFLOW_IDS.SYSTEM_PROMPT, milestone('slot', 'System prompt')],
357
+ [exports.SUBFLOW_IDS.MESSAGES, milestone('slot', 'Messages')],
358
+ [exports.SUBFLOW_IDS.TOOLS, milestone('slot', 'Tools')],
359
+ [exports.STAGE_IDS.CALL_LLM, milestone('llm-turn', 'LLM turn')],
360
+ [exports.STAGE_IDS.MERGE_LLM, milestone('llm-turn', 'LLM turn')],
361
+ // Tool execution mounts under the bare branch key 'tool-calls'.
362
+ ['tool-calls', milestone('tool-call', 'Tool call')],
363
+ [exports.SUBFLOW_IDS.TOOL_CALLS, milestone('tool-call', 'Tool call')],
364
+ [exports.SUBFLOW_IDS.ROUTE, milestone('decision', 'Route')],
365
+ // The answer failed its schema and the loop asked again — a stop worth
366
+ // scrubbing to, because everything after it is a second attempt.
367
+ [exports.STAGE_IDS.OUTPUT_RETRY, milestone('decision', 'Schema retry')],
368
+ // The answer left declared steps unrun and the one teaching nudge went
369
+ // back (9.18.0) — everything after it is the model finishing (or
370
+ // explaining) its procedure.
371
+ [exports.STAGE_IDS.STEP_NUDGE, milestone('decision', 'Step nudge')],
372
+ // The answer stated values no tool result carried and the one revision
373
+ // went back (9.35.0) — everything after it is the model's second try.
374
+ [exports.STAGE_IDS.EVIDENCE_RECHECK, milestone('decision', 'Evidence recheck')],
375
+ // The action budget ran out and the turn was wrapped up (9.56.0) —
376
+ // everything after it is the model summarizing with no tools to call.
377
+ [exports.STAGE_IDS.WRAP_UP, milestone('decision', 'Wrap up')],
378
+ ]);
331
379
  /**
332
380
  * Classify a stage id into a {@link Milestone}, or `null` when the stage is NOT
333
381
  * a milestone boundary (its commits fold into the surrounding milestone's
@@ -335,6 +383,14 @@ exports.stageRole = stageRole;
335
383
  * the Lens consumes it to build the time-travel slider (see
336
384
  * agentfootprint-lens `cursorPositionsAtDrill`).
337
385
  *
386
+ * **Since 9.90.0 this is the FALLBACK, not the fact.** The charts declare the
387
+ * same milestones as tags at build time ({@link milestoneTagsFor}), footprintjs
388
+ * 9.21 stamps them on the stage's first commit bundle (`CommitBundle.tags`), and
389
+ * `milestoneStops` reads the bundle first — it derives from the id only for a
390
+ * bundle that carries no tags (a recording made before 9.90.0). Every milestone
391
+ * stage is declared, slot branch mounts included (footprintjs 9.21.1). Same
392
+ * table either way, so the two readings agree.
393
+ *
338
394
  * Mirrors {@link stageRole}: accepts a runtimeStageId (`call-llm#17`), a
339
395
  * path-qualified id (`sf-llm-call/call-llm`), or a bare local id — only the
340
396
  * LOCAL stage segment matters, so it works at any nesting depth and for both
@@ -345,53 +401,97 @@ function milestoneFor(id) {
345
401
  // the path prefix — splitStageId expects the segment before `#`.
346
402
  const beforeHash = id.includes('#') ? id.slice(0, id.indexOf('#')) : id;
347
403
  const { localStageId } = (0, trace_1.splitStageId)(beforeHash);
348
- switch (localStageId) {
349
- // Loop entry — one per ReAct iteration. INJECTION_ENGINE is the flat loop
350
- // target; LLM_CALL is the subflow-shape loop target.
351
- case exports.SUBFLOW_IDS.INJECTION_ENGINE:
352
- case exports.SUBFLOW_IDS.LLM_CALL:
353
- return { kind: 'iteration', label: 'Iteration' };
354
- // Context slots — one stop per slot that was engineered THIS iteration. In
355
- // dynamic mode all three appear every turn; in classic mode only the slot
356
- // that actually re-ran (Messages) appears after turn 1 — so scrubbing shows
357
- // exactly "which slot got updated."
358
- case exports.SUBFLOW_IDS.SYSTEM_PROMPT:
359
- return { kind: 'slot', label: 'System prompt' };
360
- case exports.SUBFLOW_IDS.MESSAGES:
361
- return { kind: 'slot', label: 'Messages' };
362
- case exports.SUBFLOW_IDS.TOOLS:
363
- return { kind: 'slot', label: 'Tools' };
364
- case exports.STAGE_IDS.CALL_LLM:
365
- case exports.STAGE_IDS.MERGE_LLM:
366
- return { kind: 'llm-turn', label: 'LLM turn' };
367
- // Tool execution mounts under the bare branch key 'tool-calls'.
368
- case 'tool-calls':
369
- case exports.SUBFLOW_IDS.TOOL_CALLS:
370
- return { kind: 'tool-call', label: 'Tool call' };
371
- case exports.SUBFLOW_IDS.ROUTE:
372
- return { kind: 'decision', label: 'Route' };
373
- // The answer failed its schema and the loop asked again — a stop worth
374
- // scrubbing to, because everything after it is a second attempt.
375
- case exports.STAGE_IDS.OUTPUT_RETRY:
376
- return { kind: 'decision', label: 'Schema retry' };
377
- // The answer left declared steps unrun and the one teaching nudge went
378
- // back (9.18.0) — everything after it is the model finishing (or
379
- // explaining) its procedure.
380
- case exports.STAGE_IDS.STEP_NUDGE:
381
- return { kind: 'decision', label: 'Step nudge' };
382
- // The answer stated values no tool result carried and the one revision
383
- // went back (9.35.0) — everything after it is the model's second try.
384
- case exports.STAGE_IDS.EVIDENCE_RECHECK:
385
- return { kind: 'decision', label: 'Evidence recheck' };
386
- // The action budget ran out and the turn was wrapped up (9.56.0) —
387
- // everything after it is the model summarizing with no tools to call.
388
- case exports.STAGE_IDS.WRAP_UP:
389
- return { kind: 'decision', label: 'Wrap up' };
390
- default:
391
- return null;
392
- }
404
+ return MILESTONES.get(localStageId) ?? null;
393
405
  }
394
406
  exports.milestoneFor = milestoneFor;
407
+ // ─── Declared milestones — the tag vocabulary (9.90.0) ──────────────────
408
+ //
409
+ // footprintjs 9.21 lets a chart put NAMES on a stage at build time and stamps
410
+ // them on the stage's first commit bundle. footprintjs owns no vocabulary; this
411
+ // is agentfootprint's. Two names per milestone, produced by ONE function and
412
+ // read back by ONE function — no second string literal anywhere:
413
+ //
414
+ // 'milestone:<kind>' what a reader FILTERS on (tagStops(['milestone:llm-turn']))
415
+ // 'milestone-label:<label>' the human word the table gives that stage
416
+ //
417
+ // Law 3 of docs/design/2026-09-declared-tags.md (footprintjs): the tag is the
418
+ // fact; the derivation from the id is the fallback.
419
+ /** Prefix of the tag that names a milestone's KIND: `milestone:llm-turn`. */
420
+ exports.MILESTONE_TAG_PREFIX = 'milestone:';
421
+ /** Prefix of the tag that names a milestone's LABEL: `milestone-label:LLM turn`. */
422
+ exports.MILESTONE_LABEL_TAG_PREFIX = 'milestone-label:';
423
+ /** The kind tag for a {@link MilestoneKind} — `'milestone:' + kind`. */
424
+ function milestoneTag(kind) {
425
+ return exports.MILESTONE_TAG_PREFIX + kind;
426
+ }
427
+ exports.milestoneTag = milestoneTag;
428
+ /**
429
+ * The tags that DECLARE a {@link Milestone} on a stage: its kind tag and its
430
+ * label tag, in that order. What a declaration site spreads into `.tag(...)`
431
+ * or `{ tags }`; what {@link milestoneFromTags} reads back.
432
+ */
433
+ function milestoneTags(milestone) {
434
+ return [milestoneTag(milestone.kind), exports.MILESTONE_LABEL_TAG_PREFIX + milestone.label];
435
+ }
436
+ exports.milestoneTags = milestoneTags;
437
+ /**
438
+ * The tags to declare on the stage with this LOCAL id, from the same table
439
+ * {@link milestoneFor} reads — so a chart-building site names the id it is
440
+ * mounting and never spells a kind or a label. Throws at build time for an id
441
+ * the table does not classify: a declaration site that is not a milestone is
442
+ * a wiring mistake, and a silent no-op would be a forgotten tag by another name.
443
+ *
444
+ * @example
445
+ * ```ts
446
+ * builder
447
+ * .addFunction('CallLLM', callLLM, STAGE_IDS.CALL_LLM, 'LLM invocation')
448
+ * .tag(...milestoneTagsFor(STAGE_IDS.CALL_LLM)); // 'milestone:llm-turn', 'milestone-label:LLM turn'
449
+ * ```
450
+ */
451
+ function milestoneTagsFor(localStageId) {
452
+ const found = MILESTONES.get(localStageId);
453
+ if (!found) {
454
+ throw new Error(`milestoneTagsFor('${localStageId}'): not a milestone stage — add it to the MILESTONES table in ` +
455
+ 'conventions.ts (the one owner) before declaring it on a chart.');
456
+ }
457
+ return milestoneTags(found);
458
+ }
459
+ exports.milestoneTagsFor = milestoneTagsFor;
460
+ /**
461
+ * Read a {@link Milestone} back off a commit bundle's declared `tags`, or
462
+ * `null` when they carry no milestone kind tag. The kind must be one of
463
+ * {@link MILESTONE_KINDS}; the label is the `milestone-label:` tag when one was
464
+ * declared, else `labelWhenUndeclared` (a reader passes the stop's own label —
465
+ * the chart's word for the stage), else the kind itself. A stored row is
466
+ * `unknown[]`-shaped until narrowed: non-strings are ignored, never a milestone.
467
+ *
468
+ * @example
469
+ * ```ts
470
+ * milestoneFromTags(['milestone:llm-turn', 'milestone-label:LLM turn']);
471
+ * // { kind: 'llm-turn', label: 'LLM turn' }
472
+ * milestoneFromTags(['audit']); // null — tagged, but not a milestone
473
+ * milestoneFromTags(undefined); // null — an untagged bundle
474
+ * ```
475
+ */
476
+ function milestoneFromTags(tags, labelWhenUndeclared) {
477
+ if (!Array.isArray(tags))
478
+ return null;
479
+ const names = tags.filter((t) => typeof t === 'string');
480
+ // The first VALID kind wins; an unknown `milestone:` name (a foreign chart's
481
+ // vocabulary) is skipped rather than shadowing a real kind beside it.
482
+ const kinds = names
483
+ .filter((t) => t.startsWith(exports.MILESTONE_TAG_PREFIX))
484
+ .map((t) => t.slice(exports.MILESTONE_TAG_PREFIX.length))
485
+ .filter((k) => exports.MILESTONE_KINDS.includes(k));
486
+ const kind = kinds[0];
487
+ if (kind === undefined)
488
+ return null;
489
+ const labelTag = names.find((t) => t.startsWith(exports.MILESTONE_LABEL_TAG_PREFIX));
490
+ const declared = labelTag?.slice(exports.MILESTONE_LABEL_TAG_PREFIX.length);
491
+ const label = declared && declared.length > 0 ? declared : labelWhenUndeclared ?? kind;
492
+ return { kind: kind, label };
493
+ }
494
+ exports.milestoneFromTags = milestoneFromTags;
395
495
  /**
396
496
  * Scope-key convention for context injections.
397
497
  *
@@ -1 +1 @@
1
- {"version":3,"file":"conventions.js","sourceRoot":"","sources":["../src/conventions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"conventions.js","sourceRoot":"","sources":["../src/conventions.ts"],"names":[],"mappings":"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"}
@@ -54,6 +54,7 @@ const SkillRecorder_js_1 = require("../recorders/core/SkillRecorder.js");
54
54
  const typedEmit_js_1 = require("../recorders/core/typedEmit.js");
55
55
  const resilienceHooks_js_1 = require("../recorders/core/resilienceHooks.js");
56
56
  const ResilienceRecorder_js_1 = require("../recorders/core/ResilienceRecorder.js");
57
+ const receipt_js_1 = require("../lib/time-travel/receipt.js");
57
58
  const cost_js_1 = require("./cost.js");
58
59
  const RunnerBase_js_1 = require("./RunnerBase.js");
59
60
  const runInput_js_1 = require("./runInput.js");
@@ -77,6 +78,8 @@ class LLMCall extends RunnerBase_js_1.RunnerBase {
77
78
  contextBudget;
78
79
  /** `LLMCallOptions.recordSystemPrompt` (9.50.0) — opt-in, default OFF. */
79
80
  recordSystemPromptValue = false;
81
+ /** `LLMCallOptions.recordReceipt` (9.91.0) — opt-OUT, default ON. */
82
+ recordReceiptValue = true;
80
83
  structureRecorders;
81
84
  groupTranslator;
82
85
  /** Auto-resolved from provider.name at construction time (same
@@ -114,6 +117,8 @@ class LLMCall extends RunnerBase_js_1.RunnerBase {
114
117
  this.contextBudget = opts.contextBudget;
115
118
  if (opts.recordSystemPrompt === true)
116
119
  this.recordSystemPromptValue = true;
120
+ if (opts.recordReceipt === false)
121
+ this.recordReceiptValue = false;
117
122
  if (opts.structureRecorders)
118
123
  this.structureRecorders = opts.structureRecorders;
119
124
  if (opts.groupTranslator)
@@ -251,6 +256,12 @@ class LLMCall extends RunnerBase_js_1.RunnerBase {
251
256
  const pricingTable = this.pricingTable;
252
257
  const costBudget = this.costBudget;
253
258
  const thinkingHandler = this.thinkingHandler;
259
+ const recordReceipt = this.recordReceiptValue;
260
+ // THE SALT (9.91.0). `createExecutor` mints a fresh run id on every run and
261
+ // every resume, and the chart is built once — so the receipt reads it
262
+ // through `this` AT CALL TIME rather than closing over a value that would
263
+ // be one run stale on the second run of the same LLMCall.
264
+ const getRunId = () => this.currentRunContext.runId;
254
265
  // ─── Outer Client stage ─────────────────────────────────────────
255
266
  // First visit: receives args, sets userMessage on outer scope.
256
267
  // Second visit (post-loop): scope.answer has been populated by the
@@ -315,7 +326,12 @@ class LLMCall extends RunnerBase_js_1.RunnerBase {
315
326
  // reason the system-prompt join is one: `LLMCall` has no `history`, so
316
327
  // these records ARE the committed conversation, and `servedAt` rebuilds
317
328
  // it by calling this identical function over the identical records.
318
- const messages = (0, composeRequest_js_1.messagesFromInjections)(messagesInjections);
329
+ //
330
+ // The framework-field strip rides with it (9.91.0) — the third rule of
331
+ // the one assembly. It is identity on what this slot composes today, and
332
+ // it is here so the two sides cannot drift the day that changes: the
333
+ // rebuild applies it, so the mint applies it.
334
+ const messages = (0, composeRequest_js_1.stripFrameworkFields)((0, composeRequest_js_1.messagesFromInjections)(messagesInjections));
319
335
  (0, typedEmit_js_1.typedEmit)(scope, 'agentfootprint.stream.llm_start', {
320
336
  iteration,
321
337
  provider: provider.name,
@@ -329,17 +345,56 @@ class LLMCall extends RunnerBase_js_1.RunnerBase {
329
345
  ...(temperature !== undefined && { temperature }),
330
346
  });
331
347
  const startMs = Date.now();
332
- // Raw provider errors propagate untouched (reliability + merge
333
- // layers classify on the raw message). The friendly translation
334
- // for non-developers happens once at the terminal boundary —
335
- // ErrorBridge humanizes the `error.fatal` event the monitor reads.
336
- const response = await provider.complete({
348
+ // ONE request object, built once and both sent and fingerprinted —
349
+ // never assembled twice (9.91.0). A second literal at the mint would be
350
+ // a second assembly, and the whole point of a receipt is that it
351
+ // describes THIS one.
352
+ const request = {
337
353
  systemPrompt: systemPrompt.length > 0 ? systemPrompt : undefined,
338
354
  messages,
339
355
  model,
340
356
  ...(temperature !== undefined && { temperature }),
341
357
  ...(maxTokens !== undefined && { maxTokens }),
342
- },
358
+ };
359
+ // ── THE RECEIPT (9.91.0) ─────────────────────────────────────────
360
+ // Written immediately before the provider is called, so it is committed
361
+ // in the call-llm bundle that already exists — and before rather than
362
+ // after on purpose: the stage commits on the error path too, so a call
363
+ // that throws still leaves the record of what it was about to send.
364
+ //
365
+ // The mint is `receipt.ts` · `buildReceipt`, the same one the agent's
366
+ // `call-llm` calls, salted with this run's own id. There is no cache
367
+ // strategy on this chart, so the request handed out is the request
368
+ // assembled: `baseRequest` and `preparedRequest` are the same object and
369
+ // `cache.transform` records `'unchanged'` — exactly what an agent
370
+ // running a pass-through strategy records, and true for the same reason.
371
+ //
372
+ // NOT HERE: `omittedForAttention`. A slot's budget drops live in
373
+ // `slotCompositions` inside the slot's own subflow and no boundary
374
+ // bubbles them out, so the key is absent at this scope. A receipt
375
+ // records what the run knows; it does not go looking.
376
+ if (recordReceipt) {
377
+ scope[receipt_js_1.RECEIPT_KEY] = (0, receipt_js_1.buildReceipt)({
378
+ runId: getRunId(),
379
+ epoch: iteration,
380
+ model,
381
+ provider: provider.name,
382
+ systemText: systemPrompt,
383
+ systemPieces: (0, receipt_js_1.receiptPieces)(systemPromptInjections),
384
+ messages,
385
+ requestOnly: [],
386
+ tools: [],
387
+ forced: null,
388
+ withheld: null,
389
+ baseRequest: request,
390
+ preparedRequest: request,
391
+ });
392
+ }
393
+ // Raw provider errors propagate untouched (reliability + merge
394
+ // layers classify on the raw message). The friendly translation
395
+ // for non-developers happens once at the terminal boundary —
396
+ // ErrorBridge humanizes the `error.fatal` event the monitor reads.
397
+ const response = await provider.complete(request,
343
398
  // Resilience-report channel: a decorated provider's fallback /
344
399
  // retry / recovery becomes an in-run typed event here.
345
400
  (0, resilienceHooks_js_1.resilienceHooks)(scope));
@@ -384,6 +439,10 @@ class LLMCall extends RunnerBase_js_1.RunnerBase {
384
439
  }),
385
440
  outputMapper: (sfOutput) => ({ systemPromptInjections: sfOutput.systemPromptInjections }),
386
441
  })
442
+ // Declared milestones (9.90.0): these slots are `addSubFlowChartNext`
443
+ // mounts, so — unlike the Agent charts' selector branches — they CAN
444
+ // carry the `slot` tag on their first commit bundle.
445
+ .tag(...(0, conventions_js_1.milestoneTagsFor)(conventions_js_1.SUBFLOW_IDS.SYSTEM_PROMPT))
387
446
  .addSubFlowChartNext(conventions_js_1.SUBFLOW_IDS.MESSAGES, messagesSubflow, 'Messages', {
388
447
  inputMapper: (parent) => {
389
448
  // Wrap the single user message as a one-entry history for the
@@ -396,7 +455,10 @@ class LLMCall extends RunnerBase_js_1.RunnerBase {
396
455
  },
397
456
  outputMapper: (sfOutput) => ({ messagesInjections: sfOutput.messagesInjections }),
398
457
  })
399
- .addFunction('CallLLM', callLLM, conventions_js_1.STAGE_IDS.CALL_LLM, 'LLM invocation');
458
+ .tag(...(0, conventions_js_1.milestoneTagsFor)(conventions_js_1.SUBFLOW_IDS.MESSAGES))
459
+ .addFunction('CallLLM', callLLM, conventions_js_1.STAGE_IDS.CALL_LLM, 'LLM invocation')
460
+ // Declared milestone (9.90.0): the LLM turn.
461
+ .tag(...(0, conventions_js_1.milestoneTagsFor)(conventions_js_1.STAGE_IDS.CALL_LLM));
400
462
  // Conditional sf-thinking — mounted only when a ThinkingHandler
401
463
  // resolved (auto-wired by provider.name in the constructor). Same
402
464
  // build-time conditional pattern Agent uses (buildAgentChart.ts).
@@ -425,7 +487,7 @@ class LLMCall extends RunnerBase_js_1.RunnerBase {
425
487
  // TraversalResult is the answer string, which downstream
426
488
  // compositions (Sequence/Parallel/Conditional) read via
427
489
  // outputMapper's `sfOutput` parameter.
428
- return (0, footprintjs_1.flowChart)('Client', client, conventions_js_1.STAGE_IDS.CLIENT, {
490
+ return ((0, footprintjs_1.flowChart)('Client', client, conventions_js_1.STAGE_IDS.CLIENT, {
429
491
  ...(this.structureRecorders !== undefined && {
430
492
  structureRecorders: [...this.structureRecorders],
431
493
  }),
@@ -440,8 +502,11 @@ class LLMCall extends RunnerBase_js_1.RunnerBase {
440
502
  answer: sfOutput.answer,
441
503
  }),
442
504
  })
505
+ // Declared milestone (9.90.0): the mount is the iteration boundary on the
506
+ // outer log — one turn per LLMCall run.
507
+ .tag(...(0, conventions_js_1.milestoneTagsFor)(conventions_js_1.SUBFLOW_IDS.LLM_CALL))
443
508
  .loopTo(conventions_js_1.STAGE_IDS.CLIENT)
444
- .build();
509
+ .build());
445
510
  }
446
511
  }
447
512
  exports.LLMCall = LLMCall;