@smoothbricks/lmao 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/README.md +206 -206
  2. package/dist/allocator.wasm +0 -0
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -0
  6. package/dist/lib/JsBufferStrategy.d.ts +4 -3
  7. package/dist/lib/JsBufferStrategy.d.ts.map +1 -1
  8. package/dist/lib/JsBufferStrategy.js +18 -11
  9. package/dist/lib/arrow/lease.d.ts +10 -0
  10. package/dist/lib/arrow/lease.d.ts.map +1 -0
  11. package/dist/lib/arrow/lease.js +33 -0
  12. package/dist/lib/arrow/utils.d.ts +3 -4
  13. package/dist/lib/arrow/utils.d.ts.map +1 -1
  14. package/dist/lib/arrow/utils.js +12 -13
  15. package/dist/lib/arrow/vocabularyDictionary.d.ts +21 -0
  16. package/dist/lib/arrow/vocabularyDictionary.d.ts.map +1 -0
  17. package/dist/lib/arrow/vocabularyDictionary.js +95 -0
  18. package/dist/lib/bufferStrategy.d.ts +3 -2
  19. package/dist/lib/bufferStrategy.d.ts.map +1 -1
  20. package/dist/lib/cloudflare/traceRows.d.ts.map +1 -1
  21. package/dist/lib/cloudflare/traceRows.js +3 -2
  22. package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -1
  23. package/dist/lib/codegen/evaluatorGenerator.js +12 -11
  24. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +44 -82
  25. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -1
  26. package/dist/lib/codegen/fixedPositionWriterGenerator.js +223 -162
  27. package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts +63 -0
  28. package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts.map +1 -0
  29. package/dist/lib/codegen/spanLoggerClosureMaterializer.js +447 -0
  30. package/dist/lib/codegen/spanLoggerGenerator.d.ts +36 -19
  31. package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -1
  32. package/dist/lib/codegen/spanLoggerGenerator.js +164 -158
  33. package/dist/lib/convertToArrow.d.ts +7 -2
  34. package/dist/lib/convertToArrow.d.ts.map +1 -1
  35. package/dist/lib/convertToArrow.js +499 -285
  36. package/dist/lib/defineOpContext.js +1 -1
  37. package/dist/lib/enumMetadata.d.ts +19 -0
  38. package/dist/lib/enumMetadata.d.ts.map +1 -0
  39. package/dist/lib/enumMetadata.js +86 -0
  40. package/dist/lib/flushScheduler.d.ts.map +1 -1
  41. package/dist/lib/flushScheduler.js +13 -4
  42. package/dist/lib/library.d.ts +16 -98
  43. package/dist/lib/library.d.ts.map +1 -1
  44. package/dist/lib/library.js +32 -525
  45. package/dist/lib/logBinding.d.ts +21 -27
  46. package/dist/lib/logBinding.d.ts.map +1 -1
  47. package/dist/lib/op.d.ts +30 -30
  48. package/dist/lib/op.d.ts.map +1 -1
  49. package/dist/lib/op.js +15 -22
  50. package/dist/lib/opContext/createOpGroup.d.ts +1 -1
  51. package/dist/lib/opContext/createOpGroup.d.ts.map +1 -1
  52. package/dist/lib/opContext/createOpGroup.js +22 -29
  53. package/dist/lib/opContext/defineOp.d.ts +4 -4
  54. package/dist/lib/opContext/defineOp.d.ts.map +1 -1
  55. package/dist/lib/opContext/defineOp.js +53 -10
  56. package/dist/lib/opContext/opGroupTypes.d.ts +2 -2
  57. package/dist/lib/opContext/opTypes.d.ts +1 -1
  58. package/dist/lib/opContext/opTypes.d.ts.map +1 -1
  59. package/dist/lib/opContext/spanContextTypes.d.ts +33 -18
  60. package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -1
  61. package/dist/lib/opContext/types.d.ts +4 -4
  62. package/dist/lib/opContext/types.d.ts.map +1 -1
  63. package/dist/lib/physicalLayoutPlan.d.ts +89 -0
  64. package/dist/lib/physicalLayoutPlan.d.ts.map +1 -0
  65. package/dist/lib/physicalLayoutPlan.js +442 -0
  66. package/dist/lib/resolveMessage.d.ts +9 -0
  67. package/dist/lib/resolveMessage.d.ts.map +1 -0
  68. package/dist/lib/resolveMessage.js +63 -0
  69. package/dist/lib/result.d.ts +5 -7
  70. package/dist/lib/result.d.ts.map +1 -1
  71. package/dist/lib/result.js +19 -26
  72. package/dist/lib/runtimeHint.d.ts +35 -0
  73. package/dist/lib/runtimeHint.d.ts.map +1 -0
  74. package/dist/lib/runtimeHint.js +79 -0
  75. package/dist/lib/schema/typeGuards.d.ts +7 -47
  76. package/dist/lib/schema/typeGuards.d.ts.map +1 -1
  77. package/dist/lib/schema/typeGuards.js +7 -123
  78. package/dist/lib/schema/types.d.ts +1 -1
  79. package/dist/lib/schema/types.d.ts.map +1 -1
  80. package/dist/lib/span-buffer/aot/v1.d.ts +2 -0
  81. package/dist/lib/span-buffer/aot/v1.d.ts.map +1 -0
  82. package/dist/lib/span-buffer/aot/v1.js +24 -0
  83. package/dist/lib/spanBuffer.d.ts +33 -4
  84. package/dist/lib/spanBuffer.d.ts.map +1 -1
  85. package/dist/lib/spanBuffer.js +583 -91
  86. package/dist/lib/spanBufferStats.d.ts +1 -1
  87. package/dist/lib/spanBufferStats.d.ts.map +1 -1
  88. package/dist/lib/spanContext.d.ts +27 -51
  89. package/dist/lib/spanContext.d.ts.map +1 -1
  90. package/dist/lib/spanContext.js +822 -344
  91. package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -1
  92. package/dist/lib/sqlite/sqlite-common.js +20 -21
  93. package/dist/lib/testing/bun-harness.d.ts +8 -3
  94. package/dist/lib/testing/bun-harness.d.ts.map +1 -1
  95. package/dist/lib/testing/bun-harness.js +30 -18
  96. package/dist/lib/testing/extractFacts.d.ts +1 -1
  97. package/dist/lib/testing/extractFacts.d.ts.map +1 -1
  98. package/dist/lib/testing/extractFacts.js +55 -63
  99. package/dist/lib/testing/facts.d.ts +1 -1
  100. package/dist/lib/testing/facts.d.ts.map +1 -1
  101. package/dist/lib/testing/queryable-span.d.ts +1 -1
  102. package/dist/lib/testing/queryable-span.d.ts.map +1 -1
  103. package/dist/lib/testing/queryable-span.js +26 -28
  104. package/dist/lib/testing/span-query.d.ts.map +1 -1
  105. package/dist/lib/testing/span-query.js +19 -22
  106. package/dist/lib/testing/stdio-replay.d.ts.map +1 -1
  107. package/dist/lib/testing/stdio-replay.js +19 -8
  108. package/dist/lib/threadId.d.ts.map +1 -1
  109. package/dist/lib/threadId.js +6 -3
  110. package/dist/lib/traceContext.d.ts.map +1 -1
  111. package/dist/lib/traceContext.js +1 -4
  112. package/dist/lib/traceRoot.d.ts +30 -8
  113. package/dist/lib/traceRoot.d.ts.map +1 -1
  114. package/dist/lib/traceRoot.es.d.ts +17 -15
  115. package/dist/lib/traceRoot.es.d.ts.map +1 -1
  116. package/dist/lib/traceRoot.es.js +68 -34
  117. package/dist/lib/traceRoot.js +11 -0
  118. package/dist/lib/traceRoot.node.d.ts +17 -19
  119. package/dist/lib/traceRoot.node.d.ts.map +1 -1
  120. package/dist/lib/traceRoot.node.js +66 -38
  121. package/dist/lib/traceTopology.d.ts +42 -0
  122. package/dist/lib/traceTopology.d.ts.map +1 -0
  123. package/dist/lib/traceTopology.js +260 -0
  124. package/dist/lib/tracer.d.ts +9 -5
  125. package/dist/lib/tracer.d.ts.map +1 -1
  126. package/dist/lib/tracer.js +65 -71
  127. package/dist/lib/tracers/ArrayQueueTracer.d.ts +1 -1
  128. package/dist/lib/tracers/ArrayQueueTracer.js +1 -1
  129. package/dist/lib/tracers/StdioTracer.d.ts.map +1 -1
  130. package/dist/lib/tracers/StdioTracer.js +15 -13
  131. package/dist/lib/tracers/TestTracer.d.ts +4 -6
  132. package/dist/lib/tracers/TestTracer.d.ts.map +1 -1
  133. package/dist/lib/tracers/TestTracer.js +6 -8
  134. package/dist/lib/types.d.ts +49 -32
  135. package/dist/lib/types.d.ts.map +1 -1
  136. package/dist/lib/vocabularyRegistry.d.ts +25 -0
  137. package/dist/lib/vocabularyRegistry.d.ts.map +1 -0
  138. package/dist/lib/vocabularyRegistry.js +372 -0
  139. package/dist/lib/wasm/WasmBufferStrategy.d.ts +6 -10
  140. package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -1
  141. package/dist/lib/wasm/WasmBufferStrategy.js +44 -37
  142. package/dist/lib/wasm/wasmAllocator.d.ts +27 -22
  143. package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -1
  144. package/dist/lib/wasm/wasmAllocator.js +66 -44
  145. package/dist/lib/wasm/wasmPhysicalLayout.d.ts +67 -0
  146. package/dist/lib/wasm/wasmPhysicalLayout.d.ts.map +1 -0
  147. package/dist/lib/wasm/wasmPhysicalLayout.js +179 -0
  148. package/dist/lib/wasm/wasmSpanBuffer.d.ts +79 -31
  149. package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -1
  150. package/dist/lib/wasm/wasmSpanBuffer.js +442 -272
  151. package/dist/lib/wasm/wasmTraceRoot.d.ts +24 -22
  152. package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -1
  153. package/dist/lib/wasm/wasmTraceRoot.js +110 -71
  154. package/dist/vocabulary/register/v1.d.ts +2 -0
  155. package/dist/vocabulary/register/v1.d.ts.map +1 -0
  156. package/dist/vocabulary/register/v1.js +1 -0
  157. package/dist/wasm.d.ts +5 -0
  158. package/dist/wasm.d.ts.map +1 -0
  159. package/dist/wasm.js +4 -0
  160. package/package.json +54 -6
  161. package/src/index.ts +1 -0
  162. package/src/lib/JsBufferStrategy.ts +27 -9
  163. package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +335 -37
  164. package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +97 -26
  165. package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +75 -15
  166. package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +30 -6
  167. package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +18 -21
  168. package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +5 -2
  169. package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +25 -7
  170. package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +3 -2
  171. package/src/lib/__tests__/buffer-overflow.test.ts +24 -18
  172. package/src/lib/__tests__/capability-span-context.test.ts +505 -0
  173. package/src/lib/__tests__/capacity-tuning.test.ts +5 -3
  174. package/src/lib/__tests__/eager-columns.test.ts +345 -0
  175. package/src/lib/__tests__/enum-metadata-aot.test.ts +153 -0
  176. package/src/lib/__tests__/enum-metadata.test.ts +177 -0
  177. package/src/lib/__tests__/fixtures/empty-vocabulary-runtime.fixture.ts +15 -0
  178. package/src/lib/__tests__/flushScheduler.test.ts +5 -1
  179. package/src/lib/__tests__/identity-view.property.test.ts +179 -0
  180. package/src/lib/__tests__/library.test.ts +19 -235
  181. package/src/lib/__tests__/message-buffer-families.test.ts +878 -0
  182. package/src/lib/__tests__/nested-library-tasks.test.ts +14 -15
  183. package/src/lib/__tests__/op-metadata.test.ts +1 -1
  184. package/src/lib/__tests__/op-type-safety.test.ts +5 -16
  185. package/src/lib/__tests__/physical-layout-plan.test.ts +333 -0
  186. package/src/lib/__tests__/remap-descriptor-integration.test.ts +381 -0
  187. package/src/lib/__tests__/root-context-construction.test.ts +414 -0
  188. package/src/lib/__tests__/span-auto-runtime.test.ts +386 -0
  189. package/src/lib/__tests__/span-buffer-segment-stats.test.ts +221 -0
  190. package/src/lib/__tests__/span-lifecycle.test.ts +53 -25
  191. package/src/lib/__tests__/spanbuffer-materializer-parity.test.ts +266 -0
  192. package/src/lib/__tests__/sync-async-trace.test.ts +24 -23
  193. package/src/lib/__tests__/tag-writer-aot.test.ts +214 -0
  194. package/src/lib/__tests__/test-helpers.ts +67 -12
  195. package/src/lib/__tests__/threadId.test.ts +62 -0
  196. package/src/lib/__tests__/timestamp.test.ts +221 -93
  197. package/src/lib/__tests__/traceTopology.property.test.ts +383 -0
  198. package/src/lib/__tests__/type-narrowing.test.ts +63 -0
  199. package/src/lib/__tests__/vocabulary-dense-decoding.test.ts +405 -0
  200. package/src/lib/__tests__/vocabularyRegistry.test.ts +313 -0
  201. package/src/lib/arrow/lease.ts +43 -0
  202. package/src/lib/arrow/utils.ts +10 -14
  203. package/src/lib/arrow/vocabularyDictionary.ts +123 -0
  204. package/src/lib/bufferStrategy.ts +9 -1
  205. package/src/lib/cloudflare/traceRows.ts +3 -2
  206. package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +21 -141
  207. package/src/lib/codegen/__tests__/fixedPositionWriter-parity.test.ts +273 -0
  208. package/src/lib/codegen/__tests__/fixedPositionWriter-uint64.test.ts +61 -34
  209. package/src/lib/codegen/__tests__/nullBitmap.test.ts +33 -37
  210. package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +34 -18
  211. package/src/lib/codegen/__tests__/spanLoggerMaterializerParity.test.ts +503 -0
  212. package/src/lib/codegen/evaluatorGenerator.ts +18 -13
  213. package/src/lib/codegen/fixedPositionWriterGenerator.ts +329 -245
  214. package/src/lib/codegen/spanLoggerClosureMaterializer.ts +598 -0
  215. package/src/lib/codegen/spanLoggerGenerator.ts +241 -177
  216. package/src/lib/convertToArrow.ts +598 -311
  217. package/src/lib/defineOpContext.ts +1 -1
  218. package/src/lib/enumMetadata.ts +121 -0
  219. package/src/lib/flushScheduler.ts +11 -5
  220. package/src/lib/library.ts +37 -595
  221. package/src/lib/logBinding.ts +21 -27
  222. package/src/lib/op.ts +75 -18
  223. package/src/lib/opContext/__tests__/retry.test.ts +27 -21
  224. package/src/lib/opContext/createOpGroup.ts +33 -31
  225. package/src/lib/opContext/defineOp.ts +88 -11
  226. package/src/lib/opContext/opGroupTypes.ts +2 -2
  227. package/src/lib/opContext/opTypes.ts +1 -1
  228. package/src/lib/opContext/spanContextTypes.ts +122 -24
  229. package/src/lib/opContext/types.ts +7 -3
  230. package/src/lib/physicalLayoutPlan.ts +598 -0
  231. package/src/lib/resolveMessage.ts +67 -0
  232. package/src/lib/result.ts +20 -33
  233. package/src/lib/runtimeHint.ts +98 -0
  234. package/src/lib/schema/__tests__/featureFlags.test.ts +2 -1
  235. package/src/lib/schema/builder.ts +1 -1
  236. package/src/lib/schema/typeGuards.ts +7 -151
  237. package/src/lib/schema/types.ts +1 -1
  238. package/src/lib/span-buffer/aot/v1.ts +26 -0
  239. package/src/lib/spanBuffer.ts +658 -92
  240. package/src/lib/spanBufferStats.ts +1 -1
  241. package/src/lib/spanContext.ts +1350 -861
  242. package/src/lib/sqlite/sqlite-common.ts +20 -31
  243. package/src/lib/testing/__tests__/topology-traversal.test.ts +174 -0
  244. package/src/lib/testing/__tests__/vitest-harness.test.ts +2 -1
  245. package/src/lib/testing/bun-harness.ts +94 -43
  246. package/src/lib/testing/extractFacts.ts +64 -78
  247. package/src/lib/testing/facts.ts +1 -1
  248. package/src/lib/testing/queryable-span.ts +23 -30
  249. package/src/lib/testing/span-query.ts +16 -20
  250. package/src/lib/testing/stdio-replay.ts +25 -8
  251. package/src/lib/testing/vitest-harness.ts +1 -1
  252. package/src/lib/threadId.ts +6 -3
  253. package/src/lib/traceContext.ts +1 -6
  254. package/src/lib/traceRoot.es.ts +77 -42
  255. package/src/lib/traceRoot.node.ts +75 -46
  256. package/src/lib/traceRoot.ts +41 -14
  257. package/src/lib/traceTopology.ts +279 -0
  258. package/src/lib/tracer.ts +109 -98
  259. package/src/lib/tracers/ArrayQueueTracer.ts +1 -1
  260. package/src/lib/tracers/StdioTracer.ts +15 -13
  261. package/src/lib/tracers/TestTracer.ts +6 -8
  262. package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +15 -10
  263. package/src/lib/tracers/__tests__/CompositeTracer.test.ts +150 -0
  264. package/src/lib/tracers/__tests__/TestTracer.test.ts +23 -13
  265. package/src/lib/types.ts +64 -33
  266. package/src/lib/vocabularyRegistry.ts +439 -0
  267. package/src/lib/wasm/WasmBufferStrategy.ts +56 -48
  268. package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +215 -11
  269. package/src/lib/wasm/__tests__/allocatorFreeBlockClamp.test.ts +86 -0
  270. package/src/lib/wasm/__tests__/wasm-identity-view.test.ts +311 -0
  271. package/src/lib/wasm/__tests__/wasm-integration.test.ts +417 -44
  272. package/src/lib/wasm/__tests__/wasm-message-buffer-families.test.ts +588 -0
  273. package/src/lib/wasm/__tests__/wasmAllocator.test.ts +100 -668
  274. package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +419 -63
  275. package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +24 -29
  276. package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +2 -2
  277. package/src/lib/wasm/wasmAllocator.ts +131 -96
  278. package/src/lib/wasm/wasmPhysicalLayout.ts +309 -0
  279. package/src/lib/wasm/wasmSpanBuffer.ts +597 -341
  280. package/src/lib/wasm/wasmTraceRoot.ts +140 -78
  281. package/src/vocabulary/register/v1.ts +1 -0
  282. package/src/wasm.ts +19 -0
  283. package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +0 -319
  284. package/src/lib/__tests__/remapped-buffer-view.test.ts +0 -635
  285. package/src/lib/wasm/allocator.zig +0 -948
