agentfootprint-lens 0.46.0 → 0.47.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 (36) hide show
  1. package/README.md +133 -0
  2. package/dist/{Lens-Bdz-JzVm.d.ts → Lens-9wZ84e70.d.ts} +2 -2
  3. package/dist/{Lens-6elRg27j.d.cts → Lens-Ccs8UUDQ.d.cts} +2 -2
  4. package/dist/{chunk-WN2RJKEH.js → chunk-A3NWHAJ2.js} +2 -2
  5. package/dist/{chunk-SJEKKUTI.js → chunk-E5ZRMHYY.js} +503 -2
  6. package/dist/chunk-E5ZRMHYY.js.map +1 -0
  7. package/dist/{chunk-A4EIPCLY.js → chunk-ZNH33A7V.js} +1176 -279
  8. package/dist/chunk-ZNH33A7V.js.map +1 -0
  9. package/dist/core.cjs +502 -2
  10. package/dist/core.cjs.map +1 -1
  11. package/dist/core.d.cts +434 -8
  12. package/dist/core.d.ts +434 -8
  13. package/dist/core.js +18 -4
  14. package/dist/index.cjs +2129 -736
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +139 -10
  17. package/dist/index.d.ts +139 -10
  18. package/dist/index.js +22 -4
  19. package/dist/index.js.map +1 -1
  20. package/dist/{lensStops-hQ10t3Lt.d.cts → lensStops-DfNxsaH0.d.cts} +1 -1
  21. package/dist/{lensStops-DAc3GB8G.d.ts → lensStops-Di41Rg3f.d.ts} +1 -1
  22. package/dist/{resolveNavigation-o4E4cM_1.d.ts → resolveNavigation-Ckr2nXHY.d.cts} +9 -0
  23. package/dist/{resolveNavigation-o4E4cM_1.d.cts → resolveNavigation-Ckr2nXHY.d.ts} +9 -0
  24. package/dist/{selectSkillFrameContext-IPsw4Pbj.d.ts → selectSkillFrameContext-DEk_qpXr.d.ts} +1 -1
  25. package/dist/{selectSkillFrameContext-DJkvrggG.d.cts → selectSkillFrameContext-DjZDveZw.d.cts} +1 -1
  26. package/dist/skillgraph.d.cts +4 -4
  27. package/dist/skillgraph.d.ts +4 -4
  28. package/dist/why.cjs +1583 -206
  29. package/dist/why.cjs.map +1 -1
  30. package/dist/why.d.cts +5 -5
  31. package/dist/why.d.ts +5 -5
  32. package/dist/why.js +2 -2
  33. package/package.json +2 -2
  34. package/dist/chunk-A4EIPCLY.js.map +0 -1
  35. package/dist/chunk-SJEKKUTI.js.map +0 -1
  36. /package/dist/{chunk-WN2RJKEH.js.map → chunk-A3NWHAJ2.js.map} +0 -0
package/README.md CHANGED
@@ -935,6 +935,129 @@ not answer, since it takes an exact stop.
935
935
 
936
936
  ---
937
937
 
