foottrace 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/README.md +73 -2
- package/dist/esm/index.d.ts +27 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/lib/capture/freeze.d.ts +91 -0
- package/dist/esm/lib/capture/freeze.js +313 -0
- package/dist/esm/lib/capture/ownData.d.ts +18 -0
- package/dist/esm/lib/capture/ownData.js +35 -0
- package/dist/esm/lib/capture/valueKinds.d.ts +57 -0
- package/dist/esm/lib/capture/valueKinds.js +141 -0
- package/dist/esm/lib/ids/runtimeStageId.d.ts +173 -0
- package/dist/esm/lib/ids/runtimeStageId.js +193 -0
- package/dist/esm/lib/memory/EventLog.d.ts +105 -0
- package/dist/esm/lib/memory/EventLog.js +147 -0
- package/dist/esm/lib/memory/RecordFrame.d.ts +232 -0
- package/dist/esm/lib/memory/RecordFrame.js +295 -0
- package/dist/esm/lib/memory/SharedMemory.d.ts +46 -0
- package/dist/esm/lib/memory/SharedMemory.js +87 -0
- package/dist/esm/lib/memory/TransactionBuffer.d.ts +521 -0
- package/dist/esm/lib/memory/TransactionBuffer.js +946 -0
- package/dist/esm/lib/memory/admission.d.ts +81 -0
- package/dist/esm/lib/memory/admission.js +152 -0
- package/dist/esm/lib/memory/backtrack.d.ts +286 -0
- package/dist/esm/lib/memory/backtrack.js +456 -0
- package/dist/esm/lib/memory/commitLogUtils.d.ts +217 -0
- package/dist/esm/lib/memory/commitLogUtils.js +383 -0
- package/dist/esm/lib/memory/deltaEncoding.d.ts +66 -0
- package/dist/esm/lib/memory/deltaEncoding.js +121 -0
- package/dist/esm/lib/memory/equality.d.ts +93 -0
- package/dist/esm/lib/memory/equality.js +261 -0
- package/dist/esm/lib/memory/eventPosition.d.ts +18 -0
- package/dist/esm/lib/memory/eventPosition.js +1 -0
- package/dist/esm/lib/memory/honesty.d.ts +93 -0
- package/dist/esm/lib/memory/honesty.js +91 -0
- package/dist/esm/lib/memory/keyPaths.d.ts +125 -0
- package/dist/esm/lib/memory/keyPaths.js +226 -0
- package/dist/esm/lib/memory/logModel.d.ts +76 -0
- package/dist/esm/lib/memory/logModel.js +363 -0
- package/dist/esm/lib/memory/merge.d.ts +26 -0
- package/dist/esm/lib/memory/merge.js +51 -0
- package/dist/esm/lib/memory/pathOps.d.ts +118 -0
- package/dist/esm/lib/memory/pathOps.js +292 -0
- package/dist/esm/lib/memory/paths.d.ts +56 -0
- package/dist/esm/lib/memory/paths.js +60 -0
- package/dist/esm/lib/memory/placeholders.d.ts +39 -0
- package/dist/esm/lib/memory/placeholders.js +39 -0
- package/dist/esm/lib/memory/recordCommit.d.ts +45 -0
- package/dist/esm/lib/memory/recordCommit.js +60 -0
- package/dist/esm/lib/memory/scrub.d.ts +52 -0
- package/dist/esm/lib/memory/scrub.js +72 -0
- package/dist/esm/lib/memory/types.d.ts +209 -0
- package/dist/esm/lib/memory/types.js +9 -0
- package/dist/esm/lib/memory/utils.d.ts +73 -0
- package/dist/esm/lib/memory/utils.js +150 -0
- package/dist/esm/lib/memory/verbs.d.ts +333 -0
- package/dist/esm/lib/memory/verbs.js +426 -0
- package/dist/esm/lib/recorder/CommitRangeIndex.d.ts +147 -0
- package/dist/esm/lib/recorder/CommitRangeIndex.js +206 -0
- package/dist/esm/lib/slice/elementProvenance.d.ts +81 -0
- package/dist/esm/lib/slice/elementProvenance.js +189 -0
- package/dist/esm/lib/slice/forwardSliceForKey.d.ts +88 -0
- package/dist/esm/lib/slice/forwardSliceForKey.js +242 -0
- package/dist/esm/lib/slice/index.d.ts +26 -0
- package/dist/esm/lib/slice/index.js +25 -0
- package/dist/esm/lib/slice/keyIndex.d.ts +137 -0
- package/dist/esm/lib/slice/keyIndex.js +292 -0
- package/dist/esm/lib/slice/keyTimeline.d.ts +49 -0
- package/dist/esm/lib/slice/keyTimeline.js +112 -0
- package/dist/esm/lib/slice/keysReadSources.d.ts +51 -0
- package/dist/esm/lib/slice/keysReadSources.js +94 -0
- package/dist/esm/lib/slice/serialize.d.ts +78 -0
- package/dist/esm/lib/slice/serialize.js +277 -0
- package/dist/esm/lib/slice/sliceForKey.d.ts +40 -0
- package/dist/esm/lib/slice/sliceForKey.js +78 -0
- package/dist/esm/lib/slice/types.d.ts +567 -0
- package/dist/esm/lib/slice/types.js +24 -0
- package/dist/esm/lib/time-travel/axis.d.ts +119 -0
- package/dist/esm/lib/time-travel/axis.js +178 -0
- package/dist/esm/lib/time-travel/bundles.d.ts +77 -0
- package/dist/esm/lib/time-travel/bundles.js +135 -0
- package/dist/esm/lib/time-travel/chain.d.ts +93 -0
- package/dist/esm/lib/time-travel/chain.js +187 -0
- package/dist/esm/lib/time-travel/commitStops.d.ts +55 -0
- package/dist/esm/lib/time-travel/commitStops.js +201 -0
- package/dist/esm/lib/time-travel/index.d.ts +22 -0
- package/dist/esm/lib/time-travel/index.js +20 -0
- package/dist/esm/lib/time-travel/stateAt.d.ts +102 -0
- package/dist/esm/lib/time-travel/stateAt.js +152 -0
- package/dist/esm/lib/time-travel/tagStops.d.ts +72 -0
- package/dist/esm/lib/time-travel/tagStops.js +101 -0
- package/dist/esm/lib/time-travel/timeTravel.d.ts +70 -0
- package/dist/esm/lib/time-travel/timeTravel.js +359 -0
- package/dist/esm/lib/time-travel/types.d.ts +470 -0
- package/dist/esm/lib/time-travel/types.js +22 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/paths.d.ts +4 -0
- package/dist/esm/paths.js +4 -0
- package/dist/esm/write.d.ts +49 -0
- package/dist/esm/write.js +47 -0
- package/dist/index.js +67 -0
- package/dist/lib/capture/freeze.js +319 -0
- package/dist/lib/capture/ownData.js +40 -0
- package/dist/lib/capture/valueKinds.js +145 -0
- package/dist/lib/ids/runtimeStageId.js +209 -0
- package/dist/lib/memory/EventLog.js +151 -0
- package/dist/lib/memory/RecordFrame.js +299 -0
- package/dist/lib/memory/SharedMemory.js +91 -0
- package/dist/lib/memory/TransactionBuffer.js +950 -0
- package/dist/lib/memory/admission.js +158 -0
- package/dist/lib/memory/backtrack.js +462 -0
- package/dist/lib/memory/commitLogUtils.js +398 -0
- package/dist/lib/memory/deltaEncoding.js +127 -0
- package/dist/lib/memory/equality.js +265 -0
- package/dist/lib/memory/eventPosition.js +2 -0
- package/dist/lib/memory/honesty.js +94 -0
- package/dist/lib/memory/keyPaths.js +242 -0
- package/dist/lib/memory/logModel.js +371 -0
- package/dist/lib/memory/merge.js +55 -0
- package/dist/lib/memory/pathOps.js +308 -0
- package/dist/lib/memory/paths.js +66 -0
- package/dist/lib/memory/placeholders.js +42 -0
- package/dist/lib/memory/recordCommit.js +64 -0
- package/dist/lib/memory/scrub.js +77 -0
- package/dist/lib/memory/types.js +10 -0
- package/dist/lib/memory/utils.js +169 -0
- package/dist/lib/memory/verbs.js +443 -0
- package/dist/lib/recorder/CommitRangeIndex.js +210 -0
- package/dist/lib/slice/elementProvenance.js +194 -0
- package/dist/lib/slice/forwardSliceForKey.js +246 -0
- package/dist/lib/slice/index.js +42 -0
- package/dist/lib/slice/keyIndex.js +312 -0
- package/dist/lib/slice/keyTimeline.js +116 -0
- package/dist/lib/slice/keysReadSources.js +100 -0
- package/dist/lib/slice/serialize.js +285 -0
- package/dist/lib/slice/sliceForKey.js +82 -0
- package/dist/lib/slice/types.js +25 -0
- package/dist/lib/time-travel/axis.js +183 -0
- package/dist/lib/time-travel/bundles.js +143 -0
- package/dist/lib/time-travel/chain.js +192 -0
- package/dist/lib/time-travel/commitStops.js +205 -0
- package/dist/lib/time-travel/index.js +31 -0
- package/dist/lib/time-travel/stateAt.js +159 -0
- package/dist/lib/time-travel/tagStops.js +105 -0
- package/dist/lib/time-travel/timeTravel.js +363 -0
- package/dist/lib/time-travel/types.js +23 -0
- package/dist/paths.js +14 -0
- package/dist/types/index.d.ts +27 -0
- package/dist/types/lib/capture/freeze.d.ts +91 -0
- package/dist/types/lib/capture/ownData.d.ts +18 -0
- package/dist/types/lib/capture/valueKinds.d.ts +57 -0
- package/dist/types/lib/ids/runtimeStageId.d.ts +173 -0
- package/dist/types/lib/memory/EventLog.d.ts +105 -0
- package/dist/types/lib/memory/RecordFrame.d.ts +232 -0
- package/dist/types/lib/memory/SharedMemory.d.ts +46 -0
- package/dist/types/lib/memory/TransactionBuffer.d.ts +521 -0
- package/dist/types/lib/memory/admission.d.ts +81 -0
- package/dist/types/lib/memory/backtrack.d.ts +286 -0
- package/dist/types/lib/memory/commitLogUtils.d.ts +217 -0
- package/dist/types/lib/memory/deltaEncoding.d.ts +66 -0
- package/dist/types/lib/memory/equality.d.ts +93 -0
- package/dist/types/lib/memory/eventPosition.d.ts +18 -0
- package/dist/types/lib/memory/honesty.d.ts +93 -0
- package/dist/types/lib/memory/keyPaths.d.ts +125 -0
- package/dist/types/lib/memory/logModel.d.ts +76 -0
- package/dist/types/lib/memory/merge.d.ts +26 -0
- package/dist/types/lib/memory/pathOps.d.ts +118 -0
- package/dist/types/lib/memory/paths.d.ts +56 -0
- package/dist/types/lib/memory/placeholders.d.ts +39 -0
- package/dist/types/lib/memory/recordCommit.d.ts +45 -0
- package/dist/types/lib/memory/scrub.d.ts +52 -0
- package/dist/types/lib/memory/types.d.ts +209 -0
- package/dist/types/lib/memory/utils.d.ts +73 -0
- package/dist/types/lib/memory/verbs.d.ts +333 -0
- package/dist/types/lib/recorder/CommitRangeIndex.d.ts +147 -0
- package/dist/types/lib/slice/elementProvenance.d.ts +81 -0
- package/dist/types/lib/slice/forwardSliceForKey.d.ts +88 -0
- package/dist/types/lib/slice/index.d.ts +26 -0
- package/dist/types/lib/slice/keyIndex.d.ts +137 -0
- package/dist/types/lib/slice/keyTimeline.d.ts +49 -0
- package/dist/types/lib/slice/keysReadSources.d.ts +51 -0
- package/dist/types/lib/slice/serialize.d.ts +78 -0
- package/dist/types/lib/slice/sliceForKey.d.ts +40 -0
- package/dist/types/lib/slice/types.d.ts +567 -0
- package/dist/types/lib/time-travel/axis.d.ts +119 -0
- package/dist/types/lib/time-travel/bundles.d.ts +77 -0
- package/dist/types/lib/time-travel/chain.d.ts +93 -0
- package/dist/types/lib/time-travel/commitStops.d.ts +55 -0
- package/dist/types/lib/time-travel/index.d.ts +22 -0
- package/dist/types/lib/time-travel/stateAt.d.ts +102 -0
- package/dist/types/lib/time-travel/tagStops.d.ts +72 -0
- package/dist/types/lib/time-travel/timeTravel.d.ts +70 -0
- package/dist/types/lib/time-travel/types.d.ts +470 -0
- package/dist/types/paths.d.ts +4 -0
- package/dist/types/write.d.ts +49 -0
- package/dist/write.js +56 -0
- package/package.json +48 -4
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* slice/types.ts — data shapes of the variable-first slicing layer.
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS LIBRARY EXISTS (context for future readers, human or LLM):
|
|
5
|
+
* `causalChain()` (memory/backtrack.ts) answers "what influenced this STEP?"
|
|
6
|
+
* — its address space is runtimeStageIds. But every triage consumer starts
|
|
7
|
+
* from a VARIABLE: a human clicks the key `creditTier` in a UI; an LLM tool
|
|
8
|
+
* call asks "where did history[7] come from?". This library is the address
|
|
9
|
+
* translation layer: variable in → slice out. It deliberately adds NO new
|
|
10
|
+
* capture and NO new graph algorithm — it composes the commit-log primitives
|
|
11
|
+
* (findLastWriter / causalChain / the per-key verb fold) so every surface
|
|
12
|
+
* (UI panel, LLM tool, offline autopsy agent) asks the question the same way
|
|
13
|
+
* and gets the same, honestly-labeled answer.
|
|
14
|
+
*
|
|
15
|
+
* Both directions live here: BACKWARD ("why is `key` what it is" —
|
|
16
|
+
* {@link VariableSlice}) and FORWARD ("who read it, and what did it feed" —
|
|
17
|
+
* {@link ForwardSlice}, {@link KeyTimeline}). Same anchor idiom, same
|
|
18
|
+
* `KeysReadSource` strategies, same honesty vocabulary.
|
|
19
|
+
*
|
|
20
|
+
* DAG position: memory ← slice. This module may import ONLY from memory/.
|
|
21
|
+
* Recorders, engine, and runner must never be imported here — that is what
|
|
22
|
+
* keeps it a tiny, separately-evolvable library (see README.md).
|
|
23
|
+
*/
|
|
24
|
+
import type { CausalNode, KeysReadLookup } from '../memory/backtrack.js';
|
|
25
|
+
import type { ValueBasis } from '../memory/commitLogUtils.js';
|
|
26
|
+
import type { RegisteredCode } from '../memory/honesty.js';
|
|
27
|
+
import type { CommitBundle, TraceEntry, UntrackedSource } from '../memory/types.js';
|
|
28
|
+
/**
|
|
29
|
+
* A state key as consumers know it: either the plain top-level key string, or
|
|
30
|
+
* a path array for nested keys (`['customer', 'address']`). Path arrays are
|
|
31
|
+
* normalised internally — the engine's path delimiter never appears in this
|
|
32
|
+
* public contract.
|
|
33
|
+
*/
|
|
34
|
+
export type { StateKey } from '../memory/paths.js';
|
|
35
|
+
/**
|
|
36
|
+
* STRATEGY INTERFACE: where per-stage read keys come from. THE canonical
|
|
37
|
+
* strategy list lives here (implementations in keysReadSources.ts):
|
|
38
|
+
*
|
|
39
|
+
* Reads are deliberately NOT in the commit log (CommitBundle carries only the
|
|
40
|
+
* `untrackedSources` honesty flags), so a slice needs a reads provider. There
|
|
41
|
+
* are several legitimate providers with different trade-offs, and new ones
|
|
42
|
+
* will appear — hence an interface rather than a hardcoded path:
|
|
43
|
+
*
|
|
44
|
+
* - `keysReadFromExecutionTree` — post-hoc, ZERO setup: reads live in the
|
|
45
|
+
* snapshot's `StageSnapshot.stageReads` whenever `readTracking` ≠ 'off'
|
|
46
|
+
* (default 'full'; 'summary' still keeps the keys). Use when you have a
|
|
47
|
+
* finished run's snapshot.
|
|
48
|
+
* - `keysReadFromMap` — a prebuilt Map/object, e.g. collected live from
|
|
49
|
+
* `ScopeRecorder.onRead` events or deserialized from a stored trace.
|
|
50
|
+
* - a bare `KeysReadLookup` function — anything else (e.g. QualityRecorder:
|
|
51
|
+
* `(id) => rec.getByKey(id)?.keysRead ?? []`). Wrapped as kind 'custom-fn'.
|
|
52
|
+
*
|
|
53
|
+
* `kind` is a debugging/honesty breadcrumb: `VariableSlice.keysReadKind`
|
|
54
|
+
* records which strategy produced the slice, so a surprising slice can be
|
|
55
|
+
* traced back to its reads provider.
|
|
56
|
+
*/
|
|
57
|
+
export interface KeysReadSource {
|
|
58
|
+
/** Discriminator surfaced on {@link VariableSlice.keysReadKind}. */
|
|
59
|
+
readonly kind: string;
|
|
60
|
+
/** The lookup `causalChain` will call per visited node. */
|
|
61
|
+
readonly lookup: KeysReadLookup;
|
|
62
|
+
/**
|
|
63
|
+
* OPTIONAL honesty telemetry a strategy can compute while it builds:
|
|
64
|
+
* how many execution steps it saw, and how many actually had read entries.
|
|
65
|
+
* `stepsWithReads === 0` over a multi-step run is the machine-detectable
|
|
66
|
+
* signature of `readTracking: 'off'` — WITHOUT this, a reads-less slice is
|
|
67
|
+
* indistinguishable from "genuinely no upstream dependencies", which is a
|
|
68
|
+
* lie a triage tool must never tell. Copied onto
|
|
69
|
+
* {@link VariableSlice.readsCoverage}.
|
|
70
|
+
*/
|
|
71
|
+
readonly coverage?: ReadsCoverage;
|
|
72
|
+
}
|
|
73
|
+
/** See {@link KeysReadSource.coverage}. */
|
|
74
|
+
export interface ReadsCoverage {
|
|
75
|
+
/** Execution steps the strategy saw (nodes with a runtimeStageId). */
|
|
76
|
+
readonly steps: number;
|
|
77
|
+
/** Of those, steps that had at least one recorded read key. */
|
|
78
|
+
readonly stepsWithReads: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Why a slice could not be produced. Honest absence is a first-class result:
|
|
82
|
+
* - `'empty-log'` — there are no commits at all (run never executed, or
|
|
83
|
+
* snapshot came from elsewhere).
|
|
84
|
+
* - `'never-written'` — no commit in range wrote `key`: none wrote it whole,
|
|
85
|
+
* none wrote a path inside it, none changed it by writing a container around
|
|
86
|
+
* it (the writer rule, `memory/keyPaths.ts` — since 9.33.0 a subflow seed or
|
|
87
|
+
* an outputMapper merge-back of `cfg␟b` IS a write of `cfg`). The value (if
|
|
88
|
+
* any) came from the run's INITIAL state, run `input` (frozen args channel),
|
|
89
|
+
* or a closure — none of which the commit log can see. Same blind spot as
|
|
90
|
+
* `findLastWriter`.
|
|
91
|
+
*
|
|
92
|
+
* Each member is registered, with the one sentence that says what it means,
|
|
93
|
+
* in `memory/honesty.ts · HONESTY_CODES` (served on `foottrace`); the
|
|
94
|
+
* union declares its members through `RegisteredCode`, so a member the
|
|
95
|
+
* registry does not hold does not compile.
|
|
96
|
+
*/
|
|
97
|
+
export type MissingSliceReason = RegisteredCode<'empty-log' | 'never-written'>;
|
|
98
|
+
/**
|
|
99
|
+
* The result of a variable-first backward slice: "why is `key` what it is?".
|
|
100
|
+
*
|
|
101
|
+
* Anchoring rule: the slice is rooted at the LAST writer of `key` (before
|
|
102
|
+
* `before`, when given) — the commit that made the value what it currently
|
|
103
|
+
* is. Everything upstream of that writer is reached through the causal DAG.
|
|
104
|
+
*
|
|
105
|
+
* SERIALIZATION WARNING: `root` is an in-memory DAG — nodes appear in BOTH
|
|
106
|
+
* `parents` and `parentEdges[].parent`, and shared ancestors (diamonds) are
|
|
107
|
+
* the same object reached through many paths. `JSON.stringify(slice)`
|
|
108
|
+
* duplicates every shared subtree per path and explodes combinatorially.
|
|
109
|
+
* Never stringify it: use `sliceToJSON()` (flat, id-referenced, linear) for
|
|
110
|
+
* wire transfer or `formatSlice()` (bounded string) for LLM tools.
|
|
111
|
+
*/
|
|
112
|
+
export interface VariableSlice {
|
|
113
|
+
/** The state key that was asked about (normalised string form). */
|
|
114
|
+
key: string;
|
|
115
|
+
/**
|
|
116
|
+
* Exclusive commit-array-index upper bound the writer search was anchored
|
|
117
|
+
* at ("as it stood before this idx"). Undefined = the whole log (current
|
|
118
|
+
* value).
|
|
119
|
+
*/
|
|
120
|
+
before?: number;
|
|
121
|
+
/**
|
|
122
|
+
* The commit that last wrote `key` — the slice anchor. Absent when missing.
|
|
123
|
+
* Under the writer rule (9.33.0) it may have written only a path INSIDE the
|
|
124
|
+
* key (a subflow seed, an outputMapper merge-back): it then made part of the
|
|
125
|
+
* value, and earlier writers may account for the rest. An outputMapper's
|
|
126
|
+
* merge-back bundle carries the runtimeStageId of the stage BEFORE the mount
|
|
127
|
+
* (or of the branching decider), not the mount's — a known gap in the record
|
|
128
|
+
* (`SubflowExecutor · executeSubflow`), named in slice/README.md.
|
|
129
|
+
*/
|
|
130
|
+
writer?: CommitBundle;
|
|
131
|
+
/**
|
|
132
|
+
* The backward causal DAG rooted at the writer (same `CausalNode` shape as
|
|
133
|
+
* `causalChain` — parentEdges carry keyed data/control edges, honesty via
|
|
134
|
+
* `incompleteSources`/`truncated`). Absent when missing. See the
|
|
135
|
+
* serialization warning on this interface before stringifying.
|
|
136
|
+
*/
|
|
137
|
+
root?: CausalNode;
|
|
138
|
+
/** Present ONLY when `root` is absent — why there is no slice. */
|
|
139
|
+
missing?: MissingSliceReason;
|
|
140
|
+
/**
|
|
141
|
+
* F4b (9.33.0) — what the anchor rests on, when it is not an exact write: a `'nested-rows'` note when
|
|
142
|
+
* the writer reached the key only through rows inside it; a `'redacted'` note when the value it explains
|
|
143
|
+
* holds (or lost the key under) the log's placeholder; a `'from-initial-state'` note when no `set` /
|
|
144
|
+
* `delete` of the key or around it is in range, so the value rests on the pre-run state the log cannot
|
|
145
|
+
* see (the codes of `commitValueAtWithBasis` at the slice's point). ABSENT when there is nothing to say, so a
|
|
146
|
+
* slice anchored at a write on or around the key keeps its 9.32.0 shape. Each causal edge says the
|
|
147
|
+
* same per link (`CausalEdge.basis`).
|
|
148
|
+
*/
|
|
149
|
+
notes?: HonestyNote[];
|
|
150
|
+
/** Which {@link KeysReadSource} strategy resolved reads (honesty/debug). */
|
|
151
|
+
keysReadKind: string;
|
|
152
|
+
/**
|
|
153
|
+
* Honesty telemetry copied from the strategy when it provides one — see
|
|
154
|
+
* {@link KeysReadSource.coverage}. A root with no parents AND
|
|
155
|
+
* `stepsWithReads === 0` means "reads were not recorded", NOT "no
|
|
156
|
+
* dependencies"; triage tools must say so.
|
|
157
|
+
*/
|
|
158
|
+
readsCoverage?: ReadsCoverage;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* How a `fed` edge was attributed — the honesty axis of the FORWARD walk,
|
|
162
|
+
* the mirror of {@link AttributionBasis} for the backward one. The two words
|
|
163
|
+
* are deliberately `causalChain`'s `edgeAttribution` values, because they
|
|
164
|
+
* name the same two mechanisms:
|
|
165
|
+
*
|
|
166
|
+
* - `'per-write'` — EXACT. The child's write carries per-write read
|
|
167
|
+
* provenance (`TraceEntry.readKeys`, recorded under the executor's
|
|
168
|
+
* `writeProvenance: 'reads-prefix'` dial) and this key is IN it: the value
|
|
169
|
+
* was read before that write, so it could feed it. The same provenance
|
|
170
|
+
* also EXCLUDES exactly: a write whose `readKeys` omit this key gets no
|
|
171
|
+
* edge at all.
|
|
172
|
+
* - `'stage'` — CONSERVATIVE. The child's write carries no `readKeys` (the
|
|
173
|
+
* dial was off, or the log is mixed), so all that is known is stage-level
|
|
174
|
+
* co-occurrence: the stage read this key and wrote that one, in some order
|
|
175
|
+
* this log cannot see. A sound over-approximation — the edge may not be
|
|
176
|
+
* real. Never presented as exact: every conservative edge is stamped here
|
|
177
|
+
* AND summarised once on the slice as a `'conservative-fed-edges'`
|
|
178
|
+
* {@link HonestyNote}.
|
|
179
|
+
*
|
|
180
|
+
* Each member is registered, with the one sentence that says what it means,
|
|
181
|
+
* in `memory/honesty.ts · HONESTY_CODES` (served on `foottrace`); the
|
|
182
|
+
* union declares its members through `RegisteredCode`, so a member the
|
|
183
|
+
* registry does not hold does not compile.
|
|
184
|
+
*/
|
|
185
|
+
export type FedBasis = RegisteredCode<'per-write' | 'stage'>;
|
|
186
|
+
/**
|
|
187
|
+
* The code of a {@link HonestyNote} — a machine-readable honesty statement about a forward query's
|
|
188
|
+
* answer. A consumer BRANCHES on `code`; `detail` is the sentence to show.
|
|
189
|
+
*
|
|
190
|
+
* What each code means is registered ONCE, with the other honesty signals, in
|
|
191
|
+
* `memory/honesty.ts · HONESTY_CODES` (served as `HONESTY_CODES` on `foottrace`); this
|
|
192
|
+
* union declares its members through `RegisteredCode`, so a code the registry does not hold does
|
|
193
|
+
* not compile.
|
|
194
|
+
*/
|
|
195
|
+
export type HonestyNoteCode = RegisteredCode<'conservative-fed-edges' | 'nested-rows' | 'pre-run-origin' | 'reads-not-recorded' | 'unknown-key' | 'truncated' | 'redacted' | 'from-initial-state'>;
|
|
196
|
+
/** One honesty statement — see {@link HonestyNoteCode}. */
|
|
197
|
+
export interface HonestyNote {
|
|
198
|
+
code: HonestyNoteCode;
|
|
199
|
+
/** One human/LLM-readable sentence. Rendered by the formatters as `⚠ …`. */
|
|
200
|
+
detail: string;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* ONE recorded read of a key inside a value's live range: which execution
|
|
204
|
+
* step read it, and where that step sits in the commit log. Both join keys
|
|
205
|
+
* are carried (`runtimeStageId` for recorders/UIs, `commitIdx` for the log).
|
|
206
|
+
*/
|
|
207
|
+
export interface ForwardRead {
|
|
208
|
+
runtimeStageId: string;
|
|
209
|
+
stageId: string;
|
|
210
|
+
stageName: string;
|
|
211
|
+
/** Commit ARRAY position of the READING stage's own commit bundle. */
|
|
212
|
+
commitIdx: number;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* A `fed` edge: the parent node's value was live and read by a stage, and
|
|
216
|
+
* that same stage wrote `child`. The reader IS the child's writer — that is
|
|
217
|
+
* why the edge carries no separate "via" step.
|
|
218
|
+
*/
|
|
219
|
+
export interface ForwardEdge {
|
|
220
|
+
child: ForwardNode;
|
|
221
|
+
/** Exact (`'per-write'`) or conservative (`'stage'`) — see {@link FedBasis}. */
|
|
222
|
+
basis: FedBasis;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* ONE LIFE of one key's value — the forward mirror of {@link CausalNode}.
|
|
226
|
+
*
|
|
227
|
+
* A value's life starts at a write and ends at the key's NEXT write
|
|
228
|
+
* (`nextWriteIdx`). Reads inside that window saw THIS value; the writes
|
|
229
|
+
* those readers made are this value's `fedEdges`.
|
|
230
|
+
*
|
|
231
|
+
* SERIALIZATION WARNING (same as {@link VariableSlice}): `fedEdges` form an
|
|
232
|
+
* in-memory DAG with SHARED nodes — two different values read by one stage
|
|
233
|
+
* feed the same child write. `JSON.stringify` re-serializes shared subtrees
|
|
234
|
+
* per path. Use `forwardSliceToJSON()` / `formatForwardSlice()`.
|
|
235
|
+
*/
|
|
236
|
+
export interface ForwardNode {
|
|
237
|
+
/** The state key whose value this is (normalised string form). */
|
|
238
|
+
key: string;
|
|
239
|
+
/**
|
|
240
|
+
* - `'write'` — a commit in this log started this life.
|
|
241
|
+
* - `'pre-run'` — the value was already there before the log's first write
|
|
242
|
+
* of the key (initial state / frozen `input` / a closure). The
|
|
243
|
+
* identity/verb fields below are ABSENT: the commit log genuinely does
|
|
244
|
+
* not know who put it there.
|
|
245
|
+
*/
|
|
246
|
+
origin: 'write' | 'pre-run';
|
|
247
|
+
/** Execution step that wrote it. Absent for a `'pre-run'` origin. */
|
|
248
|
+
runtimeStageId?: string;
|
|
249
|
+
/** Stable stage identifier of the writer. Absent for `'pre-run'`. */
|
|
250
|
+
stageId?: string;
|
|
251
|
+
/** Human-readable stage name of the writer. Absent for `'pre-run'`. */
|
|
252
|
+
stageName?: string;
|
|
253
|
+
/** Commit ARRAY position of the write. Absent for `'pre-run'`. */
|
|
254
|
+
commitIdx?: number;
|
|
255
|
+
/** The trace verb of that write. Absent for `'pre-run'`. */
|
|
256
|
+
verb?: TraceEntry['verb'];
|
|
257
|
+
/**
|
|
258
|
+
* Commit ARRAY position of the key's NEXT write — where this value's life
|
|
259
|
+
* ends. Absent = still live at the end of the log. Reads AT this index
|
|
260
|
+
* still belong to THIS life: reads fire before their stage's commit.
|
|
261
|
+
*/
|
|
262
|
+
nextWriteIdx?: number;
|
|
263
|
+
/** BFS depth from the anchor (0 = the anchor value). */
|
|
264
|
+
depth: number;
|
|
265
|
+
/** Recorded reads of `key` inside this life, in commit order. */
|
|
266
|
+
reads: ForwardRead[];
|
|
267
|
+
/** What this value fed — one edge per downstream write. */
|
|
268
|
+
fedEdges: ForwardEdge[];
|
|
269
|
+
/**
|
|
270
|
+
* Honesty marker copied from the writer's `CommitBundle.untrackedSources`
|
|
271
|
+
* — identical meaning to {@link CausalNode.incompleteSources}.
|
|
272
|
+
*/
|
|
273
|
+
incompleteSources?: ReadonlyArray<UntrackedSource>;
|
|
274
|
+
/**
|
|
275
|
+
* Set on the ROOT only, and only when a budget actually cut the walk. Carries
|
|
276
|
+
* no code: what it means is registered as `'truncated'` in `HONESTY_CODES`.
|
|
277
|
+
*/
|
|
278
|
+
truncated?: {
|
|
279
|
+
byDepth: boolean;
|
|
280
|
+
byNodes: boolean;
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* The result of a forward slice: "who READ this value, and what did it
|
|
285
|
+
* FEED?" — the mirror of {@link VariableSlice}.
|
|
286
|
+
*
|
|
287
|
+
* Anchoring rule is the backward one, unchanged: the LAST write of `key`
|
|
288
|
+
* (before `before`, when given). What differs is the direction of the walk —
|
|
289
|
+
* `before` bounds the ANCHOR search only; the walk then runs forward past it,
|
|
290
|
+
* because "what did the value at step 12 go on to feed?" is the question.
|
|
291
|
+
*
|
|
292
|
+
* ABSENCE, split by what the recording affords (a typo must never read as
|
|
293
|
+
* "this variable has no history"):
|
|
294
|
+
* - `'empty-log'` — nothing executed.
|
|
295
|
+
* - `'never-written'` — no write (the writer rule) AND no recorded read on,
|
|
296
|
+
* inside or around the key, in a log
|
|
297
|
+
* that DOES carry recorded reads. The log can see readers and this key has
|
|
298
|
+
* none, so "no history" is a finding, not a blind spot: no root node, and
|
|
299
|
+
* an `'unknown-key'` {@link HonestyNote} names the keys the log does know.
|
|
300
|
+
* - otherwise a key with no write still gets a `'pre-run'` origin life —
|
|
301
|
+
* the value came from initial state / `input` / a closure and stages read
|
|
302
|
+
* it. When the log carries NO recorded reads at all, that pre-run node is
|
|
303
|
+
* the only honest answer and always ships the `'reads-not-recorded'` note:
|
|
304
|
+
* a typo and an unread seeded key are genuinely indistinguishable then.
|
|
305
|
+
*/
|
|
306
|
+
export interface ForwardSlice {
|
|
307
|
+
/** The state key that was asked about (normalised string form). */
|
|
308
|
+
key: string;
|
|
309
|
+
/** Exclusive commit-array-index bound the ANCHOR search used. */
|
|
310
|
+
before?: number;
|
|
311
|
+
/** The commit that wrote the anchor value. Absent for a pre-run origin. */
|
|
312
|
+
writer?: CommitBundle;
|
|
313
|
+
/** The forward DAG rooted at the anchor value. Absent when `missing`. */
|
|
314
|
+
root?: ForwardNode;
|
|
315
|
+
/** Present ONLY when `root` is absent — see {@link MissingSliceReason}. */
|
|
316
|
+
missing?: MissingSliceReason;
|
|
317
|
+
/** Which {@link KeysReadSource} strategy resolved reads (honesty/debug). */
|
|
318
|
+
keysReadKind: string;
|
|
319
|
+
/** Honesty telemetry from the strategy — see {@link KeysReadSource.coverage}. */
|
|
320
|
+
readsCoverage?: ReadsCoverage;
|
|
321
|
+
/** Always present (possibly empty) — see {@link HonestyNote}. */
|
|
322
|
+
notes: HonestyNote[];
|
|
323
|
+
}
|
|
324
|
+
/** One moment in a key's life: a write, or a recorded read. */
|
|
325
|
+
export interface KeyMoment {
|
|
326
|
+
kind: 'write' | 'read';
|
|
327
|
+
/**
|
|
328
|
+
* Commit ARRAY position — for a `'write'` its own commit, for a `'read'`
|
|
329
|
+
* the READING stage's commit. With `runtimeStageId` these are the two
|
|
330
|
+
* universal join keys (to the commit log, and to recorders/UIs).
|
|
331
|
+
*/
|
|
332
|
+
commitIdx: number;
|
|
333
|
+
runtimeStageId: string;
|
|
334
|
+
stageId: string;
|
|
335
|
+
stageName: string;
|
|
336
|
+
/** `'write'` moments only: the trace verb of the write. */
|
|
337
|
+
verb?: TraceEntry['verb'];
|
|
338
|
+
/**
|
|
339
|
+
* `'read'` moments only: the `commitIdx` of the write whose live range
|
|
340
|
+
* this read sits in — which value it saw. ABSENT when the read precedes
|
|
341
|
+
* every write of the key (pre-run origin: initial state / `input` /
|
|
342
|
+
* closure).
|
|
343
|
+
*/
|
|
344
|
+
fromWriteIdx?: number;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* The whole life of one key in commit order — every write and every recorded
|
|
348
|
+
* read. The flat, chronological companion to {@link ForwardSlice}: no graph,
|
|
349
|
+
* no budgets, no live references (already JSON-safe by construction).
|
|
350
|
+
*/
|
|
351
|
+
export interface KeyTimeline {
|
|
352
|
+
/** The state key that was asked about (normalised string form). */
|
|
353
|
+
key: string;
|
|
354
|
+
/** Exclusive commit-array-index bound: only moments before this index. */
|
|
355
|
+
before?: number;
|
|
356
|
+
/** Writes and reads in commit order. Absent when `missing`. */
|
|
357
|
+
moments?: KeyMoment[];
|
|
358
|
+
/**
|
|
359
|
+
* Present ONLY when `moments` is absent — same split as
|
|
360
|
+
* {@link ForwardSlice}: `'empty-log'` when nothing executed,
|
|
361
|
+
* `'never-written'` when a log that DOES carry recorded reads has neither
|
|
362
|
+
* a write nor a read of this key (an `'unknown-key'` note then names the
|
|
363
|
+
* keys it knows).
|
|
364
|
+
*/
|
|
365
|
+
missing?: MissingSliceReason;
|
|
366
|
+
/** Which {@link KeysReadSource} strategy resolved reads (honesty/debug). */
|
|
367
|
+
keysReadKind: string;
|
|
368
|
+
/** Honesty telemetry from the strategy — see {@link KeysReadSource.coverage}. */
|
|
369
|
+
readsCoverage?: ReadsCoverage;
|
|
370
|
+
/** Always present (possibly empty) — see {@link HonestyNote}. */
|
|
371
|
+
notes: HonestyNote[];
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Flat, id-referenced, JSON-safe projection of a {@link ForwardSlice} — the
|
|
375
|
+
* forward twin of {@link SliceJSON}, and for the same reason (shared nodes;
|
|
376
|
+
* see the serialization warning on {@link ForwardNode}).
|
|
377
|
+
*
|
|
378
|
+
* Node ids differ from `SliceJSON`'s deliberately: a forward node is a
|
|
379
|
+
* (key, write) pair, so one `runtimeStageId` can host several nodes (a stage
|
|
380
|
+
* writing two keys). Ids are therefore OPAQUE, assigned in BFS order —
|
|
381
|
+
* never parse them; join on `runtimeStageId` / `commitIdx` / `key`, which
|
|
382
|
+
* every node carries.
|
|
383
|
+
*/
|
|
384
|
+
export interface ForwardSliceJSON {
|
|
385
|
+
key: string;
|
|
386
|
+
before?: number;
|
|
387
|
+
missing?: MissingSliceReason;
|
|
388
|
+
keysReadKind: string;
|
|
389
|
+
readsCoverage?: ReadsCoverage;
|
|
390
|
+
notes: HonestyNote[];
|
|
391
|
+
/** Opaque id of the anchor node. Absent when `missing`. */
|
|
392
|
+
rootId?: string;
|
|
393
|
+
/** Every DAG node exactly once, in BFS order. */
|
|
394
|
+
nodes?: Array<{
|
|
395
|
+
id: string;
|
|
396
|
+
key: string;
|
|
397
|
+
origin: 'write' | 'pre-run';
|
|
398
|
+
runtimeStageId?: string;
|
|
399
|
+
stageId?: string;
|
|
400
|
+
stageName?: string;
|
|
401
|
+
commitIdx?: number;
|
|
402
|
+
verb?: TraceEntry['verb'];
|
|
403
|
+
nextWriteIdx?: number;
|
|
404
|
+
depth: number;
|
|
405
|
+
reads: ForwardRead[];
|
|
406
|
+
incompleteSources?: ReadonlyArray<UntrackedSource>;
|
|
407
|
+
}>;
|
|
408
|
+
/** Id-referenced edges: parent (`from`) fed child (`to`). */
|
|
409
|
+
edges?: Array<{
|
|
410
|
+
from: string;
|
|
411
|
+
to: string;
|
|
412
|
+
basis: FedBasis;
|
|
413
|
+
}>;
|
|
414
|
+
/** Copied from the root when a budget cut the walk — registered as `'truncated'` in `HONESTY_CODES`. */
|
|
415
|
+
truncated?: {
|
|
416
|
+
byDepth: boolean;
|
|
417
|
+
byNodes: boolean;
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* How an element's birth commit was determined — the honesty axis of
|
|
422
|
+
* append-fold provenance. Ordered strongest → weakest:
|
|
423
|
+
*
|
|
424
|
+
* - `'append-verb'` — the engine RECORDED this tail append
|
|
425
|
+
* (`commitValues: 'delta'`). Exact by construction.
|
|
426
|
+
* - `'prefix-inference'` — a full-value write preserved the previous array as
|
|
427
|
+
* a strict prefix, so the new tail is attributed to this commit. Heuristic:
|
|
428
|
+
* a writer that REPLACED the array with one that happens to share the old
|
|
429
|
+
* prefix is indistinguishable from an append. Right in practice (push-style
|
|
430
|
+
* growth), labeled honestly so consumers can tell.
|
|
431
|
+
* - `'whole-value'` — the array was (re)placed wholesale; every
|
|
432
|
+
* element's provenance resets to this commit. Exact but coarse.
|
|
433
|
+
*
|
|
434
|
+
* Each member is registered, with the one sentence that says what it means,
|
|
435
|
+
* in `memory/honesty.ts · HONESTY_CODES` (served on `foottrace`); the
|
|
436
|
+
* union declares its members through `RegisteredCode`, so a member the
|
|
437
|
+
* registry does not hold does not compile.
|
|
438
|
+
*/
|
|
439
|
+
export type AttributionBasis = RegisteredCode<'append-verb' | 'prefix-inference' | 'whole-value'>;
|
|
440
|
+
/**
|
|
441
|
+
* The birth record of ONE array element: which commit (and therefore which
|
|
442
|
+
* stage execution) first put it there. This is what turns the agent
|
|
443
|
+
* mega-key problem ("everything depends on `history`") into element-level
|
|
444
|
+
* answers ("history[7] was appended by tool-calls#41 in iteration 3").
|
|
445
|
+
*
|
|
446
|
+
* @see elementProvenance — the query that returns this record.
|
|
447
|
+
*/
|
|
448
|
+
export interface ElementBirth {
|
|
449
|
+
/** Element index in the reconstructed array at query time. */
|
|
450
|
+
index: number;
|
|
451
|
+
/** Commit ARRAY position (the `CommitBundle.idx` space) of the birth. */
|
|
452
|
+
commitIdx: number;
|
|
453
|
+
/** Execution step that wrote it — joins to slices, recorders, UIs. */
|
|
454
|
+
runtimeStageId: string;
|
|
455
|
+
/** Stable stage identifier of the writer. */
|
|
456
|
+
stageId: string;
|
|
457
|
+
/** Human-readable stage name of the writer. */
|
|
458
|
+
stageName: string;
|
|
459
|
+
/** The trace verb of the birth commit's entry for this key. */
|
|
460
|
+
verb: TraceEntry['verb'];
|
|
461
|
+
/** How the attribution was determined — see {@link AttributionBasis}. */
|
|
462
|
+
basis: AttributionBasis;
|
|
463
|
+
/**
|
|
464
|
+
* F4b (9.33.0) — set only by `elementProvenance`: the `basis` of the array this element sits in
|
|
465
|
+
* (`ArrayProvenance.basis` — e.g. `'from-initial-state'`, `'redacted'`). Absent when that basis is empty.
|
|
466
|
+
*/
|
|
467
|
+
valueBasis?: ValueBasis[];
|
|
468
|
+
/**
|
|
469
|
+
* The element's value as of the fold (detached clone). Redaction note:
|
|
470
|
+
* values are re-served exactly as the commit log stored them — a redacted
|
|
471
|
+
* key's `'REDACTED'` placeholder (`memory/placeholders.ts ·
|
|
472
|
+
* LOG_PLACEHOLDER`, the log's string) stays redacted; this layer never
|
|
473
|
+
* resurrects originals.
|
|
474
|
+
*/
|
|
475
|
+
value: unknown;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Why element provenance could not be produced (mirrors
|
|
479
|
+
* {@link MissingSliceReason} — one honest-absence pattern module-wide):
|
|
480
|
+
* - `'empty-log'` — no commits at all.
|
|
481
|
+
* - `'never-written'` — no commit in range wrote the key (the writer rule:
|
|
482
|
+
* a row on it, inside it, or around it that changed it).
|
|
483
|
+
* - `'not-an-array'` — the key WAS written but its folded value is not an
|
|
484
|
+
* array at the queried point: a scalar/object key, a deleted key, or a
|
|
485
|
+
* merge that degraded it. Element provenance is an array concept — for
|
|
486
|
+
* scalar keys the right query is `sliceForKey`.
|
|
487
|
+
*
|
|
488
|
+
* Each member is registered, with the one sentence that says what it means,
|
|
489
|
+
* in `memory/honesty.ts · HONESTY_CODES` (served on `foottrace`); the
|
|
490
|
+
* union declares its members through `RegisteredCode`, so a member the
|
|
491
|
+
* registry does not hold does not compile.
|
|
492
|
+
*/
|
|
493
|
+
export type MissingProvenanceReason = RegisteredCode<'empty-log' | 'never-written' | 'not-an-array'>;
|
|
494
|
+
/**
|
|
495
|
+
* Element-level provenance for one array-valued key. Mirrors
|
|
496
|
+
* {@link VariableSlice}'s honest-absence shape: on success `atIdx`/`length`/
|
|
497
|
+
* `births` are set; otherwise `missing` says why (present ONLY when `births`
|
|
498
|
+
* is absent).
|
|
499
|
+
*
|
|
500
|
+
* @see arrayProvenance — the query that returns this.
|
|
501
|
+
* @see ElementBirth — one record per element, index-aligned.
|
|
502
|
+
*/
|
|
503
|
+
export interface ArrayProvenance {
|
|
504
|
+
/** The state key (normalised string form). */
|
|
505
|
+
key: string;
|
|
506
|
+
/** Inclusive commit array idx the fold ran to. Absent when missing. */
|
|
507
|
+
atIdx?: number;
|
|
508
|
+
/** Length of the reconstructed array (births.length === length). */
|
|
509
|
+
length?: number;
|
|
510
|
+
/** One birth per element, index-aligned with the reconstructed array. */
|
|
511
|
+
births?: ElementBirth[];
|
|
512
|
+
/** Present ONLY when `births` is absent — why there is no provenance. */
|
|
513
|
+
missing?: MissingProvenanceReason;
|
|
514
|
+
/**
|
|
515
|
+
* F4b (9.33.0) — the codes `commitValueAtWithBasis` gives the key's value at `atIdx` (or at the end of
|
|
516
|
+
* the log): `'nested-rows'`, `'from-initial-state'` (elements seeded before the run are invisible to the
|
|
517
|
+
* fold), `'redacted'`, `'deleted'`. A code `missing` already says is left out (`'never-written'`, and the
|
|
518
|
+
* initial-state caveat that sentence already states). ABSENT when empty, so an exact answer keeps its
|
|
519
|
+
* 9.32.0 shape.
|
|
520
|
+
*/
|
|
521
|
+
basis?: ValueBasis[];
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Flat, id-referenced, JSON-safe projection of a {@link VariableSlice} —
|
|
525
|
+
* linear in node count (each node serialized exactly once; edges reference
|
|
526
|
+
* ids). THE shape to persist, send over the wire, or hand to structured
|
|
527
|
+
* consumers. See the serialization warning on {@link VariableSlice}.
|
|
528
|
+
*/
|
|
529
|
+
export interface SliceJSON {
|
|
530
|
+
key: string;
|
|
531
|
+
before?: number;
|
|
532
|
+
missing?: MissingSliceReason;
|
|
533
|
+
keysReadKind: string;
|
|
534
|
+
readsCoverage?: ReadsCoverage;
|
|
535
|
+
/** runtimeStageId of the anchor writer. Absent when missing. */
|
|
536
|
+
writerId?: string;
|
|
537
|
+
/** Every DAG node exactly once, keyed by runtimeStageId. */
|
|
538
|
+
nodes?: Record<string, {
|
|
539
|
+
stageId: string;
|
|
540
|
+
stageName: string;
|
|
541
|
+
keysWritten: string[];
|
|
542
|
+
depth: number;
|
|
543
|
+
incompleteSources?: ReadonlyArray<UntrackedSource>;
|
|
544
|
+
/** Copied from `CausalNode.preRunReads` (9.33.0); absent when every read had a writer. */
|
|
545
|
+
preRunReads?: {
|
|
546
|
+
code: RegisteredCode<'pre-run-origin'>;
|
|
547
|
+
keys: string[];
|
|
548
|
+
};
|
|
549
|
+
}>;
|
|
550
|
+
/** Id-referenced edges: child (`from`) depends on parent (`to`). */
|
|
551
|
+
edges?: Array<{
|
|
552
|
+
from: string;
|
|
553
|
+
to: string;
|
|
554
|
+
kind: 'data' | 'control';
|
|
555
|
+
key?: string;
|
|
556
|
+
weight: number;
|
|
557
|
+
/** Copied from `CausalEdge.basis` (9.33.0); absent for an exact edge. */
|
|
558
|
+
basis?: RegisteredCode<'nested-rows'>;
|
|
559
|
+
}>;
|
|
560
|
+
/** Copied from the root when a budget cut the slice — registered as `'truncated'` in `HONESTY_CODES`. */
|
|
561
|
+
truncated?: {
|
|
562
|
+
byDepth: boolean;
|
|
563
|
+
byNodes: boolean;
|
|
564
|
+
};
|
|
565
|
+
/** Copied from {@link VariableSlice.notes} (9.33.0); absent when the slice has none. */
|
|
566
|
+
notes?: HonestyNote[];
|
|
567
|
+
}
|