package/src/lib/tracer.ts CHANGED
@@ -60,27 +60,29 @@
60
60
  */
61
61
 
62
62
  import type { BufferStrategy } from './bufferStrategy.js';
63
- import type { TagWriter } from './codegen/fixedPositionWriterGenerator.js';
64
- import { createTagWriter } from './codegen/fixedPositionWriterGenerator.js';
65
- import { createSpanLogger as createSpanLoggerFromGenerator } from './codegen/spanLoggerGenerator.js';
66
63
  import type { LogBinding } from './logBinding.js';
67
64
  import { Op } from './op.js';
68
65
  import { createOpMetadata } from './opContext/defineOp.js';
69
66
  import type { OpContext, OpContextBinding, OpContextOf, SpanContext } from './opContext/types.js';
67
+ import {
68
+ type CallsitePlan,
69
+ getPhysicalLayoutPlan,
70
+ type PhysicalLayoutPlan,
71
+ sealCallsitePlan,
72
+ } from './physicalLayoutPlan.js';
70
73
  import { Err, Ok, type Result } from './result.js';
71
74
  import { createFeatureFlagEvaluator, type FlagEvaluator, InMemoryFlagEvaluator } from './schema/evaluator.js';
72
75
  import { ENTRY_TYPE_SPAN_EXCEPTION, ENTRY_TYPE_SPAN_OK } from './schema/systemSchema.js';
