Skip to content

Commit 16c3711

Browse files
committed
feat(m1): production hardening — CI deps, smoke test, Manim pacing
CI: - Install ffmpeg + tesseract-ocr in unit test job (all 23 tests run) - Add smoke job: config validation, narration lint, TTS dry-run Manim pacing (reduces static holds from ~57% to <1%): - Scene 01: tagline during title card, sequential output items, validation check annotations, config entries during "yaml" segment - Scene 03: exclude-pattern filter animation fills the 11s gap between checkboxes and Production tab switch Regenerated 01-overview.mp4, 03-wizard-gui.mp4, full-demo.mp4. Made-with: Cursor
1 parent 94ff0ba commit 16c3711

File tree

5 files changed

+114
-7
lines changed

5 files changed

+114
-7
lines changed

.github/workflows/ci.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,27 @@ jobs:
3131
- uses: actions/setup-python@v6
3232
with:
3333
python-version: ${{ matrix.python-version }}
34+
- name: Install system dependencies
35+
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends ffmpeg tesseract-ocr
3436
- run: pip install ".[dev]"
3537
- run: pytest tests/ --ignore=tests/e2e -v --tb=short
3638

39+
smoke:
40+
name: smoke (config + lint + tts dry-run)
41+
runs-on: ubuntu-latest
42+
steps:
43+
- uses: actions/checkout@v6
44+
- uses: actions/setup-python@v6
45+
with:
46+
python-version: "3.12"
47+
- run: pip install .
48+
- name: Validate config loads
49+
run: docgen --config docs/demos/docgen.yaml validate --help
50+
- name: Narration lint
51+
run: docgen --config docs/demos/docgen.yaml lint
52+
- name: TTS dry-run
53+
run: docgen --config docs/demos/docgen.yaml tts --dry-run
54+
3755
e2e:
3856
runs-on: ubuntu-latest
3957
steps:

docs/demos/animations/scenes.py

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,16 @@ def seg_end(i: int) -> float:
115115

116116
self.timed_play(Write(title), run_time=1.2)
117117
self.timed_play(FadeIn(subtitle, shift=UP * 0.2), run_time=0.8)
118+
119+
tagline = Text(
120+
"Reproducible · version-controlled · fully automated",
121+
font_size=16, color=GREY_B,
122+
)
123+
tagline.next_to(subtitle, DOWN, buff=0.4)
124+
self.wait_until(seg_start(1))
125+
self.timed_play(FadeIn(tagline, shift=UP * 0.15), run_time=0.7)
126+
title_group.add(tagline)
127+
118128
self.wait_until(seg_start(2))
119129

120130
# ── Beat 2: Title shrinks; show inputs ────────────────────────
@@ -188,7 +198,17 @@ def seg_end(i: int) -> float:
188198
out_group.add(ot)
189199

190200
self.timed_play(FadeIn(outputs_label), run_time=0.4)
191-
self.timed_play(*[FadeIn(o, shift=UP * 0.15) for o in out_group], run_time=0.6)
201+
202+
out_per = max(0.3, (seg_start(9) - self._clock - 1.0) / len(out_group))
203+
for o in out_group:
204+
self.timed_play(FadeIn(o, shift=UP * 0.15), run_time=out_per)
205+
206+
output_arrows = VGroup()
207+
for sb in [stage_boxes[-1]]:
208+
arr = _arrow(sb[0].get_bottom(), outputs_label.get_top(), color=C_ACCENT)
209+
output_arrows.add(arr)
210+
self.timed_play(Create(output_arrows[0]), run_time=0.5)
211+
192212
self.wait_until(seg_start(9))
193213

194214
# ── Beats 9-10: Concat + Pages ────────────────────────────────
@@ -208,6 +228,23 @@ def seg_end(i: int) -> float:
208228

209229
self.timed_play(Create(val_to_concat), FadeIn(concat_box), run_time=0.5)
210230
self.timed_play(Create(concat_to_pages), FadeIn(pages_box), run_time=0.5)
231+
232+
checks_group = VGroup()
233+
check_items = [
234+
("✓ stream presence", C_GREEN),
235+
("✓ A/V drift < 2.75s", C_GREEN),
236+
("✓ no blank frames", C_GREEN),
237+
("✓ narration lint clean", C_GREEN),
238+
]
239+
for ci, (cl, cc) in enumerate(check_items):
240+
ct = Text(cl, font_size=12, color=cc)
241+
ct.move_to(LEFT * 5.0 + DOWN * (1.8 + ci * 0.35))
242+
checks_group.add(ct)
243+
244+
check_per = max(0.3, (seg_start(11) - self._clock - 0.5) / len(check_items))
245+
for ct in checks_group:
246+
self.timed_play(FadeIn(ct, shift=RIGHT * 0.2), run_time=check_per)
247+
211248
self.wait_until(seg_start(11))
212249

