truedemo 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. truedemo-2.0.0/LICENSE +204 -0
  2. truedemo-2.0.0/PKG-INFO +315 -0
  3. truedemo-2.0.0/README.md +277 -0
  4. truedemo-2.0.0/pyproject.toml +74 -0
  5. truedemo-2.0.0/setup.cfg +4 -0
  6. truedemo-2.0.0/tests/test_capture.py +1087 -0
  7. truedemo-2.0.0/tests/test_cli.py +236 -0
  8. truedemo-2.0.0/tests/test_core.py +227 -0
  9. truedemo-2.0.0/tests/test_docker.py +810 -0
  10. truedemo-2.0.0/tests/test_exec.py +986 -0
  11. truedemo-2.0.0/tests/test_ffmpeg.py +408 -0
  12. truedemo-2.0.0/tests/test_hygiene.py +262 -0
  13. truedemo-2.0.0/tests/test_job.py +366 -0
  14. truedemo-2.0.0/tests/test_mcp.py +736 -0
  15. truedemo-2.0.0/tests/test_movie.py +1093 -0
  16. truedemo-2.0.0/tests/test_presentation.py +715 -0
  17. truedemo-2.0.0/tests/test_provenance.py +233 -0
  18. truedemo-2.0.0/tests/test_providers.py +431 -0
  19. truedemo-2.0.0/tests/test_studio.py +1624 -0
  20. truedemo-2.0.0/tests/test_terminal.py +281 -0
  21. truedemo-2.0.0/tests/test_timeframe.py +364 -0
  22. truedemo-2.0.0/truedemo/__init__.py +24 -0
  23. truedemo-2.0.0/truedemo/__main__.py +6 -0
  24. truedemo-2.0.0/truedemo/_loop.py +192 -0
  25. truedemo-2.0.0/truedemo/_version.py +9 -0
  26. truedemo-2.0.0/truedemo/assembler.py +1223 -0
  27. truedemo-2.0.0/truedemo/capture.py +653 -0
  28. truedemo-2.0.0/truedemo/card.py +132 -0
  29. truedemo-2.0.0/truedemo/cli.py +450 -0
  30. truedemo-2.0.0/truedemo/context.py +193 -0
  31. truedemo-2.0.0/truedemo/errors.py +19 -0
  32. truedemo-2.0.0/truedemo/exec.py +1420 -0
  33. truedemo-2.0.0/truedemo/ffmpeg.py +666 -0
  34. truedemo-2.0.0/truedemo/job.py +609 -0
  35. truedemo-2.0.0/truedemo/mcp_server.py +1786 -0
  36. truedemo-2.0.0/truedemo/narration.py +176 -0
  37. truedemo-2.0.0/truedemo/overlay.py +75 -0
  38. truedemo-2.0.0/truedemo/panels.py +417 -0
  39. truedemo-2.0.0/truedemo/provenance.py +228 -0
  40. truedemo-2.0.0/truedemo/provider.py +185 -0
  41. truedemo-2.0.0/truedemo/py.typed +0 -0
  42. truedemo-2.0.0/truedemo/reports.py +501 -0
  43. truedemo-2.0.0/truedemo/scaffold.py +212 -0
  44. truedemo-2.0.0/truedemo/secrets.py +161 -0
  45. truedemo-2.0.0/truedemo/snapshot.py +159 -0
  46. truedemo-2.0.0/truedemo/spec.py +1476 -0
  47. truedemo-2.0.0/truedemo/studio.py +1503 -0
  48. truedemo-2.0.0/truedemo/svg.py +150 -0
  49. truedemo-2.0.0/truedemo/terminal.py +415 -0
  50. truedemo-2.0.0/truedemo/timeframe.py +468 -0
  51. truedemo-2.0.0/truedemo/tts.py +119 -0
  52. truedemo-2.0.0/truedemo/verify.py +564 -0
  53. truedemo-2.0.0/truedemo.egg-info/PKG-INFO +315 -0
  54. truedemo-2.0.0/truedemo.egg-info/SOURCES.txt +56 -0
  55. truedemo-2.0.0/truedemo.egg-info/dependency_links.txt +1 -0
  56. truedemo-2.0.0/truedemo.egg-info/entry_points.txt +3 -0
  57. truedemo-2.0.0/truedemo.egg-info/requires.txt +15 -0
  58. truedemo-2.0.0/truedemo.egg-info/top_level.txt +1 -0