73
-
74
- import { EMPTY_SCOPE } from './spanBuffer.js';
76
+ import { EMPTY_SCOPE, getSpanBufferClass } from './spanBuffer.js';
75
77
  import {
76
78
  createSpanContextClass,
79
+ isPhysicalLayoutPlanForContext,
77
80
  type SpanContextClass,
78
81
  type SpanContextInstance,
79
82
  writeSpanEnd,
80
- writeSpanStart,
81
83
  } from './spanContext.js';
82
84
  import { generateTraceId, isValidTraceId, type TraceId } from './traceId.js';
83
- import type { TraceRootFactory } from './traceRoot.js';
85
+ import type { TraceRootFactory, TracerLifecycleHooks } from './traceRoot.js';
84
86
  import type { SpanBuffer } from './types.js';
85
87
 
86
88
  // =============================================================================
@@ -110,7 +112,7 @@ export interface TracerOptions<
110
112
  * Factory for creating platform-specific TraceRoot instances.
111
113
  * Import from '@smoothbricks/lmao/node' or '@smoothbricks/lmao/es'.
112
114
  */
113
- createTraceRoot: TraceRootFactory;
115
+ createTraceRoot: TraceRootFactory<T>;
114
116
 
115
117
  /** Feature flag evaluator - provides flag values at runtime */
