Skip to content

v5.5.16

Choose a tag to compare

@daiki-beppu daiki-beppu released this 06 Jul 13:20
a500d30

Added

  • feat(suno): /suno / /suno-lyric の成果物を検証する yt-suno-verify CLI を追加。suno-patterns.yaml / suno-prompts.json / suno-lyrics.json の曲数、entry name 整合、歌詞構造、genre_line 文字数を Suno UI 投入前に fail-loud で確認できるようにした(#1484
  • feat(helper): yt-collection-serveGET /server-info とチャンネル別 *.localhost の canonical URL 表示を追加し、suno-helper / distrokid-helper の popup がローカル配信元候補を保存・選択できるようにした(#1352)。既定候補は http://youtube-automation.localhost:7873 と legacy http://localhost:7873 を併存し、複数チャンネルのサーバーを label 付きで切り替えられる
  • feat(video-description): BAHMetadataGenerator.generate_timestamps() / format_timestamps_text()loops パラメータを追加した。master をループ生成しているコレクション(yt-generate-master --loop N / --target-duration)で全ループ分のチャプターを機械展開できる。2 周目以降の開始秒は 1 周目と同じクロスフェード算術(int(current + duration - crossfade))で連続計算し、各行に 1 始まりの loop フィールドを付与(2 周目以降のタイトル装飾は呼び出し側の LLM リネームに委ねる)。既定 loops=1 は従来挙動と完全互換。従来は 1 ループ分しか生成できず、全ループ展開運用のチャンネルでは毎回 LLM が手計算していた
  • feat(masterup): /masterup の playlist 取得直後に playlist 曲名 × suno-prompts.json entry name の突合ゲート yt-suno-verify-playlist を追加した。別コレクション曲の混入(unknown)・生成漏れ(missing)・clip 不足(underfilled、既定 2 clip/entry・--expected-clips-per-entry で調整)を fail-loud で検出し、非 0 終了時は Step 3(ダウンロード)へ進まない。曲名は /suno が Song Title 欄へ注入する {name_jp} — {name_en} を照合キーとし、NFKC・空白圧縮・casefold で表記ゆれを吸収する。背景: 最新セット未完のまま前後コレクションの曲が playlist に混入して master 化される事故の再発防止(下流チャンネル実例: 深夜コレクションに昼テーマ 2 ペア混入 + 深夜 2 entry 未生成)
  • feat(collection): コレクション標準骨格の検証・補完 CLI yt-collection-preflight を追加(#1494)。01-master/ 等の必須サブディレクトリ欠落を fail-loud で検知し、--fix で冪等・非破壊に補完する。骨格定義は youtube_automation.utils.collection_paths.REQUIRED_SUBDIRS に一本化し、yt-init-collection の scaffold も同定義を共有。/wf-new(init 直後の検証)/ /wf-next(フェーズ処理前のプリフライト)/ /suno-helper(サーバー起動前のプリフライト)/ /wf-status(詳細表示に骨格行)へ導線を追加し、/wf-new SKILL.md の scaffold 説明から漏れていた 01-master / 02-Individual-music の記載も修正
  • feat(thumbnail): thumbnail 候補の自動選択を標準化する yt-thumbnail-auto-select CLI を追加。TTP 参照画像プール(image_generation.gemini.reference_images.default)の特徴量 centroid に最も近い候補を 10-assets/thumbnail.jpg として自動確定する。config/skills/thumbnail.yamlimage_generation.auto_selection.enabled: true で opt-in(未設定チャンネルは従来の手動承認フローのまま)。dry-run / apply を分離し、apply 時は workflow-state.json に選択候補・distance・ランキング・実行時刻の監査ログを記録。候補なし・参照画像なし・16:9 逸脱・確定済みサムネ上書きは silent fallback せず明示エラーにする(#1370
  • feat(cli): 下流リポの automation 追従を機械実行する yt-automation-update CLI を追加(#1473)。check が実行場所・pin 形式(inline table / URL 直接参照の tag pin、main 追従、sha pin)・upstream 最新リリースとの差分を判定し exit code(0=最新 / 1=差分あり / 2=エラー)で返す。apply が pin 書き換え → uv lockyt-skills sync(skills / claude-md 両 asset)→ smoke check(yt-skills list / yt-config-migrate verify)を順に実行し、失敗ステップを明示して非 0 終了する。commit / push は責務外(スキル・人間側に残置)
  • feat(video-description): yt-title-duplicate-check に YouTube タイトル上限(100 codepoint)の前倒しチェックを追加した。超過時は --strict に関係なく exit 1 で報告し、/video-description の品質チェックにも「100 codepoint 以内」を明記。upload preflight(agents/_preflight.py)まで持ち越すと quota と時間を浪費するため、タイトル案の保存前に検出する(下流チャンネル実例: 104 codepoint でアップロード時に fail、2026-07-05)
  • feat(thumbnail): サムネイル文字フォントを安定して指定できる決定的合成経路を追加(#1332)。yt-thumbnail-text CLI が textless 背景(main.png 系)に実フォントファイル(.ttf/.otf/.ttc)を Pillow で描画し、同一の背景・テキスト・設定なら常に同一の出力を生成する。フォント指定は skill-config image_generation.gemini.thumbnail_text.overlayconfig/skills/thumbnail.yaml)で行い、フォント未設定・ファイル不在時は理由と代替手順(AI 経路へのフォールバック含む)を明示して停止する。AI プロンプト経路向けにも single_step.typography_clause を追加し、SKILL.md に 2 経路の使い分けを示す「フォント安定化」章を新設
  • feat(suno): /suno の Style プロンプト生成に entry ごとの自動バリエーション機構(style_variation、既定で有効)を追加。genre_line のコアジャンルを維持したまま texture / rhythm feel の descriptor を entry 通し番号ベースの決定的ローテーションで Style 第 1 行へ付与し、Suno V5.5 での楽曲同質化を防ぐ。先頭 entry は base style を維持(単一 entry の既存コレクションは出力不変)、style variant の明示 override がある entry は従来どおり優先、style_variation.enabled: false で従来動作へ戻せる。全 entry の Style 文が完全一致する組は生成時に警告する(#1456
  • feat(wf-next): config/channel/workflow.json::workflow.wf_next.skip_manual_mastering(default false)を新設。true のとき /wf-next のマスター音源検出(2-B)で 01-master/ に別ファイルが無くても assets.raw_master をそのまま assets.master_audio として採用し phase: "mastered" へ進む(raw=final 運用)。approval_gates.audio とは独立で、後方互換(未設定は従来通り停止)。docs/workflow-cheatsheet.md のよくある質問に設定手順を追記(#1449

Changed

  • refactor(suno-helper): 旧 Suno playlist capture 互換 route(POST /suno/playlists)と write_suno_playlists() / normalize_suno_title() / --playlist-capture-* を撤去し、DistroKid release 記録用の capture root を --distrokid-capture-root に分離(#1301
  • docs(distrokid): /distrokid-prep スキルを /distrokid-helper に改名し、参照スクリプトと docs/features の表記を同期(#1350
  • feat(video-analyze): yt-video-analyze を全尺解析から動画冒頭のクリップ窓解析(既定 900 秒 = 15 分、skill-config analysis_window_sec で上書き可)に変更。Gemini へ渡す Part に video_metadatastart_offset / end_offset)を付与して冒頭 2〜3 曲相当のみを解析し、長尺 Complete Collection の API コストを削減する。プロンプトをクリップ窓前提(bgm_arc.outro は窓内終盤、scene_timeline / editing_metrics は窓内対象)に整合させ、SKILL.md に解析後のレポート検証ステップ(窓超過タイムスタンプ・スキーマ欠落・不自然値の subagent レビュー)を追加。下流 /suno にも冒頭クリップ窓データである旨を注記した(#1495
  • BREAKING refactor(skills): /channel-setup スキルを削除し、/channel-new に統合した。詳細セットアップ/再生成(旧 Step 1〜8)は再生成モード(Step R1〜R8)、設定 push(旧 Step 9: yt-channel-settings diff / push / pull)は設定 push モードとして /channel-new が文脈から自動判別して受ける。共通テンプレート・スクリプト置き場は .claude/skills/channel-setup/references/ から .claude/skills/channel-new/references/ へ移設し、競合 branding snapshot 取得はインライン Python を廃止して references/fetch_branding_snapshot.py に一本化。yt-doctor / preflight の /channel-setup 案内文言と CLAUDE.md / AGENTS.md のスクリプト配置規約も /channel-new 系へ更新した。下流リポジトリは yt-skills sync の prune で追従する(#1461
  • refactor(automation-update): /automation-update スキルの機械的ステップ(実行場所判定 / pin 形式判定 / 差分判定 / pin 書き換え / uv lock / sync / smoke check)を yt-automation-update CLI 呼び出しに置き換え、スキルは判断ポイント(リリース要約 / local fix 衝突 / 同意取得 / コミット)専任に薄型化(#1473
  • feat(hooks): review 頻出パターンのうち機械検出可能なテスト差分ゼロと広すぎる Any / any 型注釈を lefthook pre-push で検出するゲートを追加。SKIP_TEST_DIFF=1 でテスト差分警告のみ明示 skip できるようにし、Python 未使用コード検出は既存 Ruff F 系継続、TS 未使用 export / dead code は既存 ts-knip 継続として docs に採否根拠を記録した(#1510)。その後の review-takt-default 指摘を受け、(1) any-usage-gate のスコープを src/ / tests/ / extensions/ / packages/ 限定からディレクトリ非依存の全 *.py / *.ts / *.tsx に拡大(.claude/skills/*/references/*.py 等も対象化)、(2) Python 側で from typing import Any 直接 import 経由の裸 Any 使用も検出、(3) test-diff-gate の extensions/*/lib/*.test.ts が lib 判定に先取りされテスト差分ありなのに誤警告するバグを修正、(4) test-diff-gate に対応テスト差分ありなら警告しない成功パスの契約テストを追加、(5) lefthook の「同一 hook で use_stdin を持てるコマンドは 1 つ」制約に対応するため test-diff-gate / any-usage-gate を独立コマンドから外し changelog-gate.sh 1 本のエントリポイントに統合、ブランチ削除 push のスキップを 3 ゲート共通にした(#1510、PR #1525 review-takt-default 指摘対応)。再レビューでの追加指摘を受け、(6) Python 側の Any import 検出を 1 行正規表現から python3/ast ベースに置き換え、複数行の括弧 import と as alias も解決できるようにし、(7) TypeScript 側は : any 直書きに加え Array<any> / Record<string, any> 等のジェネリック引数・union / intersection・tuple 要素の型位置 any も検出し、英語コメント・文字列リテラル中の "any" は誤検知しないよう型導入記号の直後という制約を追加、(8) SKIP_CHANGELOG=1 が CHANGELOG チェックのみを省略し test-diff-gate / any-usage-gate は継続する契約テストを追加した(PR #1525 2 回目の review-takt-default 指摘対応)。3 回目の review-takt-default 指摘を受け、any-usage-gate の検出方式を正規表現の継ぎ足しから構造的な解析へ刷新した: Python 側は .lefthook/pre-push/any_usage_python_resolver.py(新設)が ast でファイルを解析し、typing.Any 修飾アクセスと直接 import 経由の裸 Any(alias 含む)の両方を実際の参照行番号として解決するため、コメント・docstring・文字列リテラル中の "Any" は AST 上に現れず誤検知しない。TypeScript 側は型エイリアス代入(type X = any;)・型アサーション(value as any)も検出対象に加え、正規表現で候補行を検出したのち .lefthook/pre-push/any_usage_ts_line_cleaner.py(新設)で行コメント・文字列リテラルの中身を除去してから再判定することでコメント・文字列内の "any" 誤検知を防ぐ。あわせて diff の基準点(origin/main との merge-base)を changelog-gate.sh で一度だけ解決し PRE_PUSH_DIFF_BASE として子ゲートへ export することで、3 スクリプトが個別に基準を再計算する重複を解消した(PR #1525 3 回目の review-takt-default 指摘対応)
  • docs(channel-new): /channel-new(新規開設モード)の Step 7「簡易ペルソナ導出」冒頭に入口ゲートを追加し、承認済み TTP 対象(config/channel/analytics.json::benchmark.channels)が 0 件のままペルソナ生成へ進めないようにした。従来は 0 件検出が Step 9 の最終ゲートに集中しており、空のまま生成 → 差し戻しの手戻り(AI 生成コストの無駄)が発生し得た。判定基準は冒頭「TTP 完了条件(新規開設モード)」を単一ソースとして参照し、完了条件本体はコピーしない(#1517
  • feat(skills): comments-reply / pinned-comment に apply 実行前の承認ゲートを追加した(#1513)。両スキルの dry-run 確認ポイントを「全項目 PASS の場合のみ次フェーズへ進む」形式に統一し、1 項目でも FAIL なら dry-run を修正・再実行するまで apply へ進んではならない旨を明記した。comments-reply は Phase 4→5、pinned-comment は Phase 1→2 の間に承認ゲートを新設し、Claude Code では AskUserQuestion で dry-run 結果の要約を提示したうえで「投稿する」「キャンセル」の明示 2 択、AskUserQuestion 非対応環境(Codex 等)ではテキスト提示 + 明示的な承認発言待ちに統一した
  • feat(takt): lite workflow に提出前セルフ監査を組み込んだ(#1508)。過去の review-takt-default 指摘 371 件(183 レビュー)の全件分類から頻出 8 パターンを抽出した .takt/facets/policies/pre-review-checklist.md を新設し、implement step(自己監査 + 受入条件充足表の出力)と review step(独立照合、スコープ外の改善提案は verdict に影響させない)に注入。あわせて lite の plan step に instruction: plan を追加し、リポジトリ強化版 plan instruction(.takt/facets/instructions/plan.md)が lite でも注入されるようにした。運用・更新手順は docs/takt-operations.md の「提出前セルフ監査」節を参照
  • docs(skills): takt 各 step の固定コンテキスト削減のため全スキルの frontmatter description を短縮(合計 22.4KB → 10.1KB。同義トリガー語の羅列と処理手順の重複を削り、スキル間 dispatch の境界語と機械検証キーワードは維持)。あわせて CLAUDE.md(18.9KB → 7.4KB)/ AGENTS.md(14.6KB → 2.2KB、CLAUDE.md への一元化)をスリム化し、詳細を docs/architecture.md / docs/development.md / docs/takt-operations.md へ移設。.takt/config.yaml に observability(usage_events_phase)を有効化し、小〜中規模 issue 用の軽量 3-step workflow .takt/workflows/lite.yaml を追加(使い分け基準は docs/takt-operations.md)。さらに takt 内部実装(phase 分割実行)の調査に基づき、lite の review step を全 step codex 方針に合わせて codex 化し、structured_output.takt/schemas/review-verdict.json)+ deterministic when: ルールで状態判定 phase の LLM 呼び出しを排除。phase コストモデルと workflow 設計指針を docs/takt-operations.md に文書化
  • chore(distrokid-helper): manifest / package の shell を suno-helper 基準に揃えた(ADR-0016、#1359)。manifest 権限を lib/manifest.tsMANIFEST_PERMISSIONS / MANIFEST_HOST_PERMISSIONS に SSOT 化して wxt.config.ts から参照し、tests/manifest.test.ts と CI(extensions.yml)の生成 manifest 検査で drift(広域権限や suno-helper 専用権限の混入、distrokid.com 以外の host 追加)を機械検知するようにした。あわせて dependencies の caret 指定を既存解決値へ exact pin(@webext-core/messaging 2.3.0 / @wxt-dev/storage 1.2.8 / react react-dom 19.2.7)し、pnpm.onlyBuiltDependencies: ["esbuild"] を追加
  • fix(skills): collection-ideate と wf-new の SKILL.md に別々の散文で重複記述され、既に文言が食い違っていた stale/freshness 判定ロジック(相対比較・絶対鮮度の OR 条件)を references/freshness-rules.md へ単一ソース化した。文言の食い違い(片方のみ #1427 と自動呼び出し不可を記載、もう片方のみ deep-merge 手順を記載)を解消し、両 SKILL.md は挙動指示(stale なら中断 / /analytics-collect/analytics-analyze の順 / 自動呼び出し不可)を残したまま「定義は freshness-rules.md を正とする」参照に縮約した。判定規則の内容(日数・順序・OR 条件)自体は変更していない(#1519
  • docs(postmortem): postmortem/SKILL.md の症状判定閾値「チャンネル特性に応じて文脈調整可」に調整ルーブリックを追加した。調整して良い 3 ケース(新チャンネル: 公開 10 本未満 or 開設 30 日未満 → 平均比閾値を ±0.1 まで緩和可 / 直近テーマ転換: 過去平均比較は参考値とし ratio_vs_median 系を優先 / 外部要因の明確な痕跡: 該当指標の判定を保留し外部要因を先に記録)を表で固定し、該当ケースがなければ表の係数をそのまま使う(自由裁量での調整は不可)ことを明記した。Sonnet 級モデルでの週次分析の再現性低下(恣意的調整または無調整への偏り)を防ぐ(#1522
  • docs(skills): 後工程スキルが前工程の出力を暗黙に信じて実行し、入口ではなく途中で失敗する問題を防ぐため、4 箇所に「存在確認 → なければ前工程を案内して停止」ガードを追加した。channel-setup は Step 2.1 の inline Python 実行前に auth/token.json / auth/client_secrets.json の存在確認(無ければ /setup を案内)、Step 3.5 の転記前に docs/channel/channel-direction.md の存在確認(無ければ /channel-direction を案内、順序固定)を追加。channel-research は手順冒頭に Step 0 を新設し data/benchmark_*.json / data/comments_*.json / docs/benchmarks/*.md の存在確認(欠損種別ごとに /benchmark または /viewer-voice を案内)を追加。audience-persona-design は Phase 6 入口に docs/plans/viewing-scene-matrix.md の存在確認を追加し、ユーザーがスキップを明示した場合のみ「viewing-scene 未検証」と注記して確定できるようにした(#1516

Removed

  • BREAKING refactor(skills): /channel-import スキルを削除し、/channel-new の「既存チャンネル取り込みモード」として統合した(#1460、epic #1459 の 1/2)。取り込みモードは呼び出し文脈(「既存チャンネル」「チャンネル取り込み」「config 生成」「channel-import」)から自動判別し、ヒアリング → config 生成 → 検証 → OAuth / channel_id 取得 → 次ステップ案内を担う。旧 Step 0 のテンプレートリポジトリ clone 手順は廃止し、/channel-new の方式(現在のディレクトリ + /setup 前提)に整合させた。yt-doctorchannel_config ロード失敗時の案内と他スキル SKILL.md / docs/features.md/channel-import 言及も /channel-new(取り込みモード)へ更新。下流リポジトリは yt-skills sync の prune で削除に追従する

Changed

  • chore(ts-rewrite): main を feat/ts-rewrite へ追従 merge した(v5.5.15 まで、ADR-0008 の同期運用)。main 側の OAuth 契約 fix(#1330: installed ブロック必須化 + redirect_uris 検証)・TTP readiness(#1357)・DistroKid / comments config fix(#1211)を取り込み、OAuth boundary テストの fixture を新契約に追随。main が更新した lifecycle skill 文書(masterup の Suno 選曲 #1308/#1324、video-upload の予約公開 plan #1406、channel-import 統合 #1460 等)へ #965bunx tayk <cmd> 置換を再適用し、distrokid-prepdistrokid-helper rename にも追随した。main でリリース済みの [Unreleased] エントリは各リリースセクションへ整理
  • fix(ts-rewrite/cli): CLI smoke test が Bun デフォルト timeout(5000ms)に当たり REJECT される構造的問題を修正した(#1107)。subprocess smoke test に明示 timeout を設定し、重いロジック検証は createXxxCommand() を直接呼ぶ in-process テストに移行。subprocess テストは「dispatcher が subcommand を認識する」確認のみに限定。
  • refactor(ts-rewrite/core): registry の METADATA_GENERATE_REGISTRY_KEY 定数を除去し、service キーをリテラル文字列でインライン化した(#1112)。public export を減らし registry データ内に閉じ込めることで、外部からの参照結合を排除。回帰テスト registry-deps.test.ts で定数非 export を機械担保。
  • refactor(ts-rewrite/core): OAuth service(interactiveAuthService / refreshTokenService)を createService フレームに移行し、ADR-0003 の構造的不整合を解消した(#1139)。output schema を oauth/schema.ts に追加し、OAuth callback の state 生成・検証を追加。boundary テスト(input validation / success / failure)も追加。
  • refactor(ts-rewrite/core): ADR-0003 の service 境界 frame(try/catch → Result 変換)を createService ヘルパ(service-frame.ts)に抽出し、対象 10 service(analytics 5 + image / skills-sync 2 / suno-prompts / upload)を移行した(#1109)。新規 service は core function + schemas だけ書けば frame を正しく適用できるようになり、手書き frame のレビュー負荷と誤実装 fail mode を除去。
  • refactor(ts-rewrite/core): analytics 5 service の共通クエリ実行を analytics/query.ts::executeQuery に、列ヘッダー解決を analytics/columns.ts に集約し、各 service の try/catch/ok/err ボイラープレートを service.ts::createService ラッパーで除去した(#1110)。column-helpers.tscolumns.ts リネーム、analytics/query.ts / service.ts 新設。テスト追加: analytics-query.test.ts / service.test.ts
  • feat(ts-rewrite/core): Audience analytics の demographics / country / subscribedStatus 3 クエリを並列開始するよう変更した(#1115)。失敗時は開始済み retry が settled になるまで待ってから Result へ変換し、service 戻り後に API retry が残らないようにした。
  • refactor(ts-rewrite/core): analytics service の列ヘッダー解決とセル読み取り処理を analytics/column-helpers.ts に共通化し、channel / audience / traffic-source の重複実装を整理した(#1113)。
  • refactor(ts-rewrite/core): analytics のエラー分類ロジックを errors.ts に統合した(#1108)。analytics/query-error.tsaudience/service.ts 内の重複実装(toAnalyticsQueryError / shouldRetryAnalyticsQuery / parseRetryAfterSeconds)を削除し、classifyGaxiosError / shouldRetryApiQuery / RFC 7231 準拠の parseRetryAfterSeconds に一本化。ネットワークエラーの retry 漏れも修正。
  • feat(skills): dogfood ライフサイクルが踏む 12 skill(wf-new / wf-next / suno / suno-helper / masterup / videoup / video-upload / thumbnail / video-description / analytics-collect / playlist / distrokid-prep)の uv run yt-* 呼び出しを bunx tayk <cmd>(ADR-0007 rebrand / ADR-0004 単一 dispatcher)へ置換した(#965)。TS 版を pin した下流でも skill 経由で Python が実行され dogfood が始まらない問題を解消する。対象 skill の uv run 残骸ゼロを tests/test_lifecycle_skills_no_uv_run.py で機械担保。lifecycle 外の skill の置換は #966 で対応予定。

Added

  • feat(ts-rewrite/core): Traffic source 内訳(search / browse / external / suggested 等)を期間集計する collectTrafficSourceService を ADR-0003 準拠で実装した(#832)。packages/core/src/analytics/traffic-source/(schema / service / index)を新設し、Python utils/traffic_source_analytics.py Mixin を翻訳せず TS で新規記述。あわせて analytics 共通のエラー分類を analytics/query-error.tstoAnalyticsQueryError / shouldRetryAnalyticsQuery)へ集約し、video / channel / video-daily / traffic-source の各 service から参照する。quota(429)は withRetry で retry せず domain: "quota" の Result で返す
  • feat(ts-rewrite/core): resumable upload + thumbnail 圧縮 + metadata update を 1 atomic service に集約した uploadVideoService を ADR-0003 準拠で実装した(#837
  • feat(ts-rewrite/core): Per-video metrics(views / likes / comments / shares 等 8 指標)を YouTube Analytics API から収集する analytics video service を ADR-0003 準拠で実装した(#829
  • refactor(ts-rewrite/cli): generate-sunogetCwd() を遅延評価に変更し explicit path 指定時の不要な cwd 解決を排除。skills-bundle-pack.test.tsbeforeAll 共有 fixture を各テスト独立生成に改善(#1156

Fixed

  • fix(ts-rewrite/generate-master): review 指摘を受け、masterup.yaml fallback は audio 直下の generate-master 用キーだけを読み、finalize-master 用 namespace の audio.finalize.* は無視するよう修正した。JSON 優先は masterup override に限定し、inline / scalar audio、JSON root / audio shape 不備、空白 bitrate は config / validation error に統一した。registry 経由でも明示 CLI 値の presence が config override より優先されるよう schema 境界を分離した。ffmpeg の bitrate 指定では -b:a-q:a の併用をやめ、single MP3 も bitrate 契約どおり encode 経路へ統一した。generate-master public subpath から CLI 用 path resolver を外し、tayk generate-master の CLI flag 実行 smoke と関連回帰テストを追加した(#772
  • fix(ts-rewrite/core): ADR-0009(JSON-only config)との実装乖離を解消し、packages/core から yaml 依存を排除した(#1415)。suno-prompts の定義ファイルを JSON 化(suno-patterns.yamlsuno-patterns.jsonconfig/skills/suno.yamlsuno.json)し、parser を JSON.parse ベース(parseTopLevelJson / parsePatternsJson)に変更。packages/core/package.json から yaml を削除し、ADR-0009 に Status(乖離解消日)を追記した。
  • fix(ts-rewrite/core): uploadVideoService の予約公開時刻正規化で、不正な timezone offset(例: +25:99)を UTC 変換対象にしないよう修正した(#1120)。
  • refactor(ts-rewrite/core): collectVideoDailyAnalyticsService の列マッピングをハードコード位置参照から columnHeaders ベースの動的解決(requireHeaders / resolveColumnIndex)へ移行した(#1114)。API レスポンスの列順変更に対する堅牢性を向上
  • fix(ts-rewrite/core): readReferenceFiles の参照画像読み込み失敗時エラーに対象パスを含め、元の filesystem error を cause に保持するよう修正した(#1121)。
  • fix(config): channel-import/channel-new 取り込みモード)が生成する config/localizations.jsontitle_template がアップローダー許可プレースホルダ({scene_phrase} / {activities} / {scene_emoji})と不整合になり、アップロード時までエラーに気づけない問題を修正。yt-config-migrate verify が生成直後に不正プレースホルダを検出して失敗するようにし(validate_localizations_title_templates を新設)、channel-setup/references/localizations-template.json を許可プレースホルダのみの形へ更新、SKILL.md / config-generation-rules.md に許可リスト契約を明記した(#1471
  • fix(suno): ボーカルモードの tracks_per_pattern を prompt entry name 契約に反映し、/sunosuno-prompts.json を展開後 entry 数で生成、/suno-lyric / yt-suno-verify が同じ Take N 付き name と件数を検証するよう修正(#1484
  • fix(suno): yt-suno-verify/suno の final entry name 生成を共有化し、suno-patterns.yaml / suno-prompts.json / suno-lyrics.jsonname に外側 whitespace がある場合は暗黙正規化せず fail-loud するよう修正(#1484
  • fix(suno-helper): duration NG clip を playlist 対象から除外する処理を origin/main の run 完了時リロード・stale selection guard と統合し、全 clip が NG の場合に raw ID を resume state へ残さないようにした。playlistExpectedClipCount は OK clip 数として保存しつつ、resume / failed-only rerun の raw 観測期待数は保存済み OK IDs + 今回実行 entry 数から別計算し、Download 再開可否は full collection 完走状態で判定するよう分離。active feed poll は duration を取得できる feed v3 POST に揃え、bridge 由来 duration は finite non-negative number のみ受け入れる。retryPlaylist / failed-only rerun でも正規化済み OK clip ID 契約を維持し、duration 未観測 ID を新規 playlist 対象にしないようにした。manual adoption は未検証 ID として保持して retryPlaylist 側の duration filter に通し、duration_filter は snapshot / resume state に保存して popup 再 open 後も custom 閾値を維持する。download 完了 POST の expected_file_count は duration-filtered 採用数としてサーバー側 workflow-state / collection index / artifact 展開の完了判定にも反映する。suno-prompts.json 生成も collection-level duration_filter envelope へ対応し、bool / NaN / Infinity / 非 mapping を fail-loud にする(#1269
  • fix(doctor): yt-doctorttp_wf_new_readinessbranding/icon.png / branding/banner.png 不在時に、同名 stem の別拡張子や -vN 付き候補を branding/ から列挙してリネーム/変換を促すようにした。複数候補がある場合は最終版の人間確認を促し、自動判定しない旨を明示する。あわせて /channel-new/automation-update に、新規生成前の既存 branding ファイル確認手順を追記した(#1550
  • fix(masterup): /masterup Step 4.5 の本実行前に yt-suno-select-tracks --dry-runpair_selection.min_song_sec 未満候補を確認する手順を追加し、該当候補がある場合はファイル名・duration・設定中の min_song_sec を提示して続行可否を確認するようにした。あわせて dry-run stdout に短尺候補専用の [dropped_under_min] セクションと dropped_under_min 件数を追加した(#1526
  • fix(masterup): .claude/skills/masterup/SKILL.md の Step 1(コレクション特定条件)と「完了時の更新」セクションが workflow-state.json 旧スキーマ(v1、music.generated / music.approved / mp3_count / phase: "music-approved")のまま残っており、現行スキーマ(v2、.claude/skills/wf-new/references/schema.md)の assets.music_prompts / assets.raw_master / phase 定義と食い違っていた。/wf-next 側の既存検出ロジック(assets.music_prompts = true かつ assets.raw_master = null を対象とする)、および実装(apply_rain_layers.py が書き込むフィールドは assets.raw_master)と突き合わせて記述を修正し、/masterup は raw master 生成 + assets.raw_master 記録までを担い phase は遷移させない(raw_mastermaster_audio 確定後の "mastered" 遷移は /wf-next の責務)旨を明記した。現行スキーマに対応フィールドが存在しない mp3_count は削除した(#1521 の実装中に副次的に発見。ドキュメントのみの変更でコード変更なし)
  • fix(video-analyze): analysis_window_sec を API 呼び出し前に bool ではない正の整数として検証し、不正な channel override(0 / 負数 / 文字列 / bool / null)が Gemini VideoMetadata.end_offset へ流れないよう fail-fast にした。解析に使った窓幅は JSON の analysis_window_sec / analysis_scope と Markdown レポートに保存し、レポート検証 Step 3 には Gemini 生成物を untrusted data として扱う境界指示を追加。data/video_analysis を読む下流 skill には冒頭クリップ窓データである旨を明記した(#1495
  • fix(upload): yt-upload-collection --plan の公開設定表示が schedule 無効時に固定「即時公開 (public)」となり実効 privacy_status と乖離する問題を修正。実効値(config/channel/youtube.json::privacy_status)を反映して public / unlisted / private を正しく表示する。あわせて、どこからも参照されていなかった schedule_config.json::upload_settings.privacy_status をデフォルト設定・yt-channel-init テンプレート・schedule-template.json から撤去して設定箇所を youtube.json::privacy_status に一本化し、既存の schedule_config.json に残存する場合は警告ログで案内する(#1472
  • fix(upload): 単一言語チャンネル(supported_languages が 1 言語以下)で yt-populate-scene-phrases は no-op なのに upload preflight / metadata audit / localizations 生成が scene_phrases を必須要求してエラー停止する矛盾を解消。「scene_phrases が必要か」の判定を preflight_checks.requires_scene_phrases() に一本化し、単一言語では preflight・audit のチェックをスキップ、generate_localizations() は空 dict を返す(デフォルト言語のタイトル・概要欄は snippet 側で供給済みのため情報損失なし)。これにより populate → upload の通し実行が手動修正なしで成功する(#1470
  • fix(upload): upload preflight で workflow-state.json の存在と JSON parse を単一言語チャンネルでも常時検証するようにし、scene_phrases 完全性チェックだけを多言語チャンネル限定にした。/metadata-audit/wf-new の skill 手順も単一言語では翻訳 JSON 不要、多言語では scene_phrases 必須という契約に揃えた(#1470
  • fix(upload): metadata generator の workflow-state.json 読み込みも fail-loud に揃え、単一言語チャンネルでも壊れた workflow-state.json を localizations 空 dict の成功扱いで見逃さないようにした。yt-populate-scene-phrases の collection 名拒否テストに空・...・backslash 入力を追加し、利用者向け scene_phrases.md のエラーハンドリング表も単一言語 no-op / 多言語必須を明示した(#1470
  • fix(hooks): git worktree / Codex 実行環境で lefthook hook が stale な Nix store 固定パスや PATH 不在により silent skip され得る導線を修正。devShell の shellHook は trusted な flake 側 .lefthook/install.sh を呼び出して hook を毎回再生成し、生成済み pre-commit / pre-push は install 時の lefthook 絶対パス + PATH fallback の wrapper へ置き換え、どちらも解決できない場合は exit 1 で fail-closed する。wrapper 生成失敗は部分適用のまま成功扱いにせず、既存の LEFTHOOK=0 全 hook skip 契約も維持する。親 checkout / worktree それぞれの診断・再生成手順も docs に追加した(#1552
  • fix(automation-update): yt-automation-update apply の sync-only / smoke check / 失敗ステップ表示を hardened。URL 直接参照と inline table の ref 許可規則を main / 40 桁 sha / vX.Y.Z tag に統一し、--sync-only は local fix guard を通したうえで指定 skill の skills asset と claude-md を同期、未知 skill 名は副作用前に拒否、yt-config-migrate verify --target <repo> で対象 repo を固定、pyproject.toml 書き換え時の I/O 失敗もステップ名付きで報告するようにした(#1473
  • fix(thumbnail): yt-generate-image${typography_clause} 展開で malformed な image_generation.gemini.single_step / thumbnail_text.font 設定を {}"consistent" に丸めず、ConfigError として [ERROR] + exit 1 で fail-loud するようにした(#1332
  • fix(suno-helper): Suno UI 改装(2026-07-04 観測、Lyrics 欄の Lexical エディタ化)で連続実行が「Lyrics 欄が見つかりません」の FatalRunError で必ず中断する問題を修正した(#1506)。Suno Custom Mode の Lyrics 欄が textarea[data-testid="lyrics-textarea"] から div.lyrics-editor-content[contenteditable][data-lexical-editor](Meta Lexical エディタ)へ変わり、resolveFields が textarea 前提の解決で lyrics を見失っていた。対応: (1) shared/dom.ts::resolveFields の lyrics 解決に Lexical contenteditable の fallback を追加(従来の testid textarea を最優先に維持して旧 UI と併存、contenteditable="" の boolean 属性形式も許容、bbox 幅非ゼロで非マウント要素を除外)。ResolvedFields.lyricsHTMLTextAreaElement | HTMLElement | null へ拡張。(2) Style 解決は [data-testid="create-form-styles-wrapper"] 内の可視 textarea を一次識別に昇格(lyrics が textarea でなくなり「Lyrics 以外の可視 textarea」述語だけでは特定根拠が弱くなったため。wrapper 不在の旧 UI は従来述語へ fallback)。(3) 注入は新設の setLyricsValue が分岐する: textarea / input は従来の同期 setNativeValue、Lexical contenteditable は value setter を持たないため focus → execCommand("selectAll") → 200ms 待ち → DataTransfer + ClipboardEvent("paste") dispatch → 200ms 待ち の合成 paste で全置換する(Lexical 自身が購読する paste に text/plain を載せる React 互換経路)。selectAll の選択は Lexical が selectionchange 経由で内部 state に取り込むため反映が非同期で、同期実行では全選択が乗らず「置換」でなく「先頭挿入」に化ける(実機検証)— 200ms の selection 同期待ちが本質で、呼び出し側 content.ts::injectAndGenerate の lyrics 注入も await 化した。実ページで 6 entries × 12 clips の連続生成 → playlist 一括追加 → ZIP DL の完走を確認済み。Vitest に resolveFields の Lexical fallback 5 ケース / styles-wrapper 一次識別 2 ケース / setLyricsValue の経路分岐・selectAll→paste 順序(fake timer で同期 paste 禁止を pin)・instrumental 空文字 3 ケースを追加、Playwright e2e に Lexical mock(paste 横取りで全置換する contenteditable)への注入スモークを追加。
  • fix(suno-helper): #1506 の Lexical Lyrics 空文字注入を空 paste 依存から selectAll 後の delete command へ切り替え、readback が空にならない場合は Generate へ進まず fail-loud するようにした。actual run handler 経由で空 lyrics が Generate 前にクリア済みであること、非反映時に ERROR で止まること、共有 DOM mock が setLyricsValue export に追従していることをテストで固定した。
  • fix(wf-next): raw=final 採用時の /wf-next state 更新で workflow-state.json / 01-master / 採用音源の symlink を拒否し、collection 外の state 書き込みや外部音源採用を fail-closed にした。あわせて approval_gates.upload の非 boolean 拒否テストを audio と同じ契約で固定(#1449
  • fix(suno-helper): popup のチェック選択実行を旧 range 指定から indices payload に切り替え、done/failed 状態を含む選択復元・再実行で絶対 index がずれないようにした。旧 range UI 文言と helper を撤去し、content runner 側は indicesrange より優先して部分実行する(#1267
  • fix(suno-lyric): /suno-lyric がマルチ曲 collection で [Intro] [Pre-Chorus] [Bridge] [Extended Outro] を全曲一言一句同一のまま出力するのを防ぐため、Workflow に「これらの section も曲ごとの scene / persona で書き分ける」指示を明記し、Validation に曲間セクション重複のセルフチェックと書き分け直し手順を追加。suno-lyrics.json の曲間重複を機械検出する references/check_lyric_duplication.py を新設(重複検出時は exit 1、#1445
  • fix(doctor): ttp_wf_new_readiness の video_analysis 要件が benchmark top 5 のライブ配信(duration_iso == "P0D"、Gemini 取り込み不可で解析不能)により恒久的に充足不能になる問題を修正。live は期待集合から除外して次点 VOD を繰り上げ、VOD が不足する場合は母数を縮小し、除外時は message に「live 配信 N 本を除外」を明示する。yt-video-analyze --source benchmark も同じ選定で live をスキップして次点 VOD を解析する(#1462
  • fix(hooks): oxlint.config.ts / oxfmt.config.ts の ignorePatterns 対象パス(examples/** docs/** config/** など)のみを変更した commit で lefthook pre-commit の oxlint / oxfmt が「対象ファイルなし」を non-zero exit で返し必ず失敗する問題(#1428 の同型)を修正。lefthook.yml の両コマンドに --no-error-on-unmatched-pattern を追加し、対象 0 件を成功として扱うようにした(ignorePatterns のパスを exclude へ列挙する二重管理は回避、#1452
  • fix(videoup): generate_videos.shbuild_effect_filter()VIDEOUP_EFFECT=particles / bokeh を指定すると出力が緑一色または黒一色になる問題を修正。原因は 2 点あり、(1) geq=lum='...'cb/cr(色差)を省略すると環境によってデフォルト値が中央値 128 ではなく 0 になり YUV→RGB 変換で緑被りが発生する、(2) geq の直前が format=yuv420p(アルファプレーン無し)のままだと a= の不透明度式が無視され常時アルファ=255(完全不透明)になり、エフェクトレイヤーが背景を完全に覆い隠して黒一色化する。gradient エフェクトは元々 geq 直前に format=yuva420p を明示していたためこの問題を踏んでいなかった。particlesgeq=cb=128:cr=128 を追加して白い粒子を維持し、bokehcb='cb(X,Y)':cr='cr(X,Y)' で元の暖色 chroma を維持したまま、両方で noise=... の後・geq=... の前に format=yuva420p を挿入した。あわせて fx_baked.params に filtergraph stamp を含め、旧 filtergraph で焼いた cache を再利用しないようにした
  • fix(analytics-report): analytics-report/SKILL.md の「CTR 値の解釈」が「整数値 2606」から意味不明な式の否定を経て「そのまま使用」に至る自己矛盾した記述になっており、コード実態(reporting_api.pytotal_weighted / total_impressions が返す百分率 float。例 4.2 = 4.2%、tests/test_ctr_resolver.py のフィクスチャも 4.2)と食い違っていた。百分率 float である旨・表示フォーマット(小数 1〜2 桁 + %)・100 で割る/掛ける/整数再解釈の禁止・None 時の表示を一義的な規則として書き直した(#1514
  • fix(skills): 兄弟スキル間の frontmatter description 矛盾・発動キーワード衝突を解消。viewer-voice の「/audience-persona-design らの前提データを作る任意後続スキル」を「/audience-persona-design の必須入力(viewer-voice-analysis.md)を作る前工程。実行タイミングは任意」に書き換え、audience-persona-design 側の必須入力表記との矛盾を解消(audience-persona-design 側も対象ファイル名を明記して双方向に整合)。benchmark と channel-research が共に持っていた発動キーワード「競合分析」の重複は、benchmark を「競合データ収集」に変更し末尾に「収集済みデータの分析は /channel-research」の否定トリガーを追加、channel-research 側に「データ収集・更新は /benchmark(未実行なら先に案内)」を追記して解消。videoup / video-upload は名前類似で相互区別が無かったため、互いを名指しする一文(videoup→「YouTube への投稿は /video-upload」、video-upload→「動画ファイルの生成(MP3→MP4)は /videoup」)を追加した(#1515
  • fix(setup): /setup の GCP project ID 推奨値生成で、30 文字超過時の truncate 手順が 2 通りに読め、機械的に切ると末尾ハイフン(GCP 制約違反)の ID も生成されうる問題を修正。yt- prefix は必ず保持し slug 末尾から削る→切り詰め後の末尾ハイフンを追加除去する→6 文字未満や意味が読み取れなくなる場合は自動生成をやめカスタム入力を求める、の 3 段手順 + 31→30 文字の具体例で一義化した(slug 生成規則自体は無変更、#1523
  • fix(thumbnail): thumbnail/SKILL.md の TTP 差分プロンプト解説に地の文で置かれていた daiki-beppu/rjn(private リポジトリ)への実装事例参照を、「参考(オペレーター向け・実行時は無視してよい)」の引用ブロックへ隔離した。下流リポジトリの実行者はアクセスできない非公開リポジトリへの取得試行で時間を浪費する問題を防ぎつつ、jazzgak チャンネルの color_themes.<theme>.reference_image 多軸切替という参考情報自体は保持する(#1524
  • fix(suno): /suno の「### モード判定」がキーワードスキャン 1 本(「ボーカル要素が含まれていれば」)で、対象語リストの範囲が不定・否定文脈(no vocals / instrumental 等)の扱いが未定義・判断に迷った場合の手順が無く、誤判定が歌詞工程の要否と Suno UI の Instrumental ON/OFF を誤らせる高コストな手戻りを招き得た。4 段の決定木(1. 否定表現が先で他語より優先 → 2. ボーカル語の完全一致 → 3. どちらも該当なしは既定インスト → 4. 確信が持てない場合は推測せず該当箇所を提示して AskUserQuestion でユーザーに確認)に置き換え、リストが網羅ではない旨と該当なし語での歌唱可能性は必ず 4 に落とす旨を明記した(#1520
  • fix(live-clean): /live-clean Step 3 末尾の削除承認指示が「AskUserQuestion で確認、承認されるまで実行しない」という自由記述のみで、質問文の内容・選択肢・曖昧応答時の扱いが未指定だった。AskUserQuestion の質問文に削除対象の実数(「削除対象: N コレクション / M ファイル / X.X GB」)と「削除は取り消せません(rm -f による物理削除)」の警告を含め、選択肢を「削除を実行する」「キャンセル」の明示 2 択に固定(デフォルトを実行側にしない)。「削除を実行する」が明示的に選ばれた場合のみ Step 4 へ進み、それ以外の応答(自由文・別話題・無回答)はすべてキャンセル扱いとした。AskUserQuestion 非対応環境(Codex 等)ではテキスト提示 + 明示的な承認発言待ちを明記し、Step 4 の実行条件も同じ選択文言(「削除を実行する」が明示的に選ばれた場合のみ)に揃えた(#1518
  • fix(masterup): /masterup が部分ダウンロード(例: 10 曲中 5 曲失敗)を検知できず、assets.music_downloadedtrue のまま欠けた曲数でマスター音源を生成しうる問題を修正。コレクション特定 Step 直後に「DL 完全性チェック」を追加し、02-Individual-music/ の実ファイル数(mp3/m4a/wav)を期待曲数(suno-prompts.json の entry 数 × 2、インスト / ボーカル共通の算式)と突合する。不足時は music_downloaded フラグに関わらず揃っているとみなさず不足曲数を提示して停止、ファイルが 0 件なら /suno-helper 未実行として案内して停止する。期待曲数・実ファイル数の算出は /suno-helper の DL 完了判定・yt-collection-serve の status 判定と同じ既存ユーティリティ(suno_downloaded_workflow_state / suno_downloaded_archive)を再利用し、算式を二重管理しない(#1521
  • fix(wf-next): /wf-next の Suno パスが workflow-state.json::planning.music.suno_playlist_url に記録済みの playlist URL を確認せず、02-Individual-music/ のダウンロード完了実態も見ないまま常に AskUserQuestion で URL 再入力を要求していた問題を修正。URL 記録済み + 音声ファイル(mp3/m4a/wav)実在なら記録済み URL で /masterup <URL> を自動実行し、URL 記録済みだがファイル未実在ならダウンロード未完了の可能性を案内して停止、URL 未記録なら従来通り AskUserQuestion で入力を求めるようにした。wf-new/references/schema.mdplanning.music.suno_playlist_url / assets.music_downloaded のフィールド定義も追記(#1539
  • fix(skills): suno / lyria / videoup の SKILL.md に workflow-state.json 旧スキーマ(v1)由来のフィールド名(music.* / production.*)が残存し、現行スキーマ(v2、wf-new/references/schema.md が正)と食い違っていた問題を修正。/sunoyt-generate-suno 完了時の更新先を music.generated = true から assets.music_prompts = true に修正した(wf-new/SKILL.md の同フィールド更新箇所・wf-next/SKILL.md の Suno/Lyria 両パス前提条件と整合)。/lyria は Step 5「完了時の更新」が本来 /wf-next の責務である最終マスター確定(assets.master_audio)と v2 に存在しない phase: "music-approved" への遷移まで誤って自スキルの責務として記述していたため、Lyria 自身が担う assets.music_prompts = true への更新と assets.raw_master へのファイル名記録のみに縮約した。/videoup は自動検出条件を music.approved = true かつ production.generated = false から assets.master_audio が設定済み(null 以外)かつ assets.master_videonull に修正し、完了時の更新も production.generated = true から assets.master_video への動画ファイル名記録に修正した。init_collection.pyassets 初期化・apply_rain_layers.pyraw_master 更新など実装コードとの突合で v2 フィールド名を確認し、SKILL.md のみを修正(コード変更なし)

Migration

所要時間の目安: 0〜10 分

local fix 衝突注意:

  • videoup: generate_videos.shbuild_effect_filter()particles / bokeh)をこのバグの回避のためローカルパッチ済みの下流リポジトリは、yt-skills sync 取り込み後にローカルパッチを外すこと(残したままだと二重適用にはならないが、次回 upstream 側の当該箇所の変更が sync で上書きされずローカル差分として残り続ける)。取り込み後は VIDEOUP_EFFECT=particles / bokeh で一度動画を生成し、緑/黒一色になっていないか確認する。

サマリ:

  • /suno / /suno-lyric の成果物検証、playlist 突合、コレクション骨格 preflight、thumbnail 自動選択など、制作フローの fail-loud 化と自動化を追加した。
  • /channel-setup / /channel-import/channel-new に統合し、旧スキルを削除した。下流リポジトリは yt-skills sync の prune で追従する。
  • yt-automation-update CLI を追加し、下流リポジトリの pin 更新・lock 同期・skill sync・smoke check を機械実行できるようにした。
  • particles / bokeh エフェクトが緑一色・黒一色になる重大バグを修正した。エラーなく「生成完了」と表示されるため気づきにくく、該当エフェクトを使っている下流チャンネルは取り込み後に出力確認を推奨する。

追加移行メモ:

  • #775: Python yt-generate-suno 相当の導線は TS dispatcher の tayk generate-suno <collection-dir> [--json] に移行する。per-CLI bin は追加せず、core registry entry suno.generate 経由で suno-prompts.md / suno-prompts.json を生成する。
  • #772: Python yt-generate-master 相当の導線は TS dispatcher の tayk generate-master <collection-dir> [--json] に移行する。per-CLI bin / yt alias は追加せず、core registry entry masterup.generate-master 経由で Suno ダウンロード済み音声を master.mp3 へクロスフェード結合する。skill-config は config/skills/masterup.json を優先し、存在しない場合のみ既存 config/skills/masterup.yaml を fallback として読む。audio section は optional で、存在する場合は object のみ有効。未対応 YAML 行や空 scalar は config error として停止する。

What's Changed

New Contributors

Full Changelog: v5.5.15...v5.5.16