truedemo-2.0.0/LICENSE ADDED
@@ -0,0 +1,204 @@
1
+
2
+ Copyright 2026 Anindyasundar Bera
3
+
4
+ Apache License
5
+ Version 2.0, January 2004
6
+ http://www.apache.org/licenses/
7
+
8
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
9
+
10
+ 1. Definitions.
11
+
12
+ "License" shall mean the terms and conditions for use, reproduction,
13
+ and distribution as defined by Sections 1 through 9 of this document.
14
+
15
+ "Licensor" shall mean the copyright owner or entity authorized by
16
+ the copyright owner that is granting the License.
17
+
18
+ "Legal Entity" shall mean the union of the acting entity and all
19
+ other entities that control, are controlled by, or are under common
20
+ control with that entity. For the purposes of this definition,
21
+ "control" means (i) the power, direct or indirect, to cause the
22
+ direction or management of such entity, whether by contract or
23
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
24
+ outstanding shares, or (iii) beneficial ownership of such entity.
25
+
26
+ "You" (or "Your") shall mean an individual or Legal Entity
27
+ exercising permissions granted by this License.
28
+
29
+ "Source" form shall mean the preferred form for making modifications,
30
+ including but not limited to software source code, documentation
31
+ source, and configuration files.
32
+
33
+ "Object" form shall mean any form resulting from mechanical
34
+ transformation or translation of a Source form, including but
35
+ not limited to compiled object code, generated documentation,
36
+ and conversions to other media types.
37
+
38
+ "Work" shall mean the work of authorship, whether in Source or
39
+ Object form, made available under the License, as indicated by a
40
+ copyright notice that is included in or attached to the work
41
+ (an example is provided in the Appendix below).
42
+
43
+ "Derivative Works" shall mean any work, whether in Source or Object
44
+ form, that is based on (or derived from) the Work and for which the
45
+ editorial revisions, annotations, elaborations, or other modifications
46
+ represent, as a whole, an original work of authorship. For the purposes
47
+ of this License, Derivative Works shall not include works that remain
48
+ separable from, or merely link (or bind by name) to the interfaces of,
49
+ the Work and Derivative Works thereof.
50
+
51
+ "Contribution" shall mean any work of authorship, including
52
+ the original version of the Work and any modifications or additions
53
+ to that Work or Derivative Works thereof, that is intentionally
54
+ submitted to Licensor for inclusion in the Work by the copyright owner
55
+ or by an individual or Legal Entity authorized to submit on behalf of
56
+ the copyright owner. For the purposes of this definition, "submitted"
57
+ means any form of electronic, verbal, or written communication sent
58
+ to the Licensor or its representatives, including but not limited to
59
+ communication on electronic mailing lists, source code control systems,
60
+ and issue tracking systems that are managed by, or on behalf of, the
61
+ Licensor for the purpose of discussing and improving the Work, but
62
+ excluding communication that is conspicuously marked or otherwise
63
+ designated in writing by the copyright owner as "Not a Contribution."
64
+
65
+ "Contributor" shall mean Licensor and any individual or Legal Entity
66
+ on behalf of whom a Contribution has been received by Licensor and
67
+ subsequently incorporated within the Work.
68
+
69
+ 2. Grant of Copyright License. Subject to the terms and conditions of
70
+ this License, each Contributor hereby grants to You a perpetual,
71
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
72
+ copyright license to reproduce, prepare Derivative Works of,
73
+ publicly display, publicly perform, sublicense, and distribute the
74
+ Work and such Derivative Works in Source or Object form.
75
+
76
+ 3. Grant of Patent License. Subject to the terms and conditions of
77
+ this License, each Contributor hereby grants to You a perpetual,
78
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
79
+ (except as stated in this section) patent license to make, have made,
80
+ use, offer to sell, sell, import, and otherwise transfer the Work,
81
+ where such license applies only to those patent claims licensable
82
+ by such Contributor that are necessarily infringed by their
83
+ Contribution(s) alone or by combination of their Contribution(s)
84
+ with the Work to which such Contribution(s) was submitted. If You
85
+ institute patent litigation against any entity (including a
86
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
87
+ or a Contribution incorporated within the Work constitutes direct
88
+ or contributory patent infringement, then any patent licenses
89
+ granted to You under this License for that Work shall terminate
90
+ as of the date such litigation is filed.
91
+
92
+ 4. Redistribution. You may reproduce and distribute copies of the
93
+ Work or Derivative Works thereof in any medium, with or without
94
+ modifications, and in Source or Object form, provided that You
95
+ meet the following conditions:
96
+
97
+ (a) You must give any other recipients of the Work or
98
+ Derivative Works a copy of this License; and
99
+
100
+ (b) You must cause any modified files to carry prominent notices
101
+ stating that You changed the files; and
102
+
103
+ (c) You must retain, in the Source form of any Derivative Works
104
+ that You distribute, all copyright, patent, trademark, and
105
+ attribution notices from the Source form of the Work,
106
+ excluding those notices that do not pertain to any part of
107
+ the Derivative Works; and
108
+
109
+ (d) If the Work includes a "NOTICE" text file as part of its
110
+ distribution, then any Derivative Works that You distribute must
111
+ include a readable copy of the attribution notices contained
112
+ within such NOTICE file, excluding those notices that do not
113
+ pertain to any part of the Derivative Works, in at least one
114
+ of the following places: within a NOTICE text file distributed
115
+ as part of the Derivative Works; within the Source form or
116
+ documentation, if provided along with the Derivative Works; or,
117
+ within a display generated by the Derivative Works, if and
118
+ wherever such third-party notices normally appear. The contents
119
+ of the NOTICE file are for informational purposes only and
120
+ do not modify the License. You may add Your own attribution
121
+ notices within Derivative Works that You distribute, alongside
122
+ or as an addendum to the NOTICE text from the Work, provided
123
+ that such additional attribution notices cannot be construed
124
+ as modifying the License.
125
+
126
+ You may add Your own copyright statement to Your modifications and
127
+ may provide additional or different license terms and conditions
128
+ for use, reproduction, or distribution of Your modifications, or
129
+ for any such Derivative Works as a whole, provided Your use,
130
+ reproduction, and distribution of the Work otherwise complies with
131
+ the conditions stated in this License.
132
+
133
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
134
+ any Contribution intentionally submitted for inclusion in the Work
135
+ by You to the Licensor shall be under the terms and conditions of
136
+ this License, without any additional terms or conditions.
137
+ Notwithstanding the above, nothing herein shall supersede or modify
138
+ the terms of any separate license agreement you may have executed
139
+ with Licensor regarding such Contributions.
140
+
141
+ 6. Trademarks. This License does not grant permission to use the trade
142
+ names, trademarks, service marks, or product names of the Licensor,
143
+ except as required for reasonable and customary use in describing the
144
+ origin of the Work and reproducing the content of the NOTICE file.
145
+
146
+ 7. Disclaimer of Warranty. Unless required by applicable law or
147
+ agreed to in writing, Licensor provides the Work (and each
148
+ Contributor provides its Contributions) on an "AS IS" BASIS,
149
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
150
+ implied, including, without limitation, any warranties or conditions
151
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
152
+ PARTICULAR PURPOSE. You are solely responsible for determining the
153
+ appropriateness of using or redistributing the Work and assume any
154
+ risks associated with Your exercise of permissions under this License.
155
+
156
+ 8. Limitation of Liability. In no event and under no legal theory,
157
+ whether in tort (including negligence), contract, or otherwise,
158
+ unless required by applicable law (such as deliberate and grossly
159
+ negligent acts) or agreed to in writing, shall any Contributor be
160
+ liable to You for damages, including any direct, indirect, special,
161
+ incidental, or consequential damages of any character arising as a
162
+ result of this License or out of the use or inability to use the
163
+ Work (including but not limited to damages for loss of goodwill,
164
+ work stoppage, computer failure or malfunction, or any and all
165
+ other commercial damages or losses), even if such Contributor
166
+ has been advised of the possibility of such damages.
167
+
168
+ 9. Accepting Warranty or Additional Liability. While redistributing
169
+ the Work or Derivative Works thereof, You may choose to offer,
170
+ and charge a fee for, acceptance of support, warranty, indemnity,
171
+ or other liability obligations and/or rights consistent with this
172
+ License. However, in accepting such obligations, You may act only
173
+ on Your own behalf and on Your sole responsibility, not on behalf
174
+ of any other Contributor, and only if You agree to indemnify,
175
+ defend, and hold each Contributor harmless for any liability
176
+ incurred by, or claims asserted against, such Contributor by reason
177
+ of your accepting any such warranty or additional liability.
178
+
179
+ END OF TERMS AND CONDITIONS
180
+
181
+ APPENDIX: How to apply the Apache License to your work.
182
+
183
+ To apply the Apache License to your work, attach the following
184
+ boilerplate notice, with the fields enclosed by brackets "[]"
185
+ replaced with your own identifying information. (Don't include
186
+ the brackets!) The text should be enclosed in the appropriate
187
+ comment syntax for the file format. We also recommend that a
188
+ file or class name and description of purpose be included on the
189
+ same "printed page" as the copyright notice for easier
190
+ identification within third-party archives.
191
+
192
+ Copyright [yyyy] [name of copyright owner]
193
+
194
+ Licensed under the Apache License, Version 2.0 (the "License");
195
+ you may not use this file except in compliance with the License.
196
+ You may obtain a copy of the License at
197
+
198
+ http://www.apache.org/licenses/LICENSE-2.0
199
+
200
+ Unless required by applicable law or agreed to in writing, software
201
+ distributed under the License is distributed on an "AS IS" BASIS,
202
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
203
+ See the License for the specific language governing permissions and
204
+ limitations under the License.
@@ -0,0 +1,315 @@
1
+ Metadata-Version: 2.4
2
+ Name: truedemo
3
+ Version: 2.0.0
4
+ Summary: Create narrated, captioned demo videos of software — a real browser UI, a real terminal command, or a document it produces — from a declarative spec plus your own data; then reopen the .mp4 and verify every promise the spec made. Runs from a shell or an agent over MCP.
5
+ Author: Anindyasundar Bera
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/anindyasundarbera/truedemo
8
+ Project-URL: Repository, https://github.com/anindyasundarbera/truedemo
9
+ Project-URL: Issues, https://github.com/anindyasundarbera/truedemo/issues
10
+ Project-URL: Changelog, https://github.com/anindyasundarbera/truedemo/blob/main/CHANGELOG.md
11
+ Keywords: demo-video,screencast,video-generation,playwright,ffmpeg,mcp
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Multimedia :: Video
22
+ Classifier: Topic :: Software Development :: Documentation
23
+ Requires-Python: <3.15,>=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: PyYAML<7,>=6.0.3
27
+ Provides-Extra: capture
28
+ Requires-Dist: playwright<2,>=1.63.0; extra == "capture"
29
+ Provides-Extra: tts
30
+ Requires-Dist: piper-tts<2,>=1.8.0; extra == "tts"
31
+ Provides-Extra: mcp
32
+ Requires-Dist: mcp<3,>=1.30.0; extra == "mcp"
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest<10,>=9.1.1; extra == "dev"
35
+ Requires-Dist: pytest-cov<8,>=7.1.0; extra == "dev"
36
+ Requires-Dist: ruff<1,>=0.16.10; extra == "dev"
37
+ Dynamic: license-file
38
+
39
+ # truedemo
40
+
41
+ **truedemo creates narrated, captioned demo videos of software.** Point it at a real browser UI
42
+ or a real terminal command, give it your own data, and describe the film in a small
43
+ declarative spec — it drives the software, records what it does, draws your data onto charts,
44
+ writes the narration, and assembles the result into an `.mp4` with an `.srt`. Then it
45
+ **reopens the finished `.mp4`** to check it kept every promise the spec made. A broken promise
46
+ fails the build. Run it from a shell, or let an autonomous agent drive it over MCP.
47
+
48
+ ---
49
+
50
+ ## What it is
51
+
52
+ You have a piece of software. You need a demo video of it — for a launch page, a README, a
53
+ customer, or a release. Today you make that by hand: drive the app, record the screen, write
54
+ a script, record a voice-over, cut the takes together, and type the numbers onto the slides.
55
+ It works, and it does not scale. Change the product and the video is stale; change the
56
+ numbers and the video is a lie that nobody notices until a customer does.
57
+
58
+ truedemo automates that whole loop from a declarative spec, and — the part that makes it worth
59
+ using — refuses to let the result be dishonest. Every frame comes from something real, and a
60
+ report re-opens the render to check the claims actually held.
61
+
62
+ **It is for** anyone who makes software demo videos by hand and is tired of them drifting
63
+ out of date, and for agents that must produce one without a human watching the screen.
64
+
65
+ **It films software you can drive on screen** — a web UI in a real browser, a command in a
66
+ real terminal, or a document the software produces. It does not capture a native desktop GUI,
67
+ invent a UI, or act as a video editor: there is no timeline to drag and no keyframes to set.
68
+ You declare shots, and truedemo builds the film and checks it.
69
+
70
+ > New here? [**A tour: what happens when you build**](docs/guides/tour.md) is the orientation —
71
+ > what a spec is, what the ten stages do, and what can be on screen.
72
+
73
+ ## See it run
74
+
75
+ Thirty seconds, with no browser, no network, and no voice model — every number in this
76
+ example is counted from the files in this repository at the moment of the build:
77
+
78
+ ```bash
79
+ git clone https://github.com/anindyasundarbera/truedemo
80
+ cd truedemo
81
+ pip install -e ".[dev]" # ffmpeg and rsvg-convert are required; see Install below
82
+
83
+ truedemo doctor examples/hello-world/video.yaml # is this machine ready?
84
+ truedemo plan examples/hello-world/video.yaml # scenes, timings, guards — render nothing
85
+ truedemo build examples/hello-world/video.yaml # → hello-world.mp4 + .srt + verify.json
86
+ ```
87
+
88
+ `plan` is the cheap one: it prints the whole scene plan and the estimated runtime without
89
+ touching a pixel. `build` is the real thing, and the `verify.json` it writes is the report
90
+ this project exists to produce. This example is the fixture CI builds on every push.
91
+
92
+ ## Why it is honest
93
+
94
+ **Nothing is fabricated.** Every frame traces to something real: a live capture of a running
95
+ product, a chart drawn from a provider's measured data, or a declared graphic the engine drew
96
+ from the script's own words. There is no "mock UI" mode, because a mock UI is
97
+ indistinguishable from a real one once it is inside the `.mp4`.
98
+
99
+ **The engine then reopens the render and proves it.** `verify` does not read your spec back
100
+ to you. It decodes the finished `.mp4`, the `.srt`, and the audio track, and checks the
101
+ artifact against the promises the spec made. A broken promise fails the build.
102
+
103
+ The failure modes this prevents are boring and predictable, which is exactly why they keep
104
+ happening:
105
+
106
+ - The recording shows **development mode** while the narration says the product is live.
107
+ - A **caption runs off the screen** two lines into a sentence, so nobody reads it.
108
+ - The voice-over states a number that was **typed from memory**, not measured.
109
+ - The cut **drifts out of sync**, because the timing table was estimated rather than measured.
110
+ - The runtime is 26 minutes and the limit was 25.
111
+ - The script makes a claim the spec **explicitly forbade**, and nothing checks it.
112
+
113
+ Hand that job to an LLM agent and it hits every one of those faster, because the agent
114
+ cannot see the screen. It writes a spec, renders, and reports success. Nothing in that loop
115
+ ever asked whether the pixels agreed with the words.
116
+
117
+ And one rule that turned out to matter more than any single feature:
118
+
119
+ > **A declaration is not a measurement.** A check about what a picture *did* decodes the
120
+ > picture. A camera move declared in the spec is not a camera move until two frames of the
121
+ > finished clip disagree.
122
+
123
+ That rule has since caught real defects three separate times — including a check that could
124
+ never fail, because it compared a list against a filter of itself and cheerfully reported
125
+ *"5 of 6 shots move"* about shots that had only **said** they move.
126
+
127
+ ## What it does
128
+
129
+ Ten stages, one pass, no timeline editor anywhere in it — `data` → `panels` → `stills` →
130
+ `capture` → `exec` → `narration` → `clips` → `concat` → `render` → `verify`. Each stage
131
+ reads something, writes a file, or stops the build.
132
+
133
+ The measured audio is the **master clock**: each scene's video segment is sized to the
134
+ duration ffmpeg measured from that scene's WAV, so sync is a consequence of the pipeline
135
+ rather than something you keep by hand. The [tour](docs/guides/tour.md#the-ten-stages) walks
136
+ each stage and the [pipeline](docs/foundations/pipeline.md) defines its exact inputs,
137
+ outputs, and failure conditions.
138
+
139
+ ## Install
140
+
141
+ ```bash
142
+ pip install -e . # the engine — YAML/JSON specs
143
+ pip install -e ".[capture]" # + Playwright, to film a real browser UI
144
+ pip install -e ".[tts]" # + Piper, for a local voice
145
+ pip install -e ".[mcp]" # + the MCP server (`truedemo-mcp`)
146
+ pip install -e ".[dev]" # + pytest
147
+ ```
148
+
149
+ Required external binaries are **`ffmpeg`** and **`rsvg-convert`** (Debian/Ubuntu:
150
+ `sudo apt-get install ffmpeg librsvg2-bin`). Optional: `ffprobe` (durations are read from
151
+ ffmpeg when absent), `pdftoppm`/`gs` (for filming PDFs), Chromium (Playwright), and a Piper
152
+ voice model. The extras are additive and independent — the core suite needs none of them.
153
+
154
+ `truedemo doctor` reports exactly which of these are present, and names the **missing rung**
155
+ rather than a bare "Docker: unavailable".
156
+
157
+ ## The spec and your data
158
+
159
+ A spec is data. No code executes from it; the only code that runs is the provider module you
160
+ name. The loader refuses unknown top-level keys **by name**, so a typo is an error rather than
161
+ a silently dropped section. The [spec reference](docs/authoring/spec-reference.md) opens with
162
+ all fourteen legal keys on one screen; here is the shape:
163
+
164
+ ```yaml
165
+ project: { title: …, slug: …, output: out.mp4, size: [1920, 1080], fps: 30,
166
+ min_seconds: 60, max_seconds: 120 }
167
+ story: { slug: …, title: … } # optional manifest, or a story.yaml folder
168
+ timeframe: { start: 2026-09-07, end: 2026-10-06 } # or { days: 90, as_of: … }
169
+ voice: { engine: piper, model: voice.onnx } # engine: none → declared silent cut
170
+ narration: { source: narration.md } # "## Scene N — … · mm:ss–mm:ss", spoken lines **bold**
171
+ provider: provider # provider.py: datasets, panels, stills
172
+ captures: [ … ] exec: { steps: [ … ] } environment: [ … ] charts: [ … ]
173
+ score: { src: bed.ogg, volume: 0.45, duck_db: -12.0 }
174
+ scenes: [ … ] guard: { banned: […], required: […] } style: { … }
175
+ ```
176
+
177
+ **What can be on screen.** A scene holds one or more shots, and a shot's `weight` splits the
178
+ scene's time between them. Every shot is one of `still:`, `capture:`, `chart:`, `exec:`,
179
+ `card:`, or `solid:`, and any shot may carry `motion:` or `transition:`. The
180
+ [tour](docs/guides/tour.md#what-can-be-on-screen) lists each with what it shows, and the
181
+ [spec reference](docs/authoring/spec-reference.md#scenes) has every field and default.
182
+
183
+ **Your data.** `provider.py` is a plain module named in the spec, and it is the only code a
184
+ spec can run — all project-specific knowledge lives there, which is what keeps the engine
185
+ generic:
186
+
187
+ ```python
188
+ from truedemo import panels as panel_lib
189
+
190
+ def register(): panel_lib.register("my_chart", my_chart_renderer)
191
+ def datasets(ctx): return {"trend": fetch_trend(), "totals": compute_totals()}
192
+ def panels(): return {"trend": {"kind": "my_chart", "dataset": "trend"}}
193
+ ```
194
+
195
+ Datasets are snapshotted on every build, so a later render replays them offline — and a
196
+ *degraded* one is declared in the report rather than passed off as live. Eleven panel kinds
197
+ ship with the engine. See the [provider guide](docs/authoring/provider-guide.md) and the
198
+ [panels reference](docs/authoring/panels-reference.md).
199
+
200
+ ## The studio — driving it from an agent
201
+
202
+ `truedemo-mcp` runs **separately** from the consumer's repo: the story stays in your repo, the
203
+ tool stays a tool. It is session-oriented — an agent opens a sitting, pokes at a live
204
+ environment, tries several takes, keeps the best, builds, and reads the report back:
205
+
206
+ ```
207
+ session_open ──► session_exec / browser_open+browser_act ──► browser_shot ×3
208
+ │
209
+ take_select ┘
210
+ ▼
211
+ session_build ──► session_report
212
+ ```
213
+
214
+ There are **34 MCP tools** and **7 resources**. A selected take survives the build, and
215
+ budgets (wall-clock, container, step) are declared and refused rather than silently
216
+ overrun. The workflow, the tool groups, and the take/budget rules are in
217
+ [the studio reference](docs/operations/studio-reference.md); wiring the server into a client
218
+ is in the [MCP server](docs/operations/mcp-server.md) page.
219
+
220
+ For a transport-independent integration, the same work is available as a job:
221
+
222
+ ```bash
223
+ truedemo --json run plan --story examples/hello-world # {action, story, out} → one manifest
224
+ ```
225
+
226
+ ## Verification — the part that makes it worth using
227
+
228
+ `verify.json` is the point of the project. It is not a log; it is an argument about the
229
+ finished file, and every check can fail. There are **twenty kinds of check**, and a build
230
+ runs only the ones its spec can actually break — a typical build runs a dozen or so, covering
231
+ the runtime window, caption readability, frame size, audio presence, banned/required phrases,
232
+ the declared timeframe, live captures and filmed artifacts, sandboxed exec, dataset
233
+ freshness, and the honesty of every picture and camera move:
234
+
235
+ | A sample of the checks | What it establishes |
236
+ |---|---|
237
+ | `runtime within window` | The cut is inside the declared `min_seconds`/`max_seconds`. |
238
+ | `captions readable (<=2 lines, <=42 chars)` | Every cue fits on screen, two lines at most. |
239
+ | `banned phrase absent` / `required phrase present` | The script says what it must, and never what it must not. |
240
+ | `all live captures present` | Every capture the spec named is really in the film. |
241
+ | `every picture has an honest source` | Each artwork is a capture, a dataset, or a declared asset — nothing unknown. |
242
+ | `every camera move is accounted for` | `facts.motion[].mae` is **measured** from real frames; a move that did not move is reported. |
243
+ | `declared score is in the mix` | The bed really was mixed, with the measured ducking depth. |
244
+
245
+ The full table, and what each check does *not* prove, is in
246
+ [verification](docs/verification/verification.md). `provenance.json` answers a different
247
+ question — *what is this file?* — with the spec digest, the resolved timeframe, the provider,
248
+ and the tool versions that made it ([provenance](docs/verification/provenance.md)).
249
+
250
+ ## Examples in this repo
251
+
252
+ | Example | Proves |
253
+ |---|---|
254
+ | [`hello-world`](examples/hello-world/) | The smallest complete build: offline, silent, every number measured from disk. The CI fixture. |
255
+ | [`capture-kit`](examples/capture-kit/) | A real page, scripted interactions, and assert-before-shot. |
256
+ | [`terminal-demo`](examples/terminal-demo/) | A real command in a real sandbox, recorded through a PTY and filmed. |
257
+ | [`docker-demo`](examples/docker-demo/) | A real Postgres, written to and read back **inside one container**, then torn down. |
258
+ | [`movie-demo`](examples/movie-demo/) | A film with **no capture, no provider, no browser**: drawn cards, a moving camera, a score. |
259
+
260
+ CI builds each of these as an end-to-end probe on a clean runner, and one more probe drives
261
+ the MCP server through a whole sitting — on top of the unit suite.
262
+
263
+ ## Extending
264
+
265
+ The engine is meant to be extended from your provider, not edited — a new chart via
266
+ `panels.register()`, a new capture action, or a new TTS engine. The
267
+ [tour](docs/guides/tour.md#extending) lists the seams, and
268
+ [architecture](docs/foundations/architecture.md) maps every module, key type, and extension
269
+ point in one place.
270
+
271
+ ## Layout
272
+
273
+ The engine is 29 modules behind one ten-stage pipeline.
274
+ [architecture](docs/foundations/architecture.md) maps every module, the one-way dependency
275
+ graph, and the typed seams between them.
276
+
277
+ ## Docs
278
+
279
+ Docs are modular and machine-routable. Start at [`docs/README.md`](docs/README.md), or read
280
+ the route table in [`docs/modules.yaml`](docs/modules.yaml) — 26 routes across 7 modules.
281
+ An agent can fetch any doc by bare name over MCP (`truedemo_docs name="tour"`).
282
+
283
+ For the project's own record, see [`docs/plan/`](docs/plan/): [PLAN](docs/plan/PLAN.md) (now and
284
+ next), [HISTORY](docs/plan/HISTORY.md) (what happened, with evidence),
285
+ [DECISIONS](docs/plan/DECISIONS.md) (why, with alternatives), and the root
286
+ [ROADMAP.md](ROADMAP.md) (requirements and milestones).
287
+
288
+ ## Tests
289
+
290
+ ```bash
291
+ python3 -m pytest tests -q # 782 tests; the core needs no external tools
292
+ ```
293
+
294
+ The suite is written to **skip honestly**: six independent capability markers
295
+ (`needs_render`, `needs_sandbox`, `needs_docker`, `needs_playwright`, `needs_mcp`,
296
+ `needs_pre_312_python`) each probe *whether that capability is usable*, not whether the
297
+ toolchain looks complete. CI runs the lean suite on Python 3.10 and 3.12, then builds the
298
+ examples end to end.
299
+
300
+ ## What it is not
301
+
302
+ - **Not an NLE.** No timeline UI, no keyframe editing; a film is a sequence of shots.
303
+ - **Not a UI generator.** It films what runs. It will not invent an interface for you.
304
+ - **Not your data layer.** It reads; your provider owns the truth and the fetching.
305
+ - **Not a hosted service.** It runs locally and offline after install.
306
+ - **Not vendored.** Consumers point at the standalone server; the story stays in their repo.
307
+
308
+ ## Status
309
+
310
+ `1.0.0`, Apache-2.0, and honest about where it is: the engine, the studio surface, capture,
311
+ sandboxed exec, Docker environments, and movie mode are merged and verified, and CI builds
312
+ the examples end to end on a clean runner. The MCP server supports SDK 1.x and 2.x
313
+ (`mcp>=1.20,<3`). What remains is release bookkeeping — the `v1.0.0` tag and the version for
314
+ these post-1.0 milestones are still an open owner decision — and a compositor
315
+ (picture-in-picture, masks, text over live motion), which is deliberately unowned.