116
118
  flagEvaluator?: FlagEvaluator<OpContext>;
@@ -251,13 +253,17 @@ export type TraceFn<Ctx extends OpContext> = {
251
253
  *
252
254
  * @typeParam B - OpContextBinding type (inferred from constructor argument)
253
255
  */
254
- export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
256
+ export abstract class Tracer<B extends OpContextBinding = OpContextBinding>
257
+ implements TracerLifecycleHooks<B['logBinding']['logSchema']>
258
+ {
255
259
  private readonly logBinding: LogBinding<B['logBinding']['logSchema']>;
256
260
  private readonly SpanContextClass: SpanContextClass<OpContextOf<B>>;
261
+ private readonly physicalLayoutPlan: PhysicalLayoutPlan<B['logBinding']['logSchema'], OpContextOf<B>>;
257
262
  private readonly flagEvaluator: FlagEvaluator<OpContextOf<B>>;
258
263
  private readonly ctxDefaults: Record<string, unknown>;
264
+ private readonly requiredCtxKeys: readonly string[];
259
265
  private readonly deps: Record<string, unknown>;
260
- private readonly createTraceRoot: TraceRootFactory;
266
+ private readonly createTraceRoot: TraceRootFactory<B['logBinding']['logSchema']>;
261
267
 
262
268
  /**
263
269
  * Buffer strategy for memory management and Arrow conversion.
@@ -270,13 +276,32 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
270
276
  this.logBinding = binding.logBinding;
271
277
  this.bufferStrategy = options.bufferStrategy;
272
278
  this.ctxDefaults = binding.ctxDefaults ?? EMPTY_SCOPE;
279
+ const userContextKeys = Object.keys(this.ctxDefaults).sort();
280
+ const requiredCtxKeys: string[] = [];
281
+ for (const key of userContextKeys) {
282
+ if (this.ctxDefaults[key] === null) requiredCtxKeys.push(key);
283
+ }
284
+ this.requiredCtxKeys = requiredCtxKeys;
273
285
  this.deps = binding.deps ?? EMPTY_SCOPE;
274
286
  this.flagEvaluator = this._createFlagEvaluator(binding.flags, options.flagEvaluator);
275
287
  this.createTraceRoot = options.createTraceRoot;
276
288
 
277
289
  // Create SpanContext class for all contexts created by this tracer
278
290
  // The class closes over schema/logBinding and provides typed methods
279
- this.SpanContextClass = createSpanContextClass<OpContextOf<B>>(binding.logBinding.logSchema, binding.logBinding);
291
+ this.SpanContextClass = createSpanContextClass<OpContextOf<B>>(
292
+ binding.logBinding.logSchema,
293
+ binding.logBinding,
294
+ undefined,
295
+ userContextKeys,
296
+ );
297
+ this.physicalLayoutPlan = getPhysicalLayoutPlan(
298
+ getSpanBufferClass(binding.logBinding.logSchema),
299
+ 0,
300
+ this.SpanContextClass,
301
+ undefined,
302
+ 'strategy-selected',
303
+ userContextKeys.join('\u0000'),
304
+ );
280
305
 
281
306
  // Bind methods for destructuring (per AGENTS.md - "Always destructure")
282
307
  this.trace = this.trace.bind(this);
@@ -285,6 +310,10 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
285
310
  this.flush = this.flush.bind(this);
286
311
  }
287
312
 
313
+ getFlagEvaluatorForContext(): FlagEvaluator<OpContextOf<B>> {
314
+ return this.flagEvaluator;
315
+ }
316
+
288
317
  private _createFlagEvaluator(
289
318
  flags: B['flags'],
290
319
  evaluator: FlagEvaluator<OpContext> | undefined,
@@ -441,15 +470,15 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
441
470
  if (fnOrOp instanceof Op) {
442
471
  switch (argCount) {
443
472
  case 0:
444
- return this._trace_unknown_op(line, name, overrides, fnOrOp.metadata, fnOrOp.fn);
473
+ return this._trace_unknown_op(line, name, overrides, fnOrOp.callsitePlan, fnOrOp.fn);
445
474
  case 1:
446
- return this._trace_unknown_op(line, name, overrides, fnOrOp.metadata, fnOrOp.fn, args[fnIdx + 1]);
475
+ return this._trace_unknown_op(line, name, overrides, fnOrOp.callsitePlan, fnOrOp.fn, args[fnIdx + 1]);
447
476
  case 2:
448
477
  return this._trace_unknown_op(
449
478
  line,
450
479
  name,
451
480
  overrides,
452
- fnOrOp.metadata,
481
+ fnOrOp.callsitePlan,
453
482
  fnOrOp.fn,
454
483
  args[fnIdx + 1],
455
484
  args[fnIdx + 2],
@@ -459,7 +488,7 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
459
488
  line,
460
489
  name,
461
490
  overrides,
462
- fnOrOp.metadata,
491
+ fnOrOp.callsitePlan,
463
492
  fnOrOp.fn,
464
493
  args[fnIdx + 1],
465
494
  args[fnIdx + 2],
@@ -470,7 +499,7 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
470
499
  line,
471
500
  name,
472
501
  overrides,
473
- fnOrOp.metadata,
502
+ fnOrOp.callsitePlan,
474
503
  fnOrOp.fn,
475
504
  args[fnIdx + 1],
476
505
  args[fnIdx + 2],
@@ -482,7 +511,7 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
482
511
  line,
483
512
  name,
484
513
  overrides,
485
- fnOrOp.metadata,
514
+ fnOrOp.callsitePlan,
486
515
  fnOrOp.fn,
487
516
  args[fnIdx + 1],
488
517
  args[fnIdx + 2],
@@ -495,7 +524,7 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
495
524
  line,
496
525
  name,
497
526
  overrides,
498
- fnOrOp.metadata,
527
+ fnOrOp.callsitePlan,
499
528
  fnOrOp.fn,
500
529
  args[fnIdx + 1],
501
530
  args[fnIdx + 2],
@@ -509,7 +538,7 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
509
538
  line,
510
539
  name,
511
540
  overrides,
512
- fnOrOp.metadata,
541
+ fnOrOp.callsitePlan,
513
542
  fnOrOp.fn,
514
543
  args[fnIdx + 1],
515
544
  args[fnIdx + 2],
@@ -524,7 +553,7 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
524
553
  line,
525
554
  name,
526
555
  overrides,
527
- fnOrOp.metadata,
556
+ fnOrOp.callsitePlan,
528
557
  fnOrOp.fn,
529
558
  args[fnIdx + 1],
530
559
  args[fnIdx + 2],
@@ -566,7 +595,10 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
566
595
  op: Op<OpContextOf<B>, Args, S, E>,
567
596
  ...opArgs: Args
568
597
  ): Result<S, E> | Promise<Result<S, E>> {
569
- const ctx = this._createRootContext(line, name, overrides, op.metadata);
598
+ if (!isPhysicalLayoutPlanForContext<OpContextOf<B>>(op.callsitePlan, this.logBinding.logSchema)) {
599
+ throw new TypeError('Op physical layout plan does not match this tracer context');
600
+ }
601
+ const ctx = this._createRootContext(line, name, overrides, op.callsitePlan);
570
602
  return this._executeResultWithContext(ctx, (c) => op.fn(c, ...opArgs));
571
603
  }
572
604
 
@@ -574,14 +606,14 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
574
606
  line: number,
575
607
  name: string,
576
608
  overrides: Record<string, unknown>,
577
- metadata: ReturnType<typeof createOpMetadata>,
609
+ callsitePlan: CallsitePlan<B['logBinding']['logSchema'], OpContextOf<B>>,
578
610
  fn: (
579
611
  ctx: SpanContext<OpContextOf<B>>,
580
612
  ...opArgs: unknown[]
581
613
  ) => Result<unknown, unknown> | Promise<Result<unknown, unknown>>,
582
614
  ...opArgs: unknown[]
583
615
  ): Result<unknown, unknown> | Promise<Result<unknown, unknown>> {
584
- const ctx = this._createRootContext(line, name, overrides, metadata);
616
+ const ctx = this._createRootContext(line, name, overrides, callsitePlan);
585
617
  return this._executeResultWithContext(ctx, (childCtx) => fn(childCtx, ...opArgs));
586
618
  }
587
619
 
@@ -607,12 +639,11 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
607
639
  overrides: Record<string, unknown>,
608
640
  fn: (ctx: SpanContext<OpContextOf<B>>) => unknown,
609
641
  ): unknown {
610
- const ctx = this._createRootContext(
611
- line,
612
- name,
613
- overrides,
614
- createOpMetadata('root', 'tracer', 'runtime', 'unknown', 0),
615
- );
642
+ const metadata = Object.freeze({
643
+ ...createOpMetadata('root', 'tracer', 'runtime', 'unknown', 0),
644
+ _physicalLayoutPlan: this.physicalLayoutPlan,
645
+ });
646
+ const ctx = this._createRootContext(line, name, overrides, sealCallsitePlan(this.physicalLayoutPlan, metadata));
616
647
  return this._executeUnknownWithContext(ctx, fn);
617
648
  }
618
649
 
@@ -676,16 +707,14 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
676
707
  _line: number,
677
708
  name: string,
678
709
  overrides: Record<string, unknown>,
679
- metadata: ReturnType<typeof createOpMetadata>,
710
+ callsitePlan: CallsitePlan<B['logBinding']['logSchema'], OpContextOf<B>>,
680
711
  ): SpanContextInstance<OpContextOf<B>> {
681
712
  // Extract trace_id from overrides if present
682
713
  const traceId: TraceId = isValidTraceId(overrides.trace_id) ? overrides.trace_id : generateTraceId();
683
- const schema = this.logBinding.logSchema;
714
+ const schema = callsitePlan.schema;
684
715
 
685
- // Validate null-sentinel required fields and merge user context.
686
- // _resolveUserContext ignores trace_id (transport-only field).
687
- const overrideRecord: Record<string, unknown> = { ...overrides };
688
- const resolvedUserCtx = this._resolveUserContext(overrideRecord);
716
+ // Validate required null-sentinel fields before allocating the trace root or buffer.
717
+ this._validateRequiredUserContext(overrides);
689
718
 
690
719
  // Create TraceRoot via platform-specific factory
691
720
  const traceRoot = this.createTraceRoot(traceId, this);
@@ -693,71 +722,51 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
693
722
  // Create root SpanBuffer with pre-built TraceRoot via strategy
694
723
  const buffer = this.bufferStrategy.createSpanBuffer(
695
724
  schema,
696
- traceRoot, // pre-built TraceRoot with trace_id, anchors, tracer
697
- metadata, // opMetadata (for both callsite and op at root level)
725
+ traceRoot,
726
+ callsitePlan.metadata,
727
+ callsitePlan.capacityTier,
728
+ callsitePlan.SpanBufferClass,
698
729
  );
699
730
 
700
731
  // Write span-start entry (row 0)
701
- writeSpanStart(buffer, name);
702
-
703
- // Create tag writer and span logger (needed for constructor)
704
- const tagWriter: TagWriter<B['logBinding']['logSchema']> = createTagWriter(schema, buffer);
705
- const spanLogger = createSpanLoggerFromGenerator(schema, buffer);
706
-
707
- // Instantiate SpanContext class with direct arguments (no temp object allocation)
708
- const ctx = new this.SpanContextClass(buffer, schema, spanLogger, tagWriter);
732
+ callsitePlan.appenders.writeSpanStart(buffer, name);
709
733
 
710
- // Set up deps from config (may be EMPTY_SCOPE if none provided)
711
- ctx.deps = this.deps;
712
-
713
- ctx.ff = this.flagEvaluator.forContext(ctx);
714
-
715
- // Copy resolved user context onto SpanContext.
716
- for (const key in resolvedUserCtx) {
717
- (ctx as Record<string, unknown>)[key] = resolvedUserCtx[key];
718
- }
719
-
720
- return ctx;
734
+ return new callsitePlan.SpanContextClass(
735
+ buffer,
736
+ schema,
737
+ callsitePlan,
738
+ this.ctxDefaults,
739
+ overrides,
740
+ this.deps,
741
+ this.flagEvaluator,
742
+ );
721
743
  }
722
744
 
723
745
  /**
724
- * Validate null-sentinel required fields and merge with provided overrides.
746
+ * Validate null-sentinel required fields without materializing a merged
747
+ * user-context carrier.
725
748
  *
726
749
  * Per the ctx config pattern:
727
750
  * - Properties with null values in ctxDefaults must be provided in overrides
728
751
  * - Properties with default values can optionally be overridden
729
752
  * - undefined is allowed for optional fields
730
753
  */
731
- private _resolveUserContext(overrides: Record<string, unknown>): Record<string, unknown> {
732
- const ctxDefaults = this.ctxDefaults;
733
-
734
- // Check that all null-sentinel keys are provided in overrides
735
- for (const key of Object.keys(ctxDefaults)) {
736
- const defaultValue = ctxDefaults[key];
737
- if (defaultValue === null) {
738
- const providedValue = overrides[key];
739
- if (providedValue === null || providedValue === undefined) {
740
- throw new Error(
741
- `Required context parameter '${key}' must be provided. ` +
742
- 'Properties with null values in ctx config are required.',
743
- );
744
- }
745
- }
746
- }
747
-
748
- // Merge defaults with provided overrides (provided values win)
749
- const resolvedUserCtx: Record<string, unknown> = { ...ctxDefaults };
750
- for (const key of Object.keys(overrides)) {
751
- if (key === 'trace_id') {
752
- continue;
754
+ private _validateRequiredUserContext(overrides: Record<string, unknown>): void {
755
+ for (const key of this.requiredCtxKeys) {
756
+ if (!Object.prototype.propertyIsEnumerable.call(overrides, key)) {
757
+ throw new Error(
758
+ `Required context parameter '${key}' must be provided. ` +
759
+ 'Properties with null values in ctx config are required.',
760
+ );
753
761
  }
754
- const value = overrides[key];
755
- if (value !== undefined) {
756
- resolvedUserCtx[key] = value;
762
+ const providedValue = overrides[key];
763
+ if (providedValue === null || providedValue === undefined) {
764
+ throw new Error(
765
+ `Required context parameter '${key}' must be provided. ` +
766
+ 'Properties with null values in ctx config are required.',
767
+ );
757
768
  }
758
769
  }
759
-
760
- return resolvedUserCtx;
761
770
  }
762
771
 
763
772
  /**
@@ -771,9 +780,10 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
771
780
  ctx: SpanContextInstance<OpContextOf<B>>,
772
781
  fn: (ctx: SpanContext<OpContextOf<B>>) => Result<S, E> | Promise<Result<S, E>>,
773
782
  ): Result<S, E> | Promise<Result<S, E>> {
774
- const buffer = ctx._buffer;
783
+ const buffer = ctx._spanBuffer;
784
+ const writeSpanEndEntry = ctx._physicalLayoutPlan.appenders.writeSpanEnd;
775
785
 
776
- this.onTraceStart(buffer as SpanBuffer<B['logBinding']['logSchema']>);
786
+ this.onTraceStart(buffer);
777
787
 
778
788
  let isAsync = false;
779
789
  try {
@@ -788,7 +798,7 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
788
798
  return resolved;
789
799
  },
790
800
  (error: unknown) => {
791
- buffer._traceRoot.writeSpanEnd(buffer, ENTRY_TYPE_SPAN_EXCEPTION);
801
+ writeSpanEndEntry(buffer, ENTRY_TYPE_SPAN_EXCEPTION);
792
802
 
793
803
  const errorMessage = error instanceof Error ? error.message : String(error);
794
804
  const errorStack = error instanceof Error ? error.stack : undefined;
@@ -801,13 +811,13 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
801
811
  throw error;
802
812
  },
803
813
  )
804
- .finally(() => this.onTraceEnd(buffer as SpanBuffer<B['logBinding']['logSchema']>));
814
+ .finally(() => this.onTraceEnd(buffer));
805
815
  }
806
816
 
807
817
  writeSpanEnd(buffer, result);
808
818
  return result;
809
819
  } catch (error) {
810
- buffer._traceRoot.writeSpanEnd(buffer, ENTRY_TYPE_SPAN_EXCEPTION);
820
+ writeSpanEndEntry(buffer, ENTRY_TYPE_SPAN_EXCEPTION);
811
821
 
812
822
  const errorMessage = error instanceof Error ? error.message : String(error);
813
823
  const errorStack = error instanceof Error ? error.stack : undefined;
@@ -820,7 +830,7 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
820
830
  throw error;
821
831
  } finally {
822
832
  if (!isAsync) {
823
- this.onTraceEnd(buffer as SpanBuffer<B['logBinding']['logSchema']>);
833
+ this.onTraceEnd(buffer);
824
834
  }
825
835
  }
826
836
  }
@@ -829,10 +839,11 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
829
839
  ctx: SpanContextInstance<OpContextOf<B>>,
830
840
  fn: (ctx: SpanContext<OpContextOf<B>>) => unknown,
831
841
  ): unknown {
832
- const buffer = ctx._buffer;
842
+ const buffer = ctx._spanBuffer;
843
+ const writeSpanEndEntry = ctx._physicalLayoutPlan.appenders.writeSpanEnd;
833
844
 
834
845
  // Call trace start hook
835
- this.onTraceStart(buffer as SpanBuffer<B['logBinding']['logSchema']>);
846
+ this.onTraceStart(buffer);
836
847
 
837
848
  let isAsync = false;
838
849
  try {
@@ -846,12 +857,12 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
846
857
  if (resolved instanceof Ok || resolved instanceof Err) {
847
858
  writeSpanEnd(buffer, resolved);
848
859
  } else {
849
- buffer._traceRoot.writeSpanEnd(buffer, ENTRY_TYPE_SPAN_OK);
860
+ writeSpanEndEntry(buffer, ENTRY_TYPE_SPAN_OK);
850
861
  }
851
862
  return resolved;
852
863
  },
853
864
  (error: unknown) => {
854
- buffer._traceRoot.writeSpanEnd(buffer, ENTRY_TYPE_SPAN_EXCEPTION);
865
+ writeSpanEndEntry(buffer, ENTRY_TYPE_SPAN_EXCEPTION);
855
866
 
856
867
  const errorMessage = error instanceof Error ? error.message : String(error);
857
868
  const errorStack = error instanceof Error ? error.stack : undefined;
@@ -864,20 +875,20 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
864
875
  throw error;
865
876
  },
866
877
  )
867
- .finally(() => this.onTraceEnd(buffer as SpanBuffer<B['logBinding']['logSchema']>));
878
+ .finally(() => this.onTraceEnd(buffer));
868
879
  }
869
880
 
870
881
  // Sync path - write span-end
871
882
  if (result instanceof Ok || result instanceof Err) {
872
883
  writeSpanEnd(buffer, result);
873
884
  } else {
874
- buffer._traceRoot.writeSpanEnd(buffer, ENTRY_TYPE_SPAN_OK);
885
+ writeSpanEndEntry(buffer, ENTRY_TYPE_SPAN_OK);
875
886
  }
876
887
 
877
888
  return result;
878
889
  } catch (error) {
879
890
  // Sync exception path
880
- buffer._traceRoot.writeSpanEnd(buffer, ENTRY_TYPE_SPAN_EXCEPTION);
891
+ writeSpanEndEntry(buffer, ENTRY_TYPE_SPAN_EXCEPTION);
881
892
 
882
893
  // Write exception details
883
894
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -892,7 +903,7 @@ export abstract class Tracer<B extends OpContextBinding = OpContextBinding> {
892
903
  } finally {
893
904
  // Only call for sync path - async uses .finally() on promise
894
905
  if (!isAsync) {
895
- this.onTraceEnd(buffer as SpanBuffer<B['logBinding']['logSchema']>);
906
+ this.onTraceEnd(buffer);
896
907
  }
897
908
  }
898
909
  }
@@ -67,7 +67,7 @@ export class ArrayQueueTracer<B extends OpContextBinding = OpContextBinding> ext
67
67
  * Consume all queued buffers and clear the queue.
68
68
  * Returns an independent copy of the queue contents.
69
69
  *
70
- * @returns Array of root buffers (with child spans in _children tree)
70
+ * @returns Array of root buffers whose children live in the trace topology arena
71
71
  */
72
72
  drain(): SpanBuffer<B['logBinding']['logSchema']>[] {
73
73
  const buffers = [...this.queue];
@@ -32,6 +32,7 @@
32
32
  */
33
33
 
34
34
  import type { OpContextBinding } from '../opContext/types.js';
35
+ import { resolveEntryType, resolveMessage } from '../resolveMessage.js';
35
36
  import {
36
37
  ENTRY_TYPE_DEBUG,
37
38
  ENTRY_TYPE_ERROR,
@@ -154,21 +155,22 @@ function getLogLevel(entryType: number): string | null {
154
155
  }
155
156
 
156
157
  function formatTemplateMessage(buffer: AnySpanBuffer, row: number, template: string): string {
157
- return template.replace(/\{\{([A-Za-z0-9_]+)\}\}/g, (_full, key: string) => {
158
+ return template.replace(/\{([A-Za-z0-9_]+)\}/g, (_full, key: string) => {
159
+ const placeholder = `{${key}}`;
158
160
  const values = Reflect.get(buffer, `${key}_values`) as unknown;
159
- if (values == null) return `{{${key}}}`;
161
+ if (values == null) return placeholder;
160
162
 
161
163
  if (Array.isArray(values)) {
162
164
  const value = values[row];
163
- return value === null || value === undefined ? `{{${key}}}` : String(value);
165
+ return value === null || value === undefined ? placeholder : String(value);
164
166
  }
165
167
 
166
168
  if (ArrayBuffer.isView(values)) {
167
169
  const value = Reflect.get(values, row) as unknown;
168
- return value === null || value === undefined ? `{{${key}}}` : String(value);
170
+ return value === null || value === undefined ? placeholder : String(value);
169
171
  }
170
172
 
171
- return `{{${key}}}`;
173
+ return placeholder;
172
174
  });
173
175
  }
174
176
 
@@ -268,10 +270,10 @@ export class StdioTracer<B extends OpContextBinding = OpContextBinding> extends
268
270
  const end = current._writeIndex;
269
271
 
270
272
  for (let i = start; i < end; i++) {
271
- const level = getLogLevel(current.entry_type[i]);
273
+ const level = getLogLevel(resolveEntryType(current, i));
272
274
  if (!level) continue;
273
275
 
274
- const template = current.message_values[i] ?? '';
276
+ const template = resolveMessage(current, i) ?? '';
275
277
  const message = formatTemplateMessage(current, i, template);
276
278
  const ts = formatTimestamp(current.timestamp[i]);
277
279
  const traceId = current.trace_id;
@@ -297,7 +299,7 @@ export class StdioTracer<B extends OpContextBinding = OpContextBinding> extends
297
299
 
298
300
  onTraceStart(rootBuffer: SpanBuffer<B['logBinding']['logSchema']> | AnySpanBuffer): void {
299
301
  const traceId = rootBuffer.trace_id;
300
- const name = rootBuffer.message_values[0];
302
+ const name = resolveMessage(rootBuffer, 0);
301
303
  const ts = formatTimestamp(rootBuffer.timestamp[0]);
302
304
 
303
305
  this.out.write(`[${ts}] ${this.color(traceId)}[${traceId}]${this.reset()} ${name}\n`);
@@ -309,11 +311,11 @@ export class StdioTracer<B extends OpContextBinding = OpContextBinding> extends
309
311
  this.printLogRows(rootBuffer, 1);
310
312
  this.decrementIndent(traceId);
311
313
 
312
- const name = rootBuffer.message_values[0];
314
+ const name = resolveMessage(rootBuffer, 0);
313
315
  const startTs = rootBuffer.timestamp[0];
314
316
  const endTs = rootBuffer.timestamp[1];
315
317
  const duration = formatDuration(endTs - startTs);
316
- const entryType = rootBuffer.entry_type[1];
318
+ const entryType = resolveEntryType(rootBuffer, 1);
317
319
  const status = getStatus(entryType);
318
320
  const ts = formatTimestamp(endTs);
319
321
 
@@ -330,7 +332,7 @@ export class StdioTracer<B extends OpContextBinding = OpContextBinding> extends
330
332
  onSpanStart(childBuffer: SpanBuffer<B['logBinding']['logSchema']> | AnySpanBuffer): void {
331
333
  const traceId = childBuffer.trace_id;
332
334
  const indent = this.getIndent(traceId);
333
- const name = childBuffer.message_values[0];
335
+ const name = resolveMessage(childBuffer, 0);
334
336
  const ts = formatTimestamp(childBuffer.timestamp[0]);
335
337
 
336
338
  this.out.write(`[${ts}] ${this.color(traceId)}[${traceId}]${this.reset()} ${' '.repeat(indent)}├─ ${name}\n`);
@@ -343,11 +345,11 @@ export class StdioTracer<B extends OpContextBinding = OpContextBinding> extends
343
345
  const indent = this.getIndent(traceId);
344
346
  this.printLogRows(childBuffer, indent + 1);
345
347
 
346
- const name = childBuffer.message_values[0];
348
+ const name = resolveMessage(childBuffer, 0);
347
349
  const startTs = childBuffer.timestamp[0];
348
350
  const endTs = childBuffer.timestamp[1];
349
351
  const duration = formatDuration(endTs - startTs);
350
- const entryType = childBuffer.entry_type[1];
352
+ const entryType = resolveEntryType(childBuffer, 1);
351
353
  const status = getStatus(entryType);
352
354
  const ts = formatTimestamp(endTs);
353
355
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * TestTracer - A tracer that accumulates completed root trace buffers for test inspection.
3
3
  *
4
- * Child spans are accessible via the buffer's `_children` tree - no need to track them separately.
4
+ * Child spans are accessible through the trace topology arena; no duplicate tracking is needed.
5
5
  * This is the primary tracer for tests that need to inspect trace output, convert to Arrow tables,
6
6
  * or verify buffer contents.
7
7
  *
@@ -54,9 +54,8 @@ export interface StatsSnapshot<T extends LogSchema = LogSchema> {
54
54
  /**
55
55
  * Test tracer that accumulates root buffers for inspection.
56
56
  *
57
- * Collects all completed root trace buffers in `rootBuffers` array.
58
- * Child spans are accessible via the buffer's `_children` tree -
59
- * no need to track them separately.
57
+ * Collects all completed root trace buffers in `rootBuffers`; child spans remain reachable
58
+ * through each root's trace topology arena.
60
59
  *
61
60
  * Also tracks capacity tuning events via `statsSnapshots` to verify
62
61
  * that `onStatsWillResetFor` is called before stats are reset.
@@ -84,8 +83,7 @@ export interface StatsSnapshot<T extends LogSchema = LogSchema> {
84
83
  //#region smoo/lmao!n/tracer-implementations.test
85
84
  export class TestTracer<B extends OpContextBinding = OpContextBinding> extends Tracer<B> {
86
85
  /**
87
- * All completed root trace buffers.
88
- * Child spans are accessible via each buffer's `_children` tree.
86
+ * All completed root trace buffers. Child spans remain in each root's topology arena.
89
87
  */
90
88
  readonly rootBuffers: SpanBuffer<B['logBinding']['logSchema']>[] = [];
91
89
 
@@ -109,11 +107,11 @@ export class TestTracer<B extends OpContextBinding = OpContextBinding> extends T
109
107
  }
110
108
 
111
109
  onSpanStart(_childBuffer: SpanBuffer<B['logBinding']['logSchema']>): void {
112
- // No-op - children are in tree, accessed via rootBuffer._children
110
+ // No-op - children are registered in the trace topology arena
113
111
  }
114
112
 
115
113
  onSpanEnd(_childBuffer: SpanBuffer<B['logBinding']['logSchema']>): void {
116
- // No-op - children are in tree, accessed via rootBuffer._children
114
+ // No-op - children are registered in the trace topology arena
117
115
  }
118
116
 
119
117
  onStatsWillResetFor(buffer: SpanBuffer<B['logBinding']['logSchema']>): void {