Repository navigation
v0.39.0
[0.39.0] - 2026-09-19
Highlight: ナビゲーションの作り直しと画面遷移の刷新が中心のリリース。Home 画面と Assistant Chat を廃止し、サイドバー上端をリポジトリ/セッション/レビューの画面移動ナビに置き換えた。あわせて
AppShellを root layout へ引き上げたことで、ナビを押してもシェルが作り直されなくなった(サイドバーのスクロール位置・ホバー中の並び・ローカル state が保たれる)。遷移中のスピナーもメイン領域の中央に収まり、フルリロードのような見え方が解消している。更新まわりでは、PC の右上に「Update v{版}」ボタンが出て、更新後に「新機能と改善」を日英で表示するようになった。
Added
-
test(e2e): 画面遷移中フォールバックの高さを実寸で固定する E2E テストを追加 (#2693): ルート共通のローディング表示(
RouteLoading)がメイン領域を満たし縦中心に配置されること、スマホで下部ナビに重ならず利用可能領域の中央に来ること、および高さ auto の親でも 192px 以上の高さを維持することを、page.routeによる RSC 遅延とgetBoundingClientRectの実寸測定で固定する E2E テストを追加。 -
feat(ui): サイドバーにエージェント(インスタンス)1 つ=1 行の「セッション」表示を追加 (#2656): サイドバーの「表示」セレクトに 3 つ目の選択肢「セッション」を追加し、ブランチ単位ではなくエージェント(インスタンス)単位で 1 行ずつ並べるようにした。行は
buildSessionRows()がブランチのcliStatus(roster 全員+roster 外で稼働中のインスタンス)から作り、ドットはブランチの集約ではなくそのインスタンス自身の状態を出す(終了済みは「アイドル (終了)」)。並びはsortSessionRows()が状態(STATUS_PRIORITY昇順=承認待ちが先)を常に先にし、次に選んだ並び順を使う(並び順が「ステータス」のときだけ、状態の段が向きに従う)。エージェントごとの最終活動時刻は API に無いので「更新日時」はブランチのupdatedAt。行を押すと/worktrees/<id>?instance=<instanceId>へ移動し、詳細画面が roster 到着後に 1 回だけそのインスタンスを選ぶ(PC はヘッダーのインスタンス選択と同じ経路でトークン付きに分割へ配り、スマホは先に表示中へ加えてから選ぶ)。処理後はrouter.replaceでinstanceだけを URL から外す(他のクエリは保持)。ViewModeはVIEW_MODESから導出する形に変え、保存値の検証はisValidViewModeに一本化した。grouped/flatの中身・保存キー・ブランチ行のクリック・既存 testid は変更なし。 -
feat(release): リリース手順に release-notes/<X.Y.Z>.json の作成と検査を追加 (#2652): アプリ内の「新機能と改善」ダイアログ(#2651)が読む日英の要約ファイルの作成手順、除外規則、形式検査テストを
/releaseスキルとリリースガイドに追加した。CHANGELOG の節を書いたあとに、利用者が画面や CLI で気づく項目だけを平易な日本語と英語のプレーンテキストで 1 文にし、#2646 の形式(release-notes/<X.Y.Z>.json)で保存してtests/unit/release-notes/release-notes-files.test.tsで検査する手順を 2-2b として新設した。また、2-4 の git add と変更ファイル数の説明を 5 ファイルに更新し、手順の順序や規則を検証するtests/unit/docs/release-notes-skill.test.tsを追加した。 -
feat(ui): 更新後に「新機能と改善」ダイアログで変更点を出す (#2651): 画面を開いたとき、
localStorageのcommandmate.lastSeenAppVersionと bundle のNEXT_PUBLIC_APP_VERSIONを比べ、上がっていればGET /api/app/release-notes?from=&to=(#2646)のノートをModalで表示する新規src/components/common/WhatsNewDialog.tsxを追加し、AppShellの PC・スマホ両分岐で<VersionMismatchBanner />の直後にマウントした。文言は UI の言語(ja / en)に追従し、ノートはプレーンテキストとして描く(Markdown / HTML として解釈しない)。閉じたときに現在の版を保存し、初回・版の下がり・壊れた保存値は保存だけして何も出さず、取得に失敗したときは保存せず次回に再試行する。あわせてappApi.getReleaseNotes(from, to)とReleaseNotesResponse型をsrc/lib/api-client.tsに、common.whatsNew.*の 8 キーをlocales/{ja,en}/common.jsonに追加した。VersionMismatchBannerの位置・文言とappApiの既存関数は変更なし。 -
feat(app-update): 同梱リリースノート
release-notes/<X.Y.Z>.jsonとGET /api/app/release-notesを追加 (#2646): 更新直後に出す「新機能と改善」(#2651)を UI の言語(ja / en)で出せるように、版ごとの利用者向け要約を日英のプレーンテキストで持つファイルをパッケージに同梱し(package.jsonのfilesへrelease-notes/を追加。日本語のみのCHANGELOG.mdはこれまでどおり同梱しない)、「ある版からある版までに入った変更」を返す API を足した。src/lib/app-update/release-notes.tsのparseReleaseNote(raw, expectedVersion)は版・日付・{ ja, en }・件数(各 30)・文字数(500)の規則を 1 か所で判定し、1 つでも反すればそのファイルごと捨てる(知らないキーは返り値に含めない)。readReleaseNotesBetween(from, to, rootDir = process.cwd())はreaddirの結果のうち^\d+\.\d+\.\d+\.json$に合う通常ファイル(512 KiB 以下)だけを開き、from < v <= toを新しい順に最大 20 件返す(クエリの値でパスを組み立てないので traversal が届かない。ディレクトリとシンボリックリンクはlstatで除外)。「ノートが無い」と「読めなかった」は区別し、パスが無い(ENOENT/ENOTDIR)は[]、それ以外の I/O 例外(EACCES/EIO)は throw して route が 500 を返す。GET /api/app/release-notes?from=&to=はどちらかがX.Y.Zでなければ 400、from >= toはファイルを読まずに{ notes: [] }、全応答にCache-Control: no-storeを付け、認証は従来どおり middleware に任せる(AUTH_EXCLUDED_PATHSには入れない)。実際のノートファイルは #2652 の手順で次のリリースから作るため、release-notes/が無い間 API は常に{ notes: [] }を返す。同梱ファイルが実行時に黙って飛ばされることがないよう、名前・JSON・規則・版・シンボリックリンク・大きさの 6 種の陰性対照つきの検査(tests/unit/release-notes/release-notes-files.test.ts)を追加した。 -
feat(worktree): アクティビティバー最下部に設定メニューを追加し /more の見出しを辞書化 (#2645): PC のブランチ画面のアクティビティバー最下部に歯車ボタン(
ActivityBarSettingsMenu)を配置し、設定(/more)・スキル(/skills)・テーマ・言語・GitHub・ログアウトをまとめたメニューを追加。あわせて/moreの見出しをcommon.nav.more、説明文をcommon.settings.pageDescriptionから取得するように辞書化。 -
feat(sidebar): サイドバー上端を画面移動ナビにし要対応件数をレビュー行に集約 (#2644): サイドバーヘッダーにリポジトリ(同期ボタン含む)、セッション、レビュー(要対応件数チップ付き)のナビゲーションリスト(sidebar-nav)を追加し、表示切替と並び替えを独立したコントロール行(sidebar-list-controls)へ移動、「ブランチ」見出しと独立した要対応ピルを削除。
-
feat(release): CHANGELOG 断片(changelog.d/)の検証・集約スクリプトを追加 (#2640): 並列 PR での CHANGELOG.md 競合を防ぐため、Issue ごとの断片ファイル(
changelog.d/<Issue番号>.md)を扱うscripts/changelog-fragments.mjs(check/preview/apply)と仕様ドキュメントchangelog.d/README.mdを追加。 -
feat(orchestrate): 契約検証にunit-relatedゲートを追加 (#2639):
/orchestrateの検証(wait --verify)で、変更に関係するテストとリポジトリのファイルを読むテストだけを実行するunit-relatedゲート(scripts/run-related-unit-tests.mjs)を既定に追加。テスト全体の実行をCIに任せることで、委任完了待ちの時間を短縮。
Changed
-
refactor(navigation): 画面ナビの遷移手段を TransitionLink と useViewTransitionRouter に統一 (#2684): サイドバーのナビ行を素の
next/linkからTransitionLinkへ置き換え、コマンドパレットのルータをuseRouterからuseViewTransitionRouterへ変更することで、ヘッダーや設定画面と同様に View Transitions によるクロスフェード遷移に統一。 -
feat(worktree): PC の入力欄を手動リサイズ時も内容に応じて自動伸縮させ、保存値は拡大方向の下限として扱うよう変更 (#2681): PC の composer において、手動リサイズで保存された高さを固定高さではなく「下限(floor)」として扱うように変更。内容が下限より短ければ下限まで縮み、長ければ
COMPOSER_AUTO_MAX_HEIGHT_PX(160px)まで内容に追従して自動伸長する。呼び出し側のmaxHeight上限を描画と CSS の両方に適用し、上限変化時も追従するよう修正。 -
refactor(assistant): Assistant Chat のサーバー側を削除 (#2655): #2649 で画面を消したあと呼び出し元が無くなっていた API 7 本(
src/app/api/assistant/{conversation,current-output,messages,session,start,terminal,tools}/route.ts)、src/lib/assistant/の 10 モジュール、src/lib/polling/assistant-conversation-poller.ts、src/lib/db/assistant-conversation-db.tsを削除し、@/lib/dbからその関数・型の再 export を外した。tmux 直参照の allowlist は恒久除外 12 → 7・段階解消 16 → 15(合計 28 → 22)に、sanitizeEnvForChildProcessの呼び出し元は 6 → 5 に縮み、それぞれ.eslintrc.jsonと件数を固定するガードテストを実態へ合わせた。DB テーブル(assistant_conversations/assistant_messages/assistant_session_states/assistant_executions)とマイグレーション v28〜v30 は v1.0 まで残す(削除は #2657)ためCURRENT_SCHEMA_VERSIONは 61 のまま、既存 DB はそのまま起動できる。削除した API へのリクエストは Next の既定どおり 404 になる。返答の保存経路(src/lib/assistant-response-saver.ts)と__global__のセッション管理は別モジュールなので影響しない。 -
feat(ui): アップデートの状態をアプリ全体で持ち、PC の右上に「Update v{版}」ボタンを出す (#2654): 更新確認・更新の状態遷移(
idle/confirming/starting/updating/no-restart/timeout/error)・再起動待ちを新しいAppUpdateProvider(AppProvidersのConfirmProviderの内側)へ移した。確認は起動時と 60 分ごと(idleのときだけ)に走り、失敗やdegradedでは前回の結果を保つ。PC のブランチ画面ヘッダーと上部ナビに「Update v{版}」ボタンが出て、情報モーダルを開かずに更新を始められる(global / npx は確認ダイアログ、それ以外はリリースページ。更新中は「更新中…」、no-restart/timeout/errorは押すと従来のバナーをモーダルで出す)。スマホは info タブのバッジとバナーのまま変わらない。あわせて、情報モーダルで「今すぐアップデート」を押した直後にモーダルを閉じると再起動待ちが止まり、更新が終わってもページが再読み込みされない不具合を修正(Modalが閉じると子を unmount するため、バナーの中にあった ping ループごと消えていた)。src/hooks/useUpdateCheck.tsは廃止し、VersionSection/UpdateNotificationBanner/useWorktreeDetailControllerはuseAppUpdate()を読む。 -
feat(ui): スマホのブランチ画面で、左上をサイドバー開閉にし、Home ボタンを削除する (#2653): Home 画面の廃止(#2658)に伴い、モバイルヘッダー(MobileHeader)の左上にあった Home ボタンを削除してサイドバー(ブランチ一覧)ドロワーを開くメニューボタンに置き換え、右上は検索ボタンのみにしてタイトルが中央に来るようレイアウトを調整した。コントローラーおよび MobileHeaderProps から不要になった
onBackClick/handleBackClickおよびuseRouterを削除。 -
feat(sidebar): サイドバーの表示切替と並び替えを文字で表示 (#2648): 表示切替をアイコンからセレクト(リポジトリ/ブランチ)へ、並び順を文字トリガーへ、並び替えの向きを矢印から文字(新しい順/A→Z/要対応が先など)へ変更し、2列のグリッド(sidebar-list-controls)に配置した。
-
feat(ui): PCブランチ画面ヘッダーからホームボタンと区切り線を削除する (#2647): Home 画面の廃止(#2658)に伴い、PC のブランチ画面ヘッダー(DesktopHeader)左端にあった「ホーム」ボタンと区切り線を削除し、状態ドットから始まるように変更した。
-
feat(ui):
/(Home)のダッシュボードを廃止し、最後に開いたブランチへ移動するようにした (#2643):/はダッシュボード(概要見出し・セッション概要・最近のセッション・ToDo・クイックアクション)を描かず、共有キャッシュ(useWorktreesCacheContext)の読込完了後にrouter.replaceで行き先を決める。移動先はlocalStorage['commandmate.lastOpenedWorktreeId'](ブランチ画面を開いたときに端末ごとに記録。サーバーには送らない)が非表示リポジトリを除いた一覧にあればそのブランチ、無ければ/sessions。ポーリングで一覧が更新されても移動は 1 回だけ。初回読込中はスピナー、取得失敗で一覧が空ならエラーと再試行ボタン、取得に成功して一覧が空なら初回ガイド(OnboardingChecklist)・「ブランチがありません」・「リポジトリを追加」リンクを出して移動しない(空状態の判定はrepositoriesではなく一覧で行う。repositoriesはgetRepositoriesによる worktrees の集計なので「未登録」と「登録済み・worktree 0 件」を区別できない)。あわせてuseWorktreesCacheの成功時のsetIsLoading(false)を一覧と同じstartTransitionに入れ、「isLoading=falseかつ一覧が空」のコミットが挟まって/がリポジトリ 0 件の画面を一瞬出すのをなくし(失敗時はcatchで即時)、失敗後に一覧が空のまま再取得している間はisLoadingをtrueに戻す。ログイン後の移動先・PWA のstart_url・ヘッダーのロゴはいずれも/のままで、この振り分けで行き先が決まる。Home 専用のHomeHeading/HomeQuickActions/HomeSessionSummary/RecentSessionsList/SessionOverviewTile/TodoWidgetと、それらだけが使っていたhome.jsonのキー(title/running/waiting/sessionOverview.*/sessionSummary.*/recentSessions.*/todo.*)を削除した。 -
feat(ui): ナビから「ホーム」「チャット」を外し、
/moreを「設定」に改名。スマホ下部ナビに「ブランチ」ボタンを追加 (#2642): Home 画面と Assistant Chat の廃止(#2658)に向けて、PC 上部ナビ(Header.tsx)を「セッション / リポジトリ / レビュー・レポート / 設定」の 4 項目に、スマホ下部ナビ(GlobalMobileNav.tsx)を「ブランチ / セッション / レビュー / 設定 / 検索」の 5 枠に変更し、コマンドパレットのナビ候補からhome/chatを削除した(保存済みの Recent に残っていてもNAV_ITEMS.findが外すため表示されない)。ロゴは/へのリンクのまま。スマホではブランチ画面(/worktrees/*)以外にブランチ一覧を開く手段が無かったため、下部ナビの左端にmobile-nav-open-sidebar(ラベルcommon.sidebar.branches)を置き、useOptionalSidebarContext()でドロワーを開く(Provider が無いときはボタンのみ非表示。ドロワーとバーは同じfixed z-50でバーが後勝ちするため、ドロワーが開いている間はバーを描画せず、言語・テーマ・ログアウトの行を隠さない)。辞書はnav.homeを削除しnav.moreを「設定」/"Settings" に変更、nav.moreを借りていたリポジトリタブ帯の「…」ボタンにはrepoTabBar.overflow(ほかのリポジトリ / More repositories)を新設した。nav.chatキーと/chat本体は #2649 で削除する。 -
feat(release): CHANGELOG のエントリを changelog.d/ へ移行し、/orchestrate と /release の手順を切り替える (#2641): 並列の PR が
CHANGELOG.mdの## [Unreleased]で衝突していた(2026-09-17〜18 の run で計 7 回、手で解消)ため、## [Unreleased]にあった 16 エントリを文面を変えずにchangelog.d/<N>.mdへ移し、## [Unreleased]に空行以外の行があると落ちるガード(陰性対照つき)をtests/unit/scripts/changelog-fragments.test.tsに追加した。/orchestrateは、ワーカーにchangelog.d/<N>.mdを実装と同じコミットに含めさせ、マージ前の書き写しとエントリ数のdiff(6-4)を「PR ブランチでnode scripts/changelog-fragments.mjs checkが exit 0 で、changelog.d/<N>.mdがコミットに含まれていること」の確認に置き換えた(module-reference の断片は従来どおりオーケストレーターが一本化する)。/release(SKILL.md・templates/changelog-entry.md・docs/release-guide.md・英語版)は、check/previewで内容を確かめてからapply --version <X.Y.Z> --date <JST の日付>で節を生成し、見出しの直後に> **Highlight**:を書き足す手順に変え、applyが消した断片をgit add changelog.dでリリースのコミットに含める。 -
ci: Unit Testsジョブを4本に分割してCIを短縮 (#2638): ci-pr.yml の Unit Tests ジョブを 4 本の matrix shards (1/4〜4/4) に分割して並列実行し、集約ジョブ test-unit-result (ubuntu-latest) で結果を束ねることで CI 実行時間を短縮。cancel-pr-runs-on-close.yml のジョブ数コメントおよび orchestrate.md の並列オーケストレーション記述を更新。
-
feat(ui): ファイルツリーのアイコンを2枚重ねにする (#2616): PC の Activity Bar(スマホ横向き・タブレットも同じコンポーネント)で、ファイルツリーのアイコン(lucide
File)がメモ(StickyNote)と 20px で見分けられなかったため、ファイルが2枚重なった lucideFilesに変更。スマホ縦向きの下部タブの Files もFolderからFilesに揃えた。これまでFilesを使っていたターミナル上部の「Open Files」トグルは、ファイルツリーと同じアイコンにならないようPanelRightに変更。ラベル・Tooltip・件数バッジ・aria 属性・キーボード操作・Activity の並び順は変更なし。Activity Bar の10項目でアイコンが重複しないこと、各ボタンが描く svg(lucide-files/lucide-sticky-note/lucide-panel-right)をテストで固定した。
Removed
-
refactor(todo): Home ToDo(リポジトリ単位)の API・DB モジュール・API クライアントを削除 (#2650): #2643 で画面から外れて呼び出し元が無くなったため、
/api/todos・/api/repositories/[id]/todos/**とtodo-db.ts・todoApi・MAX_TODOS_PER_REPOSITORYを削除した。ブランチ ToDo(TodoPane/worktree_todos)とrepository_todosテーブル・マイグレーション v34 は変更なし。 -
feat(ui): Assistant Chat(
/chat)の画面側を削除 (#2649): ページ(src/app/chat/)・部品(AssistantChatPanel/AssistantMessageInput/AssistantMessageList)・API クライアント(src/lib/api/assistant-api.ts)・クライアント専用の型(src/types/assistant.ts)と、home.assistant.*・common.nav.chat(ja / en)を削除した。/chatは Next の既定どおり 404 になる(リダイレクトは足さない)。History の会話カードが使う.assistant-mdの CSS 規則は残し、.chat-mdのコメントだけ現状に合わせた。サーバー側(/api/assistant/**、src/lib/assistant/**、poller、DB モジュール)は #2655 で削除する。
Fixed
-
fix(ui): スマホで下部ナビとセーフエリアが重なってページ下端が隠れる問題を修正 (#2695): スマホで
<main>が下部ナビのために空けていた余白(pb-14= 56px)がホームインジケータなどのセーフエリア(env(safe-area-inset-bottom))を勘定に入れておらず、inset が非ゼロの端末(iOS 等)でページ内容の下端がナビに隠れる不具合を解消。ユーティリティクラス.pb-nav-safe(padding-bottom: calc(3.5rem + env(safe-area-inset-bottom, 0px)))をsrc/app/globals.cssに新設し、AppShellのモバイル<main>のパディングをpb-14から置き換えた。 -
fix(ui): 画面遷移中のスピナーがメイン領域の上端に寄る問題を修正 (#2692): ルート共通のローディング表示(
RouteLoading)のflex-1をh-fullに変更。親の<main data-view-transition="content">がdisplay: blockでありflex-1が不活性だったためメイン領域の上端 192px(min-h-[12rem])に寄って表示されていた問題を解消し、メイン領域全体の中央に配置されるよう修正。 -
fix(ui): 画面遷移中のスピナーを画面全体からメイン領域だけに収める (#2683): ルート共通のローディング表示(
RouteLoading)のmin-h-screenをflex-1 min-h-[12rem]に変更。シェルが root layout に引き上げられたことでローディングがシェルの内側(<main>)に描画されるようになり、全画面高さを保持したままではレイアウトが跳ねる問題を解消。シェルの外で使われるルートでも高さが auto の親で潰れないよう絶対値の下限(min-h-[12rem])を設け、ビューポート基準および百分率に依存しない構成にした。 -
fix(ui): 画面を移ってもサイドバーとヘッダーが作り直されないようにした (#2682): サイドバーのナビ(リポジトリ/セッション/レビュー)や歯車の設定を押すと画面全体が作り直され、フルリロードのように見えていた問題を修正。リンクの実装は正しく、原因はシェル(Sidebar / Header / main)を 9 つの
page.tsxが各自で描いていたこと——page は layout より下にあるため、ルートが変わるたびにシェルごと作り直され、サイドバーのスクロール位置・ホバー中の並び固定・シェルのローカル state が失われていた。新しいsrc/components/layout/AppShellGate.tsxを root layout(src/app/layout.tsxのAppProvidersの内側)に置き、9 つの page から<AppShell>を外した。これでシェルは一度だけ mount され、遷移で入れ替わるのは<main>の中身だけになる。/login・/offline・/proxy・/worktrees/<id>/terminal・/worktrees/<id>/files/...は従来どおりシェルなしで、判定は純関数shouldRenderShell(pathname)が持つ(前方一致はセグメント境界で見るため/loginxはシェルあり)。ファイルの移動・URL・AppShellの中身と props・useLayoutConfigの判定・各 page の中身の JSX は変更なし。シェルが root layout の内側に入るのに合わせてsrc/app/error.tsxのmin-h-screenをmin-h-fullにした(高さの二重取り対策)。シェル自身が投げた例外は、これまでの page 側 error boundary ではなく root のerror.tsxが拾うようになる。 -
fix(ui): 検索欄の狭い幅での折り返しを修正 (#2635): ファイルツリーのパネル幅が狭いときにパネル上部の検索欄(
SearchBar)で文字やボタンが折り返されて崩れる問題を修正。モード切り替え行にflex-wrap、ラベルにwhitespace-nowrap、モードボタン(mode-name/mode-content)にwhitespace-nowrap flex-shrink-0を追加し、検索語が空かつ非検索時は読み込み/クリアボタン枠(w-6)を描画しないようにして入力欄の幅を確保。 -
fix(ui): ファイルツリーの最小幅で名前が消える問題を修正 (#2634): ファイルツリーのパネルを最小(10%、ツリー幅約117px)まで狭めて深い階層を展開したとき、インデントと非伸縮要素(60px)の合計がツリー幅を超えてファイル名・ディレクトリ名の表示幅が0pxになる問題を修正。インデントの指定をインラインのpaddingLeftからCSS変数
--tree-indentに変え、行のクラスでpl-[min(var(--tree-indent),max(0.5rem,calc(100%_-_7rem)))]を適用することで、インデントの上限をツリー幅から7rem(縮まない要素60px+名前の最低幅52px)を引いた値に制限した。 -
fix(ui): ファイルツリーのツールバーの文字折り返しを修正 (#2631): PC レイアウトのファイルツリー(既定の幅 18% で約 210px、スマホ横向きで約 100px)で、ツールバーの「新規ファイル」「新規ディレクトリ」が 1 文字ずつ折り返され、アイコンも点のように潰れていた。ボタンに
whitespace-nowrap/flex-shrink-0が無く、右端のボタン群と幅を取り合っていたのが原因。ツリー(file-tree-view)をコンテナクエリの基準(@container)にし、ボタン・アイコン・Tooltip のラッパーを縮まないようにした。ラベルはツリーの幅が 360px 以上(ja でラベル 2 つと右端のボタン群が 1 行に収まる幅。FILE_TREE_TOOLBAR_LABEL_MIN_CONTAINER_PX)のときだけ表示し、それより狭いとアイコンだけになる。アイコンだけのときもaria-labelと Tooltip(ホバー・キーボードフォーカス)でボタンの意味が分かる。ツールバーと右端のボタン群はflex-wrapにし、収まらないときは縮めずに次の行へ送る。ファイル行は、名前が 1 文字まで切れていた(README.mdの横に81 B)問題も直した。各行をコンテナクエリの基準にし、インデント後に行に残る幅でメタデータ列を出し分ける(サイズ列は 176px 以上、作成日時・更新日時は 296px 以上、両方表示するときの更新日時は 416px 以上)。列が出ている間は名前に最小幅 4rem を持たせ、列の方をtruncateで縮める。値はホバーの Tooltip で確認できる。シェブロンとファイル/フォルダのアイコンも縮まないようにした。ラベルの文言、ボタンの並び、data-testidは変えていない。 -
fix(session): 作業中の copilot へ
--model付きで送ると、直後の wait が前のターンの終了で完了し、前のターンの返答が履歴に残らない問題を修正 (#2630): #2623 で/modelの前に copilot が待機状態になるまで待つ(最大 30 秒)ようになったため、その間に前のターンが終わると 2 つの不具合が起きていた。(1) 履歴のユーザー行の時刻が送信要求を受けた時刻のままで、前のターンの Stop より古くなり、wait --instance copilotがその Stop を見て、本文が copilot に届く前にCompleted (basis=hook_stop)を返していた。(2) copilot の返答を履歴に書くのはレスポンスポーラーだけ(savePendingAssistantResponseは代替画面のツールでは何もしない)なのに、前のターンを見ているポーラーが終わった画面を読む前に本文が入力され、前のターンの返答が保存されなかった。sendUserMessageの順序を「/model→ 前のターンのポーラーが返答を記録して止まるのを待つ(最大 5 秒)→ ユーザー行の時刻を決める →savePendingAssistantResponse→ 同文再送の検出 → 本文を入力」に変更した。--modelなしの送信と、待機中の copilot への--model付き送信の挙動は変わらない。単体テストは UAT の時刻を偽の時計で再現し、書いた行を実際のwaitのループ(pollWorktree)で判定する -
fix(cli-tools): copilot を
--model付きで起動すると依頼本文が実行されない問題を修正 (#2623):commandmate send <wt> "<本文>" --agent copilot --model <モデル>で copilot 1.0.85 を起動すると、/modelの後に送った本文が実行されず、wait --instance copilotは #1975 の 60 秒保留の後にbasis=scraper_readyで完了していた。原因は、copilot が起動直後にフック・スキル・MCP サーバを読み込んでいる間(入力欄の下の行が● Loading: …の間。約 3〜4.5 秒)も入力欄を表示していたこと。sendModelCommandは入力欄の有無だけで切替完了と判断して 22ms で戻っていた。読み込み中に送った/modelは読み込みが終わってから実行されるが、その後ろに送った本文は入力欄に残るか消え、UserPromptSubmit/Stopフックも発火しなかった。修正後のsendModelCommandは、ステータスバーが待機表示(/ commands · ? help)になってから/modelを送り、copilot の応答行(● Model changed from … to <id>/● Switched model to: <id>)が新しく出るまで待つ。✗ Model "<id>" is unsupported./is unavailable.が出た場合や 30 秒以内に応答が無い場合は、本文を送らずに copilot の文言を含めて送信失敗(stage: 'model')として返す。実行中のターンに/modelを送ると応答行を出さずに切り替わるため、ターンが終わるまで待ってから送る。--modelなしの送信も、読み込み中は読み込みが終わるまで待つ(実行中のターンへの送信は従来どおりすぐ送る)。Issue で疑っていたMCP Servers reloadedは起動ごとに 1 回出る表示で、/modelとは関係なかった。1.0.85 の実画面 19 枚をtests/fixtures/copilot-model-switch-2623.tsに追加した。 -
fix(test): agent-launch-plan-secrets-1933.test.ts の HOME 漏れを止める (#2622): planFor() が全 CLI の prepareLaunch() を呼ぶ際に HOME や worktreePath が隔離されておらず、agy の ~/.gemini/config/hooks.json や claude の ~/.commandmate/hooks/claude-wt-1933-*.json が実環境に書き込まれ /tmp/cm-1933-worktree にゴミが残っていた問題を、private HOME / CODEX_HOME の stub 化と一時 worktreePath の利用、afterEach でのディレクトリ削除、および afterAll での実環境 mtime / エントリ不変ガードを追加して解消。
-
fix(cli): エージェントの自己再開でターンが閉じても wait が完了と読まないようにする (#2614): Antigravity が
scheduleのタイマーやバックグラウンドのコマンドを残したままターンを閉じたとき、wait(--verifyとaskを含む)がその Stop を完了と読んでいた問題を修正。agy のStophook が payload のfullyIdle: false(agy 自身の「バックグラウンドタスクが残っている」宣言)を--detail self_resume_pendingとして relay に渡すようになり、新しい宣言stopReportsSelfResume(antigravity のみtrue)を持つソースでは、waitがその Stop を保留し、エージェントが自分で起き直してから閉じた最後の Stop で完了する。完了行はbasis=hook_stopのまま、保留したときだけheldForSelfResume=<秒>を付ける。起き直さない場合は Stop から 30 分で注記つきで完了し、--timeout/--stall-timeoutはそれより短ければ優先される。 -
fix(detection): Codex の Browser use 承認画面で状態表示と送信判定が食い違う問題を修正 (#2609): フッタが
enter to submit | esc to cancelの Codex ツール呼び出し承認フォーム(Field 1/1/1. Allow/2. Always allow/3. Cancel)を、状態 API はwaiting/prompt_detectedと表示する一方、detectCodexDialogの入口ゲートがpress enter to confirm/selectしか認めず null を返していたため、respondがprompt_no_longer_active(exit 99)で拒否され、Auto-Yes もunclassified-frameで抑止されていた。実測したフッタ行そのものだけに一致するCODEX_FORM_SUBMIT_FOOTER_PATTERN(行全体アンカー)を追加してdetectCodexDialogの入口ゲートで OR 判定し、CODEX_SELECTION_LIST_PATTERN(detect.tsの選択リスト分岐でも使う)は広げていない。esc to cancelだけ・文中への引用・回答済みブロックの scrollback は引き続き null。 -
docs(orchestrate): Phase 2.5 の copilot 指定と wait/capture の送り先表記を修正 (#2608):
.claude/commands/orchestrate.mdの Phase 2.5(バグ根本原因分析)で copilot 1.0.85 が受け付けないclaude-opus-4.6が指定されていた記述をclaude-sonnet-5に更新し、send 直後に capture で画面のモデル表記を確認する手順を追加。あわせて wait での--instance copilot抜けおよび capture での--agent表記を--instance copilotに統一。 -
fix(api): current-output の thinkingMessage をエージェント名固定から直す (#2607):
GET /api/worktrees/:id/current-output(commandmate capture --json)のthinkingMessageが文言固定だったため、Antigravity などどのエージェントのセッションでも"Claude is thinking..."を返していた(2026-09-17 に antigravity セッションで実測)。buildCurrentOutputが既存のgetCliToolDisplayName(cliToolId)で表示名を引いて"<表示名> is thinking..."(例:"Antigravity is thinking..."/"OpenCode is thinking...")を返すように修正。claude では従来どおり"Claude is thinking..."、thinkingが false のときも従来どおりnull。リポジトリ内にこの文字列を照合している呼び出し元は無く(型定義とドキュメントの claude の出力例のみ)、UI 表示にも影響しない。 -
fix(skills): orchestrate-monitor の画面判定を Antigravity のペインでも効かせる (#2606):
classify-state.shが capture のcliToolIdで目印を選び、Antigravity ではmonitor-lib.shに追加した agy 用判定(生成中 = ステータス行のesc to cancel・点字スピナー、プロンプト =↑/↓ Navigateフッター+番号つき選択肢、待機中 = 入力欄の枠)を使うよう変更。↑/↓ Navigateのある画面ではesc to cancelを生成中と読まない。上端寄せの agy ペインではrealtimeSnippetが空行ばかりになるため、realtimeSnippetとcontentの長い方から空行を除いた末尾を読む。Claude / Codex の判定は変更なし。 -
fix(test): db-migration-path のテストが、本番 DB の完全なコピーを HOME に残さないようにした (#2605):
tests/unit/db-migration-path.test.tsの 2 本は cwd と HOME を隔離せずにmigrateDbIfNeededを呼んでいた。そのため本番 DB(data/db.sqlite)がある作業ディレクトリ(/releaseが unit を回す main など)で実行するたびに、次の 2 つが起きていた。(1) 本番 DB がレガシー DB と誤認されて~/.commandmate-test-<ms>/data/cm.dbへ丸ごとコピーされる、(2)data/db.sqlite.bakが上書きされる。テストを追加した 2026-02-03 から、残骸は 1,568 個・185 GiB に達していた(既存分は手動で削除済み)。修正では、2 本を「レガシー DB が見つからない」状態(空の一時ディレクトリへのprocess.cwd()の spy、HOMEの stub、DATABASE_PATHを空にする)で呼び、migrated === falseであること、ディレクトリ作成もコピーも起きないことを assert する。あわせて、隔離した変数を関数が実際に読んでいることを示す陽性対照をtests/unit/db-migration-path-isolation.test.tsに追加した(isSystemDirectoryを sandbox の配下だけ部分 mock する。os.tmpdir()はシステムディレクトリとして拒否されるため)。両ファイルには、実際の HOME 直下の.commandmate-test-*が増えていないことを確かめるガードも入れた。src/の変更はない。 -
fix(test): Catalog から install した Skill を sync-map の分類対象から外す (#2595):
.claude/skillsおよび.agents/skills内の.commandmate-receipt.jsonを持つディレクトリを未分類ガードから除外し、receipt 保持ディレクトリがsync-map.jsonに宣言されている場合は別エラーとして検出。