Skip to content

feat(telemetry): per-tag, provenance, and failure-taxonomy properties on render events - #4004

Merged
miguel-heygen merged 3 commits into
mainfrom
add-per-tag-element-telemetry-852
Sep 16, 2026
Merged

miguel-heygen merged 3 commits into
mainfrom
add-per-tag-element-telemetry-852

Conversation

@miga-heygen

@miga-heygen miga-heygen commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • render_complete telemetry reports composition_element_count (an integer total) on essentially every render, but nothing names which elements make it up. registry_blocks_used only fires for catalog-sourced blocks, so hand-authored elements — the overwhelming majority — have no identity in the wire format.
  • countElementTags (the regex scan already run on every render without a live probe session) is replaced by scanElementTags, which returns {total, byTag, arollVideoCount, heygenVideoCount} from the same single pass over the same script/style-stripped markup: total is the sum of byTag's values by construction, so the properties cannot drift apart. countElementTags itself is removed — after this change it had zero production callers.
  • New render_complete properties from that one scan:
    • composition_element_tags: an object, {tag: count}, raw lowercase tag name — native elements like video/img/div and custom elements like hf-audio-group are both kept as-is, no grouping — capped at the top 50 tags by count with the remainder folded into an other key so a pathological composition's distinct-tag cardinality can't inflate the event payload.
    • aroll_video_count: <video data-aroll="true"> elements. data-aroll="true" can be stamped on any media element type the composition generator emits (video/image/audio), but this count is scoped to <video> only, matching its name — a-roll is a video-editing term for primary-take footage.
    • heygen_video_count: <video data-media-source="heygen"> elements. The media-use skill stamps this attribute on a mounted video only when the ledger record's provider traces to heygen.video — the ledger is the single source of truth for provenance, the HTML attribute is a projection of it. Mounting a resolved asset into a composition is always the calling agent's own edit (the skill's resolve command never writes composition HTML itself), so the stamping instruction lives in the skill's own reference doc rather than in an HTML-emitting function.
    • All three new properties are only ever set on the "static" source (the regex scan) — the "live" source (a real probe-session DOM count) never runs this scan and has no per-tag breakdown to report; this mirrors the existing composition_element_count_source split.
  • render_error gets a bucketable failure taxonomy alongside the existing free-text fields: error_name (error.name — one of the producer's ~20 typed error classes, e.g. CaptureFailure, DrawElementCaptureError, SwiftShaderAssertionError) and failed_stage_code (the same job.currentStage/failedStage value normalized to a stable snake_case code via a small map with a slugified fallback for anything unrecognized, so a future stage string still gets a distinct code without needing the map updated first). These are error-conditional by nature — render_complete has no equivalent, since a successful render has no error to name or stage to blame.

Not included

Everything below would need a browser-probe change (touching the live page.evaluate init call), cross-PR coordination, or was judged lower value relative to the risk of rushing it in the same pass as the above — left for a focused follow-up:

  • Output/composition metadata (resolution preset, format, HDR mode, frame format, GIF fps cap) — free data already in memory, straightforward to thread, but not yet wired in this PR.
  • Adapter usage, sub-composition/audio-group/color-grading counts, browser/ffmpeg version majors, authoring-skill-source/invalid flags, root/body dimension-mismatch measurement, HF_* env-override names — same category: clearly specified, no PostHog schema change needed, but each needs its own careful wiring + test pass and didn't fit in this round without risking quality.
  • The root/body mismatch measurement specifically should be coordinated with the separate runtime fix for the same symptom (a portrait composition rendering clipped inside a landscape-sized <body>) landing in parallel — the property needs to keep reporting the raw measured mismatch accurately regardless of which lands first, not assume the other's outcome.

Test plan

  • Regression tests for the grouping logic: mixed native + hf-* tag grouping, case-normalization, the cap-overflow-into-other scenario, a count/map consistency invariant (sum(byTag) === total), the <video data-aroll>/<video data-media-source="heygen"> scope (audio/img/other-provider values are not counted), and zero-match cases reporting 0/{} rather than undefined.
  • All 13 pre-existing tag-counting tests (script/style stripping, self-closing SVG, malformed input, CodeQL-flagged reform-after-strip, 40k-tag scale) pass unchanged against the refactored scan, proving the total count is byte-identical to before.
  • Existing resolveCompositionElementCount tests updated to assert the new fields are present on every "static" result and absent on the "live" result.
  • normalizeStageCode: every known updateJobStatus stage string maps to its code, an unrecognized string slugifies instead of bucketing into "unknown", and empty/punctuation-only input falls back to "unknown".
  • packages/producer/src/services/renderOrchestrator.test.ts, packages/cli/src/telemetry/events.test.ts, packages/cli/src/telemetry/renderObservability.test.ts, packages/cli/src/commands/render.test.ts — all passing. Plain unit tests with no browser/ffmpeg dependency, running in the existing producer-source-tests (unit lane) / CLI test jobs with no additional CI setup needed.
  • typecheck, oxlint, oxfmt --check clean on every touched file.

miga-heygen and others added 3 commits September 16, 2026 15:48
…lete

countElementTags's single regex scan (the ~83% of renders that get no
live probe session) is extended into scanElementTags, which returns a
per-tag breakdown and an a-roll video count alongside the same total,
all from one pass over the same script/style-stripped markup — the
total is the sum of the per-tag map by construction, so the two
properties can't drift apart. countElementTags itself is removed; it
had zero production callers after this change.

New render_complete properties: composition_element_tags ({tag: count},
raw lowercase tag names, capped at the top 50 by count with the rest
folded into an "other" key) and aroll_video_count (<video
data-aroll="true"> elements from the same scan). Both are static-scan-
only, mirroring the existing composition_element_count_source split —
the live probe-DOM path never runs this scan.

Co-Authored-By: Miguel Ángel <miguel.sierra@heygen.com>
heygenVideoCount joins arollVideoCount/byTag as a third property
derived from scanElementTags's single pass: <video
data-media-source="heygen"> elements. media-use's resolve.md now
documents that the skill stamps this attribute on a mounted video only
when the ledger record's provider is "heygen.video" (the mount itself
is always the agent's own composition edit, never written by resolve
scripts) — the ledger stays the single source of truth for provenance,
the HTML attribute is a projection of it, and no other provider value
is invented beyond this one signal.

