captions-overlay
Overlay doctrine for the embedded-captions workflow — the caption MODEL (drop / rail / embed) and the rule that captions are an OVERLAY composited on top of the film, never a reserved bottom band you shift content up to avoid. Load when adding captions/subtitles to a talking-head or launch video, when deciding whether a phrase should be dropped, ride the verbatim rail, or be promoted to a scarce embedded climax, when laying out a composition that will carry captions (do NOT reserve a keep-out band), or when centering a composition on the true frame center under captions. Quotes the rail+embed model from embedded-captions and constraint #13 (captions overlay, keep-out band retired) from the product-launch-video scene agent. Applies ON TOP of embedded-captions.
1How It Works & Mechanism
The doctrine fuses two rules into one: (1) The caption model (every spoken sentence has only three fates: drop / rail / embed, where embed is a scarce, 'earned' climax); (2) The overlay law (caption lines are an overlay composited 'on top of' the film, not a reserved area, so content must never be shifted up or given a dead margin).
Two ideas combine here. First, the **caption model** — every spoken phrase is `drop`, `rail`, or `embed`, and embed is the scarce earned peak, not the default. Second, the **overlay law** — a caption line is composited ON TOP of the film as an overlay; it is NOT a reserved zone, so you never shift content up or leave a dead band to "make room" for it.
Scarcity is a hard constraint: rail carries the vast majority of text, embed ≤1/beat, never adjacent or in the same frame, separated by ≥ one beat; short videos typically have one embed, long explainers about one per section. 'Embedding every word' is a common mistake.
**The rail carries most of the text; embed is the scarce, earned peak** — ≤1 per beat, never two adjacent/co-visible, spaced ≥ a beat apart. A short clip → usually one embed; a long explainer → ~one per section. Embedding every word is the common mistake.
The verifiable expression of the overlay law is 'compose around the true vertical center': y = H/2 (540 for landscape, 960 for portrait), and content can be drawn all the way to the canvas bottom; 0.42×H plus a bottom dead zone is a bug, not a fix.
- **Center the composition on the TRUE vertical center — y = H / 2** (landscape 540, portrait 960). Do not shift content up to "make room" for captions; a composition centered at 0.42 × H with a dead lower band is the bug, not the fix. - Content may extend to the canvas bottom.
The only retained soft avoidance: do not place small, critical readable text (URL line, legal copy, secondary subtitles) right in the bottom ~80px center zone; large graphics, cards, and environmental elements under captions are fully allowed.
**One soft courtesy rule:** avoid parking _critical small readable text_ (a URL line, a legal line, a sub-caption) exactly in the bottom ~80px center span where the caption line sits — the overlay would fight it. Large imagery / cards / ambient content under the captions is fine; the caption skin is designed to read over content.
Machine gates are deprecated: the legacy captions.mjs keepout check has been retired; readability of captions over content is now judged visually via finalize snapshot QA.
- There is no machine keep-out gate (the old `captions.mjs keepout` check is retired). Finalize snapshot QA judges caption-over-content legibility visually.
The relationship with the upstream skill is 'additive' rather than 'merged': this doctrine applies ON TOP of embedded-captions; do not expect the upstream skill to absorb it.
> **Overlay doctrine — supplements the upstream `embedded-captions` skill. Applies ON TOP of it; do not expect it folded into the upstream skill.**
Invocation timing (trigger conditions) is specified in the description: when adding captions to talking-head or launch videos, deciding whether a phrase is drop / rail / embed, laying out compositions that will host captions (and NOT reserving a keep-out band), and centering compositions to the true frame center under captions.
Load when adding captions/subtitles to a talking-head or launch video, when deciding whether a phrase should be dropped, ride the verbatim rail, or be promoted to a scarce embedded climax, when laying out a composition that will carry captions (do NOT reserve a keep-out band), or when centering a composition on the true frame center under captions.
2Core Capabilities
3External Dependencies
| Kind | Dependency / Endpoint |
|---|---|
| package | 上游 skill 依赖(被本教义叠加):embedded-captions(rail+embed 模型出处)与 product-launch-video 的场景/finalize 代理(约束 #13) |
| cli | 已退役的 captions 检查入口(仅在文中被点名为「不再存在」的检查名,本目录不含该脚本) |
4Recommended Governance & Evidence
- SKILL.md: Pure prompt directives and rule text; no script execution or external side effects
5Second-Pass Verification
- [ok] 是否真的没有任何可执行物(green 档的关键前提) — rglob 全量列举:只有 `.claude/skills/captions-overlay/SKILL.md` 一个文件;无 scripts/、无 assets/、无 references/。全文无 shebang、无 ```bash 块。
- [ok] 是否含隐藏的网络外发(域名/端点) — `https?://` 在本文件零命中;无 curl/npx/CLI 调用语句。被点名的 `captions.mjs keepout` 是「已退役」的历史检查名,本目录并不含该文件(全量清单已证)。
- [discrepancy] meta.official_desc 是否与 frontmatter 原文一致 — 本 SKILL.md 的 description 是**未加引号的 plain scalar**,正文里含 `constraint #13 (...)`——YAML 把空格后的 `#` 当注释起点,`yaml.safe_load` 因此只解析到 `…embedded-captions and constraint`,丢掉后半段(解析长度 643 vs 原文该行 782 字符)。为避免展示层出现半句话,本 JSON 按**原文逐字**保留完整 description(含 `#13 (captions overlay, keep-out band retired) … Applies ON TOP of embedded-captions.`),该串在源文件中逐字可命中。此为上游 frontmatter 的书写瑕疵,非本 skill 的行为差异。
- [ok] 「验收靠人眼」是否被误读为「无验收」 — 原文两条并存:`There is no machine keep-out gate … Finalize snapshot QA judges caption-over-content legibility visually.` 与底部 ~80px 的软避让规则。结论:有验收,但验收方式从机器闸门改为快照目视——第一遍表述准确。
- [ok] 与上游 embedded-captions 的关系是否有事实依据 — SKILL.md 开篇 blockquote 与 description 双重声明 ON TOP 关系;引用的 rail+embed 与 constraint #13 均标注了出处(embedded-captions / product-launch-video scene agent),未见与上游冲突的改写。
6Verdict & Scenarios
4983e91a90bd624b…