938
+ ## The Served tab
939
+
940
+ **At every LLM call, exactly what the model was served — provable from the log.**
941
+ The Why Lens's right rail has a second tab, **Served**, mounted for every run.
942
+ Stand on an LLM turn and it shows the request that call went out with: the system
943
+ prompt (piece by piece), the messages as sent, the tools as sent, the dials, the
944
+ cache breakpoints — and beside every field, what the record can PROVE about it.
945
+
946
+ ### Why
947
+
948
+ The request a provider receives is assembled from committed pieces and is itself
949
+ never committed — the `call-llm` bundle holds the answer, not the ask. Every
950
+ earlier "what did the model see?" panel in this family read an event
951
+ (`llm_start`) that only some runs record, or rebuilt the prompt from the pieces
952
+ with no way to know whether the rebuild matched what went out.
953
+
954
+ agentfootprint 9.88.0 closes that with two halves and one law:
955
+
956
+ ```
957
+ hash(servedAt(k)) === receiptAt(k).hash
958
+ ```
959
+
960
+ `servedAt(k)` REBUILDS the request for epoch `k` (one epoch = one LLM call) from
961
+ the committed pieces. `receiptAt(k)` reads the **receipt** — the hashes-only
962
+ record the call itself committed at the stop (system hash and pieces, one hash
963
+ per message, tool names and schema hashes, the sampling dials, the cache
964
+ verdict). When the two agree the record is complete; when they disagree,
965
+ something reached the model that the run never wrote down. The tab renders both
966
+ halves at the lens's one cursor and checks them with the library's own
967
+ `receiptHash` / `messageDigestInput`.
968
+
969
+ ### What each badge means
970
+
971
+ | badge | exactly this |
972
+ |---|---|
973
+ | **Verified** | the receipt's hash for the field EQUALS the hash of what the rebuild produced — run-salted SHA-256, computed with agentfootprint's exported `receiptHash` (over `messageDigestInput` for a message). Nothing softer earns it. |
974
+ | **Reconstructed** | rebuilt from the log, but nothing to check it against: this epoch committed no receipt, the receipt has no hash for this row, or a gap on the view covers the field (a declared hole, printed beside it). Tool NAMES are always here — they carry no hash. Tool SCHEMAS are here too, because the library hashes them over a canonical JSON it does not export, and a lookalike serializer would be a second copy of the rule. |
975
+ | **Damaged** | the record contradicts itself: the receipt's hash disagrees with the rebuild and no gap excuses it, the rebuild produced a row the receipt never witnessed (no gap says a rebuild may be LONG — the receipt is the witness in both directions), or something under the receipt key was refused as not-a-receipt (`cause: 'receipt-shape-rejected'` — the library refuses a value with no `basis.epoch`, the lens refuses one missing the containers it reads). |
976
+ | **Not on record** | the field is absent on both sides — a receipt-only field (model, provider, params, cache) on an epoch that minted no receipt. |
977
+
978
+ ### The laws the tab keeps
979
+
980
+ - **Omit, never deny.** A field a gap covers is never rendered as "empty" or
981
+ "none". The gap IS the empty state: its `why` sentence, verbatim from
982
+ `SERVED_GAPS`, is printed beside the field it covers, and the section is
983
+ marked with the gap's name.
984
+ - **The tab writes no claim sentences of its own.** Every explanatory sentence
985
+ on it is the library's — `SERVED_GAPS[k].why`, `UNGAPPED_FIELDS[k]`,
986
+ `RECEIPT_BOUNDARY` — or is computed data: a status, a count, a hash, a diff.
987
+ The strings the tab owns are labels (`SERVED_LABELS`), and
988
+ `test/served/no-own-claims.test.ts` walks every literal in the tab's source to
989
+ keep it that way; its header states what such a walk cannot catch.
990
+ - **Authority omissions come from the fold.** A receipt never names what a
991
+ caller's ROLE was not allowed to see (the library's first law). The tab's
992
+ audience is an operator, so it MAY show the skill ids hidden from the model —
993
+ but it reads them from the committed state at the stop through footprintjs's
994
+ `stateAt`, labelled **hidden from the model**, never from the receipt.
995
+ - **One cursor.** The tab takes the lens's position as props and holds none of
996
+ its own. On an llm-turn stop it shows that epoch. On any other stop it shows
997
+ the nearest PRECEDING call with the note *as of call k — this stop is between
998
+ calls*. Clicking the call's id asks the lens to move the one cursor there.
999
+ A resumed leg's first call has no previous epoch IN THIS RECORDING; the tab
1000
+ prints that epoch's number with *Not on record*, never "no previous epoch".
1001
+ - **A record never takes the Lens down.** A half-shaped receipt reads
1002
+ *Damaged*; a commit-log row the fold cannot read is data in the FOLD
1003
+ section; a render throw is caught by a boundary around the tab and printed
1004
+ as the Damaged badge plus the message. The rest of the Lens — its one
1005
+ cursor, its *What happened* tab — stays mounted.
1006
+
1007
+ ### The sections
1008
+
1009
+ **SERVED** — system prompt with per-piece boundaries (slot · source) and a
1010
+ word-level diff against the previous epoch when the text changed; messages as
1011
+ sent (role, tool-call ids, request-only lines marked with the mechanism that
1012
+ composed them); tools as sent (names, expandable schemas, the forced tool
1013
+ marked, `withheld` shown as the library states it). **BASIS** — epoch, call id,
1014
+ commit index, model, provider, params (only the dials the receipt carries — an
1015
+ absent dial is not rendered as a default), cache (transform, breakpoints
1016
+ applied). **FOLD** — `iteration`, `currentSkillId`, `stepPointer`, engagement,
1017
+ active injections, hidden skill ids, read from the fold at the stop; a row the
1018
+ fold could not read is printed there as data (skipped indices, or the fold's
1019
+ error), beside a Damaged badge.
1020
+ **OMISSIONS** — attention drops from the receipt when present, else the
1021
+ library's `UNGAPPED_FIELDS` sentence for the field. **GAPS** — every gap on the
1022
+ view: its kind, the fields it covers, its sentence verbatim, and its `cause`
1023
+ when the library established one (`receipt-shape-rejected` styled as damage).
1024
+ **SINCE PREVIOUS** — messages entered/left, tools added/removed, schemas whose
1025
+ receipt hashes changed, and the system-text word diff.
1026
+
1027
+ ### Headless
1028
+
1029
+ ```ts
1030
+ import {
1031
+ servedRowAt, servedRowForEpoch, verify, sincePrevious, foldFactsAt,
1032
+ } from 'agentfootprint-lens/core';
1033
+
1034
+ const snapshot = runner.getLastSnapshot();
1035
+ const row = servedRowAt(snapshot, { runtimeStageId: 'call-llm#18', commitIdx: 15 });
1036
+ if (row) {
1037
+ row.epoch; // 1
1038
+ row.betweenCalls; // false — on the call itself
1039
+ const checks = verify(row.view, row.receipt, row.receipt?.basis.runId ?? '');
1040
+ checks.system.status; // 'verified'
1041
+ checks.messages.map((c) => c.status); // ['verified']
1042
+ row.view.gaps.map((g) => g.why); // the library's sentences
1043
+ const prev = row.previousEpoch !== undefined
1044
+ ? servedRowForEpoch(snapshot, row.previousEpoch) : undefined;
1045
+ if (prev) sincePrevious(row, prev).tools.added; // ['charge']
1046
+ foldFactsAt(snapshot, { runtimeStageId: 'call-llm#18', commitIdx: 15 }).hiddenSkillIds;
1047
+ }
1048
+ ```
1049
+
1050
+ Every function is pure and every return is frozen. `<ServedTab runner
1051
+ cursorRuntimeStageId commitIdx onJumpTo>` is exported for shells that hold the
1052
+ one cursor themselves.
1053
+
1054
+ **A recording made before agentfootprint 9.88** still renders: the rebuild works
1055
+ on every epoch, no receipt was minted, and the tab says so with the library's
1056
+ `no-receipt-on-chart` gap and `cause: 'no-receipt-committed'` — every row
1057
+ **Reconstructed**, never a fabricated **Verified**.
1058
+
1059
+ ---
1060
+
938
1061
  ## Rendering your own detail pane