Co-Authored-By: Miguel Ángel <miguel.sierra@heygen.com>
error_name (error.name, e.g. one of the ~20 typed producer error
classes) and failed_stage_code (job.currentStage/failedStage
normalized to a stable snake_case code via normalizeStageCode)
join the existing free-text error_message/failed_stage, so a fleet
query can bucket failures without parsing prose. Error-conditional by
nature — render_complete has no equivalent, since a successful render
has no error to name or stage to blame.

Co-Authored-By: Miguel Ángel <miguel.sierra@heygen.com>
@miga-heygen miga-heygen changed the title feat(telemetry): add per-tag element and a-roll counts to render telemetry feat(telemetry): per-tag, provenance, and failure-taxonomy properties on render events Sep 16, 2026
@miguel-heygen
miguel-heygen merged commit 3704863 into main Sep 16, 2026
65 of 93 checks passed
@miguel-heygen
miguel-heygen deleted the add-per-tag-element-telemetry-852 branch September 16, 2026 16:38
miga-heygen added a commit that referenced this pull request Sep 16, 2026
- Portrait compositions render the full frame when the project was
  scaffolded at a different size: html/body are sized to the composition
  root at runtime; new lint warning root_dimensions_mismatch (#4005,
  fixes #4001)
- render_complete telemetry adds composition_element_tags,
  aroll_video_count, heygen_video_count; render_error adds error_name and
  failed_stage_code (#4004)
- Catalog docs "Source" accordion titles are plain strings, so docs
  search no longer shows [object Object] (#4006)

Co-Authored-By: Miguel Ángel <miguel.sierra@heygen.com>
miguel-heygen added a commit that referenced this pull request Sep 16, 2026
- Portrait compositions render the full frame when the project was
  scaffolded at a different size: html/body are sized to the composition
  root at runtime; new lint warning root_dimensions_mismatch (#4005,
  fixes #4001)
- render_complete telemetry adds composition_element_tags,
  aroll_video_count, heygen_video_count; render_error adds error_name and
  failed_stage_code (#4004)
- Catalog docs "Source" accordion titles are plain strings, so docs
  search no longer shows [object Object] (#4006)

Co-authored-by: Miguel Ángel <miguel.sierra@heygen.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants