Skip to content

test(cli): real-render e2e check for render telemetry properties - #4018

Merged
miga-heygen merged 1 commit into
mainfrom
feat/render-telemetry-e2e-harness
Sep 17, 2026
Merged

miga-heygen merged 1 commit into
mainfrom
feat/render-telemetry-e2e-harness

Conversation

@miga-heygen

Copy link
Copy Markdown
Contributor

Summary

Stacked on the render-telemetry-properties PR. Extends the existing add-command telemetry end-to-end check (spawns the built CLI with a fetch-intercepting hook and captures the PostHog batch, rather than a unit fixture that stubs the browser or ffmpeg) to cover render's telemetry properties the same way.

Two generated fixture compositions, no checked-in binary assets (a base64-literal 1x1 PNG, a one-second sine-wave WAV generated at test time via ffmpeg):

  • Positive fixture: an image and an audio element present, root/body CSS size deliberately mismatched from the declared composition size, a skill flag passed, one environment variable injected.
  • Negative fixture: no media elements, CSS size matching the declared composition size exactly, no skill flag, an environment stripped of every HF_/HYPERFRAMES_-prefixed variable before spawning.

Six properties are asserted on both sides in the same pair of runs: audio_count, image_count, root_body_mismatch and its delta bucket, authoring_skill_source, and hf_env_overrides. Two more, ffmpeg_version_major and browser_version_major, are asserted on the positive side only; their Docker-absent side has no Docker runtime available in this check and stays covered by a unit test instead.

Running this for real, before the environment-variable and Studio-parity fixes in the base PR existed, is what caught both bugs: the environment check first reported an unexpected extra name in hf_env_overrides, which traced back to the CLI's own bootstrap wiring rather than an operator setting. All 24 checks pass against the fixed base.

Test plan

  • node scripts/ci/cli-telemetry-e2e.mjs against the built CLI: 24/24 checks green (18 pre-existing add-command checks unaffected, 6 new render checks all passing on both fixtures)
  • Typecheck clean (no source changes, script-only)

@miga-heygen
miga-heygen force-pushed the feat/render-telemetry-e2e-harness branch from d529256 to 4f57127 Compare September 16, 2026 23:35
@miga-heygen
miga-heygen force-pushed the feat/render-telemetry-e2e-harness branch from 4f57127 to 71bc098 Compare September 17, 2026 01:52
@miga-heygen
miga-heygen marked this pull request as ready for review September 17, 2026 01:53

@miga-heygen miga-heygen left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at 71bc098, base is #4017's branch not main. Own-account, comment-only.

This is the check Home asked for by name: does the test fail if the properties were wrong, not just if they're absent. It does. cli-telemetry-e2e.mjs uses a paired positive/negative fixture: the positive fixture (media present, root/body CSS size mismatched by more than 50px, --skill flag, an injected HYPERFRAMES_E2E_MARKER env var) asserts audio_count === 1, image_count === 1, root_body_mismatch === true, root_body_delta_px_bucket === "51+", authoring_skill_source === "flag", and that hf_env_overrides includes the injected name. The negative fixture (no media, matched size, no skill flag, clean env) asserts the opposite exact values: === 0, === false, === "0", authoring_skill_source absent, hf_env_overrides empty. A stub or an always-present/always-absent implementation fails one side or the other; this is a real discriminating pair, not a presence check.

One honest gap, not a blocker: because this PR's base is #4017's branch and the repo's ci.yml only triggers pull_request runs against base: main (by design, per the workflow's own Graphite-stack comment), the full smoke suite including CLI smoke (required) (the job that actually runs this script) has not executed on either #4017's or #4018's head yet, since #4017 doesn't touch the script and #4018 is stacked. It will run once this restacks onto main. Read the script itself carefully in place of a CI run; logic is sound.

Verdict: clean, no blockers
Reasoning: the value-discriminating test design directly answers the exact failure mode this check was written to catch; the CI-hasn't-run-yet gap is structural to stacking, not this PR's fault, and Home already flagged it as expected.

@james-russo-rames-d-jusso james-russo-rames-d-jusso left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:large_green_circle: 71bc0986 LGTM

Clean extension of the existing built-CLI harness. Same fetch-wrapping hook, same batch-capture shape, same "no PostHog request escapes" invariant — just plumbing a second command through it. The positive/negative fixture pair asserts every render-telemetry property that #4017 introduced, and the pair discriminates on each (mismatch true vs false, delta bucket 51+ vs 0, image/audio counts 1 vs 0, skill source flag vs absent, one env override vs empty array). One small hygiene gap on the negative side worth noting; not a blocker.

