Skip to content

v0.25.0

Choose a tag to compare

@Kewton Kewton released this 19 Aug 14:59
· 46 commits to main since this release
dfa16e2

[0.25.0] - 2026-08-19

Highlight: 公開面(LP・README・チュートリアル・concept)を Vibe Engineering の軸へ据え替えた回(Epic #1807、子 Issue 10 件)。あわせて収録基盤 demo-video が worktree ID の path 由来化に追従できておらず実収録が必ず失敗する状態を復旧し、さらに fake-agent.sh が承認フレームを自動応答してしまい wait が「起きていない作業」に Completed を返す欠陥を修正した。これを直さないまま撮っていたら、全デモが「検証を通ったことになっている」だけの映像になっていた。製品側では実行契約と検証結果を Web UI に露出し(#1816)、codex 起動ダイアログへの Auto-Yes 誤応答(#1829)と CI のハング放置(#1830)を塞いだ。

Added

  • feat(demo-video): 新シーン・code card・静止画生成を追加する (#1810): contract-verify(tmux pane を収録し、send --contract → wait --verify の GATE / RESULT / 終了コードを実ゲートの実 exit code のまま映す)・attention-badge・review-screen・slash-palette・install-skill の 5 シーン、絵コンテの type: code(ファイルを組版する静止カード。source は絵コンテのディレクトリ配下に閉じることを解決後のパスで検証)、および LP / README 用の静止画 5 点を同じ隔離環境から機械生成する stills.ts(バイト予算はゲートで、収まらなければ書かずに落ちる)

  • feat(ui): 実行契約と検証結果を Web UI に露出する (#1816)

    • worktree 詳細ヘッダに状態チップを追加。 task 行を持つ worktree に限り、直近 task の
      title・TaskStatus・直近検証ランの RESULT を表示する。判定の理由(不合格ゲートの ID
      一覧まで)を aria-label と title の両方に出すため、ポインタでもスクリーンリーダーでも
      ペインを開かずに読める(docs/design/discoverability-principle.md 実装規約 1)
    • Activity Bar に「Verification」ペインを追加(スマホは Tools タブの「検証」サブタブ)。
      上段=現在の契約(title / goal 冒頭 / scope.allow / verify.gates / autoYes.mode)、
      中段=検証ラン一覧+「再検証」、下段=選択ランのゲート表(gate id / PASS・FAIL・TIMEOUT・SKIP /
      exit code / duration / logTail 末尾 40 行=CLI の MAX_PRINTED_LOG_TAIL_LINES と同値)。
      契約が無い worktree には commandmate send --contract と Skill cmate-task-contract を案内する
      空状態文を出す
    • 新しい API は 1 つも追加していない。 #1542 / #1543 / #1545 で既に在った
      GET /api/worktrees/:id/tasks、GET|POST /verify、GET /verify/runs[/:runId] の配線のみ
    • 独自のポーリングタイマーを増やしていない。 worktree 詳細が既に回している 2s/5s の
      ポーリング末尾で pollTick を上げ、useWorktreeVerification がそれに相乗りする
      (通常は 15s スロットル、running ラン中はティックごと)。ヘッダチップと Verification ペインは
      同じフックの 1 インスタンスを共有するので、2 面同時表示でも要求は倍にならない
    • en の RESULT / GATE 語彙は docs/design/verification-config.md §3.4 に合わせた
      (passed / failed / not_started、PASS / FAIL / TIMEOUT / SKIP)。
      tests/unit/i18n/verification-keys-1816.test.ts が en/ja のキー等価と語彙一致を固定する
    • docs/design/discoverability-principle.md の「運用者が読む層」に Web UI を追加し、
      実装規約に「新しい判定は CLI と Web UI の両方に出す」を追加

Changed

  • ci: 全ワークフローの全ジョブに timeout-minutes を設定する (#1830): GitHub Actions の既定タイムアウトは 360 分(6 時間)で、ci-pr.yml(11 ジョブ)/ pages.yml / publish.yml には timeout-minutes が 1 つも無かった。2026-08-19 に develop の run 32218070769 で E2E Tests が Install Playwright browser のまま 88 分ハングし、手動キャンセル → gh run rerun --failed で 6 分 47 秒で success(CDN 由来の一過性)。値は直近 12 ランの成功ジョブの実測(median / max)から max × 2・最低 10 分で決め、根拠は各ジョブのコメントに残した(E2E 6.2m/16.2m → 30、Unit Tests 12.3m/13.2m → 30、他は 10)。publish.yml は実測 median 14.3m / max 16.0m(n=10)が存在したため Issue 記載の 20 分ではなく 30 分とした。あわせて、自前で外部からバイトを取得するステップ(npm ci / npx playwright install / apt-get install / npm install / npm audit / npm publish)にステップ単位の timeout-minutes を付け、タイムアウト時に「どのステップで詰まったか」がログから読めるようにした。tests/unit/guards/workflow-timeouts.test.ts が、ジョブの付け漏れ・360 分以上の無意味な値・ジョブ上限以上の死んだステップ上限・未設定のインストールステップを赤にする

Documentation

  • docs(tutorial): 契約 → 検証ループを体験する構成へ改稿し、GIF 8 本を v0.24 の UI で撮り直す (#1813): ja / en のチュートリアルを Fork → 登録 → Skill 導入 → ゲートを赤で確認(exit 20) → 契約を渡して判定(exit 0)→ 2 契約を並列 → 証跡 の 8 ステップへ改稿し、各ステップに「エンジニアならここで何を気にするか」を 1 行添えた。旧 §1.5 の誤記(「Skill は同じ場所へ入れ直せない」= #1243 / #1244 以降は誤り、install 先が 1 ディレクトリ)を、更新フロー・.agents/skills と .claude/skills の 2 ディレクトリ・再起動が要る理由に置き換えた。GIF は 8 本 × ja / en を隔離環境で撮り直し(旧 5 本 × 2 は削除)、絵コンテを docs/images/tutorial/storyboards/01…08-*.yaml に差し替えた。demo-video スキルには verify-red と evidence の 2 シーン(cli-scene.sh --mode)を追加している。掲載する出力はすべて実機の実測値で、commandmate verify <id>(ゲート無指定)が work-evidence で exit 21 を返すこと、wait --verify は開いている契約に対してのみ契約ゲートで判定することも本文に明記した

  • LP(website/)を Vibe Engineering 軸の v2 へ作り替え (#1812): 文言は docs/design/public-messaging.md からコピーし(hero H1・定義文・4 カード・With / Without 7 行・キャプション・footer タグライン)、独自に言い換えていない。hero の静止画はループ図の inline SVG(要求 → CommandMate → Coding Agent → 検証された成果物、色はすべて CSS 変数で light / dark 追従、role="img" + aria-label)へ差し替え、ダッシュボード静止画は Gallery 先頭へ移した(og:image は引き続き同ファイル。SVG は social preview に描画されないため)。契約 → 実行 → 検証の 4 拍を実物のコード片(Kewton/commandmate-tutorial の verify.yaml / tasks/fix-shout.yaml、GATE / RESULT / exit 0)で見せる #loop 節を新設。競合 4 製品名の比較表(#comparison)は #with-without へ置換し、ナビも差し替えた。デモは docs/images/features/ の cm-11 / cm-03 / cm-01 / cm-12 の en 版を byte-for-byte コピーした 4 本に入れ替え(cmp で確認、旧 3 本は削除)、Track A のセットアップ質問を実装どおり 5 項目(CM_BROWSE_ROOTS を含む)に、チュートリアル導線を 15 分・fork してから・契約 → 検証へ直した。ガードは website/** からの禁止語一掃・定義文の逐語一致・#with-without 7 行・byte-for-byte・hero SVG の色がすべて CSS 変数であること、を追加した

  • README のデモ GIF 2 本を隔離環境の素材へ差し替え、旧 demo-*.mp4 を削除 (#1815): docs/images/demo-desktop.gif は cm-11-contract-verify.en.mp4 の 0〜18 秒(title カード → 契約 YAML → verify.yaml → 実ゲートの GATE 3 行・RESULT passed・0。outro の URL カードは README では冗長なので落とした)、docs/images/demo-mobile.gif は cm-03-never-miss-waiting.en.mp4 の respond-from-mobile(14〜18 秒)を 1280x800 の合成から 520x800 に切り抜いたもの。切り抜き幅はスマホ枠(実測 x=455..824 の 370px)ではなくテロップ帯の文字幅で決めた — 枠幅で切ると "Answer from your phone." が途中で切れ、帯の全幅(x=343..935 の 594px)で切るとスマホが 187px まで縮んで画面の字が読めなくなる(3 案を出力解像度のまま描画して比較した)。生成は .claude/skills/video-to-gif/scripts/to-gif.sh に現行バイト数をそのまま予算として渡し(desktop 1,929,059 / mobile 4,230,486)、両方とも rung 1(600px / 300px・10fps・256 色)で収まった: desktop 909,922 バイト(現行の 47%)・mobile 180,521 バイト(同 4%)、どちらも GIF89a。旧素材に映っていた私有情報(私有リポジトリ名 6 件・LAN IP 192.168.11.6:3001・旧製品名)は隔離環境の seed(cmdemo-app / wt-dark-mode / feature/demo-dark-mode)に置き換わっている。確認は代表フレームの目視だけで止めず、出荷される GIF から全 220 フレーム(desktop 180 / mobile 40)を復号して tesseract で OCR し、私有リポジトリ名・個人パス(/Users/)・プライベート IP・旧製品名・ポート番号のパターンに 1 件もヒットしないことを実測した。未参照のまま残っていた旧 demo-desktop.mp4(22,674,969 バイト)/ demo-mobile.mp4(47,195,161 バイト)は削除し、git ls-files docs/images | grep demo- を GIF 2 本だけにした。README(EN / JA)の alt は "CommandMate Desktop Demo" のような何も説明しない文字列をやめ、docs/design/public-messaging.md §5 / §6 の確定語彙に合わせて映像の内容を書いた

  • 特徴デモ 12 本を新シーンで撮り直し、product-highlights を Vibe Engineering 軸へ更新 (#1811): 絵コンテ 12 本(cm-11-contract-verify / cm-12-install-skill を新設)を書き直し、48 ファイル(12 × ja/en × gif/mp4)を隔離環境から一度に撮り直した。旧 10 本は同一 4 シーンの使い回しで、cm-01 と cm-08 の 9 秒地点が SSIM 0.970(ほぼ同一フレーム)だったのに対し、新しい 5 本(cm-01 / cm-03 / cm-09 / cm-11 / cm-12)は代表フレームの総当たり SSIM が最大 0.828・最小 0.080 まで離れている。cm-11 は tmux ペインを収録し、実ゲートの GATE work-evidence / scope / unit PASS ・ RESULT passed ・ 0 をそのまま映す。product-highlights(ja / en)は "control plane" を除いて docs/design/public-messaging.md の定義文と 4 段の梯子に差し替え、11・12 を先頭に置いた 12 見出し構成(ja / en 一致)にし、「デモが映している範囲」を実際のシーン構成へ更新した

  • cm-11(contract-verify)のテロップ帯が GATE 行に重なっていたのを直し、ja / en を再収録 (#1811): 端末シーンのペインを 32 行から 26 行に下げ、cli-scene.sh が send --contract と 1 回目の wait の機械可読な stdout(task id ・ プロンプト JSON、合わせて 8 行)をファイルへ逃がすようにした(バナーはリダイレクトごと表示するので、ペインは実行していないコマンドを映さない)。帯の位置(telop.html の margin-bottom: 7.5%)は他の 11 本のレイアウトを動かさないよう据え置き。あわせて 黙って切り詰められたテイクが合成を通ってしまう穴を塞いだ: respond 後の同期プローブが「生成中」だけを待っていたため、カセットが先に完走した回はプローブが 90 回空振りしてペインを収録途中で殺し、Response sent. で終わる映像がそのまま cut になっていた(実測: ja 版のテイクが 138 秒・GATE ブロックなし)。プローブは「プロンプトに留まっている / 生成中 / 応答なしで静止」の 3 状態を返すようにし、静止は capture キャッシュ(5s)を跨ぐ 6 回連続で受理する。recordTerminalScene は最終フレームに RESULT passed が無ければテイクを失敗させる

  • README(EN / JA)の hero・Key Features・ワークフロー節・比較表を Vibe Engineering 軸へ整合 (#1814): hero を docs/design/public-messaging.md の H1 +定義文に差し替え、Key Features 先頭に Task Contract / Verification Gates / Evidence & Metrics / Skills Catalog / 入力待ち通知の 5 行を追加し、Multi-Agent 行を 7 CLI(CLI_TOOL_IDS 実数)へ更新した。「Optional Workflow Layer」は ## Vibe Engineering workflow へ昇格して "optional, not required" を削除し、公式 Catalog Skill と send --contract → wait --verify の最小コマンド列で説明する構成に変えた(.claude/commands 表はこのリポジトリ限定である旨を明記して 1 行リンクへ縮退)。競合 4 製品名の比較表は With / Without CommandMate 表に置換。ガード tests/unit/docs/public-messaging.test.ts の対象に両 README を追加した

  • Mission / Vision を docs/concept.md / docs/en/concept.md に正本化し、公開面の文言表 docs/design/public-messaging.md を新設 (#1808): hero・定義文・4 カード・With / Without 表・デモのキャプションとテロップ・チュートリアル導入文・footer タグライン・禁止語リストを ja / en 両方で確定した。軸語 "Vibe Engineering" の一次情報(Simon Willison, 2025-10-07)を実際に確認し出典として記録。禁止語リストはガードテスト tests/unit/docs/public-messaging.test.ts の配列と一致していることを固定している

  • docs(en): verify / task / skills / hooks の英語ドキュメントを JA と同構成に整備 (#1817) — docs/en/user-guide/cli-operations-guide.md に sync / verify / task(実行契約・gateDefinitions・無人実行テンプレート)/ 読むモード / instances / マルチセッション / skill / report metrics の各節を追加し、docs/en/user-guide/skills.md と docs/en/user-guide/agent-event-hooks.md を新規作成。EN commands-guide.md に「このリポジトリ限定」の明記と全 27 コマンド表を追加し、tests/unit/docs/ja-en-heading-parity.test.ts が 4 対の ja/en で ## 見出し数の一致を固定する

Removed

  • refactor(review): 未使用の ReviewCard.tsx と 8 tests を削除する (#1824): src/components/review/ReviewCard.tsx(91 行)は #600(ed612bcf)で /review が ReviewTab へ移行した時点から呼び出し元がゼロで、tests/unit/ReviewCard.test.tsx の 8 tests は出荷 UI を何も保証しないまま緑を出し続けていた(実際 #1810 の review-screen シーンはこの testid を同期点に据えて起票され、収録が空振りした)。ReviewCard 固有の 4 挙動(?pane=terminal 付きリンク / nextAction 行 / 行ごとの ReviewStatus バッジ / インライン返信の children スロット)は ReviewTab の現行 UI で代替済みか、統合すると出荷中の UX 変更になるため取り込まない。どこも読まなくなった review.status.done を en / ja の locales/*/review.json と tests/unit/i18n/review-keys.test.ts の RUNTIME_KEYS から外し、i18n ガードが「実際に解決されるキー」だけを固定する状態へ戻した

Fixed

  • fix(codex): Auto-Yes が codex の起動ダイアログを勝手に確定してセッションが hooks レビュー画面で固着する (#1829): Auto-Yes は既定ルールで「既定の選択肢=option 1」を送るため、codex の Hooks need review に 1. Review hooks、update 通知に 1. Update now を撃っていた。前者は #1760 の 3(trust せず継続)を無効化して t/esc しか出口の無いレビュー画面へ、後者は #890 が防いでいた npm install -g @openai/codex(=codex プロセス死)へ繋がる。これらの画面の応答は CodexTool.waitForReady の担当だが、waitForReady は startSession 中しか見張らず Auto-Yes ポーラーはセッションと無関係に 2s で回り続けるため、先に見た方が勝つレースになっていた(起動後にダイアログが再出現した実セッション 2 本が固着)。修正は 3 点。(1) auto-answer 層のみで抑止 — getCodexLifecycleDialog(detection/cli-patterns.ts)が非 null の間、ポーラーは何も送らない。検出層は無変更で、detectPrompt はこれまで通り画面をプロンプトとして報告する(検出層で潰すと人間にも提示されなくなる)。抑止は capture --json の autoYes.lastSuppression(reason: agent-launch-dialog)に出る。(2) 固着からの復帰 — waitForReady が hooks 画面2/3 を検出したら Escape を最大 4 回まで送って上位へ戻す(t=trust は送らない)。(3) 誤表示の解消 — 画面2/3 は選択肢も confirm フッタも thinking マーカーも持たず running 既定に落ちていたので、STATUS_REASON.CODEX_HOOKS_REVIEW として waiting を返し NavigationButtons を出す。fixture は codex-cli 0.148.0 の実キャプチャ(3 画面)へ更新した

  • fix(demo-video): worktree ID の path 由来化に追従し、収録パイプラインを復旧する (#1809)

    • demo-video スキルは #1621 / #1644(v0.20.0)以降、実収録が必ずタイムアウトしていた。
      worktree ID が <repo>-<branch> から sanitize(basename(path))(deriveWorktreeId)に
      変わったのに、harness 側が旧規則の ID を定数で持っていたため。サーバが探す tmux セッション名は
      mcbd-claude-wt-dark-mode なのに harness は別名のセッションを作り、isSessionRunning が
      永久に false のまま全シーンが個別のタイムアウトで死んでいた(警告も出ない)
    • ID を定数で持つのをやめ、env-up.sh が seed ディレクトリから導出して state.env に書く。
      CM_DEMO_PRIMARY_WORKTREE_ID / CM_DEMO_WORKTREE_ID / CM_DEMO_LOGIN_WORKTREE_ID /
      CM_DEMO_UNSYNCED_WORKTREE_ID と、それぞれの *_PATH。record-scenes.ts の
      DEFAULT_WORKTREE_ID / UNSYNCED_WORKTREE_ID は削除し、引数・環境変数・state.env の
      いずれも与えなければブラウザを開く前に停止する(黙って旧値に落ちない)
    • 二重の安全策: 録画開始前とシーンごとの prepare で /api/worktrees の path と
      CM_DEMO_WORKTREE_PATH を突き合わせ、同じディレクトリが別 ID で登録されていたら
      その場で ID と path の両方を出して落ちる。ID はパス単位で初回登録時に凍結されるため、
      待っても直らない条件をタイムアウトまで待たない
    • 後片付けは記録駆動にした。fake-agent.sh --record-to が作成したセッション名を
      $CM_DEMO_SESSIONS_FILE に追記し、env-down.sh はその記録と state.env の ID から組んだ
      mcbd-<tool>-<id>[-<suffix>] だけを kill する。旧実装の grep -- '-cmdemo-app-' は
      新 ID の mcbd-claude-wt-dark-mode に一致せず、偽エージェントを取り残していた
    • 依存チェックに claude を追加。POST /api/worktrees/[id]/send は
      cliTool.isInstalled()(実体は which claude)が false だと 503 を返すため、未導入だと
      依存チェックではなく録画の途中でテイクが死ぬ。欠けていれば導入方法を出して収録前に止まる
    • テストは製品の規則を固定する形に置き換えた。旧テストは stale な定数どうしを突き合わせて
      いたので #1621 を素通りしていた。deriveWorktreeId を import して seed ディレクトリ名から
      ID を導き、env-scripts.test.ts は tmux スタブを介して「kill する名前」を実測する
      (実 tmux は触らない)
    • 隔離環境(HOME 差し替え・ポート 3466・$HOME/.commandmate-demo)で
      demo-video.sh --locale en を通しで完走させ、尺検証ゲートの通過を確認済み