agentfootprint-lens 0.59.0 → 0.61.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 (38) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-4AKGKXD6.js → chunk-3LXZ7D65.js} +2 -2
  3. package/dist/{chunk-DI4GDHM7.js → chunk-DTQ44DWN.js} +4 -4
  4. package/dist/{chunk-RMY2NAL3.js → chunk-IPCNNYQU.js} +2 -2
  5. package/dist/chunk-JMH3WAZK.js +594 -0
  6. package/dist/chunk-JMH3WAZK.js.map +1 -0
  7. package/dist/{chunk-JH5SK5E3.js → chunk-P63SOXBD.js} +2 -2
  8. package/dist/{chunk-3VTQOYYI.js → chunk-X6AWFDSB.js} +104 -15
  9. package/dist/chunk-X6AWFDSB.js.map +1 -0
  10. package/dist/{chunk-37NHCNSS.js → chunk-XEAZRBOH.js} +6 -3
  11. package/dist/chunk-XEAZRBOH.js.map +1 -0
  12. package/dist/context.cjs +732 -388
  13. package/dist/context.cjs.map +1 -1
  14. package/dist/context.d.cts +6 -1
  15. package/dist/context.d.ts +6 -1
  16. package/dist/context.js +4 -4
  17. package/dist/core.cjs +5 -2
  18. package/dist/core.cjs.map +1 -1
  19. package/dist/core.d.cts +8 -1
  20. package/dist/core.d.ts +8 -1
  21. package/dist/core.js +4 -4
  22. package/dist/index.cjs +686 -340
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +10 -0
  25. package/dist/index.d.ts +10 -0
  26. package/dist/index.js +7 -7
  27. package/dist/why.cjs +107 -15
  28. package/dist/why.cjs.map +1 -1
  29. package/dist/why.js +4 -4
  30. package/package.json +3 -3
  31. package/dist/chunk-37NHCNSS.js.map +0 -1
  32. package/dist/chunk-3VTQOYYI.js.map +0 -1
  33. package/dist/chunk-ZVBDU3F5.js +0 -340
  34. package/dist/chunk-ZVBDU3F5.js.map +0 -1
  35. /package/dist/{chunk-4AKGKXD6.js.map → chunk-3LXZ7D65.js.map} +0 -0
  36. /package/dist/{chunk-DI4GDHM7.js.map → chunk-DTQ44DWN.js.map} +0 -0
  37. /package/dist/{chunk-RMY2NAL3.js.map → chunk-IPCNNYQU.js.map} +0 -0
  38. /package/dist/{chunk-JH5SK5E3.js.map → chunk-P63SOXBD.js.map} +0 -0
package/README.md CHANGED
@@ -78,7 +78,7 @@ changes.
78
78
  |---|---|
79
79
  | `agentfootprint-lens/why` | Replay a recording as the agent's own milestones. `<WhyLens recording={...} />` takes the recording straight (`recordRun()`'s `{ snapshot, events, structure }`, or the `persistRecording` envelope), validates it at mount, and mounts the shipped `<Lens>` shell on the milestone axis — plus the axis helpers (`scrubAxisFor`, `stepForCommitIdx`, `stepForRuntimeStageId`, `resolveNavigation`) for hosts holding one cursor across views. |
80
80
  | `agentfootprint-lens/skillgraph` | Debug how a run routed through its skills. `<SkillGraphDebugger recorder={...} />` plus its headless selectors (`selectSkillRoute`, `selectSkillBeats`, `selectSkillTopology`, `selectSkillFrameContext`, `stepForRuntimeStageId`, `resolveNavigation`). |
81
- | `agentfootprint-lens/context` | What the model HAD at a stop — the served document of that epoch on top (the Served tab itself: pieces, messages, tools, verdicts, delta since the previous call) — and what it was BUILT from beneath: the record key by key, who wrote each, what moved; a long value opens in place (0.54.0). `<ContextView runner={...} />` walks the milestone axis on its own; hand it `cursor` and it follows the ONE cursor (0.53.1). |
81
+ | `agentfootprint-lens/context` | What the model HAD at a stop — the served document of that epoch on top (the Served tab itself: pieces, messages, tools, verdicts, delta since the previous call) — and what it was BUILT from beneath: the record key by key, who wrote each, what moved; a long value opens in place (0.54.0). `<ContextView runner={...} />` walks the milestone axis on its own; hand it `cursor` and it follows the ONE cursor (0.53.1). Under the record, the **Findings** band (0.61.0): on an armed run (`.findings()`, agentfootprint 9.101) the model's own ledger at the stop, folded for reading — facts, conflicts as first seen (each witness with its current standing, no verdict), open, ruled out, noise, undeclared — every string off the record, absent on an unarmed run. |
82
82
 