213250
# ── Beat 11: Single command highlight ─────────────────────────
@@ -223,6 +260,28 @@ def seg_end(i: int) -> float:
223260

224261
self.timed_play(FadeIn(cmd_group, shift=UP * 0.3), run_time=0.7)
225262
self.timed_play(Indicate(cmd_group, color=C_ACCENT, scale_factor=1.05), run_time=0.8)
263+
264+
config_items = VGroup()
265+
cfg_entries = [
266+
("segments:", C_ACCENT),
267+
(" visual_map:", C_TEAL),
268+
(" tts:", C_PURPLE),
269+
(" validation:", C_RED),
270+
(" wizard:", C_ORANGE),
271+
]
272+
for ci, (cl, cc) in enumerate(cfg_entries):
273+
ct = Text(cl, font_size=12, color=cc, font="Monospace")
274+
ct.move_to(RIGHT * 4.0 + DOWN * (1.8 + ci * 0.3))
275+
config_items.add(ct)
276+
277+
cfg_label = Text("docgen.yaml", font_size=14, color=C_ORANGE, weight=BOLD)
278+
cfg_label.move_to(RIGHT * 4.0 + DOWN * 1.4)
279+
self.timed_play(FadeIn(cfg_label), run_time=0.3)
280+
281+
cfg_per = max(0.2, (seg_start(12) - self._clock - 0.3) / len(config_items))
282+
for ct in config_items:
283+
self.timed_play(FadeIn(ct, shift=RIGHT * 0.15), run_time=cfg_per)
284+
226285
self.wait_until(seg_start(12))
227286

228287
# ── Beat 12: Final + fade out ─────────────────────────────────
@@ -352,6 +411,36 @@ def seg_end(i: int) -> float:
352411
*[FadeIn(c, shift=LEFT * 0.1) for c in checks],
353412
run_time=0.5,
354413
)
414+
self.wait_until(seg_start(6))
415+
416+
# ── Beats 6-7: Exclude patterns filter animation ─────────
417+
exclude_title = Text("Excluded by docgen.yaml:", font_size=13, color=C_ORANGE)
418+
exclude_title.move_to(RIGHT * 2.5 + UP * 0.8)
419+
420+
excluded_dirs = [
421+
"node_modules/",
422+
"__pycache__/",
423+
".pytest_cache/",
424+
".venv/",
425+
]
426+
excl_group = VGroup()
427+
for ei, edir in enumerate(excluded_dirs):
428+
et = Text(edir, font_size=11, color=C_RED, font="Monospace")
429+
cross = Text("✗", font_size=13, color=C_RED)
430+
et.move_to(RIGHT * 3.0 + UP * (0.3 - ei * 0.35))
431+
cross.move_to(RIGHT * 1.8 + UP * (0.3 - ei * 0.35))
432+
excl_group.add(VGroup(cross, et))
433+
434+
self.timed_play(FadeIn(exclude_title), run_time=0.4)
435+
436+
excl_per = max(0.3, (seg_start(8) - self._clock - 0.5) / len(excl_group))
437+
for eg in excl_group:
438+
self.timed_play(FadeIn(eg, shift=LEFT * 0.15), run_time=excl_per)
439+
440+
self.wait_until(seg_start(8) - 0.3)
441+
self.timed_play(
442+
FadeOut(exclude_title), FadeOut(excl_group), run_time=0.3,
443+
)
355444
self.wait_until(seg_start(8))
356445

357446
# ── Beat 8: Switch to Production tab ─────────────────────────
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version https://git-lfs.github.com/spec/v1
2-
oid sha256:36b52db934bd2af3e9323ed0d8fcddd6c5032089d2ad50ceb562cbc2f2810d80
3-
size 1559323
2+
oid sha256:8d9b584587fab63e8a134ececd35501966ecc0d74efd0263fe07527db79336ac
3+
size 1675150
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version https://git-lfs.github.com/spec/v1
2-
oid sha256:e09369269e481fd89e03984b5be6dcc465b35f7b492f883e7d9145d1ea61b999
3-
size 1597571
2+
oid sha256:deae84f76e390923eae96938e0ae93d413e76df8d1a67ada80eb1b6a1175753d
3+
size 1631038
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version https://git-lfs.github.com/spec/v1
2-
oid sha256:cc2bfc65a42dc9dcd22b336a78b517fdcebebfcd9728e3fad5b73f0bb1bb6def
3-
size 10663602
2+
oid sha256:dd3e0f1032a0215c6e4a1310c88b8602f1852943badd3e3ab955b81cd3c15e72
3+
size 10812896

0 commit comments

Comments
 (0)