Repository navigation
v0.46.0
[0.46.0] - 2026-10-14
Highlight: worktree 画面を ChatGPT 風に作り直した(Epic #3508)。見出しを 1 行にし、縦のアクティビティバーをなくして道具を見出しの右へ移し、パネルは本文の上に重ねて開く。サイドバーは 1 行の行と角丸の札になり、どの画面からでも依頼を送れる「New task」ダイアログ(⌘⇧O)を足した。あわせて、重ねた層の Esc が 1 回で下の層まで閉じる問題、チャット・履歴の検索で返答が 2 件以上だと最後の返答しか強調されない問題などを直した。
Added
-
feat(orchestrate): 整合性レビューの相手を
--instanceで選べるようにし、squash のコミットの題名を PR の題名にした (#3618):consistency-review.mjsに--instance <id>(既定codex)を追加。capture・ready 待ち・ask・run の記録(agent)・ロック(既定以外は.lock-<id>)が同じ値を使うので、Codex の「stream disconnected」のときに--cliのラッパーなしでcodex-2へ切り替えられる。--instanceを渡さなければ従来と同じ動き。merge-pr.mjsはgh pr merge --squash --subject "<PR タイトル> (#<PR 番号>)"を渡し(タイトルに(#<PR 番号>)が既にあれば二重にしない)、マージ後の develop のコミットの題名が PR の題名と一致する。fold・取り込みがあっても--pr指定でも PR の題名を使う。--instanceは alias も受け、サーバーの resolve-target で実 ID に直す(解決できなければ exit 2)。 -
feat(ui): どの画面からでもエージェントへ依頼を送る「New task」ダイアログを追加 (#3511):
Mod+Shift+O(Mac は ⌘⇧O、他は Ctrl+Shift+O。既存のショートカットと衝突しない)か、共通の開く関数openNewTask()(NewTaskContext。サイドバー・アイコン列のボタンは #3512 が置く)で、一覧画面でも worktree 画面でも開く。送り先はリポジトリ → ブランチ → エージェントで選び、表示名ではなく worktree ID+instance ID で持つ。既定は worktree 画面ならその worktree と選択中のエージェント、一覧画面なら最後に送った先で、最近の送り先 3 件をワンクリックで選べる(localStorage。読めない環境でも動く)。止まっているエージェントには「 を起動して送ります」と先に出し、送ると既存のPOST /api/worktrees/[id]/sendが起動して届ける。モデル指定は send route と同じ条件で出し分ける(copilot は稼働中でも切り替え、claude・antigravity は起動時だけ=稼働中・起動中は理由つきで無効、ほかのツールは対応していない旨を出す)。Auto-Yes は「この送信だけ」ではなく今の仕組み(instance に期間付き)のまま扱い、既に有効なら残り時間を出して変えず(期限を過ぎたらAutoYesToggleと同じ判定で無効扱いに戻す)、無効なら既定は「変えない」で、期間を選んだときだけ常に送る前に有効にする(有効化後に送信が失敗しても表示は有効のまま・再送で再び有効化しない)。409(プロンプト待ち)・400(モデル指定の拒否)・503(起動中/起動失敗)・送信失敗ではダイアログと依頼文を残したまま理由とサーバーの文を出し、送信中は ×・Esc・背景・closeNewTask()のどれでも閉じない(応答本文が届かなくても送信のタイムアウトで失敗にして閉じられる状態に戻る)。ほかのモーダル(?のヘルプ・設定・確認など)が開いている間は開かず、New task 表示中は?のヘルプも開かない(ターミナル内にインラインで出るプロンプトパネルや、最大化で隠れた分割の中身は「開いているモーダル」に数えない)。⌘↵/Ctrl+↵で送れ、送ったらそのブランチの画面へ?instance=<送った instance>(#2656 の経路)で移って送った instance を選んだ状態にし、トーストで送り先を出してクリックで元の画面へ戻る。?の一覧にも 2 つのキーを載せた。サーバー側の変更はない。
Changed
-
refactor(worktree): 描かれない・呼ばれない旧いコードを消す (#3620): #3591 以降 PC で描かれない
src/components/worktree/ActivityBar.tsx(とその単体テスト、他テストのvi.mock)、#3593 以降テストだけが使っていたclassifyHeaderInstances/isLabeledInstance(とHeaderInstanceSlot/ClassifiedHeaderInstance型)、#3594 で見出しの select が外れて描かれなくなったuseWorktreeDetailControllerのhandleWorktreeStatusChangeとWorktreeDetailDesktopのonWorktreeStatusChangeの受け渡しを削除。ActivityPaneのaria-labelledbyは以前から存在しないactivity-bar-button-*を指していたので外した(見出しの道具には id が無く、「…」へ畳まれると要素自体が無い)。画面の振る舞いは変わらない。 -
refactor(worktree): Sessions 画面とカードに残っていた進み具合の文言・色の写しを
src/lib/worktree-status.tsの読み出しに置き換え (#3619):STATUS_LABEL_KEYS/STATUS_BADGE_CLASSES(Sessions)とカードの進み具合ごとの分岐をWORKTREE_STATUS_OPTIONS/worktreeStatusLabelKey()/WORKTREE_STATUS_BADGE_CLASSESに寄せた。表示は変えない(カードの In Progress の色だけは共通定義と違うため従来のまま残した)。 -
feat(worktree): 分割が 1 つのときは最大化の状態に入れないよう入口をそろえる (#3612): 2 段目・分割の「…」メニュー・Mod+Shift+Enter のどれからも、分割 1 つでは「分割 1 を最大化中」だけの状態にならない。状態の源
useTerminalSplits.toggleMaximizeで分割 1 つ以下は最大化に入らず(解除は可)、分割が 1 つに減ったときも最大化を解除する。「…」の最大化項目は非表示にせずaria-disabledで無効にする。分割 2 つ以上は従来どおり(#2261)。 -
docs(ui): 利用者向け・設計の文書を今の worktree 画面(1 行の見出し・ヘッダー右の道具・2 段目の Verification の札・重ねて開くパネル)に合わせた (#3609): Epic #3508(#3589〜#3594)の画面変更に docs が追従していなかった箇所を ja/en の両方で直した。
docs/UI_UX_GUIDE.mdとdocs/architecture.mdは縦の全高 Activity Bar の図と説明を、見出し右のHeaderToolBar・2 段目のVerificationStatusChip・右から本文の上に重ねて開く ActivityPane(ピンで固定すると横に並ぶ)に置き換え、useActivityBarStateを今の動き(worktree ごとのキー・閉じた状態も__closed__で保存・未訪問は閉じた状態で始まる)に、キー操作を ←/→ に直した。webapp-guide.mdは最大化の場所(2 段目の操作バー・各分割の「…」・分割が 2 つ以上のときの見出し右端)、Verification の入口(2 段目の札。契約が無くても「未検証」として常に出る)、ファイルツリーとスキル・環境変数の入口(ヘッダー右の道具、狭いときは「…」)を直した。how-it-works.mdの GIF の alt からチップの位置の「ヘッダー」を外し、opencode-server-live-verification.mdにはMAX_HEADER_AGENT_PILLSが #3593 で無くなったことを書き足した。 -
feat(worktree): 進み具合(Status)をブランチ行の「…」から変えられるようにし、見出しの select を外した (#3594): サイドバーの行・タブ列の一覧・パンくずの一覧で共通の「…」(#3576 の
BranchRowActions)に Status を足し、サブメニューで Not set / Ready / In Progress / In Review / Done から選べるようにした(今の値は「Status」の右に出る)。保存はその行の worktree id でPATCH /api/worktrees/<id> { status }なので、表示中でない worktree も変えられる。選んだ値はすぐ行に出し、保存後は一覧の再取得(useWorktreesCacheのrefresh)でサイドバー・タブ列の一覧・パンくずの一覧・Sessions 画面・カードに反映、表示中の worktree なら詳細画面のコントローラが一覧の値の変化を取り込んで Info の欄にもすぐ出す。保存に失敗したら toast(「ステータスを変更できませんでした」)を出して元の値に戻す。行のデータSidebarBranchItemには CLI のstatusとは別のフィールドworktreeStatusを足した(混ぜない)。Not set 以外の行には(PC のみ。スマホの引き出しは Status のメニュー以外は従来どおりで札も点も出さない)ブランチ名の右に小さな札(上限 5.5rem・末尾省略)を出し、行の幅が 17rem 未満(既定 224px のサイドバーなど)では同じ色の点に縮めてブランチ名を優先する(文言は title とスクリーンリーダー向けに残す)。PC の見出しの進み具合の select は外し、Info の欄の select は残す。選択肢・札の色・保存関数はsrc/lib/worktree-status.tsにまとめた。同じ worktree の保存は id ごとの順番待ちで直列にし(最後に選んだ値が最後の PATCH になる)、行の「…」・Info の欄・詳細画面の保存はすべてこの経路を通る。進み具合の値は、成功した保存と一覧からの取り込みを 1 本の時計(worktree-status.tsの世代番号。保存の成功と取り込みのたびに進む)で「起きた順」に並べ、新しい方だけを使う。保存より前に始まった一覧(useWorktreesCache、外部ソースが無いときのWorktreeSelectionContextの取得・ポーリング・選択時の詳細取得)や詳細(useWorktreeDetailControllerのポーリング)の取得の応答で、後の保存を戻さない(詳細取得の開始→一覧から In Progress を取り込み→Info で Done を保存→詳細の応答、の順でも Done のまま)。行の「…」で続けて選んだときは最後の選択の保存と再取得が終わるまでその値を出し続け、先の選択の再取得が途中で届いても表示を戻さない。最後の選択は、その保存の後に始まった一覧の取得が成功したこと(useWorktreesCacheが成功時に記録する取得の世代markWorktreeListFetched/worktreeListFetchedSince。refreshは失敗しても正常に終わるため戻り値では判定しない)を確かめてから解除し、再取得が失敗したときは保存できた値を出したまま次の成功した取得で解除する。スマホは引き出しの「…」に Status が出る以外は変えていない。 -
feat(worktree): 見出しのセッションを「今のセッション+ほか N ▾++」にし、セッションの数や名前で欄の幅が変わらないようにした (#3593): PC の見出しのセッション欄を、名前付きの札(最大 4)と点(上限なし)と「+N」の一覧から、[今のセッション][ほか N ▾][+]の 3 つに作り直した(
HeaderSessionSwitcher)。今のセッションは選んでいる分割に表示しているセッションで、分割の側(TerminalSplitContainerのonSelectedSplitChange)が選んでいる分割の番号・その instanceId・各分割の instanceId を公開し、worktree 画面が active instance をこれに合わせるので、見出しの 1 個目・End・Auto Yes が同じセッションを指す。札と「ほか N ▾」は幅が固定で、ほかが 0 個のときもボタンの幅を空けておくため、同じ画面幅ならセッション 1・7・10 個、長い alias、どの状態でも欄の幅が同じ(実ブラウザ実測 332px)。一覧の行は状態の点・名前・状態・表示中の分割(Split 2 など)で、プロンプト待ちを上に寄せ、その件数をボタンに橙で出す(稼働中の光る点も「+N」と同じくボタンに出す)。モデル・費用・情報源の tooltip と「次の依頼待ち」の札は従来と同じ条件で出す(札は今のセッションの左)。一覧の最後に「Add session…」(+を開く)。行を押すと、未表示なら選んでいる分割に表示し(従来は分割 1)、ほかの分割に表示中ならその分割を選ぶ。行は分割へドラッグでき(受け側の規則は従来どおり。落とした分割が選ばれる)、ドラッグ中は一覧をpointer-events: noneにして一覧の下の分割にも落とせるようにし(Chrome はdragstart中に元要素が pointer を受けなくなるとドラッグを取り消すので 1 タスク後に適用)、外側クリック・フォーカス移動で閉じず、元の行をdragendまで残し、dragend(Esc での取り消しを含む)で一覧を閉じてフォーカスを「ほか N ▾」に戻す。キーボードでは ↓/↑ で開き、↓↑ Home End で移動、Enter で選択、Esc で閉じる。あわせて、ほかの分割で使用中のセッションを落としたときに実ブラウザではdropが起きず拒否の toast が出なかった問題を直した(dragoverのdropEffectを常にmoveにし、赤い枠で「ここは不可」を示す)。#2481 の札を畳む幅合わせは、畳むものが無くなったので見出しの左側を切り詰めるだけになった。スマホは変えていない。 一覧は画面に残る高さで max-height を決めて中をスクロールし、キーボードで選んだ行を見える位置へ送る(高さの低い画面でも最後の行と Add session… に届く)。一覧の行の tooltip は一覧より上の層に出す(Tooltipに任意のzIndexを追加。既定のz-40は不変)。Add session… は先に「ほか N ▾」へフォーカスを移してから+のフォームを開くので、フォームを閉じるとそこへ戻る。Add session… は+と同じ条件(roster がMAX_AGENT_INSTANCES)で無効になり、+と同じ文言で理由を出す。 -
feat(worktree): 分割が 1 つのとき、分割の見出しをやめて中身を 2 段目の行に入れる (#3592): 分割が 1 つのとき、分割の見出し(エージェントの選択・Terminal / Chat・モデル・費用・セッションのメモ・終了・検索・最大化・「…」)を出さず、同じ部品を 2 段目の行(
TerminalSplitContainerの操作バー)へ portal で移す。エージェントの選択・Terminal / Chat・モデル・費用・メモは Verification の札の右(split-action-bar-session)、検索・「…」は右端の History / Open Files の左(split-action-bar-pane-actions)。最大化のアイコンは 2 段目のもの(toggle-maximize-split、分割 1 つでは無効)だけにし、分割の最大化は「…」の項目に残す。2 段目ではメモが空でも小さな編集の入口(split-session-note-edit-N)を出し、エージェントの選択の tooltip にモデルと費用(それぞれのチップと同じ文字列)を載せる。分割は 2 段目の下端の線に接して上枠を消すので、1440×900・サイドバーを閉じた状態でターミナルの上の帯(タブ列を除く)は 44px+36px=80px。分割が 2 つ以上のときは各分割に 30px の見出し(split-header-N)を出す(中身は今のまま)。見出しの部品はペインの React ツリーに残したまま描く場所だけを変えるので、1 つ ↔ 2 つ以上の切り替えで分割の中身(入力の下書き・ポーリング・スクロール位置・Verification の理由)は作り直されない。2 段目の幅の調整は #3590 のuseSplitActionBarFitに乗り、移した部品の中身(モデル・費用・メモ)が変わると測り直し、狭い幅ではエージェントの選択・Terminal / Chat・メモも Verification と同じく「…」の奥へ退避する。移した部品には分割の印(data-split-index)を付けるので、2 段目のメモ欄でも Mod+Shift+M などの分割のショートカットが効く。メモの入力途中の文字はペインが持つので、1 つ ↔ 2 つ以上を切り替えても、編集の入口を押し直しても消えない。2 段目のメモ欄は置き場所(2 段目・退避パネル)とアンカーの移動に毎フレーム追従する。Verification の札は 1 回だけ描いて DOM ごと 2 段目と「…」の間を移すので、幅の調整や分割の数の変更で理由の開いた状態が消えない。理由を開いたまま札が閉じた「…」へ退避すると、理由は開いた状態のまま隠れ(画面の左上に残らない)、「…」を開くと札の下に出し直す(VerificationStatusChipの追従は札が DOM に無い・非表示のときは位置を持たず、そのあいだの「…」を押す操作で理由を閉じない)。「…」の中のエージェントの選択メニューで Esc を押すとメニューだけが閉じる(理由のポップアップも処理済みの Esc では閉じない)。スマホは変えない。 -
feat(worktree): 縦のアクティビティバーの列をなくし、道具を見出しの右のアイコンへ移す (#3591): PC の worktree 画面から縦 48px のアクティビティバー(
ActivityBar)の列をなくし、File Tree〜Env の道具を見出し(DesktopHeader)の右端のアイコン(新しいHeaderToolBar、並びと中身は今のまま)に移した。サイドバーを閉じたとき、左の縦の列はアプリのアイコン列 1 本だけになる。Verification の入口は 2 段目の Verification の札(#3590)だけにし、見出しの道具からは外した(HEADER_TOOLSはACTIVITIESからverificationを除いたもの。パネル・保存される状態・ラベルは不変)。パネルは右から本文の上に重ねて開き(#3589 の重ねる/固定/閉じる部品を左から右へ。固定したときだけ本文の右に並び、つまみを右へ引くとパネルが狭まる)、本文の幅は変わらない。1440×900 ではサイドバーの開閉どちらでも 9 個の道具がすべて見出しに並び、札と合わせて 10 個に上部から 1 クリックで届く(e2e で実測)。狭い幅では見出しの幅の調整(useDesktopHeaderFit、#2481)に段を足し、左側を切る前に後ろの道具から 1 個ずつ「…」へ畳む(2 クリック)。開いている道具が「…」に入ったときは「…」に印を出し、名前も「ほかの道具(○○ を表示中)」になる。キーボードはrole="tablist"aria-orientation="horizontal"で、←→ で移動(端で折り返し)、Home/End で端へ、Enter/Space で開閉、Tab で 1 歩で出入り(↑↓ は使わない)。「…」は ←→ の並びに入り、Enter/Space/↓ で一覧(縦の tablist)を開くと開いている道具か先頭へフォーカスが移り、Tab と ↑↓ で中を移動、Enter/Space で選ぶと一覧が閉じて「…」へ戻り、Esc は一覧だけを閉じる。パネルを Esc / × / キーボードで開いたファイルで閉じたとき、フォーカスは押した道具へ、畳まれていれば「…」へ、Verification なら札へ(札が 2 段目の「…」に入っていればそこへ)戻る。Verification の札もほかの道具と同じく開閉で、Verification を開いているときに押すと閉じ、ほかのパネルが開いているときは Verification に切り替わる。札の案内(title・aria-label・理由の本文)も押したときの動きに合わせ、Verification が開いているときは「検証ペインを閉じる」、それ以外は「検証ペインを開く」と出す(VerificationStatusChipのpaneOpen、新しいverification.chip.closeHint。スマホの札は開くだけなので今の文のまま)。道具・札(data-activity-entry)・札の退避先の 2 段目の「…」を押しても重ねたパネルの「外を押した」にはならない。2 段目の「…」の一覧と札の理由の吹き出しは処理済み(defaultPrevented)の Esc を無視するので、見出しの「…」の一覧で押した Esc はその一覧だけを閉じる。スマホは変えない。 -
feat(worktree): worktree の見出しを 1 行(44px)にし、Verification の札を 2 段目の並べ方のアイコンの隣へ移す (#3590): PC の見出し(
DesktopHeader)は 2 行の名前の欄をやめ、状態の点・worktree 名 ▾・リポジトリ名(押すと Repositories の画面へ)を 1 行に並べる(h-11、1440×900 で 44px を実測)。git の現在のブランチは worktree 名と違うときだけリポジトリ名の右に小さく出し((unknown)は今までどおり出さない)、未コミットの*と判定不能の?は今までと同じ条件で worktree 名の右に出す(ブランチ名を省いたときも出る)。メモ(description)は見出しに描かず、全文を worktree 名の tooltip に入れる(Info は不変)。Verification の札は見出しから 2 段目(TerminalSplitContainerの操作の行、split-layout-pickerと Equal / Maximize の右)へ移し、部品・押したときの動き・理由のポップアップは変えない。2 段目は枠線込み 36px にし、理由のボタン(32px)が切れない。2 段目に物を置く口はTerminalSplitContainerのactionBarItems1 か所に決めた(後続の #3591〜#3593 もここへ足す)。幅の調整(#2481)はsrc/hooks/useDesktopHeaderFit.tsに切り出し、見出しは従来どおりエージェントの札を「+N」へ畳んでから左側を切り、2 段目は札が収まらないと History / Files の文字を落としてアイコンだけにし、それでも足りなければ札を「…」ボタンの奥(<body>へ出した浮きパネル。実際の幅を測って左右とも画面内に収め、開くとフォーカスが先頭の操作へ、Escape で「…」へ戻る)へ退避し、最後に並べ方の操作を切る(History / Files・札・End・Update・Info は重ならず届く。1280px でサイドバーを開いた状態と、ファイルを開いてターミナル側を最小の 20% まで狭めた状態を e2e で確認)。PC の札の理由のポップアップは<body>へ出して画面内に収め、開いている間は札の位置に追従し(最大化のラベルが札の左に増えたときなど)、2 段目のoverflowやファイルパネル脇のターミナルのoverflow-hiddenで切れないようにした(スマホは従来の位置のまま)。最新 run の不合格ゲートの保持は札の親(useDesktopVerificationChip)でも行い、ファイルの 0 件 ↔ 1 件以上の切り替えで札が作り直されても消えない。2 段目の高さはh-9にmin-h-[35px]の下限を付け、表示サイズ「小」「極小」でも固定 px の札(34px)がはみ出さない。スマホは変えない。 -
feat(worktree): worktree 画面をパネルを閉じた状態で始め、アクティビティのパネルは本文の上に重ねて開く (#3589): 初めて開く worktree(保存値なし)では、アクティビティのパネル(File Tree など)と Message History をどちらも閉じた状態で始める(
INITIAL_ACTIVITY = null、worktree 画面専用のWORKTREE_DEFAULT_HISTORY_VISIBLE = false)。保存済みの値はそのまま尊重し、Sessions 画面のタイルの History の既定(共有のDEFAULT_HISTORY_VISIBLE = true)は変えない。アクティビティのパネルは開くと本文の上に重ねて出し、ターミナルの幅を変えない(1440×900・1 分割で、ターミナル部分はサイドバーを開いた状態 567px → 1166px、閉じた状態 650px → 1334px。パネルを開いても座標は不変)。パネルの見出しに × と固定(ピン)を置き、同じアイコンの再クリック・×・Esc(パネル内か起点のアイコンからなら固定中も)で閉じて × と Esc ではフォーカスを開いたアイコンへ戻す。外側クリックでも閉じるが、未保存の編集があるとき(Env はボタンでの行の追加・削除・候補の追加も含めて未保存と数え、保存すると閉じられるようになる)と、パネルから開いたダイアログ/メニュー(portal を含む)や開いているモーダル・ファイル一覧の右クリックメニューの操作中は閉じない(判定は New task と同じisAnyModalOpen()に、独自の ContextMenu が開いている間付けるdata-floating-layer="open"を足したもの。ターミナルの PromptPanel は数えない)。ファイル検索欄の Esc は検索語のクリア/blur だけ、Notes のメモ検索欄の Esc は検索を閉じるだけをしてパネルは閉じない。ファイルを開くと閉じ、キーボードで開いたときはフォーカスを Files のアイコンへ戻す。本文の中で浮く要素(セッションのメモ編集など)は重ねたパネルの下に収まる。固定するとこれまでどおり本文の横に並び(付け外しでパネルを作り直さないので Env の編集は残る)、固定は worktree をまたいでlocalStorageのcommandmate.worktree.activityPanePinnedに保存される。重ねる枠(PaneOverlayFrame)と閉じ方・ピン・未保存の通知のフック(usePaneOverlayDismiss/usePanePinnedState/useReportPaneDirty、src/hooks/useActivityPaneOverlay.ts)は他のパネルでも使える形にした。Message History の重ね表示・固定は範囲外(開くと今までどおり横に並ぶ)。スマホは変更なし。 -
feat(sidebar): ブランチの行を左右に余白のある角丸の札にし、選択中を塗りで示すようにした (#3576): サイドバーのブランチ行(
BranchListItem)を左右 8px 内側・角丸 10px の札にし、hover は薄い塗り(sidebar-hover)、選択中は一段濃い塗り(sidebar-border)で示す。左の青い線はやめた。キーボードのフォーカスは塗りとは別の枠(focus-visibleの ring)で見える。状態の点は 12px から 8px にし、#3509 の区別(プロンプト待ち=amber の脈動・依頼待ち=緑のチェック印・判定不能=灰色の中抜きの輪・稼働中=緑の光・アイドル=灰色)はそのまま。選択中の行の 2 行目(次の操作・説明)は塗りの中に残す。行の右端に「…」(新しいタブで開く・ブランチ名をコピー・パスをコピー)を足し、hover 中の行・キーボードのフォーカスがある行・選択行に出す。タッチの画面(hover: none)では選択行に常に出る。グループ見出しのドラッグの取っ手は hover/フォーカス時だけ出す(タッチの画面では従来どおり常に出し、並べ替えの操作は変えていない)。Sessions 表示の行と「Other(n)」の開閉行も同じ札に揃えた。タブ列の一覧(RepositoryTabBar)も同じ行を使うので同じ見た目になり、行の「…」のメニューを使っても、それを開いた一覧(タブ列の一覧と worktree ヘッダーのパンくずの ▾ の一覧)は閉じずに操作が完了する(外側クリックの判定は両者で共通のisBranchListOwnTarget)。 -
feat(sidebar): サイドバーの一覧の上の「絞り込み・View・Sort」の 3 段を 1 行にまとめ、一覧がすぐ始まるようにした (#3575): 一覧ツールバー(
SidebarListToolbar)を「高さ 32px・枠を薄くした絞り込み欄+右端のフィルタのアイコン」の 1 行にし、View(Repository / Branch / Session)と Sort(キー 4 つと向き)はアイコンから開く小さなメニュー(新しいSidebarListOptionsMenu、既存の RadixDropdownMenuのラジオ項目)へ移した。矢印キーで全項目に届き、Enter で選んでもメニューは開いたまま、Esc や外側のクリックで閉じるとフォーカスはアイコンへ戻る。メニューは画面端から 8px 内側に収まり幅も画面幅で頭打ちになるので、スマホの引き出し(390×844)でもはみ出さない。View か Sort が既定(Repository・Updated・Newest first)以外のときだけアイコンに点を出し、アイコンの名前とホバーの文に今の値(例「Repository · Updated · Newest first」)を出す。キーを変えるとそのキーの既定の向きになり(Updated は新しい順、ほかは昇順)、同じキーを選び直しても向きは反転しない(向きはメニューの「Newest first / Oldest first」などで選ぶ)。#3509 の決定(View / Sort は 3 表示に共通の一覧ツールバー、絞り込みは残す、⌘K で置き換えない)は保つ。サイドバー専用だったSortSelectorは使われなくなったので削除した(Sessions 画面のSortSelectorBaseは不変)。 メニュー(この View / Sort と既存の設定メニュー)が開いている間は、New task(Mod+Shift+O・openNewTask())と Mod+B のサイドバー開閉が動かない(isAnyModalOpen()がrole="menu"かつdata-state="open"の表示中の Radix メニューも数える。閉じかけ・非表示のメニューは数えない)。 -
feat(mobile): スマホの引き出しを PC のサイドバーと同じ並びにし、上端に閉じるボタンを置いた (#3515): 390px 幅の引き出し(サイドバー)を PC と同じ並び(上部の「閉じる(×)」+ロゴ → New task → 検索 → 移動先 → 一覧 → 下部の設定メニュー)にした。PC の部品
SidebarTopControls/SidebarPanelToggleをそのまま使い、スマホでは開閉ボタンを閉じるボタン(sidebar-drawer-close、名前はcommon.sidebar.close)として描き、⌘K のキー表示は出さない。New task・検索・ロゴは先に引き出しを閉じてから動く。引き出しが中にフォーカスを持ったまま閉じたときは、画面に見えている入口(下のタブ列の「Branches」か worktree ヘッダーの ☰。data-mobile-drawer-openerの付いたボタン)へフォーカスを移すので、引き出しから開いた New task ダイアログ・コマンドパレットを Cancel / Esc で閉じるとフォーカスはその入口へ戻り、閉じた引き出しの中のボタンへは戻らない(PC は従来どおり開いた行へ戻る)。外側を押して閉じる動きと、下のタブ列の「Branches」(#2642)は残した。引き出しは safe-area の上下を自分で空け(pt-safe/pb-safe、背景つき)、幅は画面の 85% までにしたので、開いている間に下のタブ列が退く(#2642)のと合わせて、下部の設定ボタンはタブ列にもホームインジケーターにも隠れない。あわせて #3514 で PC の各分割の入力欄の上に出した「To: · 」を、スマホの terminal タブにも同じ文言キー(worktree.terminal.composerTarget*)で出した。ブランチは PC(WorktreeDetailDesktop)と同じ規則で、詳細画面が持つ Git の現在のブランチ(取れなければ worktree 名)をMobileContentから渡す(/api/worktreesの一覧キャッシュはgitStatusを返さないので読まない)。#2106 の高さの予算(360x640 で端末 250px 以上)を削らないよう、行ではなく出力領域の左下に重ねて描き、直接入力のキーボードを開いている間は出さない。PC のレイアウトは変えていない。 -
feat(worktree): エージェントの追加「+」・分割の並べ方アイコン・Terminal / Chat の文字付きの札と送り先表示 (#3514): worktree 画面(PC)のヘッダーで、エージェントの札の右端に「+」を追加。ツール(未インストールは選べない。確認できないとき・サーバーが空の一覧を返したときは全ツールを表示)・名前(任意)・開く場所(新しい分割/今の分割を置き換え/追加だけ)を選ぶと、roster に登録(
PATCH /api/worktrees/[id]のagentInstances、「Add instance」と同じ書き込み)して選んだ分割に表示し、その分割にフォーカスを移す。セッションは起動しない — 既存どおり、その分割から最初に送信したとき(POST /api/worktrees/[id]/send)に起動する。分割が上限(4)のときは「新しい分割」を選べず、既定は「今の分割を置き換え」。名前変更・並べ替え・削除は従来どおり Agents ペインで行う。roster の保存(全置換)は「+」と Agents ペインのあいだで worktree ごとに直列化し、各操作は先行の保存を反映した roster から組み立てる(同時操作で ID が重複したり他方の変更が消えたりしない)。分割のアクションバーは「n / 4 splits + −」をやめ、並べ方のアイコン(1・2・3・4)から直接選ぶ(roster の数を超える並べ方は選べない。4 で 2×2・等幅・最大化(⌘⇧↵)・分割ごとの Terminal / Chat の保持は不変)。分割の見出しは Terminal / Chat の札に文字を付け、最大化・検索・セッションの終了をまとめた「…」メニューを追加し、選択中の分割をアクセント色の枠で示す(分割が 2 つ以上のとき)。各分割の入力欄の上に「To: <エージェント> · <ブランチ>」を表示する(入力欄は分割ごとのまま)。 -
feat(ui): リポジトリのタブ列をアイコン列と同じ面にそろえ、worktree ヘッダーをパンくず(ブランチ ▾)にする (#3513): タブ列(#2374)は背景をアイコン列と同じ
bg-sidebarにし、選択中のタブだけを本文色の角丸の札で示す(ボタン自体は帯の高さいっぱいのままなので、押せる範囲と #2480 の高さの約束は不変。高さは 32px のまま — Issue の 40px は既存テストの期待値と食い違うため見送り)。タブの一覧と「…」一覧の高さの上限は、10 行ぶん(medium で 520px)に加えてアンカーの下に残った画面の高さを超えないようにした(#3512 でタブ列が Header の下に移り、高さ 580px の画面では一覧の末尾が画面外に出ていた)。上限は開いたままのウィンドウの高さの変化にも追従する(useViewportHeight)。worktree 画面のヘッダーは worktree 名を見出しにして ▾ を付け、押すとタブと同じブランチ一覧(RepositoryBranchPopover・行はBranchListItem)を開く。行を選ぶ処理はタブ列と共通(useOpenWorktreeFromBranchList:selectWorktree()で選択 ID と既読を登録してから遷移)で、タブ列とパンくずの一覧は同時に開かない(一方を開くと他方が閉じ、行を選ぶと今の worktree でもすべて閉じる)。リポジトリ名は色付きフォルダつきで小さく残す(タブ列が出ない状態=サイドバーを開いたとき・hidden 設定でも、同じ名前のdevelopを見分けられるように)。今の Git のブランチと未コミットの印もそのまま残す。表示サイズの切り替えは設定メニュー(#3510 / #3512)に移ったので worktree ヘッダーから外した。タブ列の動き(Enter / ↓ で開く・Esc で閉じる・「…」・溢れ時の選択タブ・hover で開かない)とスマホは変えていない。 -
feat(ui): サイドバーを閉じてもアイコン列から移動先に届き、開閉ボタンの位置が変わらない (#3512): PC でサイドバーを閉じると幅 56px のアイコン列(
SidebarRail)が残り、開閉・New task・検索(⌘K)・Sessions・Repositories・Review(待ち件数)・設定メニューに 1 クリックで届く。開閉ボタン(SidebarPanelToggle、開閉で形の変わるパネルのアイコン、aria-expanded付き)は開いたサイドバーの左上とアイコン列の先頭の同じ位置に置き(px 指定のセルなので表示サイズを変えてもずれず、既定のタブ列モードで閉じたときに現れるタブ列はヘッダーの下・アイコン列の右に出してボタンを押し下げない)、worktree 画面の ActivityBar 上端の ☰ と未使用だったSidebarToggleは削除。ActivityBar 下端の歯車(#2645)も、サイドバーのフッターかアイコン列に同じ設定メニューが常にあり重複するため外した。サイドバー上部はロゴと開閉 → New task → 検索の行 → 移動先 3 行の順。global Header は画面名と、接続状態・アプリ更新(どちらも今までと同じ条件で出る)だけになり、移動先・⌘K 検索・表示サイズ・タブ列モード・テーマ・GitHub はサイドバー/アイコン列/設定メニューへ移した。開閉のショートカット Mod+B を追加(?の一覧にも載る。Mod+Shift+B・入力欄・ターミナル(tmux の Ctrl+B)・ほかのモーダル(Git のチェックアウト確認など)の表示中は奪わない)。コマンドパレットの Actions に「New task」を追加。設定メニューの「設定…」は/moreへのリンクになり、通常クリックは今どおりモーダル(スマホは/more)、⌘/Ctrl/Shift/中クリックは新しいタブで開く(旧 Header の #2709 の動き)。役割は、アイコン列=画面をまたぐ移動(サイドバーを閉じたときだけ出る)、ActivityBar(48px)=worktree の中の移動。使われなくなった i18n キー(common.nav.repositoriesShort/nav.reviewReport、worktree.activityBar.toggleSidebar/activityBar.settings)を削除。スマホは変えていない(#3515)。 -
feat(ui): 設定の入口を共通の設定メニュー(
SettingsMenu)にまとめた (#3510): サイドバー下部と ActivityBar の歯車が同じポップオーバー部品を開くようにした。中身は 設定… / Skills / テーマ(ライト・ダーク・システム)/ 言語 / 表示サイズ / リポジトリタブ帯の表示モード / GitHub / バージョン / ログアウト(認証有効時)で、表示サイズとタブ帯モードは PC のサイドバー側メニューにだけ出る(スマホでは従来の Header セレクタと同じく出さない)。サイドバー下部(フッター)はこのメニューを開くボタン 1 つ(data-testid="sidebar-settings-menu"、表示は「設定」)にし、これまでフッターにあった設定ボタン(sidebar-settings)・言語セレクト(locale-switcher)・テーマ切替・ログアウトはすべてメニューの項目から届く。「設定…」は #2709 のまま(PC は設定モーダル、スマホは/moreへ遷移してドロワーを閉じる)で、モーダルを閉じるとフォーカスはメニューのボタンへ戻る。Esc で閉じるとフォーカスは開いたボタンへ戻り、矢印キーで全項目に届く(Radix のui/DropdownMenu)。幅 390px でもはみ出さないようcollisionPaddingと幅・高さの上限を付けた。接続状態(ConnectionStatusIndicator)とアプリ更新(AppUpdateButton)はメニューに入れず、Header の項目も今回は外していない(#3512)。ログアウト処理はLogoutButton.tsxのlogout()に一本化した。 -
feat(sidebar): サイドバーの一覧を 1 行の行に作り直し、224px でもブランチ名が読めるようにした (#3509): ブランチ行を 1 行(約 34px)にし、状態は左の点だけで表す(プロンプト待ち=amber の脈動、依頼待ち=緑のチェック印、判定不能=灰色の中抜きの輪、稼働中=緑の光、アイドル=灰色)。「次の操作」と説明は選択中の行とツールチップへ移した(ホバーできない端末では、待ちの 2 状態の「次の操作」を従来どおり行に出す)。一覧の上に Needs attention(
selectAttentionWorktreesをそのまま使い 1 worktree=1 件。件数は Review の approval と一致し、非表示リポジトリの worktree も数えて印を付ける)を最大 3 件のプレビュー+ Review(/review?filter=approval)への導線で置いた。detached-<commit>の worktree はリポジトリの中で「Other(n)」に収める(選択中・待ち・稼働中は収めない。絞り込み中は展開する)。View / Sort は絞り込み欄と一緒に 3 つの表示に共通の一覧ツールバーへ移し、グループ見出しは大文字をやめて 12px の薄い字にした。Sessions 表示の行も 1 行にした。
Fixed
-
fix(orchestrate): env-clean が zsh の補完キャッシュを違反に数える問題と、run-log が短い SHA を受け付ける問題を修正 (#3664):
env-cleanのhome-entriesが~/.zcompdumpと~/.zcompdump.<host>.<pid>(ワーカーのシェル起動が作る zsh の compinit キャッシュ)を、.commandmate-demo-vitest-<pid>と同じく名前の形で数えなくなった(ignoredByConfigに残りレポートに名前が出る。.zcompdump-<host>-<ver>など他の.zcompdump*風の名前は従来どおり違反)。run-log.mjs appendは--head/--work-headに 40 桁の SHA だけを受け付け、短い SHA は exit 2 で拒否してgit rev-parse HEADを案内する(publish-pr.mjsは 40 桁で記録を探すため、短い SHA の記録は「記録が無い」と読まれていた)。すでに書かれた 7 桁の行はstatusが従来どおり読む。 -
test(unit): 負荷の高いときだけ落ちていた 3 本のテストを、時間に頼らない形に直す (#3662): 並列のワーカーが検証を同時に走らせているときにだけ落ちていたテストの原因を落ちた出力から特定し、待ち時間や timeout を延ばさずに直した(製品コードの変更なし)。
useInlinedHtmlImagesの上限のテストは、20 MB の結果を jsdom で 2 回解析し直すこと(1 回約 0.8 秒)が 5000ms の timeout を超えていたので、結果を文字列で確かめる形にした(1.7 秒→約 70ms)。opencode-resilience-1900のポート判定のテストと、対になるopencode-portsの「使用中のポートを飛ばす」テストは、固定のポート番号を同時に走る別のコピーと奪い合って EADDRINUSE で落ちていたので、カーネルが選ぶポート、または自分で確保できた候補を使うようにした。session-ownership-ws-relay-3334は、各テスト内のawait import('@/lib/ws-server')などで初回のモジュール読み込み(単独 2.6 秒)が最初のテストの時間に計上されて timeout し、打ち切られたテストが次のテストの裏で動き続けてtransport.subscribeの呼び出し回数を狂わせていたので、ファイル先頭の静的 import にした(実装側の欠陥ではない)。CPU 負荷(vitest 8 本並行+yes14 本)の下で、直す前は 24 回中 16 回・2 回・7/8 回落ちていたものが、直した後は 24 回中 0 回。 -
fix(search): チャット・履歴の検索で、返答が 2 件以上あると最後の返答以外が強調されない問題と、強調の位置を原文から写す端の入力 3 件を修正 (#3661): Chat・History は返答ごとに
applyHistoryHighlightsを呼んでいたが、呼ぶたびに namespace のCSS.highlights登録を上書きし、現在の 1 件を持たない返答の呼び出しが目印(overlay)を消していた(返答 2 件・各 2 ヒットの 1/4 で overlay 無し・2 件目の返答だけが光る/返答 6 件 13 ヒットの 1/13 で画面のどこも光らない)。namespace ごとに「コンテナ → 範囲」を持ち、登録はその和にする(呼び出しは自分のコンテナの範囲だけを置き換え、文書から外れたコンテナは落とす。clearHistoryHighlightsで全部を忘れる)。overlay は現在の 1 件を持つ呼び出し(currentIndex >= 0)だけが動かし、別の返答の呼び出しは自分の中にある overlay だけを消す。あわせて #3554 のレビューで見つかった写し方の端を直す: (1)
が作った改行が原文の次の改行を先取りして後続の本文が置けなくなる — 空白は前後の文字のあいだにある原文の空白にだけ置き、無ければ置かない。描画どおりでない文字参照(<など、コード外)は描いた UTF-16 の単位すべて(fjのfj、𝔄のサロゲートペア)をその&に置き、名前の文字を後続の本文の置き場にしない(Markdown が知らない名前は書いたとおり描かれるので、その文字列に置く) (2) 思考の 2 節が 1 つのコードブロックになると、つなぎの空行(原文に無い行)でrawSpansが null を返し要素ごと印が無くなる — 作られた行は隙間として飛ばす (3) 置けなかったヒットが生の offset のまま無関係な文字(チップのラベルなど)を光らせる — 置けなかったヒットは強調しない(n/m の件数と移動は検索側のままで変えない)。 -
fix(ui): Verification の札の理由と 2 段目の「…」パネルを Esc で閉じたとき、重ねて開いた Files などのパネルまで一緒に閉じないようにする (#3660): PC で重ねる表示のパネル(Files など)を開いたまま、札の ⓘ で理由を開いて Esc を押すと、理由とパネルが 1 回で両方閉じていた(札はパネルの Esc の対象領域
[data-activity-entry]で、パネルの document の listener が先に走るため)。札は理由が開いている間、札の中で押された Esc を React のonKeyDownで受けてpreventDefault()し理由だけを閉じる(見出しの道具の「…」と同じ形。開いたときにフォーカスを ⓘ へ移すので、クリックでフォーカスが移らない Safari でも Esc が札に届く)。2 段目の「…」パネル(ActionBarItemsOverflow)は開いている間data-floating-layer="open"を付け(見出しの道具の「…」リストと同じ印)、パネルの最初の操作が札になる狭い幅でも 1 回目の Esc は「…」パネルだけを閉じる。理由・「…」パネル・重ねるパネルが重なっているときは Esc 1 回につき 1 層ずつ閉じる。印の副作用として、「…」パネルが開いている間の外側の押下も「…」パネルだけを閉じて重ねるパネルは残す。スマホ(重ねるパネルが無く、理由は札の下に出る)は札の変更を共有するだけで、下に閉じる層は無い。 -
fix(ui): UAT の小さな残り 4 件(使われていない部品の削除・/more の見出しの翻訳・英語 docs の表記・「…」の吹き出しの位置) (#3651): どこからも描画されていなかった
SortSelectorBase(Sessions 画面は #1046 から Radix のSelect、サイドバーは #3575 からアイコンのメニュー)とWorktreeCard(#1135 で最後の描画元WorktreeListを削除済み)をテストごと削除。/more のクイックリンク「Repositories」をcommon.nav.repositoriesに(ja は「リポジトリ」)。英語の Web アプリガイドのセッション欄の表記を画面どおり「[N more ▾]」に。2 段目の「…」の吹き出しは左端を画面ではなく本文(terminal-split-container)の左端で止め、max-widthも本文の左端から測る(1024×768・サイドバーを開いた状態で、吹き出しが x=8 からサイドバーの上に描かれていた)。あわせて、削除で使われなくなったworktree.card.*(en / ja)とisNextActionKey()を消し、docs/en/UI_UX_GUIDE.mdの「[N others ▾]」を「[N more ▾]」に、docs/features/sidebar-status-indicator.mdのWorktreeCardの記述を今の表示先(サイドバー行と PC の詳細ヘッダー)に直した。吹き出しの幅を本文から測ると 768px・サイドバー 480px で約 272px になるため、吹き出しの中は折り返す(flex-wrap。退避したセッションの欄はmax-w-fullで箱に収め、長い部分は省略表示)。退避したセッションの欄の中(選択・Terminal / Chat・メモと日時・実行中の終了ボタン)も、吹き出しの中では折り返す(欄がdata-foldedのgroup/bar-sessionになり、split-bar-session-Nの行がflex-wrap。2 段目に収まっているときは 1 行のまま)。 -
fix(ui): Files パネルの表示設定メニューで Esc を押すとパネルまで閉じる問題を修正 (#3650): 重ねて開いた Files パネルの中でファイル情報の表示設定メニュー(
FileMetadataToggle)を開いて Esc を押すと、メニューとパネルが 1 回で両方閉じていた。メニューを開いている間は右クリックメニュー(ContextMenu、#3589)と同じくdata-floating-layer="open"を付け、パネルの Esc / 外側の押下はメニューが閉じるまで待つ(1 回目の Esc でメニューだけ、2 回目でパネルが閉じる)。パネルの document の keydown はメニューより先に登録されるのでpreventDefault()だけでは間に合わないため、印のほうで止める。メニューが閉じる Esc はpreventDefault()もして、window で受ける下の層(吹き出し、最大化したファイルパネル)にも渡さない。メニューは、開くときにフォーカスを歯車へ移し(クリックでフォーカスが動かないブラウザでも外の要素に残さない)、フォーカスがメニューの外の要素へ入ったとき(Tab でファイルの行へ、前面の画面が開く)に閉じ、Esc もボタン・メニュー内か何もフォーカスしていない(body)ときだけ自分のものとして扱う — 開いたまま前面に出たスマホの FileViewer や最大化したファイルパネルの Esc を、背面のメニューが消費しないため。自分の Esc で閉じたときはフォーカスを歯車へ戻し(見出しの道具の「…」リストと同じ)、固定したパネルでも 2 回目の Esc でパネルが閉じる。見出しの道具の吹き出し(Tooltip)の Esc は今どおり押下を奪わない — フォーカスで即座に出るため、道具をクリックしてパネルを開いた直後はその道具の吹き出しが出ており、そこからの Esc でパネルを閉じる操作が 2 回押しになるのを避ける(理由はコメントに記載)。 -
fix(hooks): 負荷の高いときだけ落ちていた #3304 のテスト(PC の幅で同じツールの別インスタンスへ切り替えても取りにいかない)を直す (#3641): 原因は前のテストの置き土産。スマホの面で codex へキーを送るテストが終わると、
useSpecialKeysが送信のNAV_KEY_REFRESH_DELAY_MS(100ms)後にonKeysSent(コントローラーのfetchCurrentOutput)を呼ぶ timer が unmount 後も残り、負荷で次のテストの準備がその 100ms に収まらないと、unmount 済みの画面のcurrent-output?cliTool=codex&instance=codexが後のテストの server に届いて「呼び出し 0 件」の期待に 1 件が混ざっていた(実測:tests/unit/hooksを--maxWorkers=12で 8 本並行 × 3 回、直す前 24 回中 4 回失敗 → 直した後 0 回)。テストの後始末(afterEach)で、キーを送ったテストだけ期限まで待ち、取り直しをそのテストの server で受けてから終えるようにした。期待(0 件)は緩めていない。timer は呼ぶ側(親の取り直し)が生きている前提の挙動なので、useSpecialKeysの実装は変えていない。後始末が漏らさないことを固定するテストを足した。 -
fix(orchestrate): orchestrate の道具の残り(一本化だけのブランチの作業証跡・instance の解決の接続先・新しい task の検出・残ったロック・gh の 5xx)を直す (#3633): work-evidence ゲートが orchestrate 6-4 の module-reference 一本化のコミット(trailer
Orchestrator-Fold: module-referenceを持ちdocs/module-reference.mdだけを変える非 merge のコミット。#3588 で scope ゲートが除くようにしたもの)を作業証跡のコミット数に数えていたため、一本化だけのブランチを verify すると scope は変更ゼロで合格・work-evidence もコミット 1 件で合格し、未着手として止まらなかった。判定は scope-gate.ts のcollectBranchCommitChanges(scope ゲートと同じ規則を export。写しは作らない)で、除いた数は log に(N orchestrator fold commit(s) excluded)と出る。ワーカーのコミットが 1 つでもあれば今までどおり合格する。consistency-review.mjs / wait-verify.mjs の--instanceの解決を、capture・ask・wait と同じ--cliのreply <wt> --instance <指定> --json越しにした(以前はprocess.envだけで組んだ URL への curl と、固定のdist/を親の環境で読む形で、.env・CM_BIND・HTTPS や--cliのラッパーの設定が解決にだけ効かず、別のサーバーに聞くことがあった)。受け付ける alias は CLI・サーバーと同じ条件(/を含む alias も可)で、ロック名は解決後の ID。wait-verify.mjs は、--taskが task 一覧(20 件)の外にあってもtask showで個別に読んで新しい task との比較を続け、開始時の一覧の照会が失敗したら待ち始める前に読み直して、待ち始めの task にverify --taskを結び付ける。consistency-review.mjs のロックに持ち主の pid・host・開始時刻を書き、kill されて持ち主が居ないロックは外して取る(以前は 3 時間、何も出さずに待った)。生きている持ち主は 1 分ごとにlock … held by pid …を stderr に出して待ち、上限は ask の上限+600 秒(3000 秒)。ロックを外すのは<lock>.reclaimを mkdir で取った待機者 1 人だけで、持ち主を読み直して同じ死んだ持ち主のときだけ動かすので、2 人が同時に同じ死んだロックを見ても、片方が取った新しいロックをもう片方が消さない。publish-pr.mjs / merge-pr.mjs の読み取りのgh(pr view/pr list/pr checks/run view、gh apiの GET など)はpr-common.mjsのwithGhRetryを通り、HTTP 502/503/504 と接続エラーだけを 10・30・60 秒あけて最大 4 回まで呼び直して、そのたびに stderr へretryingを出す(4xx や本当の失敗は呼び直さない)。書き込み(pr create/pr merge/run rerun/issue close)は 504 でも GitHub 側で済んでいることがあるので送り直さず、読み取りで 1 回確かめて(PR が開いた・マージされた・run の試行番号が送る前より増えた(status では見ない)・Issue が閉じた)、済んでいれば成功として続け、済んでいなければ今までどおり失敗で止まる(HEAD ごとに rerun は 1 回の制御は不変)。orchestrate.md の 3-4 の表の exit 3 に「待機中に同じ instance の新しい task ができた → 新しい task id でwait-verify.mjs --taskを呼び直す」を足し、詳細は docs/orchestrate/exit-codes.md に置いた。 -
fix(ui): 設定の Repositories 説明の英語直書きと、In Progress バッジの dark 色の写しを直した (#3632):
SettingsPanelの「Manage repositories and worktrees」をcommon.repositories.pageDescriptionに置き換え(ja で日本語、en は末尾にピリオドが付く)。WorktreeCardの In Progress の色の写し(dark:bg-accent-900/dark:text-accent-300)を消し、共通定義WORKTREE_STATUS_BADGE_CLASSES(dark:bg-accent-900/30/dark:text-accent-400)に揃えた(ダークで少し薄くなる)。agent-status-display.tsの古いコメントを直し、#3620 で失われた ACTIVITIES のアイコン検査(重複なし・Files と Notes が別アイコン)をtests/unit/config/activity-bar-icons-3632.test.tsに戻した。 -
fix(ui): 分割が 2 つ以上のとき、各分割の見出しのエージェント名が 1 文字まで縮む問題を修正 (#3631): 30px の見出しのエージェントの選択は
min-w-0で、2x2 の狭い分割(1280 幅・Files と History を開いた状態)では名前が 0px まで縮んでいた。見出しでは名前にmin(48px, 名前そのものの幅)の下限を置き(BAR_SESSION_LABEL_MIN_WIDTHを流用。短い名前を引き伸ばさないため幅を測って決める)、選択のボタンはmin-w-0を外して自分の最小幅を保つので、先にモデル名・費用・メモのチップが縮む。分割 1 つの 2 段目(#3615 の「…」へ退避する形)は不変。あわせて webapp-guide(ja/en)の「エージェント設定」を今の追加の流れ(ヘッダーのセッションの欄の[+]、名前の変更・並べ替え・削除はヘッダーの道具「エージェント」、モバイルは CMATE → Agent、1〜10 件)に書き直し、discoverability-principle の「worktree ヘッダの状態チップ」を 2 段目の Verification の札(VerificationStatusChip)に直した。 -
fix(ui): 上の層が処理済みの Esc で、下の層まで 1 回で閉じる問題を修正 (#3630): #3611 の
isUnhandledEscape()を、document / window のkeydownで Esc を受けていた SortSelectorBase・ContextMenu・useContextMenu・FileViewer(全画面と統合画面の段階)・FilePanelContent(最大化)・MarkdownEditor(編集欄の最大化)にも適用し、上の層がpreventDefaultした Esc では閉じないようにした。VerificationStatusChip・TerminalSplitContainer・useActivityPaneOverlay のインライン判定もisUnhandledEscape()に寄せた(振る舞いは不変)。Modal / FullScreenModal / Mobile*Sheet / CommandPalette は最上位の層なので対象外。 -
fix(worktree): ダークで Git のパネル全体が濃い青になる問題を修正 (#3617): デスクトップの Git のパネルで読む系のグループ(
git-group-readの Current Status と、flex-1でパネルの大半を覆うgit-group-historyの Commit History)が不透明なbg-info-subtle(ダークでは blue-950)で塗られていた。#818 B の薄い色味(bg-sky-50/40 dark:bg-sky-950/20と/30・/10)が #1140 のトークン移行で不透明に変わったのが原因で、#3591 より前の並べる配置でも同じだった。2 つのグループをbg-info-subtle/40 dark:bg-info-subtle/20とbg-info-subtle/30 dark:bg-info-subtle/10の薄い色味に戻した。--info-subtleは変えていないため、本来の用途の情報アラート面(Toast など)・左の青い線・Files のパネル・モバイルの Git のタブは変わらない。 -
fix(worktree): 見出しのセッション一覧(「ほか N ▾」)の行の tooltip が次の行の名前を隠す問題を修正 (#3616): 一覧の行の tooltip を行の下(
bottom)ではなく行の横に出すようにした。右に収まらないときは左へ回り、一覧のほかの行を覆わない(一覧そのものの幅・位置は変えない)。共有のTooltipに任意のfallbackPlacementを追加し、computeTooltipPositionは指定した側が画面端を越え、代わりの側が収まるときだけ代わりの側を使う。左右どちらにも収まらない長い文言(狭い幅・サイドバーを開いた状態など)では、空きの広い側に出し、bubble の最大幅をその空きに合わせて折り返すので、一覧の上へ寄せ戻されない(resolveTooltipWrap。空きが 80px 未満なら従来の寄せ方)。指定しない既存の Tooltip は従来どおり(指定した側で画面内に寄せる)。e2e で、行を hover/フォーカスしたとき(1440 幅、1024 幅+サイドバーの長い文言、スクロールで一部だけ見える行)の tooltip の座標がほかの行・一覧と重ならないことを確かめる。 -
fix(worktree): 分割 1 つのとき 2 段目のエージェント名が 1 文字まで縮む問題を修正 (#3615): PC の幅 1024px・サイドバーを開いた状態で、2 段目へ移したエージェントの選択(
split-bar-session-0)の名前が「C」まで切り詰められていた。名前のtruncateは「はみ出し」に数えられず、操作バーの幅の調整(useSplitActionBarFit)が「…」へ退避する段まで進まなかったため。名前に読める幅(48px、約 7 文字。「Claude」は 39px)をdata-fit-min-widthで宣言し、contentOverflows()はそれを割って切り詰められた要素を「収まらない」と数えるようにした。切り詰められていない短い名前は自然な幅のまま(最小幅で余白を足さない)。段の順は変えない(History / Files のラベルを外す方が、選択を「…」の奥へ送るより安い)。1280 / 1440 幅の表示は変わらない(e2e で計測)。 -
fix(e2e): Files を押す e2e の指定を見出しの道具の testid に置き換え (#3614):
file-tree-operations/recursive-delete/markdown-editorの spec がgetByRole('button', { name: /Files/i })で Files を押しており、「Open Files」のボタンにも当たって strict mode 違反になりうる状態だった(CI は worktree が無く skip されるため未検出)。PC 幅はheader-tool-files、スマホ幅(375x667)はmobile-tab-filesに置き換えた。 -
fix(worktree): Info 欄の進み具合の保存失敗を toast で知らせ、選択を元に戻す (#3613):
WorktreeInfoFieldsの進み具合 select(mobile-status-dropdown)は PATCH が失敗してもcatchで黙殺し何も知らせなかった。サイドバー行の「…」の Status(#3594)と同じく、失敗したらcommon.branchItem.statusChangeFailedの toast を出し、select の値を保存前に戻す。成功時の動きは不変。 -
fix(ui): 上の層が処理した Esc で、下のパンくず・タブ列の一覧・表示項目の設定・吹き出しまで閉じる問題を修正 (#3611):
Tooltip・FileMetadataToggle・WorktreeBreadcrumb(ブランチの ▾ 一覧)・RepositoryTabBar(タブ列の一覧)の document / window の Esc 受けが、上の層(メニュー・見出しの「…」一覧など)がpreventDefault済み(defaultPrevented)かを見ていなかったため、1 回の Esc で上下の層がまとめて閉じ、フォーカスも下の層のボタンへ移っていた。判定を新設のsrc/lib/escape-key.tsのisUnhandledEscape()1 か所に置き、4 部品とも「処理済みの Esc は無視する」にそろえた(#3591 のActionBarItemsOverflow・#3592 のVerificationStatusChipと同じ動き)。Tooltipは WAI-ARIA の「Esc はまず吹き出しだけを消す」(preventDefaultで Esc を奪う)は採らず、処理済みの Esc を無視するだけにした — ホバーで偶然出ている吹き出しが Esc を奪うと、モーダルやメニューを閉じるのに 2 回押す必要が出るうえ、defaultPreventedを見ない既存の Esc 受けが多く、#2319 の「利用側の Esc 処理を妨げない」という約束も崩れるため。吹き出しはwindowの bubble 段で受けるので、document の層(capture・bubble とも)が常に先に処理する順序をテストで固定した。 -
fix(skills): デモ動画の録画スクリプトが無くなった縦のアクティビティバーの入口を待つ問題を修正 (#3610):
demo-videoのrecord-scenes.ts(.claude/.agentsの写し両方)が #3591 で消えたactivity-bar-button-skills/activity-bar-button-gitを待っていたため install-skill / review-diff のシーンが進めなかった。見出しの道具header-tool-skills/header-tool-gitに置き換え、スクリプトが待つ入口の testid がsrc/に実在することを固定する単体テストを追加。 -
fix(verification): module-reference の一本化コミットの後に再指示した worktree を scope ゲートが必ず落とす問題を修正 (#3588): orchestrate 6-4 の一本化コミット(
docs/module-reference.mdだけを変える)が PR ブランチに積まれた後にワーカーへ再指示してverify --taskで裁定し直すと、scope ゲートがブランチ全体の差分(origin/develop 比)にあるこのファイルを範囲外と数えて必ず exit 20 になっていた(#3514 / PR #3560、#3579 / PR #3584 で発生)。collectChangedPathsが<merge-base>..HEADの各コミットを読み、一本化のコミット(merge でなく、変更ファイルが 1 つ以上ありすべてがORCHESTRATOR_FILES、かつ trailerOrchestrator-Fold: module-referenceを持つ)だけが触ったパスをコミット済みの差分から除き、log_tailのexcluded節に出す。一本化のコミットにはこの trailer を付ける(.claude/commands/orchestrate.md6-4 と docs/orchestrate/ci-merge.md 6-4 にコマンド例)。trailer の無いコミット(ワーカーが module-reference だけを単独でコミットした場合を含む)・未コミットの変更は今までどおり違反。merge コミット自身の編集は、ORCHESTRATOR_FILESの中なら承認済みの統合(develop の取り込みで共有ファイルの衝突を機械解決したもの)として除外に残し、それ以外のパスの編集はワーカーの変更として scope で判定する。各コミットのファイルはgit diff-tree -zでコミットごとに読むので、改行や制御文字で始まるパス名も改変しない。merge-pr.mjsのworkHeadsはファイルの規則だけのまま。ORCHESTRATOR_FILESはpr-common.mjsとscope-gate.tsの 2 か所になり、単体テストが .mjs を import して中身の一致を固定する。 -
fix(orchestrate):
wait-verify.mjsが同じ worktree に来た 2 本目の契約に気づかず古い task で検証する問題を修正 (#3587):--instanceは最初にサーバーのGET /api/worktrees/<WT>/resolve-target(wait/captureと同じ権威)で解決し、待機・検証・task の比較・capture・Auto-Yes のすべてにその id を使う(解決できなければ exit 2 で何も送らない)。開始時のcommandmatedev task list <WT> --jsonに渡された task(--task。無ければ開始までに作られたその instance の最新の task)があるか、一覧が読めなかったときは、wait --verify1 本をやめて--verifyなしのwait→ 新しい task の確認 →verify <WT> --task <task> --instance <id>に分け、検証を始める直前をスクリプトが握る(--instanceはwait --verifyと同じ裁定にするため。一覧が読めなかったときは読めた時点で基準を取り直す。一覧が読めて task が無いときだけ従来どおり 1 本)。確認は待機中(既存の 30 秒の間隔)・verifyの直前(再検証・Antigravity の合図待ちも)・検証の後で裁定を確定する前に行い、同じ instance に基準より新しい task(基準が一覧にあれば一覧の順序、無ければ作成時刻で比べる)があれば exit 3 で抜ける(記録はfail、要約はunconfirmed: a newer task <新> was created for this instance after task <旧>; … auto-yes=kept)。照会は 15 秒で打ち切り、失敗・時間切れはその回の確認を飛ばす。確認が例外で落ちても待機中のwaitは止める。実測(2026-10-11、#3575 / #3576 / #3579): 1 本目の task のverifyが scope で必ず落ちるのに unit-related を 20 分ずつ走らせ、2 本目の task の検証がその後ろに並んだ。 -
fix(i18n):
/repositoriesの説明文が日本語設定でも英語固定だった問題を修正 (#3586):src/app/repositories/page.tsxのManage repositories and worktrees.の直書きをcommon.repositories.pageDescription(en は従来の文、ja は「リポジトリとワークツリーを管理します。」)へ置き換えた。見出し(#3579)だけ日本語で説明文が英語という食い違いを解消。/sessions・/review・/more・/skillsは既に翻訳キー経由で、直書きは無かった。 -
fix(ui): ⌘K のコマンドパレットが、ほかのモーダルや開いたメニューの上に開く問題を修正 (#3585):
CommandPalette.tsxの ⌘K / Ctrl+K ハンドラが、閉じているときに限りisAnyModalOpen()(modal-open.ts)を見て、表示中のrole="dialog" aria-modal="true"(設定・ヘルプなど)や開いた Radix メニュー(設定メニュー・View/Sort・行の「…」)があれば開かないようにした。New task(Mod+Shift+O)・Mod+B と同じ規則で、フォーカスの拘束が重ならない。パレット自身の表示中の ⌘K で閉じる動きは変わらない(パレット自身の dialog を数えないよう、判定は閉じているときだけ)。 -
fix(ui): 一覧画面の上端に全幅で残っていた「画面名だけ」の帯をやめ、サイドバー/アイコン列を画面の上端から始める (#3579):
/sessions・/repositories・/reviewなどで global Header が高さ 64px の帯として全幅に残り、サイドバー/アイコン列がその下(top-16)から始まっていたため、開閉ボタンの位置が worktree 画面 (8, 8) と一覧画面 (8, 72) で食い違い、画面名も帯と本文の見出しで二重に出ていた。PC ではサイドバー/アイコン列を全ルートでtop-0 h-full(インラインの top オフセットも廃止)にし、タブ列(#2374)と Header を<main>の先頭行へ移した(タブ列が最上段、その下に Header。<main>のpaddingLeftに乗るのでドラッグ中の幅変更にも追従し、collapsed / always / hidden の 3 モードと表示サイズの倍率でサイドバーの位置が変わらない)。Header は画面名を出さず(各一覧画面は自前の<h1>を持つ)、接続状態(ConnectionStatusIndicator)とアプリ更新(AppUpdateButton)を今と同じ条件で右寄せに出す行になり、どちらも出ていないときはempty:hiddenで高さを持たない。自前の見出しが無い/(初回画面)だけは従来どおりCommandMateを出す。スマホの配置は変更なし。一覧画面の見出しは唯一の画面名になったため、英語の固定文字だった/repositoriesの見出しをcommon.nav.repositoriesに替え(ja で「リポジトリ」)、5 画面とも日英でサイドバーの移動先と同じ語になる。タブ列はサイドバーの右に並ぶので、サイドバーの開閉や幅のドラッグでタブ列の幅が変わったとき(溢れの有無が変わらなくても、一覧の取得後に現れたタブ列や一度消えて再び現れたタブ列でも)選択中のタブを表示範囲へ戻す(同じ幅でのデータ更新ではスクロールしない)。 -
fix(sidebar): worktree 画面を直接開く・再読み込み・戻る/進むでもサイドバーの選択表示が開いている worktree に一致するよう修正 (#3578): サイドバー(Grouped / Flat / Sessions / Other / 引き出し)は
selectWorktree()でしか更新されないselectedWorktreeIdだけで選択を決めていたため、URL で直接開くとどの行もaria-currentにならなかった。タブ列が使うresolveActiveWorktreeId(pathname, selectedWorktreeId)(パス優先)をsrc/lib/sidebar-utils.tsへ移して両方が import し、選択の決め方を一本化。Other に収める判定(選択中は収めない、#3509)も同じ値を使うので、Other に収まる detached の worktree を直接開くとその行は Other の外に出る。 -
fix(sidebar): サイドバーとアイコン列の移動先の並びを Sessions → Repositories → Review にそろえた (#3577): 開いたサイドバー(Repositories → Sessions → Review)とアイコン列(Sessions → Repositories → Review)で順が食い違っていたため、順を
sidebar-utils.tsのSIDEBAR_NAV_ORDER1 か所に定義し、Sidebar.tsxのsidebar-navとSidebarRail.tsxの両方がそれを回して描くようにした(モックどおりの順、Repositories 行の同期ボタンは従来どおり)。両方の描画を読んで順を確かめる単体テストと e2e を追加。 -
fix(worktree): 分割ごとの「To:」表示が端末の本文の高さを削っていた問題を修正し、設定モーダルの e2e を新しい入口に合わせる (#3572): #3514 で入力欄の上に足した「To: · 」の行(
split-composer-target-N)が独立した 1 行(文字 11px+footer のspace-y-2の 8px)を取り、#2598 の 2 段の composer の上に積まれて本文の高さが #2598 の予算(MAX_BODY_LOSS_PX= 48px)を超えていた(e2e 実測 61px)。表示を入力欄の上の枠線に重ねる見出し(fieldset の legend 型。absoluteで流れから外し、入力欄と共有するrelativeの包みsplit-composer-Nが gap を 1 回だけ払う)に変え、本文の減りを 42px に戻した(予算と基準の数値は不変)。表示・aria-label・入力欄の直前という位置は分割ごとに残り、pointer-events-noneで下の高さハンドルのドラッグを妨げない。あわせてtests/e2e/modal-outside-click-2715.spec.tsの設定モーダルの開き方を、#3512 で Header から外れたリンクから、サイドバー下部の設定メニュー(sidebar-settings-menu→「設定…」)へ直した(確かめる中身は不変)。 -
fix(ui): New task が FullScreenModal / FileViewer の上に重なる問題と、Auto-Yes の期限を遅く表示する問題を修正 (#3563): モーダル判定から
tabindexの条件を外し、表示中のaria-modalダイアログのうちインラインの PromptPanel(data-testid="prompt-panel")以外を数える(tabindexを持たないFullScreenModal・FileViewerの表示中も New task が開かなくなる)。/auto-yesの応答本文がタイムアウトしたとき、タイムアウト時刻+期間を確定した期限として保持するのをやめ、状態を「不明」(autoYesStateUnknown)として返す。サーバーは有効化した時刻+期間で期限を決めるため、従来は表示が最大 30 秒遅くなり、その間の再送で有効化を省いていた。不明の間はカウントダウンを出さず、再送では有効化を省かない。ダイアログは不明の状態を送り先ごとに保持し「状態を確認できなかった(有効になっている可能性がある)」旨を出して、「変えない(無効のまま)」とは書かない。 -
fix(search): チャットの答え・思考の検索の位置が、整形で削った行の端や節をつなぐ空行で原文に戻らなくなる問題を修正 (#3554): チャットは答えから思考とツールログを畳み、答えを
trim()・空行の折り畳み、思考を節ごとに引用を外して空行でつないで描く。表示した文字列の位置を原文へ戻す写像(chatMarkdownRawOffsets)は文字列の照合で後から作り直していて、その規則は「行の前を落とす」しか知らなかったため、答えの最終行(思考の節の直前の行を含む)の改行用の 2 空白・タブ、見出しが LF で本文が CRLF の混在の最終行の\r、先頭の全角空白・NBSP、旧形式(見出しの直後に>行が無い)の思考の 2 節以上で null になり、図の無い返答では #3523 の原文の位置での強調が Markdown の記法の分だけずれ、入れ子のリストの中の図は予備の照合(findMermaidFences)が読めず強調されなかった。splitChatThinkingと同じ走査で、答えと思考の各行が原文のどの行の何文字目から来たかを返すchatThinkingLineOriginsを足し、写像はその出自から直接作る(mapDerivedLines。節をつなぐ空行のような原文に無い行は null で、別の出現に割り当てない)。表示とコピーの文字列は変えない。ツールログの写像は従来どおり。また、答えの段落の行と行の間から思考の節を除いたとき(intro\n> **Thinking**\n> sentinel\nsentinel)、強調の段(rehypeSearchRawText)がテキストノードの両端の範囲だけを書き、検索がその範囲の先頭から照合し直していたため、思考の中の同じ語に本文の強調が当たっていた。描いた行ごとに出自の原文の行の範囲を書くようにした(原文で隣り合う行だけの段落は従来どおり 1 つの範囲。History は畳まないので不変)。表示の改行が原文の行と合わないノード(
で増える・インラインコードで空白になる)も、要素とテキストの範囲を原文の行の範囲の並び(s,e,s2,e2…)で書き、除いた節の範囲を照合の候補から外す(原文に無い空白は置かずに残す)。 -
fix(polling): worktree ID の一括移行で、入れ替え(A↔B)や連鎖(A→B→C)のときに dedup の状態が失われる問題を修正 (#3553):
migrateResponsePollerWorktreeIdsはタイマーの停止こそバッチ全体で先に行っていたが、dedup の Map(response のハッシュ・重複の連続数・#2399 の再照会、prompt のハッシュと連続数、#1695 のスキップ集計、#2230 の paused の chain)は移送元ごとに 1 件ずつ付け替えていたため、A→B の時点で B の状態が上書きされ、続く B→A で A に A の状態が戻って B が空になっていた。新設のrenameResponseHashCacheKeys/renamePromptHashCacheKeys/renamePromptDedupSkipsBatchで、稼働中と paused を合わせたすべての移送元の状態を先に退避してから移送先へ書く。ハッシュ無しの再照会(lineCountIsCursorの経路)も移って旧キーに残らず、ハッシュが移った移送先にあった別ターンの再照会は消して混ぜない。単独のrenameResponseHashCacheKey/renamePromptHashCacheKey/renamePromptDedupSkipsの振る舞い(#3552 の連続数の置き換えを含む)は変えない。 -
fix(polling):
duplicate-response-skippedの連続の数え上げを、重複でない tick で戻し、rename で古い回数を残さない (#3552): #3519 で間引いたduplicate-response-skippedの連続回数(__duplicateResponseSkipStreak)は、新しい返答・clearResponseHashCache・rename でしか戻らず、同じ応答 H の重複の間に未完了のフレーム・生きたプロンプト(pause・resume を含む)・空の応答を挟んでも続きとして数えられ、戻った直後の最初の重複のログが最大 29 tick(約 58 秒)遅れ、次の行のconsecutiveも間をまたいだ通算になっていた。response-dedup.tsにresetDuplicateResponseSkipStreak(pollerKey)(ハッシュは残して数え上げだけを戻す。#3538 の prompt 側と同じ形)を足し、response-checker.tsの「フレームを読んで未完了」「完了フレームに生きたプロンプト」「空の応答(掃除後に空になるものを含む)」の経路で呼ぶ。完了フレームの入口では戻さず、行数で抽出を見送った tick(null)とカーソルで返る tick でも戻さない(連続を保ち、1・31・61 回目にだけ出る)。renameResponseHashCacheKeyは移送先のハッシュを置き換えるとき、数え上げも移送元のもので置き換える(無ければ消す)。応答の保存の抑止(#1268)・#1695 の tally・#2399 の再照会・ログの payload の形は不変。あわせてprompt-dedup.tsのresetDuplicatePromptSkipStreakの JSDoc を、実際に呼ぶ 2 か所と呼ばない tick に合わせた。