1仕組みと動作原理
入力はチェンジログのマークダウン(週次 HyperFrames ダイジェスト形式のトピックと項目)であり、出力は `projects/active/weekly-changelog-<range>/` 配下の lint クリーンかつ seam-gate がグリーンの HyperFrames プロジェクトです。レンダリングは明示的に要求された場合のみ実行されます。
Input: a changelog .md (themes + items, like the weekly HyperFrames digest). Output: a lint-clean, seam-gate-green HyperFrames project in `projects/active/weekly-changelog-<range>/`. Render only when asked.
ロード順序は交渉不可の厳格な要件です。本スキルを実行する前に、必ず `motion-doctrine`(カーソルが存在する場合は `cut-the-curve` / `oversized-cursor` / `seam-craft` を追加)および `captions-overlay` を読み込む必要があります。本スキルはチェンジログ専用のパイプラインのみを提供し、モーションの規約は Doctrine 側が担います。
**Load first, non-negotiable:** `motion-doctrine` (+ `cut-the-curve`, `oversized-cursor` if a cursor appears, `seam-craft`) and `captions-overlay`. This skill supplies the changelog-specific pipeline; the doctrine supplies the motion law.
最重要原則は「箇条書きではなく視覚化」です。各トピックは実際の UI のアニメーションモック、または忠実なアナロジーを用いて変更の体験を演出する必要があり、テキストの箇条書きは禁止されています。また、原稿作成前に必ず `references/visualization-registry.md` のルーティングを通します(`ui-recreate` / `ui-analog` / `terminal` / `checklist` を決定)。テキストのチェックリストは最後の手段であり、真に視覚化が不可能な項目にのみ適用されます。
Every theme is illustrated by an **animated mock of the actual UI or a faithful analog** acting out the change in experience — never text bullets. Route every theme/item through `references/visualization-registry.md` BEFORE writing the script; the registry decides ui-recreate / ui-analog / terminal / checklist. Text checklist is the LAST resort, reserved for genuinely non-visual items (reliability fix lists).
ステップ 0 はブランドのブートストラップであり、必須工程です。本スキルに同梱されているフォント、BGM、スケルトンを最初にコピーし、付属の `bg-pattern.mp4` を `ffmpeg` で動画の正確な尺に合わせてループエンコードおよび減光処理し、`build-spec.md` の全文を読んでから制作に着手します。過去動画の `index.html` をコピーしたり、自前で `@font-face` を記述したり、WebGL 背景を設計しようとした場合は、直ちに中止(STOP)して現在の `index.html` を削除し、スケルトンからやり直す自己チェックルールが定められています。
**Do this before writing any composition HTML. Skipping it always produces a video that looks like a similar project you built before, NOT this skill's brand — that's the single most common way this skill goes off-brand.**
再生時間と項目数のバジェットは厳格な数値目標です。全体で 45〜60 秒、オープニング ≤2 秒、エンディング ≤3.5 秒、4 つのトピックはそれぞれ約 9〜12 秒とします。各トピックで保持できる主役の視覚化は 1 つ、ナレーション項目は最大 3 つまでとし、残りはエンディングの「完全版ダイジェスト」への誘導に回します。30 項目のチェンジログであってもナレーションのビートは ≤14 に絞り込み、トピックはストーリー順(注目の新機能 → プロダクト面 → パフォーマンス → 信頼性)に配置します。
- **Budget: 45-60s total.** Title ≤2s, outro ≤3.5s, 4 themes ≈ 9-12s each. - Per theme keep ONE hero visualization + at most 3 spoken items. Everything else exists only as the outro's "full digest" pointer.
原稿は 2 層の契約(トークン行)で管理されます。ナレーションは `spoken` レイヤーを読み上げ、字幕は `display` レイヤーを描画します。すべての技術用語には `spoken` の読み方(`references/lexicon.json` 由来)を付与する必要があり、辞書に存在しない単語は推測せず、作業を止めてユーザーに発音を確認し、辞書に追加しなければなりません。
conversational register, every technical term carrying a `spoken` phonetic form from `references/lexicon.json` while `display` keeps standard spelling. Captions show `display`; the VO reads `spoken`. Any term not in the lexicon: STOP and ask the user how it's pronounced, then add it to the lexicon.
音声は Annie のボイス ID(`330290724a1b470fb63153f34d4c0183`、変更不可「do not substitute」と明記)に固定され、HeyGen CLI(0.3.0 以上、OAuth ログイン)経由で TTS を呼び出し、必ず `vo-words.json`(spoken テキストの単語レベルのタイムスタンプ)を出力する必要があります。その後、`align-captions.mjs` を使用して spoken のタイムスタンプを display トークンにマッピングし、`captions.json`(caption-rail への入力:display の表記 + spoken のタイミング)を生成します。
node skills/hyperframes-media/scripts/heygen-tts.mjs ./vo-spoken.txt \ -o voiceover.mp3 --words vo-words.json \ --voice 330290724a1b470fb63153f34d4c0183 # Annie — lifelike (do not substitute)
単語レベルのタイムスタンプは厳格なゲートです。ステップ 5 に進む前に、`vo-words.json` が空でなく、各単語に `start`/`end` を持つ `words[]` 配列が含まれていることを確認する必要があります。空または配列が欠落している場合(TTS が音声のみを返しタイムスタンプを返さない既知のエラーパターン)、タイムスタンプなしで続行することは禁止されています。フォールバックとして、ローカルの Whisper(`uvx --from openai-whisper`)で生成済み音声の強制アライメントを行い、その結果を `align-captions.mjs` に渡します。
**Word-timings are a hard gate.** Before moving on to step 5, verify `vo-words.json` is non-empty and has a `words: [...]` array with `start`/`end` per word. If it's empty (0 bytes) or missing the array — a known failure mode when the TTS provider returns audio but no timestamp payload — DO NOT proceed without them.
字幕は必須要件です。スケルトンには `LINES` 配列を読み込む字幕レール IIFE が組み込まれており、配列を空のままにする行為はスタイルの選択ではなく「未解決のバグの納品」とみなされます。ステップ 4 で `captions.json` を生成し、ステップ 5 でそれを IIFE に貼り付け、ステップ 6 の第 5 ゲートでレンダリングされたフレームに実際に文字が存在することを確認しなければなりません。
**Captions are non-optional.** The master-skeleton ships a caption-rail IIFE that reads a `LINES` array — leaving that array empty is a shipped bug, not a style choice.
ステップ 6 のゲートは必須です。① リポジトリ内の CLI(`npx hyperframes@latest` は禁止。リポジトリ内の CLI がコンポジション契約の信頼できる唯一の情報源であるため)で `caption-zone` を指定して 26 箇所のタイムスタンプをサンプリングし、エラー 0 件で `check` を通過させること。② `seam-gate verify` が失敗 0 件であること。③ プレビューサーバーを再起動(バンドルをキャッシュするため)した上で、`__player.seek` で 3〜4 つのビートを抜き取り確認すること。④ 明示的に要求されない限りレンダリングは行わない。レンダリングした場合はフレームを抜き出して検証すること(字幕が存在すること、背景動画が黒画面でないこと、フリーズや極小フレームがないこと)。⑤ 字幕存在のハードゲート:ナレーション区間全体から 3〜4 フレームをサンプリングし、1 フレームでも字幕が欠けていればレッドとみなし、ステップ 5 の `LINES` への流し込みに立ち戻って調査すること。
5. **Caption presence gate — hard fail.** Sample 3-4 frames spread across the VO's spoken window (e.g. `t=3`, `t=15`, `t=30`, `t=42` for a 48s VO) and confirm the caption rail at `top: 990` renders visible text on each.
プロジェクト構成とトランジション(Seam)の実装手法は厳格に固定されています(`build-spec.md` が正式な設計仕様書となります)。単一ドキュメント `index.html`(シーンはスライド形式、シームはスタンプ済み)+ `ledger.json` + `script-tokens.json` + `vo-spoken.txt`/`voiceover.mp3`/`vo-words.json`/`captions.json` + `bgm.mp3` + `assets/fonts` および `assets/bg-pattern-<dur>s.mp4`。通常のシームは例外なく `cut-the-curve LEFT` を使用し、退場・入場のセレクターは `#s-*` の clip 要素ではなく内側の `.swrap`(`#w-*`)を指定する必要があります(clip 要素のアニメーションはエラーレベルの lint 違反となります)。内部のビートは `vo-words.json` の単語タイムスタンプと一致させなければなりません。
- `ledger.json`: every ordinary seam `cut-the-curve LEFT` (x, dir −1), exit and entry selectors = the inner `.swrap` wrappers (`#w-*`), NEVER the `#s-*` clip element — `gsap_animates_clip_element` is an error-severity lint rule and every stamped seam writes `autoAlpha`.
字幕レールの実装パラメータは `script-voice.md` と `build-spec.md` の双方で定義されています。1080 正方形画面において、`top:990` / `height:52` / TT Norms Pro 500 32px / ink .94 / 柔らかい暗色の `text-shadow`。単語は個々のタイムスタンプに基づき 0.12 秒でフェードインし、フレーズ単位で画面が切り替わります。重要な小さめの文字は、下部約 100px の中央エリア(`captions-overlay` のソフト回避帯)を避けて配置する必要があります。
Caption rail per `script-voice.md` (top: 990, font-size: 32px, height: 52). Mandatory — populate the master-skeleton's `LINES` array from `captions.json` before render; see SKILL.md step 5.
視覚化ルーティングテーブルの判定基準:4 つのカテゴリを優先度順に配置(`ui-recreate` が最上位、次いで `ui-analog`、`terminal`、最後が `checklist`)し、「既知の画面(Known surfaces)」テーブル(Studio エディタ / タイムライン、Inspector、Canvas + 要素、バリアントレンダリング、Storyboard、ターミナル、レンダリングパネル)および「実績のある演出(proven choreography)」を提供します。アナロジーは存在しない製品画面を捏造するのではなく、振る舞い(速度、バッチ処理、キャッシュなど)を演出しなければなりません。エンディングのチェックリストに関しては、新しいテーブルを初回モック作成時に 1 行追加し、次回以降再利用できるようにします。
The routing table for "show, don't tell". Classes, strongest first: 1. **ui-recreate** — the change lives in a surface we can faithfully mock.
リリース後の作業:S3 への配置後、指定された CloudFront ディストリビューションに対して必ず無効化(invalidation)を実行しなければなりません。これを怠ると CDN が古いファイルをキャッシュし続けます(この項目はアンチパターン表の「Don't」列に記載されており、無効化を行わないデリバリーはアンチパターンと定義されています)。
Run `aws cloudfront create-invalidation` on distribution `E2BSLVSZ7FG3U0` for the exact path after any S3 replace — CDN caches the old file otherwise
5 つのゲートの定義と実行順序は固定されています:`check`(エラー 0 件)→ `seam-gate`(失敗 0 件)→ プレビューのスポット確認 →(任意)レンダリング後のフレーム抜き取り確認 → 字幕存在のハードゲート。また、バンドルがキャッシュされるのを防ぎ、古いビルドで検証してしまう事態を避けるため、「プレビューサーバーの再起動」が明示的に義務付けられています。
3. Restart the preview server (it caches the bundle), spot-check 3-4 beats via `__player.seek` on the raw comp page.
2コア機能
3外部依存関係
| Kind | Dependency / Endpoint |
|---|---|
| cli | heygen CLI ≥0.3.0(OAuth 登录,用于 TTS;SKILL.md 以仓库内 heygen-tts.mjs 为调用封装) |
| cli | ffmpeg(背景 pattern 循环编码 + 时长压暗;渲染后抽帧核验) |
| cli | 仓库内 hyperframes CLI(check --caption-zone 与 preview;SKILL.md 明确禁止用 npx hyperframes@latest 代替) |
| cli | seam-stamp.mjs / seam-gate.mjs(来自 motion-doctrine,作为构建与验证闸门) |
| cli | aws CLI(交付后对固定 CloudFront distribution 做 invalidation) |
| package | uvx / openai-whisper(备用强制对齐:下载包与模型,仅当 TTS 未返回词级时间戳时) |
| network | 产物期 CDN 引用:骨架 HTML 引 jsdelivr 的 GSAP(浏览器端拉取,执行期不外发) |
| package | 上游/兄弟 skill 依赖(被指名加载):motion-doctrine / cut-the-curve / oversized-cursor / seam-craft / captions-overlay |
4推奨統制措置と判定根拠
- scripts/: ローカルスクリプトまたはコマンドの実行: `node <SKILL_DIR>/scripts/align-captions.mjs --tokens script-tokens.json --w`
- 网络端点: 外部ネットワークへのアクセス宣言: HeyGen TTS サービス(`heygen` CLI 経由、OAuth 認証。`vo-spoken.txt` のテキストを送信して音声および単語レベルのタイムスタンプを取得し、クレジットを消費)
- 本地工作目录: ファイルの読み書きと成果物出力: プロジェクトディレクトリ `projects/active/weekly-changelog-<range>/`: `index.html`、`ledger.json`、`scrip`
5二重目の独立検証
- [discrepancy] SKILL.md Step 4 点名的仓库内 TTS 封装路径在 pin 上是否存在(照抄会不会立刻失败) — 不存在。SKILL.md 写 `node skills/hyperframes-media/scripts/heygen-tts.mjs`,并在注释里说明「the changelog-video skill runs from the hyperframes repo root, so it uses the tracked hyperframes-media TTS helper directly」;但 pin 内 skills/ 下没有 hyperframes-media 目录,全仓 heygen-tts* 唯一命中是 `skills/media-use/audio/scripts/heygen-tts.mjs`。同一过期路径还出现在 `.claude/skills/README.md`(TTS uses the tracked …)。结论:Step 4 命令按字面执行会 ENOENT,需改用 media-use 侧脚本(SKILL.md 自己留了 swap in your own path 的余地,故不算虚假声明)。
- [discrepancy] 自带 bg-pattern.mp4 / bgm.mp3 是否真的可用(Step 0 的 cp 与 ffmpeg 是否拿到媒体) — 在未拉 LFS 的检出里是 LFS 指针,不是媒体。实检:assets/bg-pattern.mp4 = 133 字节、assets/bgm.mp3 = 132 字节,内容为 `version https://git-lfs.github.com/spec/v1 / oid sha256:… / size 12817182`(mp4)与 `size 5318438`(mp3);仓库 .gitattributes 明写 `.claude/skills/**/*.mp4|*.mp3 filter=lfs`;`git cat-file -s HEAD:<path>` 亦返回 133(blob 即指针)。因此 Step 0 的 cp 与 `ffmpeg -i <SKILL_DIR>/assets/bg-pattern.mp4` 在未 git lfs pull / 未装 git-lfs 的环境会失败或产出坏文件(本工作副本的 git 甚至没有 lfs 子命令)。这是 pin 检出相关的真实差异,不是文档错误——但照本文档流程跑的人必须先确保 LFS 已拉取。
- [ok] 「字幕非可选」是否真有连锁校验(是否只是口号) — 三处闭环可查:① 骨架 HTML 里确有读 LINES 的字幕 IIFE(`const LINES = /* paste captions.json lines … */ [];` 与 #cap-line 容器、tl.set/tl.to 逐词淡入);② SKILL.md Step 5 给出把 captions.json 贴进 IIFE 的具体写法;③ Step 6 第 5 道闸要求跨旁白采样 3-4 帧确认字幕可见,并点名 Jul 13-20 v4 的失败。口号有实现支撑。
- [ok] align-captions.mjs 的行为是否与 script-voice.md 的描述一致 — 脚本注释与实现一致:tokens {lines:[{id,tokens:[str|{display,spoken}]}]} + words [{text,start,end}] → captions.json {lines:[{id,end,w:[[display,start],…]}]};贪婪 consume 支持「一个 display token 覆盖多个 spoken 词」;用 norm(去非字母数字)+ Levenshtein close 做模糊匹配;有 MISMATCH 计数并 `process.exit(mismatches ? 1 : 0)`。无网络、无子进程,只 readFileSync ×2 + writeFileSync ×1。
- [ok] check 的 --caption-zone 与 preview 缓存提醒是否自洽(是否存在互相矛盾的验收) — Step 6 第 1 条用仓库内 CLI 跑 caption-zone(x0=0;y0=.90;x1=1;y1=1;severity=error,26 个 seek 点)拿 0 error;第 3 条要求重启预览服务后再用 __player.seek 抽查——两处不冲突(前者静态闸、后者运行期抽查),且都与 build-spec 的「字幕轨 top:990(=1080×0.9167,落在 .90–1 带内)」一致。
- [discrepancy] Stage ground 与本 skill 骨架是否一致(跨 skill 一致性) — seam-craft / cut-the-curve 教义要求把不透明底色刷在 #root(`#root { background: var(--canvas-deep, var(--canvas, #000)) }`)。本 skill 的 master-skeleton.html 实测把底色放在 `html, body { background: #0a0c0b }`,#root 只有 data-* 属性、没有 background 声明;#root 内首个子元素是满幅 bg-video(track0)+ scrim。对本骨架而言白闪仍被 body 底色挡住(body 也是不透明深色),观感风险低;但与教义字面要求的形式不一致,且未用 --canvas-deep/--canvas 变量(该变量在 pin 内零命中)。记录为形式差异,不改档位。
- [ok] CloudFront invalidation 是否只是可选建议(影响档位判断) — 它写在 Anti-patterns 表的「Don't」列:`Delivered without CloudFront invalidation` → `Run aws cloudfront create-invalidation on distribution E2BSLVSZ7FG3U0 …`。即「交付却不做 invalidation」被定义为反模式,属交付流程的必需步骤而非可选花絮——这是判橙(触碰用户云凭据)的依据。
- [ok] 是否存在被忽略的其他外发(例如字体/CDN 在构建期拉取) — 字体是本地 woff2(5 个文件实检非 LFS 指针,约 488KB),build-spec 明确要求 `local @font-face with format('woff2') embeds at render`;唯一 CDN 引用是 master-skeleton 的 jsdelivr GSAP(产物期,浏览器端)。未发现构建期遥测、上报或未知端点。
6結論
f474b43e1565756e…