Conversation
…(F1) Playwright's record_video_dir always writes WebM. Capture scripts that shutil.copy those bytes into a .mp4 path (to satisfy filename-based validators) end up with a WebM payload masquerading as MP4. The runner now sniffs the EBML header and transcodes in place via ffmpeg so downstream consumers always get a real ISO MP4. Real MP4 outputs pass through unchanged (back-compat preserved). Co-authored-by: John Menke <jmjava@gmail.com>
Adds 'docgen demo-function' for rendering one short, single-purpose video per function (~the docs-site analogue of one Playwright test() per behavior). Inputs are declarative — either a *.docgen.yaml sidecar or a @pytest.mark.docgen(...) decorator on a Python test, read statically via ast (never imported / exec'd). Outputs are five files in --output-dir: rendered.mp4 (real ISO MP4), poster.png, fragment.txt (fn-<slug>), manifest.json (snapshot), cache-status.txt (hit/miss). Exit codes: 0 success, 1 invalid manifest / render failure, 2 missing ffmpeg / playwright (with install hint), 78 neutral skip (placeholder manifest with no demonstration.url) — mirrors Tekton's documented Skip exit code so CI does not flag placeholder-shaped manifests as failures. Action vocabulary (8 kinds): goto, click, fill, type, wait_for, wait_for_text, wait, screenshot. wait_for_text uses the native locator API instead of wait_for_function with embedded JS strings (F6). When OPENAI_API_KEY is set, the intent line is narrated via gpt-4o-mini-tts and muxed onto the video with -shortest. When unset, emits a documented warning to stderr and continues with a visual-only video (narration: null in manifest.json). Cache: when --cache-dir is given, content-addressed by sha256(identifier + intent + sorted(fixture_paths) + concat(fixture_contents))[:16]. Hits copy all four content files into output-dir verbatim and skip Playwright/ffmpeg/TTS entirely. Adds 31 unit tests covering manifest loading (both shapes), validation (resolution/duration/kind), action rendering, generated-script compile, fragment_id and cache_key stability, CLI exit codes, end-to-end render of kind=cli (ffmpeg-only, no Playwright), and the F7 docstring regression. Tests pass without Playwright or browsers installed. Co-authored-by: John Menke <jmjava@gmail.com>
Adds a README subsection describing 'docgen demo-function' (one paragraph + example invocation) and links to examples/. Bumps the package version to 0.2.0 since this adds a new public CLI surface. Co-authored-by: John Menke <jmjava@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
docgen demo-function, a new CLI subcommand for rendering one short, single-purpose MP4 per function — the docs-site analogue of a single Playwrighttest('…')describing one behavior. Inputs are declarative (either a*.docgen.yamlsidecar or a@pytest.mark.docgen(...)decorator on a Python test, read statically viaast); outputs are five files in--output-dir. Bumps version to0.2.0.This absorbs the behavior of the downstream
tools/docgen-shim/demo_function.pyshim (~600 lines) intodocgenitself, plus adds the seven sharp-edge fixes the spec called for. F1 also fixes the existingdocgen playwrightrunner (back-compat preserved).Subcommand contract
Artifacts in
--output-dir:rendered.mp4(real ISO MP4, libx264, yuv420p, +faststart, sized to manifest resolution),poster.png(last frame),fragment.txt(fn-<slug>, no trailing newline),manifest.json(snapshot with the seven documented keys),cache-status.txt(hit\normiss\n).Exit codes:
0success ·1invalid manifest / render failure ·2missing tooling (with install hint) ·78neutral skip (placeholder manifest with nodemonstration.url— mirrors Tekton's documented Skip code).Sharp-edge fixes shipped
.mp4outputs and transcode WebM-in-MP4-path via ffmpeg. Real MP4 passes through unchanged.src/docgen/playwright_runner.pysrc/docgen/demo_function.pyrecord_video_sizedriven frommanifest.output_budget.resolution, notdocgen.yaml.src/docgen/demo_function.pygpt-4o-mini-tts, muxed with-shortest. Soft-warns whenOPENAI_API_KEYis unset.src/docgen/demo_function.py@pytest.mark.docgen(...)on Python tests via<path>.py::<test_name>syntax.src/docgen/demo_function.py::_load_pytest_markerwait_for_textuses nativepage.locator(sel).filter(has_text=text).first.wait_for(...)— no JS-in-Python-string-template gymnastics._render_action,_execute_actionsast.parse+ decorator walk; neverregexover source. Includes a regression test against module-docstring text that mentions the marker._load_pytest_marker+tests/test_demo_function.py::test_python_marker_ignores_docstring_textFiles
src/docgen/demo_function.py(manifest dataclasses, YAML + AST loaders, validator, action renderer, capture-script template, cache lookup/store, ffmpeg helpers, narration, render orchestration,run_cliexit-code mapping).tests/test_demo_function.py(31 tests; pure-data tests run without Playwright or ffmpeg installed; the few end-to-end render tests skip when ffmpeg is missing).examples/lesson_compile.docgen.yaml,examples/sample_test.py(both manifest shapes for one identifier).src/docgen/cli.py(@main.command("demo-function")).src/docgen/playwright_runner.py(F1).tests/test_playwright_runner.py(two new tests for F1: WebM transcode + real-MP4 pass-through).README.md(new section + CLI table row).pyproject.toml(0.1.0→0.2.0).Acceptance-criteria coverage
0on a valid runtest_render_cli_kind_emits_artifacts+ manual smokerendered.mp4is real ISO MP4 (not WebM)ftypheader asserted; manualfileconfirmsISO Media, MP4 Base Media v1poster.pngresolution matches manifestfileconfirmsPNG image data, 320 x 240for a320x240manifestfragment.txtmatches^fn-[a-z0-9-]+$, no trailing newlinetest_fragment_id_format+test_render_cli_kind_emits_artifactsmanifest.jsonparses, has the seven keystest_render_cli_kind_emits_artifactscache-status.txtismiss\nthenhit\ntest_render_cli_kind_emits_artifactstest_yaml_and_python_marker_produce_equivalent_manifestsdemonstration.url→ exit 78, no writestest_run_cli_neutral_skip+ manual smokeduration_seconds: 120→ exit 1 with hard-cap messagetest_run_cli_invalid_manifest_duration+ manual smokeOPENAI_API_KEY→ warning + visual-only; with key → AAC track + non-nullmanifest.json.narrationtest_render_warns_when_openai_key_missing(negative half); positive half exercised in_generate_narrationintegrationdocgen playwrightkeeps workingtest_playwright_runner.pysuite still green; F1 path is gated on EBML header +.mp4suffixTest results
(31 new + 114 pre-existing; ruff clean.)
Out of scope (per spec)
Hosting / CDN choices, replacing
docgen generate-all, non-pytest annotation discovery, web-UI manifest authoring, cache eviction policy.