What the change is, verified end-to-end
• Extends scripts/ci/cli-telemetry-e2e.mjs (already wired at .github/workflows/ci.yml:803, and the job already installs ffmpeg + exercises puppeteer via the preceding smoke render — no new CI dependency).
• Fixtures are generated at test time: PIXEL_PNG_BASE64 decoded into pixel.png, and spawnSync("ffmpeg", ..., "sine=frequency=440:sample_rate=48000", "-t", "1", ...) for tone.wav. Nothing checked in, no LFS. Grepped the diff — no new asset files.
• withoutHfEnv(process.env) uses /^(HF|HYPERFRAMES)_/, which matches production HF_ENV_OVERRIDE_RE in packages/cli/src/commands/render/plan.ts verbatim — so the harness's own inherited env can't leak into hf_env_overrides, and injected HYPERFRAMES_E2E_MARKER reliably surfaces. The PR body's story about this catching the bootstrap-wiring bug is consistent with CLI_INTERNAL_HF_ENV_KEYS.
• --skill "e2e-smoke-test" passes SKILL_SLUG (/^[a-z0-9][a-z0-9-]{0,63}$/) in packages/cli/src/telemetry/skill.ts, so it drives authoringSkillSource="flag" end-to-end via plan.ts → render.ts → events.ts:445. The assertion is real.
• authoring_skill_source on the negative side deliberately uses !("... in ...) rather than === undefined — correct, because it guards against the regression where the field lands as a literal null (which would still evaluate as absent under === undefined on JSON parse). Comment in the harness even calls out "not a falsy placeholder". Good.
• runRender uses async spawn (not spawnSync), which is required — the fixture registry is served from this same process. Comment already covers this for runAdd; the render path is consistent.

Concerns
• (non-blocker) Negative side is missing the check("exactly one render_complete event", neg.completeEvents.length === 1, ...) sanity check that the positive side has. If the neg fixture ever emits zero render_complete events, negEvent = {} and !("authoring_skill_source" in {}) passes vacuously. The other neg checks (=== 0, === false, === "0") would still fail on undefined, so the harness overall would go red — the vacuous pass hides in a run that's already failing, not one that's silently green. But cheap to close: add the count assertion right after const negEvent = .... If it fires twice with divergent properties, [0] also silently ignores the second — same fix covers it.

Nits
• stdio: "ignore" on the render children means a genuine pipeline failure in CI produces no browser/ffmpeg stderr in the job log — you'd have to re-run locally to see it. Matches the existing runAdd pattern so consistent, but on a render (which has substantially more failure surface than add) piping stderr and dumping it only on non-zero would pay for itself. Not important.
• writeFixtureMedia's throw on ffmpeg failure skips server.close() and the rmSync(sandbox, ...) cleanup, so a bad run leaks the temp dir + listening port. Node's unhandled-rejection default kills the process, so no test hangs — just tidiness. A try/finally around the pos/neg block would cover it.

What I didn't verify
• Didn't run the harness locally against a built CLI — CI status rollup shows all 13 checks green on 71bc0986 and the PR body reports 24/24 (18 pre-existing + 6 new).
• Runtime cost of two --quality draft --workers 1 renders inside the 25-min job budget — the preceding smoke render in the same job establishes the browser is warm and the fixtures are one-frame 800x450, so should be fast, but I didn't wall-clock it.

— Review by Rames D Jusso

@miga-heygen
miga-heygen changed the base branch from feat/render-telemetry-output-and-environment to main September 17, 2026 02:06
@miga-heygen
miga-heygen dismissed james-russo-rames-d-jusso’s stale review September 17, 2026 02:06

The base branch was changed.

@james-russo-rames-d-jusso james-russo-rames-d-jusso left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:large_green_circle: 71bc0986 LGTM (re-stamp after base retarget)

Prior APPROVE 5230226196 was auto-dismissed when the base retargeted from feat/render-telemetry-output-and-environment to main. HEAD SHA is unchanged, no new commits since my prior review (ca ee f0 90 of 71bc0986 verified). #4017 squash-merged into main at 02:10:28Z, so once this rebases onto main the visible 16-file / 1569-add surface collapses back to the single 196-line test-file extension I reviewed. All CI green end-to-end at HEAD (44 checks success, 14 skipped, zero failures).

Prior verification carried forward verbatim:

Clean extension of the existing built-CLI harness. Same fetch-wrapping hook, same batch-capture shape, same "no PostHog request escapes" invariant — just plumbing a second command through it. The positive/negative fixture pair asserts every render-telemetry property that #4017 introduced, and the pair discriminates on each (mismatch true vs false, delta bucket 51+ vs 0, image/audio counts 1 vs 0, skill source flag vs absent, one env override vs empty array). One small hygiene gap on the negative side worth noting; not a blocker.

What the change is, verified end-to-end
• Extends scripts/ci/cli-telemetry-e2e.mjs (already wired at .github/workflows/ci.yml:803, and the job already installs ffmpeg + exercises puppeteer via the preceding smoke render — no new CI dependency).
• Fixtures are generated at test time: PIXEL_PNG_BASE64 decoded into pixel.png, and spawnSync("ffmpeg", ..., "sine=frequency=440:sample_rate=48000", "-t", "1", ...) for tone.wav. Nothing checked in, no LFS. Grepped the diff — no new asset files.
• withoutHfEnv(process.env) uses /^(HF|HYPERFRAMES)_/, which matches production HF_ENV_OVERRIDE_RE in packages/cli/src/commands/render/plan.ts verbatim — so the harness's own inherited env can't leak into hf_env_overrides, and injected HYPERFRAMES_E2E_MARKER reliably surfaces. The PR body's story about this catching the bootstrap-wiring bug is consistent with CLI_INTERNAL_HF_ENV_KEYS.
• --skill "e2e-smoke-test" passes SKILL_SLUG (/^[a-z0-9][a-z0-9-]{0,63}$/) in packages/cli/src/telemetry/skill.ts, so it drives authoringSkillSource="flag" end-to-end via plan.ts → render.ts → events.ts:445. The assertion is real.
• authoring_skill_source on the negative side deliberately uses !("... in ...) rather than === undefined — correct, because it guards against the regression where the field lands as a literal null (which would still evaluate as absent under === undefined on JSON parse). Comment in the harness even calls out "not a falsy placeholder". Good.
• runRender uses async spawn (not spawnSync), which is required — the fixture registry is served from this same process. Comment already covers this for runAdd; the render path is consistent.

Concerns
• (non-blocker) Negative side is missing the check("exactly one render_complete event", neg.completeEvents.length === 1, ...) sanity check that the positive side has. If the neg fixture ever emits zero render_complete events, negEvent = {} and !("authoring_skill_source" in {}) passes vacuously. The other neg checks (=== 0, === false, === "0") would still fail on undefined, so the harness overall would go red — the vacuous pass hides in a run that's already failing, not one that's silently green. But cheap to close: add the count assertion right after const negEvent = .... If it fires twice with divergent properties, [0] also silently ignores the second — same fix covers it.

Nits
• stdio: "ignore" on the render children means a genuine pipeline failure in CI produces no browser/ffmpeg stderr in the job log — you'd have to re-run locally to see it. Matches the existing runAdd pattern so consistent, but on a render (which has substantially more failure surface than add) piping stderr and dumping it only on non-zero would pay for itself. Not important.
• writeFixtureMedia's throw on ffmpeg failure skips server.close() and the rmSync(sandbox, ...) cleanup, so a bad run leaks the temp dir + listening port. Node's unhandled-rejection default kills the process, so no test hangs — just tidiness. A try/finally around the pos/neg block would cover it.

What I didn't verify
• Didn't run the harness locally against a built CLI — CI status rollup shows 44 checks green + 14 skipped on 71bc0986 and the PR body reports 24/24 (18 pre-existing + 6 new).
• Runtime cost of two --quality draft --workers 1 renders inside the 25-min job budget — the preceding smoke render in the same job establishes the browser is warm and the fixtures are one-frame 800x450, so should be fast, but I didn't wall-clock it.

HF-OSS require_last_push_approval=true — any push voids this stamp.

— Review by Rames D Jusso

Extends scripts/ci/cli-telemetry-e2e.mjs (already used to verify the `add`
command's telemetry) to spawn the built `render` command against two
generated fixture compositions and assert on the captured PostHog batch,
rather than a unit fixture that stubs the browser or ffmpeg.

One fixture sets every probed property (audio and image elements present,
root/body CSS size deliberately mismatched from the declared composition
size, a skill flag, one injected environment override) and its pair sets
none, so each property is asserted on both its present-and-correct side and
its absent-or-zero side in the same pair of runs: audio_count, image_count,
root_body_mismatch and its delta bucket, authoring_skill_source,
hf_env_overrides, and ffmpeg/browser_version_major.

Co-Authored-By: Miguel Ángel <[email protected]>
@miga-heygen
miga-heygen force-pushed the feat/render-telemetry-e2e-harness branch from 71bc098 to 437c012 Compare September 17, 2026 02:37
@miga-heygen
miga-heygen merged commit f4cdccd into main Sep 17, 2026
48 checks passed
@miga-heygen
miga-heygen deleted the feat/render-telemetry-e2e-harness branch September 17, 2026 02:49
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