@hviana/sema 0.2.3 → 0.2.5

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 (60) hide show
  1. package/dist/src/geometry.d.ts +26 -0
  2. package/dist/src/geometry.js +32 -3
  3. package/dist/src/mind/attention.d.ts +246 -7
  4. package/dist/src/mind/attention.js +771 -173
  5. package/dist/src/mind/bridge.d.ts +30 -0
  6. package/dist/src/mind/bridge.js +569 -0
  7. package/dist/src/mind/index.d.ts +2 -0
  8. package/dist/src/mind/junction.d.ts +30 -1
  9. package/dist/src/mind/junction.js +73 -18
  10. package/dist/src/mind/match.d.ts +15 -2
  11. package/dist/src/mind/match.js +3 -8
  12. package/dist/src/mind/mechanisms/cast.d.ts +54 -0
  13. package/dist/src/mind/mechanisms/cast.js +268 -37
  14. package/dist/src/mind/mechanisms/cover.js +16 -31
  15. package/dist/src/mind/mechanisms/recall.js +66 -0
  16. package/dist/src/mind/mind.d.ts +2 -0
  17. package/dist/src/mind/rationale.d.ts +7 -2
  18. package/dist/src/mind/rationale.js +6 -5
  19. package/dist/src/mind/reasoning.d.ts +11 -0
  20. package/dist/src/mind/reasoning.js +58 -2
  21. package/dist/src/mind/recognition.js +127 -7
  22. package/dist/src/mind/traverse.js +90 -25
  23. package/dist/src/mind/types.d.ts +57 -2
  24. package/dist/src/mind/types.js +38 -7
  25. package/dist/src/store.d.ts +12 -3
  26. package/dist/src/store.js +9 -3
  27. package/package.json +1 -1
  28. package/src/geometry.ts +52 -3
  29. package/src/mind/attention.ts +1199 -128
  30. package/src/mind/bridge.ts +596 -0
  31. package/src/mind/index.ts +16 -0
  32. package/src/mind/junction.ts +125 -16
  33. package/src/mind/match.ts +19 -5
  34. package/src/mind/mechanisms/cast.ts +290 -38
  35. package/src/mind/mechanisms/cover.ts +23 -36
  36. package/src/mind/mechanisms/recall.ts +79 -0
  37. package/src/mind/mind.ts +15 -0
  38. package/src/mind/rationale.ts +12 -4
  39. package/src/mind/reasoning.ts +71 -2
  40. package/src/mind/recognition.ts +132 -7
  41. package/src/mind/traverse.ts +91 -24
  42. package/src/mind/types.ts +95 -6
  43. package/src/store.ts +19 -5
  44. package/test/36-already-answered-fusion.test.mjs +128 -0
  45. package/test/37-cluster-dispersion-fusion.test.mjs +190 -0
  46. package/test/38-reason-restate-guard.test.mjs +94 -0
  47. package/test/39-cast-restate-guard.test.mjs +102 -0
  48. package/test/40-choosenext-scale-guard.test.mjs +75 -0
  49. package/test/41-seatofnode-direction.test.mjs +85 -0
  50. package/test/42-recognise-trace-idempotence.test.mjs +106 -0
  51. package/test/43-cast-analog-seat.test.mjs +244 -0
  52. package/test/44-recognise-edge-whitespace.test.mjs +63 -0
  53. package/test/45-liftanswer-restated-trim.test.mjs +60 -0
  54. package/test/46-recognise-multibyte-edge.test.mjs +85 -0
  55. package/test/47-cast-comparison-coverage.test.mjs +134 -0
  56. package/test/48-recognise-turn-connective.test.mjs +125 -0
  57. package/test/49-natural-units-synonym-bridge.test.mjs +175 -0
  58. package/test/50-cast-analog-consensus-floor.test.mjs +179 -0
  59. package/test/51-structural-resonance-ladder.test.mjs +552 -0
  60. package/test/52-climb-consensus-instrumentation.test.mjs +324 -0
@@ -1,3 +1,4 @@
1
+ import { Vec } from "./vec.js";
1
2
  import { Sema, Space } from "./sema.js";
2
3
  import { Alphabet } from "./alphabet.js";
