footprint-explainable-ui 0.28.0 → 0.30.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.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react from 'react';
2
+ import { ReactNode } from 'react';
2
3
  import { Node, Edge } from '@xyflow/react';
3
4
 
4
5
  /** Snapshot of a single pipeline stage — the core data shape for all components. */
@@ -318,6 +319,45 @@ interface StageDetailPanelProps extends BaseComponentProps {
318
319
  }
319
320
  declare function StageDetailPanel({ snapshots, selectedIndex, mode: controlledMode, showToggle, onModeChange, size, unstyled, className, style, }: StageDetailPanelProps): react.JSX.Element;
320
321
 
322
+ /**
323
+ * Same-Rail Rewind (tracing mode) — the rail's AXIS never changes, only its
324
+ * stops do: every dependency was committed earlier than the value it fed, so
325
+ * a backward slice is a sub-sequence of this same timeline. When `tracing`
326
+ * is set, slice members stay landable ("stops"), everything else fades to
327
+ * unlandable ticks, and prev/next walk stop-to-stop ("◀ earlier cause").
328
+ * The cursor stays the ONE `selectedIndex` — no second position exists.
329
+ *
330
+ * THEMING: tracing mode recolors its chrome with ONE token, `--fp-tracing`
331
+ * (default #0d9488 teal) — the TRACING badge, the rail's bottom border, the
332
+ * stop ticks, the walk buttons, and Done — so the tracing rail is
333
+ * unmistakably not normal time-travel. Consumers retheme by setting
334
+ * `--fp-tracing` on any ancestor. Normal mode never reads the token.
335
+ */
336
+ interface TracingRail {
337
+ /** The traced variable — rendered in the mode header. */
338
+ tracedKey: string;
339
+ /** Set while an ingredient filter is active ("▸ via key"). */
340
+ viaKey?: string | null;
341
+ /** Snapshot indices that are stops, ASCENDING. All other ticks become
342
+ * faint and unlandable (context, not destinations). */
343
+ stopIndices: number[];
344
+ /** 1-based position of the cursor in WALK order (newest first) + total —
345
+ * the "stop 2 of 6" label. */
346
+ stopOrdinal: number;
347
+ totalStops: number;
348
+ /** Exit tracing (Done button / Escape). The cursor stays put. */
349
+ onExit: () => void;
350
+ /** Clear the via filter back to the full walk (breadcrumb's "show all"). */
351
+ onShowAll?: () => void;
352
+ /** Ingredient count at the CURRENT stop. Together with `onForkPrompt`,
353
+ * >= 2 turns the walk-back control into "choose cause…": it PROMPTS
354
+ * instead of moving, so a silent default never hides one parent of a
355
+ * fork. 0/undefined = not a fork — classic earlier-cause behavior. */
356
+ forkCount?: number;
357
+ /** Open the fork chooser — fired INSTEAD of a cursor move when
358
+ * `forkCount >= 2` (click or ArrowLeft on the walk-back control). */
359
+ onForkPrompt?: () => void;
360
+ }
321
361
  interface TimeTravelControlsProps extends BaseComponentProps {
322
362
  /** Stage snapshots */
323
363
  snapshots: StageSnapshot[];
@@ -327,8 +367,10 @@ interface TimeTravelControlsProps extends BaseComponentProps {
327
367
  onIndexChange: (index: number) => void;
328
368
  /** Enable auto-play with Gantt-proportional timing */
329
369
  autoPlayable?: boolean;
370
+ /** Same-Rail Rewind session — when set, the rail is in tracing mode. */
371
+ tracing?: TracingRail | null;
330
372
  }
331
- declare function TimeTravelControls({ snapshots, selectedIndex, onIndexChange, autoPlayable, size, unstyled, className, style, }: TimeTravelControlsProps): react.JSX.Element;
373
+ declare function TimeTravelControls({ snapshots, selectedIndex, onIndexChange, autoPlayable, tracing, size, unstyled, className, style, }: TimeTravelControlsProps): react.JSX.Element;
332
374
 
333
375
  /**
334
376
  * One entry in the execution timeline. `<TracedFlow>` keys time-travel
@@ -1109,9 +1151,148 @@ interface InspectorPanelProps {
1109
1151
  /** Fires when the user switches tabs — lets the shell paint the chart's
1110
1152
  * dependency cone while the Data Trace tab is open. */
1111
1153
  onTabChange?: (tab: "state" | "trace") => void;
1154
+ /** Controlled tab — when provided the SHELL owns the tab (it must force
1155
+ * Data Trace open on tracing entry); clicks still fire onTabChange. */
1156
+ tab?: "state" | "trace";
1157
+ /** Replaces the Data Trace tab body (the shell swaps in the Same-Rail
1158
+ * Rewind stop card / entry chips); default = the classic frames list. */
1159
+ traceContent?: ReactNode;
1112
1160
  }
