fix(producer): fail closed when no live element count is available

R4 review finding, and the comment I wrote in R3 was simply wrong: the
probe session is NOT running for every render. probeStage's needsBrowser
gate launches one only for unknown duration, unresolved compositions, or
specific media cases — and hasRuntimeInsertedMedia matches only
createElement("video"|"audio"), never createElement("span"). So the exact
shape that motivated the live-DOM fix (a known-duration, media-free
caption comp building thousands of nodes in script) gets NO probe, falls
back to the static source scan, reads as ~2 elements, and could enter the
applied cohort at 40k live nodes. The R3 fix measured the right thing but
only for the population that already had a probe.

Now the count carries provenance and the band fails closed:

- resolveCompositionElementCount returns { count, source: "live" |
  "static" }. Only "live" — an actual DOM measurement — may open the band.
- resolveDeShortBand gains a third decisive outcome, "unmeasured", for
  the static case. It deliberately does NOT report skipped_elements: a
  static undercount is not a real oversize observation, and putting it in
  the control arm would contaminate the DiD just as putting it in the
  treatment arm would. Neither cohort; never routes.
- composition_element_count_source ships alongside the count, so the
  fleet rate of "static" sizes the population a future
  conditional-probe-launch would unlock — which is the data PR B needs to
  decide whether that launch cost is worth paying.

Regression coverage walks the real chain rather than a full render, using
the production functions in pipeline order: probeRequiresBrowser (newly
extracted from the inline needsBrowser expression, so the gate is
testable at all) returns false for the caption-comp shape → the resolver
reports static and a count under the ceiling → the band reports
unmeasured, not applied. Fault injection confirms it bites: removing the
one guard line fails exactly these three tests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vance Ingalls
2026-07-29 17:02:26 -07:00
co-authored by Claude Opus 5
parent def98f79c3
commit 4dbf0d90b0
8 changed files with 259 additions and 50 deletions
+4
View File
@@ -73,6 +73,7 @@ export interface RenderObservabilityTelemetryPayload {
captureDeWorkerInversion?: string;
captureDePreInversionWorkers?: number;
captureCompositionElementCount?: number;
captureCompositionElementCountSource?: string;
captureDeShortBand?: string;
captureDeParallelRouter?: string;
captureDeGpuRenderer?: string;
@@ -133,6 +134,7 @@ function renderObservabilityEventProperties(props: RenderObservabilityTelemetryP
de_worker_inversion: props.captureDeWorkerInversion,
de_pre_inversion_workers: props.captureDePreInversionWorkers,
composition_element_count: props.captureCompositionElementCount,
composition_element_count_source: props.captureCompositionElementCountSource,
de_short_band: props.captureDeShortBand,
de_parallel_router: props.captureDeParallelRouter,
gpu_renderer: props.captureDeGpuRenderer,
@@ -209,6 +211,7 @@ export function trackRenderComplete(
deWorkerInversion?: string;
dePreInversionWorkers?: number;
compositionElementCount?: number;
compositionElementCountSource?: string;
deShortBand?: string;
deParallelRouter?: string;
dePreRouterWorkers?: number;
@@ -310,6 +313,7 @@ export function trackRenderComplete(
de_worker_inversion: props.deWorkerInversion,
de_pre_inversion_workers: props.dePreInversionWorkers,
composition_element_count: props.compositionElementCount,
composition_element_count_source: props.compositionElementCountSource,
de_short_band: props.deShortBand,
de_parallel_router: props.deParallelRouter,
de_pre_router_workers: props.dePreRouterWorkers,
@@ -43,6 +43,7 @@ export function renderObservabilityTelemetryPayload(
captureDeWorkerInversion: capture.deWorkerInversion,
captureDePreInversionWorkers: capture.dePreInversionWorkers,
captureCompositionElementCount: capture.compositionElementCount,
captureCompositionElementCountSource: capture.compositionElementCountSource,
captureDeShortBand: capture.deShortBand,
captureDeParallelRouter: capture.deParallelRouter,
captureDeGpuRenderer: capture.deGpuRenderer,