3
4
  /** The store's geometric identity bar: cosine ≥ 1 − 1/√D is the similarity at
@@ -144,6 +145,31 @@ export declare function stablePrefixFoldIncremental(space: Space, alphabet: Alph
144
145
  tree: Sema;
145
146
  fold: StableFold;
146
147
  };
148
+ /** Plain river fold WITHOUT the final root normalize — the segment-level
149
+ * building block of {@link stablePrefixFold} (interiors must keep their
150
+ * byte-proportional magnitude; only the whole perception's root is ever
151
+ * normalized). Exported so callers that COMPOSE already-existing structural
152
+ * parts into a hypothetical synthetic root (see {@link composeStructuralGist})
153
+ * can feed the same raw primitive instead of duplicating its mathematics. */
154
+ export declare function riverFoldRaw(space: Space, row: Folded[]): Folded;
155
+ /** One already-existing structural vector to compose, paired with the byte
156
+ * span (query-slot) length it stands in for. `len`, not the vector's own
157
+ * magnitude, is what {@link composeStructuralGist} restores — the composed
158
+ * slot's NATURAL span, exactly as the linear river fold would carry it. */
159
+ export interface StructuralPart {
160
+ v: Vec;
161
+ len: number;
162
+ }
163
+ /** Synthesize a hypothetical internal structure from already-existing
164
+ * structural vectors — NOT from bytes. This is the raw positional
165
+ * composition the linear river fold already uses (see the folding header
166
+ * above): each part is positionally bound into its own seat, its natural
167
+ * span magnitude is preserved, the parts are linearly superposed, and only
168
+ * the final synthetic root is normalized. It never calls {@link gistOf}
169
+ * (there is no `gistOf` here — geometry.ts has no store), never perceives a
170
+ * concatenated byte string, and never interns or stores a new node: the
171
+ * result is an opaque, ungrounded Vec for an ANN probe only. */
172
+ export declare function composeStructuralGist(space: Space, parts: readonly StructuralPart[]): Vec;
147
173
  /** The PLAIN fold's full level pyramid — every level's item list, bottom
148
174
  * (leaves) to top (root). Left-grouped folding is RADIX-ALIGNED: the item
149
175
  * at level L, index i, covers exactly bytes [i·mg^L, (i+1)·mg^L) whenever
@@ -6,7 +6,7 @@
6
6
  // that cross the stable-prefix boundary are split so the prefix folds
7
7
  // identically regardless of what follows — pure structural stability.
8
8
  // 3. The same rule recurses level after level until one root remains.
9
- import { normalize } from "./vec.js";
9
+ import { addInto, copy, normalize, zeros } from "./vec.js";
10
10
  import { sema } from "./sema.js";
11
11
  // ---- geometric constants ----
12
12
  //
@@ -374,8 +374,10 @@ function fold2(space, a, b) {
374
374
  /** Plain river fold WITHOUT the final root normalize — the segment-level
375
375
  * building block of {@link stablePrefixFold} (interiors must keep their
376
376
  * byte-proportional magnitude; only the whole perception's root is ever
377
- * normalized). */
378
- function riverFoldRaw(space, row) {
377
+ * normalized). Exported so callers that COMPOSE already-existing structural
378
+ * parts into a hypothetical synthetic root (see {@link composeStructuralGist})
379
+ * can feed the same raw primitive instead of duplicating its mathematics. */
380
+ export function riverFoldRaw(space, row) {
379
381
  if (row.length === 0) {
380
382
  const z = new Float32Array(space.D);
381
383
  return { tree: sema(z, new Uint8Array(0), null), len: 0 };
@@ -390,6 +392,33 @@ function riverFoldRaw(space, row) {
390
392
  }
391
393
  return level[0];
392
394
  }
395
+ /** Synthesize a hypothetical internal structure from already-existing
396
+ * structural vectors — NOT from bytes. This is the raw positional
397
+ * composition the linear river fold already uses (see the folding header
398
+ * above): each part is positionally bound into its own seat, its natural
399
+ * span magnitude is preserved, the parts are linearly superposed, and only
400
+ * the final synthetic root is normalized. It never calls {@link gistOf}
401
+ * (there is no `gistOf` here — geometry.ts has no store), never perceives a
402
+ * concatenated byte string, and never interns or stores a new node: the
403
+ * result is an opaque, ungrounded Vec for an ANN probe only. */
404
+ export function composeStructuralGist(space, parts) {
405
+ const foldedParts = [];
406
+ for (const part of parts) {
407
+ if (part.len <= 0)
408
+ continue;
409
+ const direction = copy(part.v);
410
+ normalize(direction);
411
+ const scaled = zeros(space.D);
412
+ addInto(scaled, direction, Math.sqrt(part.len));
413
+ foldedParts.push({ tree: sema(scaled), len: part.len });
414
+ }
415
+ if (foldedParts.length === 0)
416
+ return zeros(space.D);
417
+ const rawRoot = riverFoldRaw(space, foldedParts);
418
+ const result = copy(rawRoot.tree.v);
419
+ normalize(result);
420
+ return result;
421
+ }
393
422
  /** Plain bytes→tree (identical to capability-less {@link bytesToTree}) that
394
423
  * also RETURNS its pyramid, reusing `prev` — the pyramid of a PROPER
395
424
  * prefix of `bytes` (caller guarantees content match and
@@ -1,16 +1,201 @@
1
1
  import type { DerivationStep } from "./graph-search.js";
2
- import type { AncestorReach, Attention, AttentionRead, DFMode, MindContext, Region, RegionVote, SaturationInfo } from "./types.js";
2
+ import type { AncestorReach, Attention, AttentionRead, DFMode, MindContext, Region, RegionVote, SaturationInfo, SaturationStop } from "./types.js";
3
+ import { type StructuralPart } from "../geometry.js";
4
+ import { type JunctionSynonymSides } from "./junction.js";
5
+ /** How the newly-added graded junction ladder (junction.ts / attention.ts's
6
+ * {@link CrossRegionTier}) is reported on a `junctionVotes` entry. The
7
+ * instrumentation spec this implements predates that ladder and only knew
8
+ * two tiers ("exact" | "synonym"); with the richer `CrossRegionTier` now
9
+ * the real shape of a junction vote's provenance, `junctionVotes[].tier`
10
+ * reports it DIRECTLY (the tier as-is: "exact" | "single-synonym" |
11
+ * "double-synonym" | "structural-resonance") rather than collapsing every
12
+ * non-exact tier into a lossy "synonym" bucket — the whole point of
13
+ * exposing `tier` here is to let a debugger tell a halo-sibling
14
+ * substitution apart from a structural-resonance ANN guess, which the
15
+ * spec's original two-value type cannot do. */
16
+ export type ClimbConsensusJunctionTier = CrossRegionTier;
17
+ export type RegionOutcome = "voted" | "no-ann-hit" | "no-structural-reach" | "saturated-abstention" | "nonpositive-df-weight" | "contrastive-margin-rejection";
18
+ export interface ConsensusRegionTrace {
19
+ index: number;
20
+ source: "perceived" | "recognised";
21
+ span: [number, number];
22
+ chunk: boolean;
23
+ known: boolean;
24
+ canonicalId?: number;
25
+ canonicalUsable: boolean;
26
+ canonicalFailed: boolean;
27
+ annQueried: boolean;
28
+ annHitsReturned: number;
29
+ annHitsExamined: number;
30
+ selected?: {
31
+ source: "canonical" | "ann";
32
+ node: number;
33
+ rank?: number;
34
+ score: number;
35
+ fallback?: "orphan" | "saturated-tie";
36
+ };
37
+ reachNode?: number;
38
+ outcome: RegionOutcome;
39
+ idf?: number;
40
+ dfWeight?: number;
41
+ contrastiveMargin?: number;
42
+ contrastiveNoiseFloor?: number;
43
+ mutualWeight?: number;
44
+ voteWeightPerRoot?: number;
45
+ focusWeightPerRoot?: number;
46
+ ordinaryVoteProduced: boolean;
47
+ superseded: boolean;
48
+ }
49
+ export interface ConsensusReachTrace {
50
+ node: number;
51
+ roots: number[];
52
+ contextsReached: number;
53
+ saturated: boolean;
54
+ saturation?: SaturationStop;
55
+ }
56
+ export type AnchorRejectionReason = "below-natural-break" | "below-consensus-floor" | "leading-saturation";
57
+ export interface ConsensusAnchorTrace {
58
+ anchor: number;
59
+ rank: number;
60
+ pooledVote: number;
61
+ idfVote: number;
62
+ candidateBreadth: number;
63
+ contributingVotes: number;
64
+ contributingEvidence: number;
65
+ breadth: number;
66
+ contributingSpans: Array<[number, number]>;
67
+ clusters: number;
68
+ commit: {
69
+ status: "root" | "overlap" | "rejected";
70
+ dominant: boolean;
71
+ passesNaturalBreak?: boolean;
72
+ passesConsensusFloor?: boolean;
73
+ pastLeadingSaturation?: boolean;
74
+ rejectionReasons: AnchorRejectionReason[];
75
+ };
76
+ }
77
+ export interface JunctionVoteTrace {
78
+ container: number;
79
+ span: [number, number];
80
+ roots: number[];
81
+ sourceRegionIndices: number[];
82
+ explainedAwayRegionIndices: number[];
83
+ absorbed: number;
84
+ tier?: ClimbConsensusJunctionTier;
85
+ }
86
+ export interface ClimbConsensusData {
87
+ version: 1;
88
+ cache: {
89
+ hit: boolean;
90
+ detailAvailable: boolean;
91
+ };
92
+ config: {
93
+ annK: number;
94
+ crossRegionProbeLimit: number;
95
+ mode: DFMode;
96
+ corpusN?: number;
97
+ dimension?: number;
98
+ hubBound?: number;
99
+ estimatorNoise?: number;
100
+ naturalBreak?: number;
101
+ consensusFloor?: number;
102
+ };
103
+ candidates: {
104
+ perceived: number;
105
+ recognised: number;
106
+ total: number;
107
+ };
108
+ regions?: ConsensusRegionTrace[];
109
+ reaches?: ConsensusReachTrace[];
110
+ crossRegion?: {
111
+ eligibleRegions: number;
112
+ maximalRegions: number;
113
+ probeLimit: number;
114
+ probesAttempted: number;
115
+ junctionVotes: JunctionVoteTrace[];
116
+ supersededOrdinaryVotes: number;
117
+ };
118
+ saturation?: {
119
+ regionIntervals: Array<{
120
+ start: number;
121
+ end: number;
122
+ }>;
123
+ hasLeading: boolean;
124
+ leadingEnd: number;
125
+ };
126
+ pooling?: {
127
+ inputVotes: number;
128
+ eligibleVotes: number;
129
+ saturationMaskedVotes: number;
130
+ };
131
+ anchors?: ConsensusAnchorTrace[];
132
+ result: AttentionRead;
133
+ }
134
+ /** The mutable collection buffers threaded through one traced consensus
135
+ * climb — allocated exactly once, in {@link computeAttention}, only when
136
+ * `ctx.trace` is set. Every field mirrors a `ClimbConsensusData` array/map,
137
+ * built incrementally as the pipeline runs so commit-time decisions (in
138
+ * particular) are recorded LIVE, not reconstructed afterward. */
139
+ interface TraceDraft {
140
+ perceivedCount: number;
141
+ regions: ConsensusRegionTrace[];
142
+ crossRegionJunctionVotes: JunctionVoteTrace[];
143
+ crossRegionSummary?: {
144
+ eligibleRegions: number;
145
+ maximalRegions: number;
146
+ probeLimit: number;
147
+ probesAttempted: number;
148
+ };
149
+ supersededOrdinaryVotes: number;
150
+ saturation?: {
151
+ regionIntervals: Array<{
152
+ start: number;
153
+ end: number;
154
+ }>;
155
+ hasLeading: boolean;
156
+ leadingEnd: number;
157
+ };
158
+ pooling?: {
159
+ inputVotes: number;
160
+ eligibleVotes: number;
161
+ saturationMaskedVotes: number;
162
+ };
163
+ anchors: ConsensusAnchorTrace[];
164
+ }
165
+ /** The config/corpus context {@link traceAttention} needs to fill in
166
+ * `ClimbConsensusData.config` and `.result` at whichever exit fires —
167
+ * threaded down from {@link computeAttention} rather than re-derived, so
168
+ * every emission point reports the SAME numbers the real climb used. */
169
+ interface ClimbConsensusCfg {
170
+ k: number;
171
+ mode: DFMode;
172
+ perceivedCount: number;
173
+ totalRegions: number;
174
+ N?: number;
175
+ reachMemo?: ReadonlyMap<number, AncestorReach>;
176
+ naturalBreak?: number;
177
+ consensusFloor?: number;
178
+ }
3
179
  /** Climb the query's perceived byte regions up the structural DAG via
4
180
  * resonance, pool the evidence, and return only the ROOT points of
5
181
  * attention — those that cleared commitVotes' significance floor. */
6
182
  export declare function climbAttention(ctx: MindContext, query: Uint8Array, k: number, mode?: DFMode): Promise<Attention[]>;
7
183
  /** Full read-out of one consensus climb: both the roots (dominant points of
8
- * attention) and the entire ranked list. Cached via ctx.climbMemo when
9
- * ctx.trace is null. */
184
+ * attention) and the entire ranked list. Cached via ctx.climbMemo, ALWAYS —
185
+ * see {@link recognise} for why this memo (and recognise()'s own) must
186
+ * never be skipped while tracing: computeAttention's collectRegions walks
187
+ * the query's perceived tree via the same foldTree whose subtree-resolution
188
+ * fast path makes a second call on identical bytes non-idempotent once
189
+ * ctx._resolvedSubtrees is warm (which a multi-turn conversation's shared
190
+ * prefix subtrees guarantee by the second turn). A cache hit still emits
191
+ * a trace step — abbreviated, since the full per-sub-region voting detail
192
+ * {@link traceAttention} builds isn't preserved by the cached read-out —
193
+ * so a traced response is never silently blacked out for a repeated
194
+ * query. */
10
195
  export declare function climbAttentionAll(ctx: MindContext, query: Uint8Array, k: number, mode?: DFMode): Promise<AttentionRead>;
11
196
  export declare function computeAttention(ctx: MindContext, query: Uint8Array, k: number, mode: DFMode): Promise<AttentionRead>;
12
197
  export declare function collectRegions(ctx: MindContext, query: Uint8Array): Region[];
13
- export declare function voteRegions(ctx: MindContext, query: Uint8Array, regions: readonly Region[], k: number, mode: DFMode, N: number, reachMemo?: Map<number, AncestorReach>): Promise<{
198
+ export declare function voteRegions(ctx: MindContext, query: Uint8Array, regions: readonly Region[], k: number, mode: DFMode, N: number, reachMemo?: Map<number, AncestorReach>, td?: TraceDraft): Promise<{
14
199
  votes: RegionVote[];
15
200
  saturated: boolean[];
16
201
  voters: Array<{
@@ -31,7 +216,7 @@ export declare function voteRegions(ctx: MindContext, query: Uint8Array, regions
31
216
  * merely logs alongside it. `votesIdf`/`support` are the same two
32
217
  * read-outs {@link commitVotes} always gated on; only how they accumulate
33
218
  * changed. */
34
- export declare function poolVotes(ctx: MindContext, regionVotes: readonly RegionVote[], sat: SaturationInfo, N: number): {
219
+ export declare function poolVotes(ctx: MindContext, regionVotes: readonly RegionVote[], sat: SaturationInfo, N: number, td?: TraceDraft): {
35
220
  votes: Map<number, number>;
36
221
  votesIdf: Map<number, number>;
37
222
  support: Map<number, {
@@ -42,6 +227,8 @@ export declare function poolVotes(ctx: MindContext, regionVotes: readonly Region
42
227
  /** Per-anchor SCALE-INVARIANT support: Σ RegionVote.absorbed over the
43
228
  * distinct contributing regions — see Attention.breadth. */
44
229
  regionSupport: Map<number, number>;
230
+ /** Per-anchor contributing region spans — see Attention.clusters. */
231
+ regionSpans: Map<number, Array<[number, number]>>;
45
232
  steps: DerivationStep[];
46
233
  };
47
234
  export declare function commitVotes(ctx: MindContext, pooled: {
@@ -53,12 +240,13 @@ export declare function commitVotes(ctx: MindContext, pooled: {
53
240
  w: number;
54
241
  }>;
55
242
  regionSupport: Map<number, number>;
243
+ regionSpans: Map<number, Array<[number, number]>>;
56
244
  steps: DerivationStep[];
57
245
  }, sat: SaturationInfo, regions: readonly Region[], regionVoter: ReadonlyArray<{
58
246
  id: number;
59
247
  score: number;
60
248
  w: number;
61
- } | null>, N: number): AttentionRead;
249
+ } | null>, N: number, td?: TraceDraft, cfg?: ClimbConsensusCfg): AttentionRead;
62
250
  export declare function detectSaturated(ctx: MindContext, regions: ReadonlyArray<{
63
251
  start: number;
64
252
  end: number;
@@ -66,6 +254,56 @@ export declare function detectSaturated(ctx: MindContext, regions: ReadonlyArray
66
254
  }>, saturated: ReadonlyArray<boolean>): SaturationInfo;
67
255
  export declare function canonicalChunkId(ctx: MindContext, regionBytes: Uint8Array, N: number, reachMemo?: Map<number, AncestorReach>): number | null;
68
256
  export declare function naturalBreak(votes: number[]): number;
257
+ export type CrossRegionTier = "exact" | "single-synonym" | "double-synonym" | "structural-resonance";
258
+ export interface StructuralVariant {
259
+ left: StructuralPart;
260
+ right: StructuralPart;
261
+ kind: "exact-exact" | "left-synonym" | "right-synonym" | "double-synonym";
262
+ semanticConfidence: number;
263
+ leftSiblingId?: number;
264
+ rightSiblingId?: number;
265
+ }
266
+ export interface StructuralResonanceProposal {
267
+ id: number;
268
+ annScore: number;
269
+ semanticConfidence: number;
270
+ effectiveScore: number;
271
+ variant: StructuralVariant["kind"];
272
+ leftSiblingId?: number;
273
+ rightSiblingId?: number;
274
+ }
275
+ /** Build, bound and order every mandatory structural variant (§7-8): the
276
+ * exact/exact composition is always kept; up to `ctx.cfg.haloQueryK`
277
+ * synonym variants (single- and double-synonym combined, one shared
278
+ * budget) are appended, ordered by confidence, then kind, then sibling id. */
279
+ export declare function buildStructuralVariants(ctx: MindContext, ra: Region, rb: Region, sides: JunctionSynonymSides): {
280
+ variants: StructuralVariant[];
281
+ exactLeft: StructuralPart;
282
+ exactRight: StructuralPart;
283
+ };
284
+ /** The final approximate tier: compose every retained structural variant,
285
+ * ANN-query each, merge proposals by candidate id, and validate the winner
286
+ * through the SAME structural gates every other tier answers to (saturation,
287
+ * roots, IDF, contrastive margin). Returns null when nothing survives. */
288
+ export declare function structuralResonance(ctx: MindContext, query: Uint8Array, ra: Region, rb: Region, sides: JunctionSynonymSides, k: number, N: number, reachMemo: Map<number, AncestorReach>,
289
+ /** Each side's OWN individual climb roots (from voteRegions), when it cast
290
+ * one — the self-evidence backstop structural-resonance needs and the
291
+ * exact tier gets for free from literal byte containment (§11's whole
292
+ * premise: recover a JOINT context neither side votes for alone). A
293
+ * candidate whose reach is exactly one side's own conclusion is not new
294
+ * evidence of a joint whole; it is that side's resonance rediscovering
295
+ * itself through a synthetic gist still dominated by its own direction. */
296
+ ownRootsA: readonly number[] | undefined, ownRootsB: readonly number[] | undefined): Promise<{
297
+ proposal: StructuralResonanceProposal;
298
+ reach: AncestorReach;
299
+ idf: number;
300
+ } | null>;
301
+ /** Emit the "climbConsensus" step — the human-readable note this always
302
+ * produced, now paired (when `ctx.trace` and `cfg` are both present) with
303
+ * the structured {@link ClimbConsensusData} payload on the SAME step's
304
+ * `data` field. Every exit of {@link computeAttention} funnels through
305
+ * here, so instrumentation and the existing rationale text can never drift
306
+ * apart — see the instrumentation spec's §9 "every exit path". */
69
307
  export declare function traceAttention(ctx: MindContext, regions: ReadonlyArray<{
70
308
  start: number;
71
309
  end: number;
@@ -73,4 +311,5 @@ export declare function traceAttention(ctx: MindContext, regions: ReadonlyArray<
73
311
  id: number;
74
312
  score: number;
75
313
  w: number;
76
- } | null>, roots: ReadonlyArray<Attention>, steps?: ReadonlyArray<DerivationStep>): void;
314
+ } | null>, roots: ReadonlyArray<Attention>, steps?: ReadonlyArray<DerivationStep>, td?: TraceDraft, cfg?: ClimbConsensusCfg, ranked?: ReadonlyArray<Attention>): void;
315
+ export {};