sync: update from private repo (2336949a)
CI / build-and-test (push) Canceled after 0s

This commit is contained in:
oss-sync
2026-09-17 11:29:31 +00:00
parent 28f74c4e37
commit 57702b4f34
2139 changed files with 321270 additions and 17494 deletions
+27 -1
View File
@@ -40,12 +40,21 @@ worker.ts
| `COMPLETE` | `complete` ツール | `completed` | — | — | 終了 |
| `ABORT`(`cancelled` 含む) | キャンセル経路 | `cancelled` | — | — | 終了 |
| `ABORT` | `complete`/各種ガード(`text_only_limit`・`max_iterations` 等) | `aborted` | — | — | 終了 |
| `ASK` | `complete({status:'needs_user_input'})` | `waiting_human`(上限超で `aborted`) | 現在の movement | — | 待機 |
| `ASK` | `complete({status:'needs_user_input'})` | `waiting_human`(上限超は停車せず、同じ movement へ戻して自己判断を促す。差し戻しが `MAX_ASK_LIMIT_DEFLECTIONS` 回に達したら `ask_limit_reached` で打ち切り。#1299) | 現在の movement | — | 待機 |
| `WAIT_SUBTASKS` | `transition`(rules 経由)/**WaitSubTask ツール(提案)** | `waiting_subtasks` | `default_next`(ツール版は現在の movement に変更予定) | — | 待機 |
| `WAITING_HUMAN_BROWSER` | `BrowseWeb`(ログイン要求時) | `waiting_human` | 現在の movement | `browser_login` | 待機 |
| `WAITING_HUMAN_BROWSER` | `RequestCaptchaHelp`(検索が CAPTCHA で全滅したとき・#1199 段階 2) | `waiting_human` | 現在の movement | `captcha` | 待機 |
| `WAITING_HUMAN_TOOL_REQUEST` | `RequestTool` | `waiting_human` | 現在の movement | `tool_request` | 待機 |
| `WAITING_HUMAN_SPAWN_REQUEST` | `SpinOffTask`(別ワークスペース指定時) | `waiting_human` | 現在の movement | `spawn_request` | 待機 |
| `null` | 異常(ツール未決着) | `error` | — | — | 異常 |
> `WAITING_HUMAN_BROWSER` は**待ち理由違いで 2 つの入口**を共有する例。人が解く相手が
> 「そのタスクのブラウザ」か「ワークスペース共有の確認画面」かだけが違い、下流の分岐
> (piece-runner)は同じものを通る。再開の口は別で、captcha 側は
> `POST /captcha-pool/resolve` が**同じ画面で止まっている全ジョブ**をまとめて queued に
> 戻す(`resumeCaptchaJobsForSpace`)。どの画面を待っているかは `jobs.captcha_space_id`
> に残す——`jobs.space_id` は個人ワークスペースだと NULL のままなので代用できない。
> `WAIT_SUBTASKS` だけは現状 `rules[].next` にも書ける(rules ベース経由)。ツール版(WaitSubTask)を足すと、**同じ sentinel に「ルール不要の入口」**が増える。下流の `mapMovementResult` 分岐は共有。
## 新しい park ツールを足すレシピ
@@ -63,8 +72,25 @@ worker.ts
- **ツール内で同期ブロックして待たない。** 待機は必ず「停車=ワーカー解放」で表現する。in-tool で `await` し続けると親ワーカーを占有し、最悪ワーカー枯渇でデッドロックする(`WAIT_SUBTASKS` が遷移=停車である理由)。
- **resume 先を意識する。** `default_next` が `COMPLETE` のピース(単一 movement)で再開させると終了に飛ぶ。多くの待機ツールは**現在の movement に再入**させて、再開後に結果を読んで `complete` させる。
- **terminal と park を混同しない。** `COMPLETE`/`ABORT` はジョブを終わらせる(再開なし)。`WAITING_*`/`WAIT_SUBTASKS` は停車→再開。`resumeMovement` の有無が分かれ目。
- **停車から戻ったら同じ呼び出しが来る前提で書く。** 再開は movement を頭からやり直すので、LLM は同じ引数で同じツールをもう一度呼ぶ。決着済みの申請を掴んで短絡する経路(`RequestPackage` の `declinedPackages` / `installedPackages`、`SpinOffTask` の `findDecidedSpawnRequestForJob`)が無いと、却下で永久ループ・承認で 2 枚目のカードになる。
- **sentinel は `rules` の enum に出さない。** これらは engine-internal。`rules[].next` に書けるのは別 movement 名と `WAIT_SUBTASKS` のみ(`loadPiece`/lint が `COMPLETE`/`ABORT`/`ASK` を reject する)。
## KV キャッシュと tools 安定性(2026-07-22 実測・変更禁止事項)
transition ツールは **movement 毎ではなく piece 全体で 1 つ**(enum = `collectPieceTransitionTargets` による全 movement の遷移先の和集合、description は静的)。一見「その movement の rules だけを enum に出す」方が正しく見えるが、**戻してはいけない**。
根拠は llama-server (llama.cpp) への統制プローブと実タスク計測(`return_progress` の `prompt_cache` ログ、PR #931)で確定した以下の実測法則:
1. 追記のみのリクエスト → ほぼ全キャッシュ再利用(評価は追記分のみ)
2. 末尾付近の書き換え → 分岐点以降のみ再評価(部分再利用は健在)
3. 共通接頭辞が全体の半分未満 → 全損(`slot_prompt_similarity` 既定 0.5 の門前払い)
4. **tools 配列の変更 → 位置・大小問わず全損(description 1 文字でも)**
5. 描画順は system 本文 → tools → 会話(Qwen3 テンプレート)
movement 毎に transition ツールを作り替えると法則 4 に直撃し、**遷移のたびに会話全体 (~20k トークン / ~12 秒) を再評価**する(実測: 遷移直後の再利用率 0%、tools 安定なら 99%+)。movement 単位の遷移制約は runtime 検証(`processTransitionCalls` → `validateTransition`、無効なら有効選択肢つきエラーを tool result で返す)と、movement guidance の選択肢一覧(会話への追記なのでキャッシュ無害)が引き続き完全に担保している。
この構造を変更する場合は、開発サーバーで movement 遷移を跨ぐタスクを流し、`[llm-stream] ... prompt_cache reused=/pct=` で遷移直後の再利用率が 99% 台を維持することを必ず実測確認すること。
## 関連
- 設計: `docs/design/2026-06-26-subtask-wait-and-safety.html`(WaitSubTask ツール=この型の新規適用例)