Repository navigation
perf: 暇なときの報告の束ね待ちを 30 秒に伸ばす(質問・許可確認・人間は待たせない) - #5404
Merged
Merged
Conversation
暇なときに最初に届いた報告だけ、固定窓 30 秒(既定)で待ってから束ねる。 外部の合図の待ち(既定 2.5 秒・ALTEROID_INBOX_SETTLE_MS・上限 10 秒)は変えない。 報告の窓は ALTEROID_REPORT_SETTLE_MS(0〜120000ms、0 で無効)かコンストラクタの reportSettleMs で変える。読めない値・範囲外は既定で走り noteUnreadableRecord で跡を残す。 報告の窓の打ち切りは人間起点だけにしない(待ち候補以外が届いたら切る)。 人間起点だけだと、窓の途中で stop() が積む shutdown の蒸留が最大 30 秒待たされ、 stop() が同じだけ止まるため。 既存の試験のうち報告の到着から 2.5 秒前提のものは、報告の窓を 2.5 秒(または 0)に固定して 期待を変えずに通す。 Issue #5400 に触れる。
報告の窓の打ち切りが「待ち候補以外」だったため、外部の合図(runner-registry の 作業者の落ちなど)や失敗の知らせが窓を切らず最大 30 秒待たされていた。 「報告(manager_message かつ kind=report)以外が届いたら切る」に直す。 外部の窓自体(2.5 秒・人間起点だけで切る)は変えない。 ALTEROID_REPORT_SETTLE_MS を前例 #5369 と同じく APP_ENV_VAR_DEFAULTS(既定 30000)と .env.example に登録し、credential set で restartRequired が返るようにする。 compose.yaml のコメントも実装に合わせる。 Issue #5400 に触れる。
担当の失敗・停止の知らせは manager.ts の #emit が kind: report・synthesized: true で 出すため、報告の長い窓の対象(と窓を切らない側)に入り、30 秒待たされていた。 長い窓の対象を synthesized でない報告だけにし、合成の報告は従来どおり短い窓 (外部と同じ 2.5 秒)で扱い、報告の窓の途中に届けば窓を切る。 Inbox#settle は待ちを張った後に push された合図しか interruptWhen にかけず、 #pump で取り出してから待ちに入るまでの await の間に積まれた人間の発言・蒸留は 窓の長さぶん待たされた。待ちに入る時点で待ち行列に割り込みがあれば待たない。 外部の窓でも、待ち行列に既に人間起点の合図があれば即抜けるようになる。 .env.example の「播種される7つ」を 9 つに直す。 Issue #5400 に触れる。
This was referenced Oct 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
何をするか
暇なときに最初に届いた報告(
manager_messageのkind==='report'かつsynthesizedでないもの)だけ、固定窓 W 秒(先頭の報告が着いてから W 秒で閉じる。後続の報告でも延ばさない)待ってから束ねる。既定 W=30 秒。ALTEROID_REPORT_SETTLE_MS(0〜120000ms、0 で無効=今の挙動)、clone のコンストラクタ引数reportSettleMs。空・読めない・範囲外は既定で走りnoteUnreadableRecordで跡を残す(resolveInboxSettleMsと同じ書き方)。external)の待ちは変えない(既定 2.5 秒・ALTEROID_INBOX_SETTLE_MS・上限 10 秒)。isSettleCandidateのまま)。担当の失敗・停止の知らせ(世代の 409・停止・quotaStop)は manager.ts の#emitがkind: 'report'・synthesized: trueで出すので、30 秒の窓の対象から外し(isPlainReport)、従来どおり待ち候補のまま短い窓(外部と同じ 2.5 秒・人間起点だけで切る)で扱う。報告の窓の途中に届けば窓を切る。測りの数字(何を測ったか)
2026-10-27(JST の暦日 = 2026-10-26T15:00Z〜2026-10-27T15:00Z)の本番の日誌(クローン teto が GET で書き出し、
turn-census.mjsの節 (e) で再現計算)。代償
報告への反応が最大 30 秒遅れる(固定窓なので 1 件あたりの追加待ちは 30 秒で頭打ち)。質問・許可確認・人間は待たせない。W は
ALTEROID_REPORT_SETTLE_MSで変えられる(0 で無効)。読んで確かめたこと(実装側)
Inbox#settleの固定タイマー(先頭で 1 回だけ張る)。後続で延びない。#mergedManagerReportBatch・混合の束)は待ちの後で束が決まるので壊れない。turn_timingのqueue段はarrivedAtが合図のatのままなので、待ちは従来どおりqueueに乗る(30 秒ぶん伸びる)。close()(stop()の中)は待ちを即座に畳む。ただしstop()はclose()より前に shutdown の蒸留を#postAndWaitで積み、その完了を待つ。従来の打ち切り条件は人間起点だけなので、窓の途中に stop すると蒸留が窓の満了まで待たされ、stop が窓の長さぶん止まる(2.5 秒では目立たず、30 秒では実害)。→ 報告の窓の打ち切りを「合成していない報告(manager_message・kind=report・synthesizedでない)以外が届いたら」に広げた(人間・質問・許可確認・合成の失敗の知らせ・外部の合図(runner-registry の知らせなど)・tick(自発・定期)・蒸留で切る)。初版は「待ち候補(報告・外部)以外」で切っていたため外部の合図が窓を切らず、さらに担当の失敗・停止の知らせがsynthesized: trueのkind: 'report'で出るために「報告」側に入り、窓の対象にも切らない側にも入って最大 30 秒待たされていた(レビュー指摘。初版の PR 本文は「失敗の知らせは待たせない」と逆のことを書いていた)。外部の窓自体(2.5 秒)は従来どおり人間起点だけで切る。試験で、この修正を外すと stop が 30 秒止まることを確認している(下の変異)。#inFlightは立てたまま(従来どおり)。人間のinterruptTurnの分類(starting 扱い)は変わらない。tick・蒸留・質問は上の打ち切りで窓を切るので 30 秒ぶん塞がない。試験
新規
clone-report-settle.test.ts(偽の時計): (1) 30 秒の窓に連続した報告は 1 ターン (2) 窓の外の報告は別ターン・窓は延びない (3) 窓の途中の人間の発言で打ち切り (4) 質問・許可確認は待たない(窓の途中の質問でも打ち切り) (5)reportSettleMs: 0で即ターン (6) 外部の窓は 2.5 秒のまま (7) 窓の途中の停止・セッションがある状態の停止で 30 秒待たず抜ける、タイマーが残らない。環境変数の解決(既定・空・数値・0・上限・小数・範囲外・読めない値)。既存の試験の直し方(期待は弱めていない):
clone-test-harness.tsのsetupはinboxSettleMs: 0と同じくreportSettleMs: 0を既定にした(cloneOptions で上書き可)。inboxSettleMs: 0を直接渡していた試験 11 本はreportSettleMs: 0を並べた。clone-inbox-settle.test.tsは 2.5 秒の窓そのものを測る試験なので、ONを{ inboxSettleMs: 2500, reportSettleMs: 2500 }、OFFを両方 0 にして固定(期待・コメントは変えていない)。createCloneを直接呼び設定を渡さず、これまで実時間で 2.5 秒待って通っていた試験 11 本はreportSettleMs: 2500を渡して従来と同じ待ちに固定(30 秒になると落ちるため)。変異の確認(足した試験が落ちること)
clone-report-settle.test.ts5 本が落ちた(窓の連続・窓は延びない・人間で打ち切り・質問で打ち切り・0 で即ターン)。戻して緑。interruptWhenを() => false(打ち切らない)にする → 3 本が落ちた(人間で打ち切り・質問で打ち切り・セッションがある状態の停止が窓の間止まる)。戻して緑。!isSettleCandidate(queued)(外部の合図が窓を切らない)に戻す → 「窓の途中で外部の合図が届くと打ち切る」が落ちた。isPlainReportからsynthesized !== trueを外す(直す前と同じ扱い)→ 本物の形(manager_message・kind: 'report'・synthesized: true)を使う 2 本が落ちた(窓の途中に届いても窓が切れない/先に届いても 2.5 秒の窓で済まず待たされる)。戻して緑。Inbox#settle冒頭の待ち行列の確認を外す → 「待ちに入る前に積まれていた人間の発言・蒸留・合成の失敗の知らせでは待たずに戻る」が落ちた。戻して緑。(初版の
externalの'ci-failure'という試験は実在しない形だったので外し、上の本物の形の試験に置き換えた。)検証
vitest run packages/core apps/daemon apps/cli scripts(と web の restart-required 試験) --maxWorkers=2: 19,315 件 失敗 0(最終コミット後。web の restart-required 試験は前回の実行で通過)。.env.example149 行の「播種される7つ」も 9 つに直した。tsc --noEmit -p packages/core・eslint(変更した主要ファイル)・prettier 通過。確かめていないこと
本番での実際の束なり方・減り方は未確認(上の数字は到着の列からの理想化)。実時間の stop の遅れは偽の時計の試験でのみ確認。自発・定期 tick 単体の打ち切りは、蒸留・質問と同じ「報告以外」の判定で切れる(同じ述語)が、tick を投げる専用の試験は足していない。
ALTEROID_REPORT_SETTLE_MSは前例 #5369(ALTEROID_INBOX_SETTLE_MS)と同じくcompose.yamlの素通り・APP_ENV_VAR_DEFAULTS(既定 30000。DAEMON_RESTART_REQUIRED_ENV_NAMESはここから導出されるので、credential setで restartRequired が返る)・.env.example(播種される 9 つ)に登録した。ALTEROID_INBOX_SETTLE_MSが現れる箇所はgit grepで洗い、上の 3 箇所以外に件数・一覧・試験の期待は無かった(env-vars-boot.test.tsはAPP_ENV_VAR_DEFAULTS.lengthから導出)。待ちに入る前に届いた割り込み(
Inbox#settleの修正)Inbox#settleは待ちを張った後に push された合図しかinterruptWhenにかけなかった。#pumpは取り出してから待ちに入るまでに await(#closeRecoveredQuotaStopRows・#quotaFoldNoticeFor)を挟むので、その間に積まれた人間の発言・蒸留は窓の長さぶん待たされた。settleの冒頭で待ち行列にinterruptWhenに当たるものが既にあれば待たずに戻す。外部の窓(2.5 秒・人間起点だけで切る)にも同じ判定が効く: 待ち行列に既に人間起点の合図があれば、従来は 2.5 秒待っていたのが即抜ける(人間を待たせない向きの変化のみ。人間起点以外は従来どおり窓を切らない)。既知の挙動
窓の最中に人間が
interruptTurn()で止めようとすると、止めるべき走行中のターンがまだ無いので'idle'が返り、窓が明けると報告のターンが始まる(従来の 2.5 秒の窓でも同じ形で、30 秒に伸びたぶん目立つ)。人間の発言が届けば窓は切れる。