939
1062
 
940
1063
  `slots.detail` replaces the CONTENT of the shipped right column. The column
@@ -1154,6 +1277,16 @@ exact `formatSlice` text the LLM tool returns. Honest absence stays honest:
1154
1277
  "never written — initial state / args / a closure", and reads-off runs say
1155
1278
  "unknowable, not absent".
1156
1279
 
1280
+ ### `<ServedTab>` — what the model was served at the cursor's call
1281
+
1282
+ `<ServedTab runner cursorRuntimeStageId commitIdx onJumpTo?>`. The Why Lens
1283
+ mounts it as the right rail's second tab; exported for consumer-built shells.
1284
+ Renders `servedAt(k)` and `receiptAt(k)` (agentfootprint 9.88.0) at the one
1285
+ cursor with a **Verified / Reconstructed / Damaged / Not on record** badge per
1286
+ field, the library's gap sentences verbatim, the fold's hidden skill ids, and a
1287
+ since-previous diff. Headless: `servedRowAt` · `verify` · `sincePrevious` ·
1288
+ `foldFactsAt` in `/core`. See "The Served tab" above.
1289
+
1157
1290
  ### `<BugReportButton>` — report a bug with the run attached, consent first
1158
1291
 
1159
1292
  A small button for a debug UI. The dialog it opens shows every selectable unit