1113
1161
  declare const InspectorPanel: react.NamedExoticComponent<InspectorPanelProps>;
1114
1162
 
1163
+ /**
1164
+ * traceWalk — the SAME-RAIL REWIND walk: a variable-anchored backward slice,
1165
+ * linearized in REVERSE COMMIT ORDER so it can be driven by the existing
1166
+ * time slider ("◀ earlier cause" stop by stop).
1167
+ *
1168
+ * THE LOAD-BEARING FACT (why one linear walk can cover a DAG): every
1169
+ * dependency was committed strictly EARLIER than the value derived from it,
1170
+ * so a backward slice is always a sub-sequence of the run's timeline — and
1171
+ * sorting its frames by commitIdx DESCENDING is a valid topological order.
1172
+ * One monotone "earlier" button therefore visits EVERY frame, including
1173
+ * both parents of a fork, with no branch-choosing UI and no second cursor.
1174
+ *
1175
+ * FORKS are explained, not navigated: each stop carries its `ingredients`
1176
+ * (the read keys + who wrote each), so a 2-parent value shows both chips;
1177
+ * "follow one ingredient" is a RE-ANCHORED walk (same function, key = the
1178
+ * ingredient, before = this stop) — never a special traversal mode.
1179
+ *
1180
+ * HONEST ABSENCE, two truthful sentences (they are different facts):
1181
+ * 'never-written' — no commit in the WHOLE log wrote the key: it came
1182
+ * in with the run's inputs.
1183
+ * 'not-yet-written' — a later commit writes it, but none at or before
1184
+ * the cutoff: "not yet" is not "never".
1185
+ *
1186
+ * Shares the read→write BFS with dataTrace.ts (the causalChain mirror);
1187
+ * eui still never imports footprintjs — snapshot SHAPES only.
1188
+ */
1189
+ /** One read key of a stop, resolved to the commit that wrote it. */
1190
+ interface TraceIngredient {
1191
+ key: string;
1192
+ /** null = no commit before this stop wrote the key (a run-input terminus). */
1193
+ writerRuntimeStageId: string | null;
1194
+ writerStageName: string | null;
1195
+ writerCommitIdx: number | null;
1196
+ }
1197
+ /** One stop on the rewind rail — a slice frame with its rail position. */
1198
+ interface TraceStop {
1199
+ runtimeStageId: string;
1200
+ stageId: string;
1201
+ stageName: string;
1202
+ /** Position in the commit log — the stop's place on the time rail. */
1203
+ commitIdx: number;
1204
+ /** The slice keys DOWNSTREAM members read from this stop (what it
1205
+ * contributed to the traced value). The anchor contributes the traced
1206
+ * key itself. */
1207
+ contributedKeys: string[];
1208
+ keysWritten: string[];
1209
+ ingredients: TraceIngredient[];
1210
+ /** BFS hop distance from the anchor (tooltip-grade info, NOT the walk
1211
+ * order — the walk order is time). */
1212
+ depth: number;
1213
+ /** 1-based pass number when the same stage appears more than once in
1214
+ * the walk (loop iterations); 0 = appears once. */
1215
+ loopPass: number;
1216
+ }
1217
+ interface TraceWalkMissing {
1218
+ reason: "never-written" | "not-yet-written";
1219
+ /** For 'not-yet-written': where the FIRST write actually happens. */
1220
+ firstWriteCommitIdx?: number;
1221
+ firstWriterRuntimeStageId?: string;
1222
+ firstWriterStageName?: string;
1223
+ }
1224
+ interface TraceWalk {
1225
+ key: string;
1226
+ /** Stops in WALK ORDER: commitIdx DESCENDING. stops[0] is the anchor
1227
+ * (the last writer of `key` within the cutoff). */
1228
+ stops: TraceStop[];
1229
+ /** Non-null ⇒ zero stops: the honest-absence card, not an empty chain. */
1230
+ missing: TraceWalkMissing | null;
1231
+ /** Read keys that NO commit ever wrote — the run's inputs ("came in the
1232
+ * door"), deduped, in first-encounter order. */
1233
+ inputTermini: string[];
1234
+ /** False when the snapshot recorded no reads anywhere — the chain is
1235
+ * UNKNOWABLE (not absent) beyond the anchor. */
1236
+ readsAvailable: boolean;
1237
+ /** True when the underlying slice hit its frame/depth budget — the
1238
+ * earliest stop may not be the true origin. */
1239
+ truncated: boolean;
1240
+ }
1241
+ /**
1242
+ * Build the rewind walk for `key`.
1243
+ *
1244
+ * `beforeCommitIdx` (EXCLUSIVE) scopes the question to "the value as it
1245
+ * stood before that moment" — it is also how ingredient-following works:
1246
+ * follow ingredient K at stop S = buildTraceWalk(K, { beforeCommitIdx:
1247
+ * S.commitIdx }) — one function, no traversal modes.
1248
+ */
1249
+ declare function buildTraceWalk(commitLog: unknown[], executionTree: unknown, key: string, opts?: {
1250
+ beforeCommitIdx?: number;
1251
+ maxDepth?: number;
1252
+ maxFrames?: number;
1253
+ }): TraceWalk;
1254
+ /**
1255
+ * formatTraceWalk — THE parity artifact: the [Copy story] button and any
1256
+ * LLM backtrack tool emit THIS string, so the human's board and the
1257
+ * agent's answer are the same text, not two translations.
1258
+ *
1259
+ * `stepNumberOf` maps a runtimeStageId to the 1-based step number shown on
1260
+ * the rail (null = not on the rail); walk order and wording match the
1261
+ * stop cards exactly.
1262
+ */
1263
+ declare function formatTraceWalk(walk: TraceWalk, stepNumberOf: (runtimeStageId: string) => number | null): string;
1264
+
1265
+ interface TraceWalkCardProps {
1266
+ walk: TraceWalk;
1267
+ /** The ONE cursor — the card highlights its stop; null falls back to the anchor. */
1268
+ cursorRuntimeStageId: string | null;
1269
+ /** Active ingredient filter (breadcrumb "▸ via key"). */
1270
+ viaKey?: string | null;
1271
+ /** Map a stop to its 1-based rail step number (null = not on this rail). */
1272
+ stepNumberOf: (runtimeStageId: string) => number | null;
1273
+ /** Value preview for a contributed key at the current stop (the shell
1274
+ * reads snapshot.memory — state as of that moment). */
1275
+ previewValueOf?: (key: string) => unknown;
1276
+ /** Follow an ingredient: re-anchor the walk on ing.key before this stop. */
1277
+ onFollowIngredient?: (ing: TraceIngredient) => void;
1278
+ /** Jump the cursor to a stop (itinerary row click). */
1279
+ onJumpToStop?: (runtimeStageId: string) => void;
1280
+ onShowAll?: () => void;
1281
+ onExit?: () => void;
1282
+ /** F2 fork chooser: when true AND the current stop has 2+ ingredients,
1283
+ * a loud chooser block asks WHICH ingredient the walk should follow —
1284
+ * the rail's walk-back control opens it instead of moving. */
1285
+ forkChooserOpen?: boolean;
1286
+ /** The chooser's neutral option — today's behavior: step to the nearest
1287
+ * earlier stop in time. The SHELL computes the move; the card only
1288
+ * fires this. */
1289
+ onContinueTimeOrder?: () => void;
1290
+ /** False at the walk's earliest stop — there IS no earlier stop, so the
1291
+ * chooser's time-order button must not pretend to move (review fix). */
1292
+ canContinueTimeOrder?: boolean;
1293
+ }
1294
+ declare const TraceWalkCard: react.NamedExoticComponent<TraceWalkCardProps>;
1295
+
1115
1296
  interface InsightConfig {
1116
1297
  /** Unique ID (matches recorder id). */
1117
1298
  id: string;
@@ -1139,4 +1320,4 @@ interface CompactTimelineProps {
1139
1320
  }
1140
1321
  declare const CompactTimeline: react.NamedExoticComponent<CompactTimelineProps>;
1141
1322
 
1142
- export { type NarrativeEntry as AdapterNarrativeEntry, type AgentfootprintTrace, type BaseComponentProps, type CausalFrame, CompactTimeline, type CompactTimelineProps, type DarkModeTokensOptions, DataTracePanel, type DataTracePanelProps, type DefaultExpanded, type DiffEntry, type EntryRangeIndex, ExplainableShell, type ExplainableShellProps, FootprintTheme, GanttTimeline, type GanttTimelineProps, type InsightConfig, InsightPanel, type InsightPanelProps, InspectorPanel, type InspectorPanelProps, type MemoryChange, MemoryInspector, type MemoryInspectorProps, MemoryPanel, type MemoryPanelProps, type NarrativeEntry, NarrativeLog, type NarrativeLogProps, NarrativePanel, type NarrativePanelProps, NarrativeTrace, type NarrativeTraceProps, type PanelLabels, type RecorderView, ResultPanel, type ResultPanelProps, type RuntimeSnapshotInput, ScopeDiff, type ScopeDiffProps, type ShellTab, type Size, SnapshotPanel, type SnapshotPanelProps, type StageDetailMode, StageDetailPanel, type StageDetailPanelProps, type StageSnapshot, StoryNarrative, type StoryNarrativeProps, SubflowTree, type SubflowTreeEntry, type SubflowTreeProps, type ThemePresetName, type ThemeTokens, TimeTravelControls, type TimeTravelControlsProps, type TraceParseError, type TraceTheme, TraceViewer, type TraceViewerProps, buildEntryRangeIndex, computeRevealedEntryCount, coolDark, coolLight, createSnapshots, defaultTokens, extractSubflowNarrative, mergeWritePatch, rawDefaults, subflowResultToSnapshots, themePresets, toVisualizationSnapshots, tokensToCSSVars, useDarkModeTokens, useFootprintTheme, warmDark, warmLight };
1323
+ export { type NarrativeEntry as AdapterNarrativeEntry, type AgentfootprintTrace, type BaseComponentProps, type CausalFrame, CompactTimeline, type CompactTimelineProps, type DarkModeTokensOptions, DataTracePanel, type DataTracePanelProps, type DefaultExpanded, type DiffEntry, type EntryRangeIndex, ExplainableShell, type ExplainableShellProps, FootprintTheme, GanttTimeline, type GanttTimelineProps, type InsightConfig, InsightPanel, type InsightPanelProps, InspectorPanel, type InspectorPanelProps, type MemoryChange, MemoryInspector, type MemoryInspectorProps, MemoryPanel, type MemoryPanelProps, type NarrativeEntry, NarrativeLog, type NarrativeLogProps, NarrativePanel, type NarrativePanelProps, NarrativeTrace, type NarrativeTraceProps, type PanelLabels, type RecorderView, ResultPanel, type ResultPanelProps, type RuntimeSnapshotInput, ScopeDiff, type ScopeDiffProps, type ShellTab, type Size, SnapshotPanel, type SnapshotPanelProps, type StageDetailMode, StageDetailPanel, type StageDetailPanelProps, type StageSnapshot, StoryNarrative, type StoryNarrativeProps, SubflowTree, type SubflowTreeEntry, type SubflowTreeProps, type ThemePresetName, type ThemeTokens, TimeTravelControls, type TimeTravelControlsProps, type TraceIngredient, type TraceParseError, type TraceStop, type TraceTheme, TraceViewer, type TraceViewerProps, type TraceWalk, TraceWalkCard, type TraceWalkCardProps, type TraceWalkMissing, type TracingRail, buildEntryRangeIndex, buildTraceWalk, computeRevealedEntryCount, coolDark, coolLight, createSnapshots, defaultTokens, extractSubflowNarrative, formatTraceWalk, mergeWritePatch, rawDefaults, subflowResultToSnapshots, themePresets, toVisualizationSnapshots, tokensToCSSVars, useDarkModeTokens, useFootprintTheme, warmDark, warmLight };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react from 'react';
2
+ import { ReactNode } from 'react';
2
3
  import { Node, Edge } from '@xyflow/react';
3
4
 
4
5
  /** Snapshot of a single pipeline stage — the core data shape for all components. */
@@ -318,6 +319,45 @@ interface StageDetailPanelProps extends BaseComponentProps {
318
319
  }
319
320
  declare function StageDetailPanel({ snapshots, selectedIndex, mode: controlledMode, showToggle, onModeChange, size, unstyled, className, style, }: StageDetailPanelProps): react.JSX.Element;
320
321
 
322
+ /**
323
+ * Same-Rail Rewind (tracing mode) — the rail's AXIS never changes, only its
324
+ * stops do: every dependency was committed earlier than the value it fed, so
325
+ * a backward slice is a sub-sequence of this same timeline. When `tracing`
326
+ * is set, slice members stay landable ("stops"), everything else fades to
327
+ * unlandable ticks, and prev/next walk stop-to-stop ("◀ earlier cause").
328
+ * The cursor stays the ONE `selectedIndex` — no second position exists.
329
+ *
330
+ * THEMING: tracing mode recolors its chrome with ONE token, `--fp-tracing`
331
+ * (default #0d9488 teal) — the TRACING badge, the rail's bottom border, the
332
+ * stop ticks, the walk buttons, and Done — so the tracing rail is
333
+ * unmistakably not normal time-travel. Consumers retheme by setting
334
+ * `--fp-tracing` on any ancestor. Normal mode never reads the token.
335
+ */
336
+ interface TracingRail {
337
+ /** The traced variable — rendered in the mode header. */
338
+ tracedKey: string;
339
+ /** Set while an ingredient filter is active ("▸ via key"). */
340
+ viaKey?: string | null;
341
+ /** Snapshot indices that are stops, ASCENDING. All other ticks become
342
+ * faint and unlandable (context, not destinations). */
343
+ stopIndices: number[];
344
+ /** 1-based position of the cursor in WALK order (newest first) + total —
345
+ * the "stop 2 of 6" label. */
346
+ stopOrdinal: number;
347
+ totalStops: number;
348
+ /** Exit tracing (Done button / Escape). The cursor stays put. */
349
+ onExit: () => void;
350
+ /** Clear the via filter back to the full walk (breadcrumb's "show all"). */
351
+ onShowAll?: () => void;
352
+ /** Ingredient count at the CURRENT stop. Together with `onForkPrompt`,
353
+ * >= 2 turns the walk-back control into "choose cause…": it PROMPTS
354
+ * instead of moving, so a silent default never hides one parent of a
355
+ * fork. 0/undefined = not a fork — classic earlier-cause behavior. */
356
+ forkCount?: number;
357
+ /** Open the fork chooser — fired INSTEAD of a cursor move when
358
+ * `forkCount >= 2` (click or ArrowLeft on the walk-back control). */
359
+ onForkPrompt?: () => void;
360
+ }
321
361
  interface TimeTravelControlsProps extends BaseComponentProps {
322
362
  /** Stage snapshots */
323
363
  snapshots: StageSnapshot[];
@@ -327,8 +367,10 @@ interface TimeTravelControlsProps extends BaseComponentProps {
327
367
  onIndexChange: (index: number) => void;
328
368
  /** Enable auto-play with Gantt-proportional timing */
329
369
  autoPlayable?: boolean;
370
+ /** Same-Rail Rewind session — when set, the rail is in tracing mode. */
371
+ tracing?: TracingRail | null;
330
372
  }
331
- declare function TimeTravelControls({ snapshots, selectedIndex, onIndexChange, autoPlayable, size, unstyled, className, style, }: TimeTravelControlsProps): react.JSX.Element;
373
+ declare function TimeTravelControls({ snapshots, selectedIndex, onIndexChange, autoPlayable, tracing, size, unstyled, className, style, }: TimeTravelControlsProps): react.JSX.Element;
332
374
 
333
375
  /**
334
376
  * One entry in the execution timeline. `<TracedFlow>` keys time-travel
@@ -1109,9 +1151,148 @@ interface InspectorPanelProps {
1109
1151
  /** Fires when the user switches tabs — lets the shell paint the chart's
1110
1152
  * dependency cone while the Data Trace tab is open. */
1111
1153
  onTabChange?: (tab: "state" | "trace") => void;
1154
+ /** Controlled tab — when provided the SHELL owns the tab (it must force
1155
+ * Data Trace open on tracing entry); clicks still fire onTabChange. */
1156
+ tab?: "state" | "trace";
1157
+ /** Replaces the Data Trace tab body (the shell swaps in the Same-Rail
1158
+ * Rewind stop card / entry chips); default = the classic frames list. */
1159
+ traceContent?: ReactNode;
1112
1160
  }
1113
1161
  declare const InspectorPanel: react.NamedExoticComponent<InspectorPanelProps>;
1114
1162
 
1163
+ /**
1164
+ * traceWalk — the SAME-RAIL REWIND walk: a variable-anchored backward slice,
1165
+ * linearized in REVERSE COMMIT ORDER so it can be driven by the existing
1166
+ * time slider ("◀ earlier cause" stop by stop).
1167
+ *
1168
+ * THE LOAD-BEARING FACT (why one linear walk can cover a DAG): every
1169
+ * dependency was committed strictly EARLIER than the value derived from it,
1170
+ * so a backward slice is always a sub-sequence of the run's timeline — and
1171
+ * sorting its frames by commitIdx DESCENDING is a valid topological order.
1172
+ * One monotone "earlier" button therefore visits EVERY frame, including
1173
+ * both parents of a fork, with no branch-choosing UI and no second cursor.
1174
+ *
1175
+ * FORKS are explained, not navigated: each stop carries its `ingredients`
1176
+ * (the read keys + who wrote each), so a 2-parent value shows both chips;
1177
+ * "follow one ingredient" is a RE-ANCHORED walk (same function, key = the
1178
+ * ingredient, before = this stop) — never a special traversal mode.
1179
+ *
1180
+ * HONEST ABSENCE, two truthful sentences (they are different facts):
1181
+ * 'never-written' — no commit in the WHOLE log wrote the key: it came
1182
+ * in with the run's inputs.
1183
+ * 'not-yet-written' — a later commit writes it, but none at or before
1184
+ * the cutoff: "not yet" is not "never".
1185
+ *
1186
+ * Shares the read→write BFS with dataTrace.ts (the causalChain mirror);
1187
+ * eui still never imports footprintjs — snapshot SHAPES only.
1188
+ */
1189
+ /** One read key of a stop, resolved to the commit that wrote it. */
1190
+ interface TraceIngredient {
1191
+ key: string;
1192
+ /** null = no commit before this stop wrote the key (a run-input terminus). */
1193
+ writerRuntimeStageId: string | null;
1194
+ writerStageName: string | null;
1195
+ writerCommitIdx: number | null;
1196
+ }
1197
+ /** One stop on the rewind rail — a slice frame with its rail position. */
1198
+ interface TraceStop {
1199
+ runtimeStageId: string;
1200
+ stageId: string;
1201
+ stageName: string;
1202
+ /** Position in the commit log — the stop's place on the time rail. */
1203
+ commitIdx: number;
1204
+ /** The slice keys DOWNSTREAM members read from this stop (what it
1205
+ * contributed to the traced value). The anchor contributes the traced
1206
+ * key itself. */
1207
+ contributedKeys: string[];
1208
+ keysWritten: string[];
1209
+ ingredients: TraceIngredient[];
1210
+ /** BFS hop distance from the anchor (tooltip-grade info, NOT the walk
1211
+ * order — the walk order is time). */
1212
+ depth: number;
1213
+ /** 1-based pass number when the same stage appears more than once in
1214
+ * the walk (loop iterations); 0 = appears once. */
1215
+ loopPass: number;
1216
+ }
1217
+ interface TraceWalkMissing {
1218
+ reason: "never-written" | "not-yet-written";
1219
+ /** For 'not-yet-written': where the FIRST write actually happens. */
1220
+ firstWriteCommitIdx?: number;
1221
+ firstWriterRuntimeStageId?: string;
1222
+ firstWriterStageName?: string;
1223
+ }
1224
+ interface TraceWalk {
1225
+ key: string;
1226
+ /** Stops in WALK ORDER: commitIdx DESCENDING. stops[0] is the anchor
1227
+ * (the last writer of `key` within the cutoff). */
1228
+ stops: TraceStop[];
1229
+ /** Non-null ⇒ zero stops: the honest-absence card, not an empty chain. */
1230
+ missing: TraceWalkMissing | null;
1231
+ /** Read keys that NO commit ever wrote — the run's inputs ("came in the
1232
+ * door"), deduped, in first-encounter order. */
1233
+ inputTermini: string[];
1234
+ /** False when the snapshot recorded no reads anywhere — the chain is
1235
+ * UNKNOWABLE (not absent) beyond the anchor. */
1236
+ readsAvailable: boolean;
1237
+ /** True when the underlying slice hit its frame/depth budget — the
1238
+ * earliest stop may not be the true origin. */
1239
+ truncated: boolean;
1240
+ }
1241
+ /**
1242
+ * Build the rewind walk for `key`.
1243
+ *
1244
+ * `beforeCommitIdx` (EXCLUSIVE) scopes the question to "the value as it
1245
+ * stood before that moment" — it is also how ingredient-following works:
1246
+ * follow ingredient K at stop S = buildTraceWalk(K, { beforeCommitIdx:
1247
+ * S.commitIdx }) — one function, no traversal modes.
1248
+ */
1249
+ declare function buildTraceWalk(commitLog: unknown[], executionTree: unknown, key: string, opts?: {
1250
+ beforeCommitIdx?: number;
1251
+ maxDepth?: number;
1252
+ maxFrames?: number;
1253
+ }): TraceWalk;
1254
+ /**
1255
+ * formatTraceWalk — THE parity artifact: the [Copy story] button and any
1256
+ * LLM backtrack tool emit THIS string, so the human's board and the
1257
+ * agent's answer are the same text, not two translations.
1258
+ *
1259
+ * `stepNumberOf` maps a runtimeStageId to the 1-based step number shown on
1260
+ * the rail (null = not on the rail); walk order and wording match the
1261
+ * stop cards exactly.
1262
+ */
1263
+ declare function formatTraceWalk(walk: TraceWalk, stepNumberOf: (runtimeStageId: string) => number | null): string;
1264
+
1265
+ interface TraceWalkCardProps {
1266
+ walk: TraceWalk;
1267
+ /** The ONE cursor — the card highlights its stop; null falls back to the anchor. */
1268
+ cursorRuntimeStageId: string | null;
1269
+ /** Active ingredient filter (breadcrumb "▸ via key"). */
1270
+ viaKey?: string | null;
1271
+ /** Map a stop to its 1-based rail step number (null = not on this rail). */
1272
+ stepNumberOf: (runtimeStageId: string) => number | null;
1273
+ /** Value preview for a contributed key at the current stop (the shell
1274
+ * reads snapshot.memory — state as of that moment). */
1275
+ previewValueOf?: (key: string) => unknown;
1276
+ /** Follow an ingredient: re-anchor the walk on ing.key before this stop. */
1277
+ onFollowIngredient?: (ing: TraceIngredient) => void;
1278
+ /** Jump the cursor to a stop (itinerary row click). */
1279
+ onJumpToStop?: (runtimeStageId: string) => void;
1280
+ onShowAll?: () => void;
1281
+ onExit?: () => void;
1282
+ /** F2 fork chooser: when true AND the current stop has 2+ ingredients,
1283
+ * a loud chooser block asks WHICH ingredient the walk should follow —
1284
+ * the rail's walk-back control opens it instead of moving. */
1285
+ forkChooserOpen?: boolean;
1286
+ /** The chooser's neutral option — today's behavior: step to the nearest
1287
+ * earlier stop in time. The SHELL computes the move; the card only
1288
+ * fires this. */
1289
+ onContinueTimeOrder?: () => void;
1290
+ /** False at the walk's earliest stop — there IS no earlier stop, so the
1291
+ * chooser's time-order button must not pretend to move (review fix). */
1292
+ canContinueTimeOrder?: boolean;
1293
+ }
1294
+ declare const TraceWalkCard: react.NamedExoticComponent<TraceWalkCardProps>;
1295
+
1115
1296
  interface InsightConfig {
1116
1297
  /** Unique ID (matches recorder id). */
1117
1298
  id: string;
@@ -1139,4 +1320,4 @@ interface CompactTimelineProps {
1139
1320
  }
1140
1321
  declare const CompactTimeline: react.NamedExoticComponent<CompactTimelineProps>;
1141
1322
 
1142
- export { type NarrativeEntry as AdapterNarrativeEntry, type AgentfootprintTrace, type BaseComponentProps, type CausalFrame, CompactTimeline, type CompactTimelineProps, type DarkModeTokensOptions, DataTracePanel, type DataTracePanelProps, type DefaultExpanded, type DiffEntry, type EntryRangeIndex, ExplainableShell, type ExplainableShellProps, FootprintTheme, GanttTimeline, type GanttTimelineProps, type InsightConfig, InsightPanel, type InsightPanelProps, InspectorPanel, type InspectorPanelProps, type MemoryChange, MemoryInspector, type MemoryInspectorProps, MemoryPanel, type MemoryPanelProps, type NarrativeEntry, NarrativeLog, type NarrativeLogProps, NarrativePanel, type NarrativePanelProps, NarrativeTrace, type NarrativeTraceProps, type PanelLabels, type RecorderView, ResultPanel, type ResultPanelProps, type RuntimeSnapshotInput, ScopeDiff, type ScopeDiffProps, type ShellTab, type Size, SnapshotPanel, type SnapshotPanelProps, type StageDetailMode, StageDetailPanel, type StageDetailPanelProps, type StageSnapshot, StoryNarrative, type StoryNarrativeProps, SubflowTree, type SubflowTreeEntry, type SubflowTreeProps, type ThemePresetName, type ThemeTokens, TimeTravelControls, type TimeTravelControlsProps, type TraceParseError, type TraceTheme, TraceViewer, type TraceViewerProps, buildEntryRangeIndex, computeRevealedEntryCount, coolDark, coolLight, createSnapshots, defaultTokens, extractSubflowNarrative, mergeWritePatch, rawDefaults, subflowResultToSnapshots, themePresets, toVisualizationSnapshots, tokensToCSSVars, useDarkModeTokens, useFootprintTheme, warmDark, warmLight };
1323
+ export { type NarrativeEntry as AdapterNarrativeEntry, type AgentfootprintTrace, type BaseComponentProps, type CausalFrame, CompactTimeline, type CompactTimelineProps, type DarkModeTokensOptions, DataTracePanel, type DataTracePanelProps, type DefaultExpanded, type DiffEntry, type EntryRangeIndex, ExplainableShell, type ExplainableShellProps, FootprintTheme, GanttTimeline, type GanttTimelineProps, type InsightConfig, InsightPanel, type InsightPanelProps, InspectorPanel, type InspectorPanelProps, type MemoryChange, MemoryInspector, type MemoryInspectorProps, MemoryPanel, type MemoryPanelProps, type NarrativeEntry, NarrativeLog, type NarrativeLogProps, NarrativePanel, type NarrativePanelProps, NarrativeTrace, type NarrativeTraceProps, type PanelLabels, type RecorderView, ResultPanel, type ResultPanelProps, type RuntimeSnapshotInput, ScopeDiff, type ScopeDiffProps, type ShellTab, type Size, SnapshotPanel, type SnapshotPanelProps, type StageDetailMode, StageDetailPanel, type StageDetailPanelProps, type StageSnapshot, StoryNarrative, type StoryNarrativeProps, SubflowTree, type SubflowTreeEntry, type SubflowTreeProps, type ThemePresetName, type ThemeTokens, TimeTravelControls, type TimeTravelControlsProps, type TraceIngredient, type TraceParseError, type TraceStop, type TraceTheme, TraceViewer, type TraceViewerProps, type TraceWalk, TraceWalkCard, type TraceWalkCardProps, type TraceWalkMissing, type TracingRail, buildEntryRangeIndex, buildTraceWalk, computeRevealedEntryCount, coolDark, coolLight, createSnapshots, defaultTokens, extractSubflowNarrative, formatTraceWalk, mergeWritePatch, rawDefaults, subflowResultToSnapshots, themePresets, toVisualizationSnapshots, tokensToCSSVars, useDarkModeTokens, useFootprintTheme, warmDark, warmLight };