83
83
  The axis model in three sentences: one run leaves one causal trace, and each
84
84
  lens replays one AXIS of it — the Why reading scrubs the milestones, the Flow
@@ -3,7 +3,7 @@ import {
3
3
  servedRowForEpoch,
4
4
  sincePrevious,
5
5
  verify
6
- } from "./chunk-37NHCNSS.js";
6
+ } from "./chunk-XEAZRBOH.js";
7
7
 
8
8
  // src/core/context/contextAt.ts
9
9
  import * as trace from "footprintjs/trace";
@@ -139,4 +139,4 @@ function contextAt(recording, cursor, options = {}) {
139
139
  export {
140
140
  contextAt
141
141
  };
142
- //# sourceMappingURL=chunk-4AKGKXD6.js.map
142
+ //# sourceMappingURL=chunk-3LXZ7D65.js.map
@@ -14,19 +14,19 @@ import {
14
14
  structureGraphFromRunner,
15
15
  tagLegend,
16
16
  toSidecar
17
- } from "./chunk-RMY2NAL3.js";
17
+ } from "./chunk-IPCNNYQU.js";
18
18
  import {
19
19
  useNarrowRow
20
20
  } from "./chunk-S3WZBG5I.js";
21
21
  import {
22
22
  ServedTab
23
- } from "./chunk-3VTQOYYI.js";
23
+ } from "./chunk-X6AWFDSB.js";
24
24
  import {
25
25
  snapshotLogKey,
26
26
  snapshotOfRunner,
27
27
  tagAxisPositions,
28
28
  tagStopsStrategy
29
- } from "./chunk-37NHCNSS.js";
29
+ } from "./chunk-XEAZRBOH.js";
30
30
  import {
31
31
  MODE_PALETTES,
32
32
  T,
@@ -4784,4 +4784,4 @@ export {
4784
4784
  useBookmarkSidecar,
4785
4785
  Lens
4786
4786
  };
4787
- //# sourceMappingURL=chunk-DI4GDHM7.js.map
4787
+ //# sourceMappingURL=chunk-DTQ44DWN.js.map
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-62D2ENRC.js";
7
7
  import {
8
8
  mountLogsOf
9
- } from "./chunk-37NHCNSS.js";
9
+ } from "./chunk-XEAZRBOH.js";
10
10
  import {
11
11
  selectAgentInstances
12
12
  } from "./chunk-2JAWSPNG.js";
@@ -2700,4 +2700,4 @@ export {
2700
2700
  noBookmarkStore,
2701
2701
  tagLegend
2702
2702
  };