@@ -3,8 +3,8 @@ import { ToolChoiceCall, ToolChoiceSummary } from 'agentfootprint/observe';
3
3
  import * as agentfootprint from 'agentfootprint';
4
4
  import { CommentaryTemplates } from 'agentfootprint';
5
5
  import React__default, { Ref } from 'react';
6
- import { d as NavigationResult, C as CursorPosition, L as LensRecorder } from './resolveNavigation-o4E4cM_1.js';
7
- import { C as ChartGroupHighlight, a as LensCursorPort, H as Humanizer } from './lensStops-DAc3GB8G.js';
6
+ import { d as NavigationResult, C as CursorPosition, L as LensRecorder } from './resolveNavigation-Ckr2nXHY.js';
7
+ import { C as ChartGroupHighlight, a as LensCursorPort, H as Humanizer } from './lensStops-Di41Rg3f.js';
8
8
  import { NodeTypes } from '@xyflow/react';
9
9
  import { TraceGraph, TraceFlowLayout, RuntimeOverlay } from 'footprint-explainable-ui/flowchart';
10
10
 
@@ -3,8 +3,8 @@ import { ToolChoiceCall, ToolChoiceSummary } from 'agentfootprint/observe';
3
3
  import * as agentfootprint from 'agentfootprint';
4
4
  import { CommentaryTemplates } from 'agentfootprint';
5
5
  import React__default, { Ref } from 'react';
6
- import { d as NavigationResult, C as CursorPosition, L as LensRecorder } from './resolveNavigation-o4E4cM_1.cjs';
7
- import { C as ChartGroupHighlight, a as LensCursorPort, H as Humanizer } from './lensStops-hQ10t3Lt.cjs';
6
+ import { d as NavigationResult, C as CursorPosition, L as LensRecorder } from './resolveNavigation-Ckr2nXHY.cjs';
7
+ import { C as ChartGroupHighlight, a as LensCursorPort, H as Humanizer } from './lensStops-DfNxsaH0.cjs';
8
8
  import { NodeTypes } from '@xyflow/react';
9
9
  import { TraceGraph, TraceFlowLayout, RuntimeOverlay } from 'footprint-explainable-ui/flowchart';
10
10
 
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  formatBytes,
3
3
  structureGraphFromRunner
4
- } from "./chunk-SJEKKUTI.js";
4
+ } from "./chunk-E5ZRMHYY.js";
5
5
 
6
6
  // src/core/buildStepGraphFromSnapshot.ts
7
7
  function buildStepGraphFromSnapshot(snapshot) {
@@ -1189,4 +1189,4 @@ export {
1189
1189
  decisionSentence,
1190
1190
  isConsentDecision
1191
1191
  };
1192
- //# sourceMappingURL=chunk-WN2RJKEH.js.map
1192
+ //# sourceMappingURL=chunk-A3NWHAJ2.js.map