Repository navigation
[0.49.0] - 2026-10-27
Highlight: Auto-Yes の有効時間を 1〜24 時間から選べるようになり、チャットのコードブロックにコピーボタンが付きました。codex まわりでは、入力欄に残った貼り付けの印(
[Pasted Content N chars])を消せず送信を断り続ける問題と、容量超過(Selected model is at capacity)を検出できず 40 分待つ問題を直しました。並列の検証が mutex 待ちで裁定不能(exit 99)になった回は、自動で並び直すようになりました。
Added
-
feat(auto-yes): Auto-Yes の有効時間を 1〜24 時間から選べるようにする(1h / 3h / 8h はプリセットとして残す) (#3913): 有効時間を 1〜24 時間の整数時間に広げた。定義は依存の無い新モジュール
src/config/auto-yes-duration.tsにまとめ(全部の候補AUTO_YES_DURATIONS=24 値の literal union の型AutoYesDuration、プリセットPRESET_AUTO_YES_DURATIONS=1h / 3h / 8h、CLI の書式^(?:[1-9]|1[0-9]|2[0-4])h$)、auto-yes-config.tsと CLI のduration-constants.tsは再 export する(CLI の1h|3h|8hの写しと旧名ALLOWED_DURATIONS/DURATION_MAP/DURATION_LABELSは廃止)。APIPOST /api/worktrees/:id/auto-yesは有効化のときだけ 1〜24 時間(3600000 の倍数)を受け付け、範囲外・端数・型違いは 400 で状態も poller も変えない(省略時 1h、無効化は duration を見ないのは従来どおり)。setAutoYesEnabledも有効化時に検査し、不正な値はRangeErrorで状態を書き換えない。CLI のauto-yes --enable --durationとsend --durationは1h〜24h(0h・25h・1.5h・90m・01h・+1h・1Hなどは従来どおり exit 2)、scripts/orchestrate/launch-worker.mjsも同じ書式。確認ダイアログは 1h / 3h / 8h のボタンに「その他」(1〜24 時間の select)を足し、開くたびに 1h に戻す(ダイアログは常にマウントされていて前回の選択が次の初期値になっていた)。タスク作成ダイアログの select も 1〜24 時間。表示名は ICU(ja{hours}時間、en{hours, plural, one {# hour} other {# hours}})。長くすると慎重のモードでも自動で答える許可の確認が増える旨の注記を追加。期限切れ・停止条件・再起動での解除・答え方のモードの安全装置は変えていない。 -
feat(chat): チャットのコードブロックにコピーボタンを付ける (#3912):
ChatMarkdownBodyを通る画面(保存済み・実行中・確定待ちの吹き出し。PC の分割・スマホ・Sessions のタイルもChatSurface経由で同じ)で、回答・思考・ツールログの各コードブロックに、ファイルのプレビューと同じCodeBlockWithCopyのコピーボタンを付けた。押すとそのブロックの文字列だけ(色付けの span を除いたもの)をコピーし、空・空白だけのブロックにはボタンを出さない。componentsのpreは 1 つにまとめ、renderDiagrams && isMermaidPreChild(children)のときだけ図の枠を素通しにする(MERMAID_MARKDOWN_COMPONENTSからはcodeだけを使うので、mermaid のpreが新しいpreを上書きしない。renderDiagrams=falseの mermaid の fence はコードとしてボタンが付く)。インラインコード・ユーザー本文・端末の平文・History(ConversationPairCard)には付けない。共通の部品も直した(ファイルのプレビュー・ファイルのページ・TodoPane にも効く):CopyButtonにdata-search-skipとselect-noneを付け、検索の強調の対応づけと範囲選択の Cmd/Ctrl+C にCopy/Copiedが混ざらないようにした(コードを包む要素には付けない)。@media (hover: none)の端末では幅にかかわらずボタンを常に表示し(.code-copy-button)、<pre>の右に余白を取って 1 行のコードにボタンが重ならないようにした(.code-block-with-copy > pre。ボタンは<pre>の外なので横スクロールでも動かない)。チャットの最初・最後のコードブロックの上下の余白は従来どおり 0。 -
feat(verification): 検証の待ちと実行を人向けの表示と run の記録にも出す (#3909): #3884 でゲートの
log_tail末尾に入った[timing] queue= mutex= run=を、commandmate verify/wait --verifyの GATE 行(GATE unit PASS (exit=0, 600.0s, queue=30.0s, mutex=120.0s, run=600.0s)。waited=の代わりに出す)とverify historyの人向けの行(行末のtiming: unit(queue=… mutex=… run=…))に出す。行の無いゲート(何も待たなかったもの・#3884 より前のサーバの run)と mutex 待ちの SKIP は今までの表示のまま。/orchestrateのwait-verify.mjsは最後の verify の GATE 行を合計してverifyの記録のqueueSec/mutexSec/runSecに渡し、run-log.mjs status --jsonのstages.verifyで読める(どのゲートも出さなかった run には書かない)。あわせて、run の最初の実行枠の待ちも取り消せるようにした: 2 枠が長いゲートを実行している間に取り消した run は、そのどちらかが終わるまでrunningのまま取消し API がrequested(202)を返していたが、すぐcancelledで閉じる(ゲートの行は作らない。空いた枠は次に待つ run へ渡る)。standalone のcmate-verifyのverify-run.shは commandmate-skills と byte-identical の pin があるためwaited=の形式のままとし、理由と揃え方をdocs/design/verification-config.md§9.3.1 に書いた(§9.2.1 のロックを取る場所も precheck の追加後に合わせて直した)。
Changed
-
refactor(prompt-response): 手動回答の送信エラーを分類する
manualOutcomeOfSendErrorを 1 か所にまとめた (#3926):/respondにあった写しを消し、prompt-response/answer-delivery.tsから export した関数を 2 つの route が import する。判定(既知の拒否 → not-sent、keysSent/answerDeliveryの優先順位、null を返す場合)は変えていない。 -
refactor(detection): Claude の画面の枠(タスクパネル・セッション差分 HUD・プレビュー枠)を読む処理を
prompt-detect-multiple-choice-chrome.tsへ分割 (#3924):findClaudeTaskPanelLines/findClaudeChrome/maskClaudeChrome/ClaudeChromeとCLAUDE_TASK_PANEL_*・CLAUDE_SESSION_DIFF_HUD_PATTERN、それらが使うSUMMARY_LINE_PATTERNをコメントごと挙動不変で新モジュールへ移し、元のprompt-detect-multiple-choice.tsは移した公開名を再 export する(公開 API・import 元は不変、新モジュールは元を import しない)。元のファイルは 1,561 行 → 1,350 行(1,500 行の閾値と前回の 1,442 行を下回る)。新モジュールの単体テストprompt-detect-multiple-choice-chrome.test.tsを追加。 -
feat(orchestrate): precheck の保留(exit 3)を案内し、merge-pr で不合格と分ける (#3908): orchestrate.md の precheck / merge-pr の exit 表に 3(保留。再実行・再指示しない)を追加。merge-pr は取り込み後の precheck が exit 3 のとき
did not passではなく「保留」と表示し exit 3 で返す(不合格は従来どおり exit 1)。switching.md の担当切替・格上げ後の待機は wait-verify.mjs を通す形に変更し、設計書の修正指示(4-3)と根本原因分析の依頼は launch-worker.mjs を通さない理由を明記。3-3 に合格行の HEAD 確認を 1 行追加。 -
refactor(session):
waiting-episode-state.tsを型・状態表・episode の書き込みに分割(682 行 → 203 行) (#3865): 型とインターフェースをwaiting-episode-state-types.ts、globalThisの状態表・listener の登録と通知・読み取り・テスト seam をwaiting-episode-state-store.ts、open / close / replace / rebind / updateKind をwaiting-episode-state-ops.tsへ移し、waiting-episode-state.tsはdeclare global・observeWaitingEdge・binding resolver の登録を持ち、これまでの export をすべて再 export する入口にした。import 元は変更なし、振る舞いの変更なし。
Fixed
-
fix(orchestrate):
wait-verify.mjsが mutex 待ちだけの exit 99 を受けたら検証を自動で並び直す (#3938): 並列の検証でcpu.heavyがtimeoutSec(5400 秒)の間ずっと埋まり、ゲートがreason=mutex-waitの SKIP になって裁定不能(exit 99)になった回を、人が--after-reinstructで直列に回し直していた(2026-10-25〜26 の run で verify 23 回中 6 回)。verify show <run> --jsonのゲートのlogTailの 1 行目で、SKIP がすべてreason=mutex-waitかつ FAIL・TIMEOUT・ほかの SKIP が無い run だけを--mutex-retries <n>(既定 2)回まで始め直す。通常の検証・--after-reinstruct・3-3 の確認が始める再検証の 3 経路で同じ。始め直す前に新しい task(exit 3)と HEAD(動いたらmutex-requeue-stopped=head-movedで 99 のまま)を確かめ直し、環境の manifest を取り直す。各試行のログはwait-<N>.verify.try<k>.logに残り、記録の要約にmutex-requeue=<n> mutex-runs=<id,…> mutexSec-total=<秒>、記録のqueueSec/mutexSec/runSecは全試行の合計になる。run が読めない・理由が読めない・run がcancelledなど passed/failed/error 以外で終わったときは今までどおり exit 99。裁定に至らなかった検証(3-3 の確認が始める再検証の 99 も)は Auto-Yes を切らない。製品のcommandmate verifyと.commandmate/verify.yamlは変えていない。 -
fix(cli-tools): codex の入力欄に残った貼り付けの印
[Pasted Content N chars]を消せず、送信前のクリアが送信を断り続ける問題を修正 (#3937):clearComposerは毎回C-e+C-uだけを送っており、codex 0.164.0 で印が 12 回とも残ってcleared=falseになっていた(2026-10-25 実機。手でBSpaceを 1 回送ると消えた)。codex の入力欄が 印 1 つだけ(前後に手入力なし) のときに限り、その 1 回を新設のclearComposerPasteToken(C-e+BSpace)にする。印+手入力・印 2 つ・本文が印の文字列を引用する場合は従来のC-e+C-uのままで、送るたびに読み直して判定する作りも変えない(claude と印のない codex は送るキー不変)。遅れて描かれて入力欄に残った印も、次の送信の前のクリアと未送信バーの Clear がこの 1 回で消せるようになる(送信中に遅れて届く印を待って取り下げる仕組みは、同じ instance への送信の直列化が要るため別 Issue)。実機の codex 0.164.0 でBSpaceが印を丸ごと消すことと、印+手入力での動きは未確認。 -
fix(detection): codex の「Selected model is at capacity」を上流障害として検出し、整合性レビューが 40 分待たないようにする (#3936):
UPSTREAM_FAULTSに codex の容量超過の規則model-capacity(selfRetrying: false)を追加。錨は codex 自身のエラー行の形(列 0 の■ Selected model is at capacity)で、返答の本文が文言を引用しただけの行(•/字下げ)・入力のエコー(›)・claude の 529 行のThe API is at capacityには当たらない。これで codex でもask/wait --fail-on-upstream-faultが exit 11、capture --jsonがupstreamFault、失敗の push 通知が働く(以前は規則が無く、入力欄に戻った後もターン終了の報告待ちのままask --timeout 2400まで待って 124 になっていた)。push の判定(response-checker)は生の末尾 100 行ではなくcaptureのrealtimeSnippetと同じ切り出し(buildRealtimeSnippet)を使うようにし、inline の codex の画面で capture には出るのに通知が鳴らない食い違いを解消。scripts/orchestrate/consistency-review.mjsはaskの exit 11 を他の失敗と分け、run の記録の note にupstream fault id=<id>を載せる(model-capacityはswitch --instance、ほかは id に応じて。別 instance への自動切り替えはしない)。また、最初のcapture --jsonがisRunning: false/session_not_runningでstartingSinceの無い instance には、作業を頼まない短い起動の文をsendで 1 回だけ送ってからreadyを待つ(起動後の上限は 30 回。起動の send が失敗したら依頼を送らずreview=fail。起動中の instance には送らず待つ)。以前は止まっている instance がreadyにならず 180 回・30 分待ってnot readyで止まっていた。上流障害の id の説明(CLI の型・サーバーの型・CLI 操作ガイド ja/en)にcontext-limitとmodel-capacityを追加。capacity の画面は実機で採れておらず、fixture は summary の引用から作った合成(tests/fixtures/upstream-faults/README.md)。 -
fix(demo-video):
env-up.shの背景起動で bash のchild setpgid … Operation not permittedが stderr に出る問題を修正 (#3935):set -mのジョブ制御下では bash が親と子の両方でsetpgid(子, 子)を呼び、親が先に成功すると子の側が EPERM になって、子がサブシェルのリダイレクトより前に継承した stderr へ 1 行書いていた(macOS の負荷下で約 0.3〜0.7%。PGID は親の呼び出しで正しく、実害はメッセージだけ)。これがenv-up-listener-owner.test.ts/env-scripts.test.tsのexpect(result.stderr).toBe('')を検証の重い負荷の中でだけときどき落としていた。set -m〜set +mを{ … } 2>>"$LOG_FILE"で囲んでその間の bash の出力をサーバーログへ送り、サブシェルは事前に切り詰めたログへ追記(>>)するのでその行は診断用にログに残る。サーバーの PGID=PID・SERVER_PGIDの読み直し・pid_is_ours・cleanup_failed_boot・env-down.shは不変。.claude/と.agents/の両方に適用。負荷下の再現(tests/scripts/demo-video-bg-setpgid-load.sh、8 並列×1,500 回)は旧形 41 回・新形 0 回。 -
fix(verification):
wait-verifyの note のゲート一覧を保存済みの run から作り、取消し API の JSDoc を直す (#3928):summarizeVerdictがログ全体のGATE行を拾うため、落ちたゲートの本文にGATE行があると同じゲートがpassed=unit,unitと二重に数えられていた。note は timing と同じ保存済みの run(verify show --json)のゲートから作り、run が読めないときだけログ本文から読み、その場合も 1 つの id は 1 回に限る。verify/runs/[runId]/cancel/route.tsの JSDoc も、最初の枠を待つ run も取消しで待ちを抜ける実際の動き(#3909)に合わせた。 -
fix(terminal): ダイアログの下に隠れた codex の古い入力欄を未送信バーに出さない (#3927): codex の画面で、古い複数行の入力欄の下にダイアログ(承認など)の選択肢が出ているとき、PC とスマホの未送信バーが古い本文を出し続け、「消去」は効かず(クリアは #3906 から
no_composerで何もしない)、「実行」の Enter はダイアログの選択肢を確定しうる状態だった。「下段にダイアログがあれば入力欄は無いものとする」規則(codexDialogBelow/findCodexLiveComposerRow)をsrc/lib/session/composer-clear.tsからブラウザーも読めるsrc/lib/detection/composer-text.tsへ移し(logger を引くtools/codex/cli-patterns.tsの行の読み取りは同じモジュールの SGR 走査で書き直し、全 codex fixture の全行で移す前と同じ判定になることをテストで固定)、新しいextractLiveComposerText()に載せた。サーバーの公開値(current-output-builderのcomposerText/composerState、capture --jsonも同じ)、ブラウザーでの抽出(useTerminalPanePolling)、クリアの 3 つがこれを読むので、その画面ではcomposerText: null/composerState: 'no_composer'になり未送信バーは出ない。extractComposerText()自体の読み方、送信側(submit-verified-sender)のabsentの判定、Auto-Yes の Enter フォールバックは変えていない。入力欄だけの codex 画面と codex 以外のツールの画面は従来どおり。 -
fix(respond): 構造化回答(
decisionId指定・id 無し)が Auto-Yes に手動回答を知らせない問題を修正 (#3925):POST /api/worktrees/[id]/respondの構造化の経路(PC・スマホの入力欄のPromptPanelが使う{ decisionId, answer }と、commandmate respondが使う{ answer })は、承認・質問の回答を agent の API で届ける前にnoteManualAnswerStartedを呼んでいなかったため、進行中の Auto-Yes の tick が失効せず、送った直後の短い手動保持も掛からず、同じ確認画面に tick が重ねて答える余地があった。messageIdの経路(#3907)と同じ順序で、所有範囲の確認・404・409・不正回答の拒否を先に済ませてから開始を通知し、送る直前の画面を取得してnoteManualSendStartingで登録し、送信の結果を通知する。結果は source の受領で読み、届いた(delivered: true)はanswered、届かなかった(delivered: false)はnot-sent、受領が無いときは結果不明としてabandonManualSendのみ、例外はmanualOutcomeOfSendErrorで分類してから従来どおり 500 にする。拒否では開始通知を呼ばない。送る直前の画面は tmux の所有を確かめてから読み、別サーバーの同名セッション・所有を確認できないときは読まずに(#2885)「画面なし」で送信を登録する(API での配送と結果の通知は従来どおり)。/prompt-responseの構造化段も同じ分類で結果を通知するので、同じ承認にどちらの URL で答えても、以前の結果不明の送信の保持が同じように解除・維持される(answerStructuredDecisionの結果に source の受領そのものreceipt(受領なしは null)を足し、/prompt-responseの構造化段はそれで分類する。従来のdeliveredは受領なしをfalseに畳むので、受領なしでもnot-sentとして以前の保持を解除していた。deliveredと他の呼び出しの振る舞いは不変)。送る直前の画面の読み取り(screenAtSend)は route.ts からrespond/screen-at-send.tsへ移し、両経路で共有する(構造化側が route.ts を import する循環を避けるため)。 -
fix(orchestrate): plan-check routes の検査抜けと precheck の重さ見積りの精度を修正 (#3910):
plan-check routesがcheckと同じ違反で止まり(不正な plan は一覧を出さず exit 1)、状態名を NFKC・内部空白の畳み込み・大文字小文字無視で照合し、precheck は解析に失敗したファイルの参照を全部残し、型の位置のimport('…').T・typeof import('…')・import type x = require()を実行時の辺から外す。 -
fix(cli):
capture --prompts --jsonが確認画面のreadingと承認対象の完全性を落とす問題と、respondのmessageId経路が手動回答の結果を Auto-Yes に伝えない問題を修正 (#3907):capture --prompts --jsonの各 prompt に、保存された行のapprovalTargetCompletenessとreading(#3881)をwaitと同じ値で出す(無い行ではnull。CLI の型CapturePromptEntryを追加)。テキスト表示は変えない。POST /api/worktrees/:id/respondの{ messageId, answer }経路は、今の PC・スマホ・CLI からは呼ばれていないが既存テストが公開の形として固定しているため廃止せず、/prompt-responseと同じく手動回答の ticket(#3821 / #3880)を通す: 最初のキーの前にnoteManualAnswerStarted(進行中の tick を止め、しばらく画面を人に任せる)、送信は送る直前に取り直した画面(/prompt-responseと同じ読み方assessPromptAnswerability)で登録し、保存行の画面では固定しない(読めなければ識別できない画面として保持)。取り直した同じフレームをsendPromptAnswerのframeに渡し、数字の回答の検査が画面を読み直して登録と送り先がずれないようにする、送信の終わり方でsettleManualAnswer(通った・キー前に拒否=保持を解放、キーが画面に残った可能性/結果不明=その確認画面を保持)。これまでは、この経路の送信が結果不明で終わると保持の期限後に Auto-Yes が同じ確認へ再び打鍵し、送信が通っても Auto-Yes 自身の結果不明の保持が残っていた。 -
fix(cli-tools): codex の入力欄が読み取り窓の外にあるときの到着確認と送信後の判定の食い違いを修正 (#3906): codex への送信の確認(#3880)は入力欄の本文を全量比較するが、入力欄を探す窓(末尾 12 行・末尾 4 ブロック)は土台のままだった。1 行の段落+空行+20 行の段落のように
›行が末尾 12 行の外に出ると、同じ画面を到着確認はunseen(本文があるのに引き戻して失敗)、送信後の判定はsubmittedと読んでいた。また段落が多く入力欄が末尾 4 ブロックに入らないと、marker reader の 1 行目の先頭一致だけでlandedになりえた。extractComposerTextが見つけた入力欄は窓の外でもそのまま読み、4 ブロックの外では最下段の本物の入力欄行から footer までを全量比較の対象として引き継ぐ。その行はfindCodexBottomGlyphRowと同じく下から読み、承認ダイアログの選択肢(›)が先に出たら入力欄は無いとみなす(ダイアログの上に残った古い入力欄が本文の先頭と一致してもpendingにせず、ダイアログへ Enter を再送しない)。この規則はextractComposerTextが末尾 4 ブロックの中で複数行の入力欄を見つけた枝にも、クリア側にも同じく効く。ANSI の属性が無い›行(ダイアログの選択肢と見分けられない)はこの探索で入力欄とみなさない。codex 0.153〜0.160 が履歴エコーを dim でなく太字だけで描く行(ESC[1m› ESC[0m、空白が太字の中)も入力欄とみなさない。窓の外の本物の入力欄(空行を挟まない 20 行の入力欄のように抽出器が複数行で読む枝も含む)が本文と一致しないときは、別の/…なら窓の中と同じくreplaced、それ以外の文字なら新しいindeterminate(Enter を再送せず読み直し、解消しなければsubmit could not be confirmedで失敗=送信状態は indeterminate)にして、成功扱いにしない。awaitTypedBodyの短い本文(512 bytes 以下)は codex では入力欄の全量一致だけを到着とする(5 段落のうち第 1 段落だけ描画された画面で Enter を押さない)。clearComposerも codex で抽出器が入力欄を見つけないとき同じ規則で入力欄を探して読むので、送信側がpastingと読んで取り下げる多段落の本文を消し、消せなければcontentのまま返して次の本文を入力しない。実機の codex は動かさず、静的な画面の対照と既存の codex fixture 全件の判定(修正前と同じ)で確かめた。