2703
- //# sourceMappingURL=chunk-RMY2NAL3.js.map
2703
+ //# sourceMappingURL=chunk-IPCNNYQU.js.map
@@ -0,0 +1,594 @@
1
+ import {
2
+ contextAt
3
+ } from "./chunk-3LXZ7D65.js";
4
+ import {
5
+ ServedTab
6
+ } from "./chunk-X6AWFDSB.js";
7
+ import {
8
+ snapshotLogKey,
9
+ snapshotOfRunner,
10
+ tagAxisPositions
11
+ } from "./chunk-XEAZRBOH.js";
12
+ import {
13
+ TimeTravel
14
+ } from "./chunk-CO5R2ODI.js";
15
+ import {
16
+ lensCursorFrom,
17
+ scrubAxisFor
18
+ } from "./chunk-BFAI2IPA.js";
19
+
20
+ // src/react/components/ContextView.tsx
21
+ import { useMemo as useMemo2, useState } from "react";
22
+
23
+ // src/react/components/FindingsBand.tsx
24
+ import React, { useMemo } from "react";
25
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
26
+ var LABELS = Object.freeze({
27
+ band: "findings",
28
+ rows: "rows",
29
+ facts: "facts",
30
+ /** The conflict ROWS — the history of when each was first seen, not the current set (see the header). */
31
+ conflicts: "conflicts first seen",
32
+ open: "open",
33
+ ruledOut: "ruled out",
34
+ noise: "noise",
35
+ undeclared: "undeclared",
36
+ settles: "settles",
37
+ line: "line"
38
+ });
39
+ var isRecord = (v) => typeof v === "object" && v !== null;
40
+ function subjectOf(v) {
41
+ if (!isRecord(v) || typeof v.kind !== "string" || typeof v.id !== "string") return void 0;
42
+ return { kind: v.kind, id: v.id };
43
+ }
44
+ function assertionOf(v) {
45
+ if (!isRecord(v) || typeof v.predicate !== "string") return void 0;
46
+ const subject = subjectOf(v.subject);
47
+ if (subject === void 0) return void 0;
48
+ return {
49
+ subject,
50
+ predicate: v.predicate,
51
+ value: v.value,
52
+ ...typeof v.provenance === "string" ? { provenance: v.provenance } : {}
53
+ };
54
+ }
55
+ function standingOf(row) {
56
+ if (!isRecord(row) || row.kind !== "standing") return void 0;
57
+ if (typeof row.toolCallId !== "string" || typeof row.standing !== "string") return void 0;
58
+ const assertions = Array.isArray(row.assertions) ? row.assertions.flatMap((a) => {
59
+ const shaped = assertionOf(a);
60
+ return shaped !== void 0 ? [shaped] : [];
61
+ }) : [];
62
+ return {
63
+ toolCallId: row.toolCallId,
64
+ standing: row.standing,
65
+ assertions,
66
+ ...typeof row.toolName === "string" ? { toolName: row.toolName } : {},
67
+ ...typeof row.settles === "string" ? { settles: row.settles } : {},
68
+ ...typeof row.line === "string" ? { line: row.line } : {}
69
+ };
70
+ }
71
+ function witnessOf(v) {
72
+ if (!isRecord(v) || typeof v.toolCallId !== "string" || typeof v.predicate !== "string") return void 0;
73
+ const subject = subjectOf(v.subject);
74
+ if (subject === void 0) return void 0;
75
+ return { toolCallId: v.toolCallId, subject, predicate: v.predicate };
76
+ }
77
+ function conflictOf(row) {
78
+ if (!isRecord(row) || row.kind !== "conflict" || typeof row.key !== "string") return void 0;
79
+ if (!Array.isArray(row.witnesses)) return void 0;
80
+ const witnesses = row.witnesses.flatMap((w) => {
81
+ const shaped = witnessOf(w);
82
+ return shaped !== void 0 ? [shaped] : [];
83
+ });
84
+ return { key: row.key, witnesses };
85
+ }
86
+ function resultIdOf(entry) {
87
+ return isRecord(entry) && typeof entry.toolCallId === "string" ? entry.toolCallId : void 0;
88
+ }
89
+ function foldFindings(rows, toolResults) {
90
+ const standing = /* @__PURE__ */ new Map();
91
+ const conflictRows = [];
92
+ for (const row of rows) {
93
+ const s = standingOf(row);
94
+ if (s !== void 0) {
95
+ standing.set(s.toolCallId, s);
96
+ continue;
97
+ }
98
+ const c = conflictOf(row);
99
+ if (c !== void 0) conflictRows.push(c);
100
+ }
101
+ const conflicts = conflictRows.map(
102
+ (c) => Object.freeze({
103
+ key: c.key,
104
+ witnesses: Object.freeze(
105
+ c.witnesses.map((w) => {
106
+ const now = standing.get(w.toolCallId)?.standing;
107
+ return Object.freeze({ ...w, ...now !== void 0 ? { standing: now } : {} });
108
+ })
109
+ )
110
+ })
111
+ );
112
+ const facts = [];
113
+ const open = [];
114
+ const ruledOut = [];
115
+ const noise = [];
116
+ for (const s of standing.values()) {
117
+ if (s.standing === "fact") for (const assertion of s.assertions) facts.push({ toolCallId: s.toolCallId, assertion });
118
+ else if (s.standing === "open") open.push(s);
119
+ else if (s.standing === "ruled-out") ruledOut.push(s);
120
+ else if (s.standing === "noise") noise.push(s.toolCallId);
121
+ }
122
+ const undeclared = [];
123
+ for (const entry of toolResults ?? []) {
124
+ const id = resultIdOf(entry);
125
+ if (id !== void 0 && !standing.has(id)) undeclared.push(id);
126
+ }
127
+ return Object.freeze({
128
+ rows: rows.length,
129
+ facts: Object.freeze(facts),
130
+ conflicts: Object.freeze(conflicts),
131
+ open: Object.freeze(open),
132
+ ruledOut: Object.freeze(ruledOut),
133
+ noise: Object.freeze(noise),
134
+ undeclared: Object.freeze(undeclared)
135
+ });
136
+ }
137
+ function valueText(value) {
138
+ if (typeof value === "string") return value;
139
+ return JSON.stringify(value) ?? String(value);
140
+ }
141
+ function FindingsBand(props) {
142
+ const { rows, toolResults, since } = props;
143
+ const fold = useMemo(() => foldFindings(rows, toolResults), [rows, toolResults]);
144
+ return /* @__PURE__ */ jsxs("div", { style: band, "data-testid": "context-findings", "data-rows": fold.rows, "data-since": since ?? "", children: [
145
+ /* @__PURE__ */ jsxs("span", { style: dim, children: [
146
+ LABELS.band,
147
+ " \xB7 ",
148
+ fold.rows,
149
+ " ",
150
+ LABELS.rows
151
+ ] }),
152
+ fold.facts.length > 0 && /* @__PURE__ */ jsx(Group, { id: "facts", label: LABELS.facts, count: fold.facts.length, children: fold.facts.map((f, i) => /* @__PURE__ */ jsxs("li", { style: mono, "data-testid": "context-findings-fact", "data-tool-call-id": f.toolCallId, children: [
153
+ /* @__PURE__ */ jsx(AssertionLine, { assertion: f.assertion }),
154
+ " \u2190 ",
155
+ /* @__PURE__ */ jsx("code", { children: f.assertion.provenance ?? f.toolCallId })
156
+ ] }, i)) }),
157
+ fold.conflicts.length > 0 && /* @__PURE__ */ jsx(Group, { id: "conflicts", label: LABELS.conflicts, count: fold.conflicts.length, children: fold.conflicts.map((c, i) => /* @__PURE__ */ jsx("li", { style: mono, "data-testid": "context-findings-conflict", "data-key": c.key, children: c.witnesses.map((w, j) => /* @__PURE__ */ jsxs(
158
+ "div",
159
+ {
160
+ "data-testid": "context-findings-witness",
161
+ "data-tool-call-id": w.toolCallId,
162
+ "data-standing": w.standing ?? "",
163
+ children: [
164
+ /* @__PURE__ */ jsxs("code", { children: [
165
+ w.subject.kind,
166
+ "/",
167
+ w.subject.id
168
+ ] }),
169
+ " \xB7 ",
170
+ /* @__PURE__ */ jsx("code", { children: w.predicate }),
171
+ " \u2190 ",
172
+ /* @__PURE__ */ jsx("code", { children: w.toolCallId }),
173
+ w.standing !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
174
+ " \xB7 ",
175
+ /* @__PURE__ */ jsx("code", { children: w.standing })
176
+ ] })
177
+ ]
178
+ },
179
+ j
180
+ )) }, i)) }),
181
+ fold.open.length > 0 && /* @__PURE__ */ jsx(Group, { id: "open", label: LABELS.open, count: fold.open.length, children: fold.open.map((s) => /* @__PURE__ */ jsxs("li", { style: mono, "data-testid": "context-findings-open-row", "data-tool-call-id": s.toolCallId, children: [
182
+ /* @__PURE__ */ jsx(StandingHead, { standing: s }),
183
+ s.assertions.map((a, i) => /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(AssertionLine, { assertion: a }) }, i)),
184
+ s.settles !== void 0 && /* @__PURE__ */ jsxs("div", { children: [
185
+ /* @__PURE__ */ jsx("span", { style: dim, children: LABELS.settles }),
186
+ " \xB7 ",
187
+ s.settles
188
+ ] })
189
+ ] }, s.toolCallId)) }),
190
+ fold.ruledOut.length > 0 && /* @__PURE__ */ jsx(Group, { id: "ruled-out", label: LABELS.ruledOut, count: fold.ruledOut.length, children: fold.ruledOut.map((s) => /* @__PURE__ */ jsxs("li", { style: mono, "data-testid": "context-findings-ruled-out-row", "data-tool-call-id": s.toolCallId, children: [
191
+ /* @__PURE__ */ jsx(StandingHead, { standing: s }),
192
+ s.line !== void 0 && /* @__PURE__ */ jsxs("div", { children: [
193
+ /* @__PURE__ */ jsx("span", { style: dim, children: LABELS.line }),
194
+ " \xB7 ",
195
+ s.line
196
+ ] })
197
+ ] }, s.toolCallId)) }),
198
+ fold.noise.length > 0 && /* @__PURE__ */ jsx(Group, { id: "noise", label: LABELS.noise, count: fold.noise.length, children: /* @__PURE__ */ jsx("li", { style: mono, children: /* @__PURE__ */ jsx(IdList, { ids: fold.noise, testId: "context-findings-noise-id" }) }) }),
199
+ fold.undeclared.length > 0 && /* @__PURE__ */ jsx(Group, { id: "undeclared", label: LABELS.undeclared, count: fold.undeclared.length, children: /* @__PURE__ */ jsx("li", { style: mono, children: /* @__PURE__ */ jsx(IdList, { ids: fold.undeclared, testId: "context-findings-undeclared-id" }) }) })
200
+ ] });
201
+ }
202
+ function Group({
203
+ id,
204
+ label,
205
+ count,
206
+ children
207
+ }) {
208
+ return /* @__PURE__ */ jsxs("div", { "data-testid": `context-findings-${id}`, "data-count": count, children: [
209
+ /* @__PURE__ */ jsxs("span", { style: dim, children: [
210
+ label,
211
+ " \xB7 ",
212
+ count
213
+ ] }),
214
+ /* @__PURE__ */ jsx("ul", { style: list, children })
215
+ ] });
216
+ }
217
+ function AssertionLine({ assertion }) {
218
+ return /* @__PURE__ */ jsxs("span", { "data-testid": "context-findings-assertion", children: [
219
+ /* @__PURE__ */ jsxs("code", { children: [
220
+ assertion.subject.kind,
221
+ "/",
222
+ assertion.subject.id
223
+ ] }),
224
+ " \xB7 ",
225
+ /* @__PURE__ */ jsx("code", { children: assertion.predicate }),
226
+ " = ",
227
+ /* @__PURE__ */ jsx("code", { children: valueText(assertion.value) })
228
+ ] });
229
+ }
230
+ function StandingHead({ standing }) {
231
+ return /* @__PURE__ */ jsxs("div", { children: [
232
+ /* @__PURE__ */ jsx("code", { children: standing.toolCallId }),
233
+ standing.toolName !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
234
+ " \xB7 ",
235
+ /* @__PURE__ */ jsx("code", { children: standing.toolName })
236
+ ] })
237
+ ] });
238
+ }
239
+ function IdList({ ids, testId }) {
240
+ return /* @__PURE__ */ jsx(Fragment, { children: ids.map((id, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
241
+ i > 0 && " \xB7 ",
242
+ /* @__PURE__ */ jsx("code", { "data-testid": testId, children: id })
243
+ ] }, id)) });
244
+ }
245
+ var band = {
246
+ display: "flex",
247
+ flexDirection: "column",
248
+ gap: 4,
249
+ paddingTop: 6,
250
+ borderTop: "1px solid",
251
+ borderTopColor: "currentColor"
252
+ };
253
+ var dim = { opacity: 0.7 };
254
+ var mono = {
255
+ fontFamily: "monospace",
256
+ fontSize: 12,
257
+ wordBreak: "break-word"
258
+ };
259
+ var list = { margin: "2px 0 0", paddingLeft: 18 };
260
+
261
+ // src/react/components/ContextView.tsx
262
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
263
+ var LABELS2 = Object.freeze({
264
+ view: "Context",
265
+ keys: "keys",
266
+ wroteBy: "wrote by",
267
+ at: "at",
268
+ entered: "entered",
269
+ changed: "changed",
270
+ unchanged: "unchanged",
271
+ left: "left",
272
+ unattributed: "unattributed",
273
+ rows: "rows",
274
+ served: "served",
275
+ why: "why",
276
+ epoch: "epoch",
277
+ system: "system",
278
+ tools: "tools",
279
+ redacted: "redacted",
280
+ skipped: "skipped",
281
+ foldError: "fold error",
282
+ servedError: "served error",
283
+ json: "JSON",
284
+ empty: "{ }",
285
+ more: "more",
286
+ less: "less",
287
+ builtFrom: "built from"
288
+ });
289
+ var MILESTONE_AXIS = Object.freeze([
290
+ "milestone:iteration",
291
+ "milestone:slot",
292
+ "milestone:llm-turn",
293
+ "milestone:tool-call",
294
+ "milestone:decision"
295
+ ]);
296
+ function positionsOf(snapshot) {
297
+ return tagAxisPositions(snapshot, MILESTONE_AXIS, []) ?? [];
298
+ }
299
+ function servedCursorOf(cursor) {
300
+ return {
301
+ runtimeStageId: cursor.at.runtimeStageId,
302
+ commitIdx: cursor.at.commitIdx
303
+ };
304
+ }
305
+ function previousOf(cursor, positions) {
306
+ if (cursor.at.step <= 0) return void 0;
307
+ const p = positions?.[cursor.at.step - 1];
308
+ return p !== void 0 ? { runtimeStageId: p.runtimeStageId, commitIdx: p.commitIdx } : void 0;
309
+ }
310
+ function ContextView(props) {
311
+ const { runner, events, shared, recorder } = props;
312
+ const fresh = snapshotOfRunner(runner);
313
+ const logKey = snapshotLogKey(fresh);
314
+ const snapshot = useMemo2(() => fresh, [runner, logKey]);
315
+ const ownPositions = useMemo2(
316
+ () => props.cursor !== void 0 ? void 0 : recorder !== void 0 ? scrubAxisFor(recorder, "group") : positionsOf(snapshot),
317
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- the recorder's axis moves with the log key
318
+ [snapshot, props.cursor, recorder, logKey]
319
+ );
320
+ const [ownStep, setOwnStep] = useState(0);
321
+ const cursor = props.cursor ?? (shared !== void 0 ? shared.over(ownPositions ?? []) : lensCursorFrom(
322
+ ownPositions ?? [],
323
+ Math.min(ownStep, Math.max(0, (ownPositions?.length ?? 1) - 1)),
324
+ setOwnStep
325
+ ));
326
+ const mover = props.cursor === void 0 && cursor.total > 0 && cursor.at.step >= 0;
327
+ const [mode, setMode] = useState(props.initialMode ?? "keys");
328
+ const context = useMemo2(
329
+ () => contextAt(snapshot, servedCursorOf(cursor), {
330
+ previous: props.previous ?? previousOf(cursor, ownPositions),
331
+ events
332
+ }),
333
+ [snapshot, cursor.at.runtimeStageId, cursor.at.commitIdx, cursor.at.step, ownPositions, events]
334
+ );
335
+ return /* @__PURE__ */ jsxs2(
336
+ "div",
337
+ {
338
+ style: panel,
339
+ "data-testid": "context-view",
340
+ "data-step": cursor.at.step,
341
+ "data-commit": cursor.at.commitIdx,
342
+ children: [
343
+ /* @__PURE__ */ jsxs2("div", { style: header, children: [
344
+ /* @__PURE__ */ jsx2("span", { style: title, children: LABELS2.view }),
345
+ /* @__PURE__ */ jsxs2("span", { style: dim2, children: [
346
+ cursor.at.label,
347
+ " \xB7 ",
348
+ cursor.at.step + 1,
349
+ "/",
350
+ cursor.total
351
+ ] }),
352
+ /* @__PURE__ */ jsxs2("span", { style: { marginLeft: "auto", display: "flex", gap: 6 }, children: [
353
+ /* @__PURE__ */ jsx2(
354
+ "button",
355
+ {
356
+ type: "button",
357
+ style: btn,
358
+ "aria-pressed": mode === "keys",
359
+ onClick: () => setMode("keys"),
360
+ "data-testid": "context-mode-keys",
361
+ children: LABELS2.keys
362
+ }
363
+ ),
364
+ /* @__PURE__ */ jsx2(
365
+ "button",
366
+ {
367
+ type: "button",
368
+ style: btn,
369
+ "aria-pressed": mode === "json",
370
+ onClick: () => setMode("json"),
371
+ "data-testid": "context-mode-json",
372
+ children: LABELS2.json
373
+ }
374
+ )
375
+ ] })
376
+ ] }),
377
+ mover && /* @__PURE__ */ jsx2("div", { "data-testid": "context-transport", children: /* @__PURE__ */ jsx2(
378
+ TimeTravel,
379
+ {
380
+ total: cursor.total,
381
+ focusSeq: Math.max(0, cursor.at.step),
382
+ onFocusChange: (n) => cursor.moveTo(n),
383
+ isLive: false,
384
+ compact: true
385
+ }
386
+ ) }),
387
+ /* @__PURE__ */ jsx2(Facts, { context }),
388
+ /* @__PURE__ */ jsx2(ServedLayer, { context, runner, cursor }),
389
+ /* @__PURE__ */ jsxs2("div", { style: dim2, "data-testid": "context-built-from", children: [
390
+ LABELS2.builtFrom,
391
+ " \xB7 ",
392
+ context.keys.length,
393
+ " ",
394
+ LABELS2.keys
395
+ ] }),
396
+ mode === "json" ? /* @__PURE__ */ jsx2(JsonPane, { context }) : /* @__PURE__ */ jsx2(KeyTable, { context }),
397
+ /* @__PURE__ */ jsx2(FindingsLayer, { context }),
398
+ /* @__PURE__ */ jsx2(WhyBand, { context })
399
+ ]
400
+ }
401
+ );
402
+ }
403
+ function FindingsLayer({ context }) {
404
+ const ledger = context.keys.find((k) => k.path === "findingsLedger");
405
+ if (ledger === void 0 || !Array.isArray(ledger.value)) return null;
406
+ const results = context.keys.find((k) => k.path === "toolResults")?.value;
407
+ return /* @__PURE__ */ jsx2(
408
+ FindingsBand,
409
+ {
410
+ rows: ledger.value,
411
+ ...Array.isArray(results) ? { toolResults: results } : {},
412
+ ...ledger.since !== void 0 ? { since: ledger.since } : {}
413
+ }
414
+ );
415
+ }
416
+ function Facts({ context }) {
417
+ const facts = [];
418
+ if (context.redacted) facts.push(LABELS2.redacted);
419
+ if (context.skipped !== void 0) facts.push(`${LABELS2.skipped} ${context.skipped.join(",")}`);
420
+ if (context.foldError !== void 0) facts.push(`${LABELS2.foldError}: ${context.foldError}`);
421
+ if (context.servedError !== void 0) facts.push(`${LABELS2.servedError}: ${context.servedError}`);
422
+ if (facts.length === 0) return null;
423
+ return /* @__PURE__ */ jsx2("div", { style: dim2, "data-testid": "context-facts", children: facts.join(" \xB7 ") });
424
+ }
425
+ function KeyTable({ context }) {
426
+ if (context.keys.length === 0 && context.left.length === 0) {
427
+ return /* @__PURE__ */ jsx2("div", { style: mono2, "data-testid": "context-empty", children: LABELS2.empty });
428
+ }
429
+ return /* @__PURE__ */ jsxs2("table", { style: table, "data-testid": "context-keys", children: [
430
+ /* @__PURE__ */ jsxs2("colgroup", { children: [
431
+ /* @__PURE__ */ jsx2("col", { style: { width: "28%" } }),
432
+ /* @__PURE__ */ jsx2("col", { style: { width: "34%" } }),
433
+ /* @__PURE__ */ jsx2("col", {})
434
+ ] }),
435
+ /* @__PURE__ */ jsxs2("tbody", { children: [
436
+ context.keys.map((k) => /* @__PURE__ */ jsx2(KeyRow, { k }, k.path)),
437
+ context.left.map((path) => /* @__PURE__ */ jsxs2("tr", { "data-testid": "context-key", "data-since": "left", style: { opacity: 0.6 }, children: [
438
+ /* @__PURE__ */ jsx2("td", { style: cell, children: /* @__PURE__ */ jsx2("code", { children: path }) }),
439
+ /* @__PURE__ */ jsx2("td", { style: cell, children: LABELS2.left }),
440
+ /* @__PURE__ */ jsx2("td", { style: cell })
441
+ ] }, `left:${path}`))
442
+ ] })
443
+ ] });
444
+ }
445
+ function KeyRow({ k }) {
446
+ const since = k.since === void 0 ? void 0 : LABELS2[k.since];
447
+ return /* @__PURE__ */ jsxs2(
448
+ "tr",
449
+ {
450
+ "data-testid": "context-key",
451
+ "data-path": k.path,
452
+ "data-since": k.since ?? "",
453
+ style: k.since === "unchanged" ? { opacity: 0.6 } : void 0,
454
+ children: [
455
+ /* @__PURE__ */ jsxs2("td", { style: cell, children: [
456
+ /* @__PURE__ */ jsx2("code", { children: k.path }),
457
+ since !== void 0 && /* @__PURE__ */ jsx2("span", { style: pill, children: since })
458
+ ] }),
459
+ /* @__PURE__ */ jsx2("td", { style: cell, "data-testid": "context-wrote-by", children: k.wroteBy !== void 0 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
460
+ /* @__PURE__ */ jsxs2("span", { style: dim2, children: [
461
+ LABELS2.wroteBy,
462
+ " "
463
+ ] }),
464
+ /* @__PURE__ */ jsx2("code", { children: k.wroteBy }),
465
+ /* @__PURE__ */ jsxs2("span", { style: dim2, children: [
466
+ " ",
467
+ LABELS2.at,
468
+ " #",
469
+ k.wroteAt,
470
+ " \xB7 ",
471
+ k.verb
472
+ ] })
473
+ ] }) : /* @__PURE__ */ jsx2("span", { style: dim2, children: LABELS2.unattributed }) }),
474
+ /* @__PURE__ */ jsx2("td", { style: { ...cell, ...mono2 }, children: /* @__PURE__ */ jsx2(ValueCell, { value: k.value }) })
475
+ ]
476
+ }
477
+ );
478
+ }
479
+ function ValueCell({ value }) {
480
+ const [open, setOpen] = useState(false);
481
+ const text = JSON.stringify(value) ?? "";
482
+ const long = text.length > 160;
483
+ if (!long) return /* @__PURE__ */ jsx2("span", { children: text });
484
+ return /* @__PURE__ */ jsxs2("span", { "data-testid": "context-value", "data-open": open, children: [
485
+ open ? /* @__PURE__ */ jsx2("pre", { style: { ...mono2, ...pre }, "data-testid": "context-value-full", children: text }) : /* @__PURE__ */ jsx2("span", { children: `${text.slice(0, 157)}\u2026` }),
486
+ " ",
487
+ /* @__PURE__ */ jsx2("button", { type: "button", style: btn, onClick: () => setOpen(!open), "data-testid": "context-value-toggle", children: open ? LABELS2.less : LABELS2.more })
488
+ ] });
489
+ }
490
+ function JsonPane({ context }) {
491
+ const object = {};
492
+ for (const k of context.keys) object[k.path] = k.value;
493
+ return /* @__PURE__ */ jsx2("pre", { style: { ...mono2, ...pre }, "data-testid": "context-json", children: JSON.stringify(object, null, 2) });
494
+ }
495
+ function ServedLayer({
496
+ context,
497
+ runner,
498
+ cursor
499
+ }) {
500
+ const served = context.served;
501
+ if (served === void 0) return null;
502
+ return /* @__PURE__ */ jsxs2("div", { style: band2, "data-testid": "context-served", "data-epoch": served.row.view.epoch, children: [
503
+ /* @__PURE__ */ jsxs2("span", { style: dim2, children: [
504
+ LABELS2.served,
505
+ " \xB7 ",
506
+ LABELS2.epoch,
507
+ " ",
508
+ served.row.view.epoch
509
+ ] }),
510
+ /* @__PURE__ */ jsx2(
511
+ ServedTab,
512
+ {
513
+ runner,
514
+ cursor,
515
+ onJumpTo: (runtimeStageId) => {
516
+ const to = cursor.resolve(runtimeStageId);
517
+ if (to.ok && to.step !== void 0) cursor.moveTo(to.step);
518
+ }
519
+ }
520
+ )
521
+ ] });
522
+ }
523
+ function WhyBand({ context }) {
524
+ if (context.why.length === 0) return null;
525
+ return /* @__PURE__ */ jsxs2("div", { style: band2, "data-testid": "context-why", children: [
526
+ /* @__PURE__ */ jsx2("span", { style: dim2, children: LABELS2.why }),
527
+ /* @__PURE__ */ jsx2("ul", { style: list2, children: context.why.map((w) => /* @__PURE__ */ jsxs2("li", { style: mono2, children: [
528
+ /* @__PURE__ */ jsx2("code", { children: w.name }),
529
+ " ",
530
+ /* @__PURE__ */ jsxs2("span", { style: dim2, children: [
531
+ "#",
532
+ w.seq
533
+ ] })
534
+ ] }, w.seq)) })
535
+ ] });
536
+ }
537
+ var panel = {
538
+ display: "flex",
539
+ flexDirection: "column",
540
+ gap: 8,
541
+ padding: 10,
542
+ fontSize: 13
543
+ };
544
+ var header = {
545
+ display: "flex",
546
+ alignItems: "center",
547
+ gap: 10
548
+ };
549
+ var title = { fontWeight: 600 };
550
+ var dim2 = { opacity: 0.7 };
551
+ var mono2 = {
552
+ fontFamily: "monospace",
553
+ fontSize: 12
554
+ };
555
+ var pre = {
556
+ margin: 0,
557
+ whiteSpace: "pre-wrap",
558
+ wordBreak: "break-word"
559
+ };
560
+ var table = {
561
+ borderCollapse: "collapse",
562
+ width: "100%",
563
+ tableLayout: "fixed"
564
+ };
565
+ var cell = {
566
+ wordBreak: "break-all",
567
+ overflowWrap: "anywhere",
568
+ padding: "4px 6px",
569
+ verticalAlign: "top",
570
+ borderTop: "1px solid",
571
+ borderTopColor: "currentColor"
572
+ };
573
+ var pill = {
574
+ marginLeft: 6,
575
+ padding: "0 6px",
576
+ borderRadius: 8,
577
+ fontSize: 11,
578
+ border: "1px solid",
579
+ borderColor: "currentColor"
580
+ };
581
+ var band2 = {
582
+ paddingTop: 6,
583
+ borderTop: "1px solid",
584
+ borderTopColor: "currentColor"
585
+ };
586
+ var list2 = { margin: "4px 0 0", paddingLeft: 18 };
587
+ var btn = { fontSize: 12, padding: "2px 8px" };
588
+
589
+ export {
590
+ LABELS2 as LABELS,
591
+ MILESTONE_AXIS,
592
+ ContextView
593
+ };
594
+ //# sourceMappingURL=chunk-JMH3WAZK.js.map