This commit is contained in:
@@ -0,0 +1,387 @@
|
||||
# MAESTRO タスク実行アーキテクチャ
|
||||
|
||||
この文書は、MAESTROでタスク依頼を受け付けてから、Worker、Piece、Movement、LLM、ツール、承認、再試行、通知、UI反映を経て完了するまでの現行処理を示す。機能追加やリファクタリング時の影響確認に使用する。
|
||||
|
||||
## 文書の扱い
|
||||
|
||||
- 実装を正とし、処理経路を変更したPRではこの文書も更新する。
|
||||
- 通常経路だけでなく、ASK、承認待ち、サブタスク待ち、再試行、キャンセル、失敗を維持する。
|
||||
- 図中の名称は主要なファイル、関数、状態名に対応させる。
|
||||
- 特定機能の将来設計は含めず、現行コードの動作だけを記載する。
|
||||
|
||||
## 調査対象コミット
|
||||
|
||||
- 基準ブランチ: `origin/main`
|
||||
- PR #935実装コミット: `a86fea5523d9f8245cd42c53e3c1c167ccb26388`
|
||||
- 最終照合HEAD: `2ba26737742464f9ef7ccfd4459012e00175fd88`
|
||||
- 対象変更: PR #935「systemプロンプト静的化 + 動的コンテキスト末尾注入」
|
||||
- 調査日: 2026-07-24
|
||||
|
||||
## 主要な実装境界
|
||||
|
||||
| 境界 | 主なファイル・関数 |
|
||||
|---|---|
|
||||
| タスク作成 | src/bridge/local-tasks-crud-api.ts |
|
||||
| コメント・interjection・ASK再開 | src/bridge/local-tasks-comments-api.ts |
|
||||
| 継続・キャンセル | src/bridge/local-tasks-control-api.ts |
|
||||
| Tool承認 | src/bridge/local-tasks-tool-requests-api.ts |
|
||||
| Package承認 | src/bridge/local-tasks-package-requests-api.ts |
|
||||
| Job永続化・claim・再開 | src/db/repositories/jobs.ts |
|
||||
| Worker実行・終了処理 | src/worker.ts |
|
||||
| Piece・Movement制御 | src/engine/piece-runner.ts |
|
||||
| Agent iteration | src/engine/agent-loop.ts |
|
||||
| LLM stream | src/engine/agent-loop/llm-iteration.ts、src/engine/llm-stream.ts |
|
||||
| Tool dispatch | src/engine/agent-loop/tool-dispatcher.ts、tool-execution.ts |
|
||||
| チャット表示 | ui/src/components/chat/ChatPane.tsx、ChatMessageFeed.tsx |
|
||||
| 承認UI | ui/src/components/chat/ToolRequestApproval.tsx、PackageRequestApproval.tsx |
|
||||
| 通知・監査 | src/notifications/*、src/progress/*、ui/src/components/activity/* |
|
||||
|
||||
## 1. タスク依頼から完了までの全体フロー
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
U[ユーザー / 外部クライアント]
|
||||
UI[React UI<br/>CreateTaskDialog / ChatComposer]
|
||||
API_CREATE[POST /api/local/tasks]
|
||||
API_COMMENT[POST /api/local/tasks/:id/comments]
|
||||
API_CONTINUE[POST /api/local/tasks/:id/continue]
|
||||
OTHER[Scheduler / A2A / Reflection / Subtask]
|
||||
|
||||
U --> UI
|
||||
UI --> API_CREATE
|
||||
UI --> API_COMMENT
|
||||
UI --> API_CONTINUE
|
||||
|
||||
API_CREATE --> VALIDATE[入力・可視性・Space・LLM選択・添付検証]
|
||||
VALIDATE --> CLASSIFY[Piece選択 / Grounded固定 / LLM Router]
|
||||
CLASSIFY --> TASKDB[(local_tasks / comments)]
|
||||
CLASSIFY --> WORKSPACE[Space解決<br/>persistent/ephemeral workspace・runtime dir]
|
||||
WORKSPACE --> JOBDB[(jobs: queued)]
|
||||
|
||||
API_COMMENT --> WRITE_GATE[Task write gate]
|
||||
WRITE_GATE --> PREV{最新Job状態}
|
||||
PREV -->|running / dispatching / waiting_subtasks| INTERJECT[interjection comment保存<br/>既存Jobへ次iterationで投入]
|
||||
PREV -->|tool/package approval待ち| CONFLICT[409: 承認を先に要求]
|
||||
PREV -->|queued / retry| REUSE[既存pending Jobを再利用]
|
||||
PREV -->|ASK待ち・終端・Jobなし| FOLLOWUP[resumeMovement/askCount継承<br/>Job作成]
|
||||
REUSE --> JOBDB
|
||||
FOLLOWUP --> JOBDB
|
||||
|
||||
API_CONTINUE --> CONTINUE_GATE[所有権・Piece存在・前Job終端確認]
|
||||
CONTINUE_GATE --> HANDOFF[continuedFromJobIdとhandoff comment<br/>新Jobは transcript replay で前会話を引き継ぐ]
|
||||
HANDOFF --> JOBDB
|
||||
|
||||
OTHER --> JOBDB
|
||||
|
||||
JOBDB --> POLL[Worker.processNext polling]
|
||||
POLL --> CLAIM[retry期限優先→queued<br/>worker/model/profile適合<br/>issue lockなし]
|
||||
CLAIM --> RUNNING[原子的にstatus=running<br/>worker_id設定]
|
||||
RUNNING --> EXEC[Worker.executeJob]
|
||||
|
||||
EXEC --> PREP[workspace / reporter / Space / Piece / model / MCP / browser / context準備]
|
||||
PREP --> RUNPIECE[runPiece]
|
||||
RUNPIECE --> MOVEMENT[Movement loop]
|
||||
MOVEMENT --> RESULT{PieceRunResult}
|
||||
|
||||
RESULT -->|completed| SUCCESS[succeeded<br/>workspace commit・最終結果]
|
||||
RESULT -->|waiting_human: ASK| ASKWAIT[waiting_human<br/>回答コメントで再開]
|
||||
RESULT -->|waiting_human: tool_request| TOOLWAIT[waiting_human<br/>承認APIで再開]
|
||||
RESULT -->|waiting_human: package_request| PKGWAIT[waiting_human<br/>承認・install後に再開]
|
||||
RESULT -->|waiting_subtasks| SUBWAIT[子Job完了待ち<br/>全完了で親queued]
|
||||
RESULT -->|cancelled| CANCELLED[cancelled<br/>子Job取消]
|
||||
RESULT -->|error / aborted| RETRY{再試行可能か}
|
||||
RETRY -->|yes| RETRYDB[retry + next_retry_at]
|
||||
RETRY -->|fatal / 上限| FAILED[failed]
|
||||
|
||||
ASKWAIT --> API_COMMENT
|
||||
TOOLWAIT --> APPROVE_TOOL[tool request decide API]
|
||||
APPROVE_TOOL -->|approve/deny| JOBDB
|
||||
PKGWAIT --> APPROVE_PKG[package request decide API]
|
||||
APPROVE_PKG -->|approve/deny| JOBDB
|
||||
SUBWAIT --> JOBDB
|
||||
RETRYDB --> POLL
|
||||
|
||||
SUCCESS --> EVENTS[Audit / events.jsonl / activity / metrics]
|
||||
ASKWAIT --> EVENTS
|
||||
TOOLWAIT --> EVENTS
|
||||
PKGWAIT --> EVENTS
|
||||
SUBWAIT --> EVENTS
|
||||
CANCELLED --> EVENTS
|
||||
FAILED --> EVENTS
|
||||
EVENTS --> NOTIFY[Push / Webhook / Notification projection]
|
||||
EVENTS --> UIREFRESH[REST polling + SSE stream]
|
||||
UIREFRESH --> UI
|
||||
```
|
||||
|
||||
## 2. WorkerとPiece実行
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Worker.processNext]
|
||||
A --> B[claimNextRetryJob または claimNextJob]
|
||||
B --> C[runJobTracked]
|
||||
C --> D[executeJob]
|
||||
D --> E[issue lock取得 / running監査 / Push]
|
||||
E --> F{Reflection Jobか}
|
||||
F -->|yes| FR[Reflection専用経路]
|
||||
F -->|no| G[prepareJobWorkspace]
|
||||
G --> H[Space・folderContext・runtimeDir解決]
|
||||
H --> I[Piece読込・定義検証]
|
||||
I --> J{worker/model適合}
|
||||
J -->|不一致| JQ[queuedへ戻す]
|
||||
J -->|適合| K{required MCP tokenあり}
|
||||
K -->|不足| KH[waiting_human: mcp_auth_required]
|
||||
K -->|OK| L[LLM client生成]
|
||||
L --> M[Tool Policy・SSH・grant・package解決]
|
||||
M --> N[Mission / conversation / provenance / browser / skill context]
|
||||
N --> O[runPiece]
|
||||
O --> P[EventLogger・Conversation・ContextManager初期化]
|
||||
P --> P2{continuedFromJobIdあり<br/>= Continue経由}
|
||||
P2 -->|yes| REPLAY[transcript.jsonl を loadFrom → allReplayableThreads<br/>全スレッドを古い順に連結(system行が境界)<br/>掃除はスレッド毎・重複call_idは付け替え<br/>transition保持は最終スレッドかつ同一pieceのときだけ<br/>seedContinuation で新会話の頭に再生]
|
||||
P2 -->|no| Q
|
||||
REPLAY --> Q[開始Movement選択<br/>resume > override > piece start]
|
||||
Q --> R[loop/revisit/cancel guard]
|
||||
R --> S[prepareMovementContext]
|
||||
S --> T[executeMovement]
|
||||
T --> U[MovementResult mapping]
|
||||
U --> V{next}
|
||||
V -->|別Movement| Q
|
||||
V -->|COMPLETE / ASK / WAIT / ABORT| W[PieceRunResult]
|
||||
W --> X[handlePieceResult]
|
||||
X --> Y[DB状態・コメント・監査・通知・親子Job処理]
|
||||
Y --> Z[heartbeat/guard停止・metrics・unlock]
|
||||
```
|
||||
|
||||
`prepareMovementContext`では、Workspace Tool Policyを唯一のtool/edit/SSH権限源とし、タスク内承認済みtoolをunionする。task instructionへ、Movement feedback、follow-up notice、subtask resume notice、checklist、lessonsを加える。
|
||||
|
||||
transcript(`runs/{taskId}/transcript.jsonl`)はタスクのruntime directoryに置く正規化された会話記録で、通常はturnを追記し、Continuation seedやprompt guardによる整形時には全体を再構築する。**transcript replayが走るのはContinue経由(`continuedFromJobId`あり)のみ**。コメントやASK回答による新Jobではreplayせず、コメント文脈をtask instructionへ含める。この場合に再利用可能なのは条件が一致する静的接頭辞までで、実際の再利用量は保証しない。replayの整形規則は`Conversation.replayableTurns`を参照。
|
||||
|
||||
## 3. Movement・LLM・ツール内部
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
M0[executeMovement] --> M1[prepareMovement]
|
||||
M1 --> TOOLS[getToolDefs + complete<br/>遷移先があるPieceではtransitionも追加]
|
||||
M1 --> STATIC[static preamble構築<br/>AGENTS・Memory・Skills・tool説明]
|
||||
M1 --> DYNAMIC[dynamic context構築<br/>時刻・files・Mission・handoff・console]
|
||||
M1 --> GUIDE[Movement guidance + task instruction]
|
||||
M1 --> SEED[プロンプト要素をConversationへ順序どおり配置]
|
||||
STATIC --> SEED
|
||||
DYNAMIC --> SEED
|
||||
GUIDE --> SEED
|
||||
SEED --> DCFG{delegate許可かつ<br/>再帰深度上限未満}
|
||||
DCFG -->|yes| DINJECT[runDelegateをtoolCtxへ注入]
|
||||
DCFG -->|no| LOOP[iteration loop]
|
||||
DINJECT --> LOOP
|
||||
TOOLS --> REQUEST[LLM request入力<br/>toolsはConversationの外で保持]
|
||||
|
||||
LOOP --> CANCEL{cancel/deadline signal}
|
||||
CANCEL -->|yes| MCANCEL[cancel result]
|
||||
CANCEL -->|no| INJECT[未処理interjectionをuser messageへ追加]
|
||||
INJECT --> WATCH[watchdog / loop guard]
|
||||
WATCH --> PGUARD[prompt guard<br/>estimate・dedup・compact・summarize]
|
||||
PGUARD -->|overflow復旧不能| ABORT[context overflow result]
|
||||
PGUARD -->|変更あり| REWRITE[Conversation.rewrite<br/>正規化後transcriptを再構築]
|
||||
PGUARD -->|変更なし| LLM[runLlmIteration]
|
||||
REWRITE --> LLM
|
||||
REQUEST --> LLM
|
||||
LLM --> CLIENT_GUARD[LLM client側の<br/>最終token上限検査]
|
||||
CLIENT_GUARD --> STREAM[OpenAI-compatible streaming<br/>text/tool deltas/usage/retry/thinking/backend]
|
||||
STREAM --> ERR{LLM error}
|
||||
ERR -->|recoverable| LOOP
|
||||
ERR -->|terminal| LERR[llm error result]
|
||||
ERR -->|no error| CALLS{tool callsあり}
|
||||
|
||||
CALLS -->|なし| TEXT[text-only warning/retry]
|
||||
TEXT --> LOOP
|
||||
CALLS -->|あり| SPLIT[regular と transition/completeを分類]
|
||||
SPLIT --> TLOOP[重複tool loop判定]
|
||||
TLOOP -->|上限| TABORT[tool loop abort]
|
||||
TLOOP --> DISPATCH[dispatchRegularToolCalls]
|
||||
DISPATCH --> PAR{read-only parallel可能か}
|
||||
PAR -->|yes| PEXEC[Promise.all]
|
||||
PAR -->|no| SEXEC[sequential]
|
||||
PEXEC --> TOOL[executeRegularToolCallCached]
|
||||
SEXEC --> TOOL
|
||||
TOOL --> AUTH[tool存在・引数・権限・sandbox・cache]
|
||||
AUTH --> TOOL_KIND{delegateか}
|
||||
TOOL_KIND -->|yes| DELEGATE[runDelegateSubAgent<br/>隔離した子ConversationでexecuteMovement]
|
||||
TOOL_KIND -->|no| IMPL[各tool execute]
|
||||
DELEGATE --> TResult[tool_resultをconversation・UI・eventへ記録]
|
||||
IMPL --> TResult
|
||||
|
||||
TResult --> WAIT{待機フラグ}
|
||||
WAIT -->|browser| WB[waiting_human]
|
||||
WAIT -->|tool request| WT[waiting_human tool_request]
|
||||
WAIT -->|package request| WP[waiting_human package_request]
|
||||
WAIT -->|subtask| WS[waiting_subtasks]
|
||||
WAIT -->|なし| TERM{complete / transition winner}
|
||||
TERM -->|complete success + pending child| WS
|
||||
TERM -->|complete| COMPLETE[completed / needs_user_input / abort mapping]
|
||||
TERM -->|transition valid| TRANS[next Movement]
|
||||
TERM -->|invalid| RET[tool_result errorを追加してiteration再試行]
|
||||
TERM -->|none| LOOP
|
||||
```
|
||||
|
||||
`tools`はConversationへ格納されない。`prepareMovement`が`messages`と並ぶ別の戻り値として返し、`runLlmIteration`へ渡す。`delegate`は通常tool dispatchの一種だが、実行前に`runDelegate`を`toolCtx`へ注入し、呼び出された場合は隔離した子Conversationで再帰的に`executeMovement`を実行する。
|
||||
|
||||
### 3.1 LLMリクエストのキャッシュ境界
|
||||
|
||||
PR #935以降は、単にプロンプトの内容を分割するだけでなく、LLMへ渡す`tools`と`messages`の順序を次の形に固定する。図中の「キャッシュ再利用可能」は、同一モデル・同一チャットテンプレート・同一Pieceなど、先行要素がバイト一致し、バックエンド側に対象キャッシュが残っている場合を表す。再利用量そのものを保証するものではない。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
REGULAR[Workspace Tool Policyで解決した<br/>regular tools] --> TOOLS[tools配列を構築]
|
||||
TRANSITION[transition<br/>遷移先がある場合のみ<br/>enumはPiece全体の和集合] --> TOOLS
|
||||
COMPLETE[complete] --> TOOLS
|
||||
TOOLS --> TOOLS_STABLE[同一Piece内でtools配列を<br/>バイト単位で安定化]
|
||||
|
||||
STATIC[static preamble<br/>共通ルール・tool概要・AGENTS・Memory Index<br/>Skills Index・Working Directory] --> SYSTEM[先頭の単一system message]
|
||||
FIRST_GUIDANCE[開始Movement guidance] --> SYSTEM
|
||||
SYSTEM --> REPLAY{Continueかつ<br/>再生可能transcriptあり}
|
||||
REPLAY -->|yes| PRIOR[過去の非system turnを順番に再生]
|
||||
REPLAY -->|no| NO_PRIOR[過去turnなし]
|
||||
PRIOR --> USER[末尾の単一user message]
|
||||
NO_PRIOR --> USER
|
||||
DYNAMIC[dynamic context<br/>日時・Mission・files・console<br/>handoffは再生可能turnがないContinue時のみ] --> USER
|
||||
INSTRUCTION[task instruction] --> USER
|
||||
USER --> MESSAGES[messages配列完成]
|
||||
|
||||
TOOLS_STABLE --> REQUEST[LLM request]
|
||||
MESSAGES --> REQUEST
|
||||
TOOLS_STABLE -. キャッシュの先行条件 .-> SYSTEM
|
||||
SYSTEM -. 同一なら静的接頭辞を再利用 .-> PRIOR
|
||||
PRIOR -. 過去requestと一致する範囲を再利用 .-> USER
|
||||
USER -. ここから新規評価 .-> GENERATE[生成開始]
|
||||
```
|
||||
|
||||
実際のメッセージ列は次の形になる。`dynamic context`と`task instruction`は、厳密なrole交互制約を持つモデルでも扱えるよう、別々の`user` messageではなく一つに結合する。
|
||||
|
||||
```text
|
||||
tools = [regular tools..., transition(遷移先がある場合), complete]
|
||||
|
||||
messages = [
|
||||
system(static preamble + 開始Movement guidance),
|
||||
...replayable prior turns, // Continue時のみ
|
||||
user(dynamic context + task instruction),
|
||||
]
|
||||
```
|
||||
|
||||
Movement 2以降のguidance、interjection、watchdog警告などは、既存会話の末尾へ`user` messageとして追加する。先頭へ挿入しないため、そこまでのキャッシュ済み接頭辞を壊さない。
|
||||
|
||||
### 3.2 初回・遷移・再開経路ごとのプロンプト構築
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
START[Job開始] --> KIND{開始・再開の種類}
|
||||
|
||||
KIND -->|新規Job| NEW[Conversation.seed]
|
||||
NEW --> NEW_MESSAGES["system: static + 開始guidance<br/>user: dynamic + instruction"]
|
||||
NEW_MESSAGES --> NEW_CACHE[過去turnの再利用なし]
|
||||
|
||||
KIND -->|同一Job内のMovement遷移| MOVE[Conversation.enterMovement]
|
||||
MOVE --> MOVE_MESSAGES["既存messages末尾へ<br/>user: 次Movement guidance"]
|
||||
MOVE_MESSAGES --> MOVE_CACHE["toolsはPiece内で安定<br/>既存prefixをそのまま再利用可能"]
|
||||
|
||||
KIND -->|同一PieceをContinue| SAME[loadFrom → replayableTurns<br/>keepTransitions=true]
|
||||
SAME --> SAME_MESSAGES["systemを新しく構築<br/>過去の非system turnを再生<br/>Error回答でないcompleteを除去<br/>handoffを省略して末尾へdynamic + instruction"]
|
||||
SAME_MESSAGES --> SAME_CACHE["static・tools・再生turnが一致する範囲を再利用可能"]
|
||||
|
||||
KIND -->|別PieceをContinue| CROSS[loadFrom → replayableTurns<br/>keepTransitions=false]
|
||||
CROSS --> CROSS_MESSAGES["旧Pieceのtransitionを除去<br/>新Pieceのsystem・toolsを使用<br/>再生turnがあればhandoffを省略"]
|
||||
CROSS_MESSAGES --> CROSS_CACHE["Piece固有のguidance/toolsが変わるため<br/>同一Piece相当の再利用は保証しない"]
|
||||
|
||||
KIND -->|コメント・ASK回答による新Job| COMMENT[transcript replayなし]
|
||||
COMMENT --> COMMENT_MESSAGES["system: static + 開始guidance<br/>user: dynamic + コメント文脈を含むinstruction"]
|
||||
COMMENT_MESSAGES --> COMMENT_CACHE["条件が一致する静的接頭辞のみ再利用可能<br/>再利用量は保証せず、過去turnも再生しない"]
|
||||
```
|
||||
|
||||
### 3.3 transcript replayの整形
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
LOAD[transcript.jsonlをloadFrom] --> THREAD[system行を境界にスレッド分割<br/>全スレッドを古い順に連結<br/>掃除はスレッド毎・重複call_idは付け替え]
|
||||
THREAD --> DROP_SYSTEM[スレッド先頭のsystemを除外]
|
||||
DROP_SYSTEM --> COMPLETE_CHECK{assistantにcompleteがあるか}
|
||||
COMPLETE_CHECK -->|Errorで始まる結果あり| KEEP_COMPLETE[拒否された中間completeを保持]
|
||||
COMPLETE_CHECK -->|結果なし、またはError以外| DROP_COMPLETE[completeを除外]
|
||||
DROP_COMPLETE --> DROP_COEMITTED[同じassistant messageで<br/>同時出力されたtransitionも除外]
|
||||
COMPLETE_CHECK -->|completeなし| TRANSITION_CHECK{transitionか}
|
||||
KEEP_COMPLETE --> TRANSITION_CHECK
|
||||
DROP_COEMITTED --> VALIDATE
|
||||
TRANSITION_CHECK -->|回答済みtransition かつ keepTransitions=true<br/>(最終スレッドかつ同一PieceのContinue)| KEEP_TRANSITION[call/resultペアを保持]
|
||||
TRANSITION_CHECK -->|keepTransitions=false<br/>(別PieceのContinue、および古いスレッドでは一括除去)| DROP_TRANSITION[除外]
|
||||
TRANSITION_CHECK -->|通常tool call| KEEP_REGULAR[call/resultペアを保持]
|
||||
KEEP_TRANSITION --> VALIDATE[未回答call・孤立result・空assistantを除外]
|
||||
DROP_TRANSITION --> VALIDATE
|
||||
KEEP_REGULAR --> VALIDATE
|
||||
VALIDATE --> SEED_CONTINUATION[seedContinuation]
|
||||
```
|
||||
|
||||
判定基準は厳密には「成功済みか」ではなく、対応するtool resultが`Error`で始まるかである。`Error`回答された`complete`は、その後も会話が続いた中間履歴として保持する。結果がない、または`Error`以外の`complete`は除外し、同じassistant messageで同時出力された`transition`も一緒に除外する。
|
||||
|
||||
transcriptはタスクのruntime directoryに置く会話記録で、コメント追いメッセージのJobは新しいスレッド(先頭はsystem)を追記するため複数スレッドが蓄積し得る。replayは蓄積された全スレッドを古い順に連結して使う(`Conversation.allReplayableThreads`。issue #1343。以前は最後の再生可能スレッドだけを採っていたが、質問への回答で前の話が落ちる形で表に出たため既定から外した。経緯は docs/design/2026-07-26-transcript-last-thread-replay.html の冒頭の注記)。掃除(`replayableTurns`)はスレッド毎にかける——まとめてかけると、別スレッドが同じ`tool_call`のidを使い回したときに対応付けが狂い、終了済みの`complete`が生き残る。連結後にスレッドをまたいで重なったidは決定的に付け替える(`gen_call_{n}`はジョブ毎に1番から振り直されるため実際に重なる)。`keepTransitions`は最終スレッドにだけ当てる——その値の元になる`samePieceContinuation`は直前のジョブ1件から決まる判断で、古いスレッドがどのpieceで走ったかは記録に無いため。**最終スレッドが空でない限り**、この形でも連結前より再生量は増える(古いスレッドは以前は捨てていた)。例外は最終スレッドが空のとき——クラッシュや書き込み途中で切れてsystem行しか無いジョブがそれで、以前の`lastReplayableThread`は空スレッドを飛ばして1つ前を採っていたため、そこに`keepTransitions`が当たっていた。いまは1つ前が「古いスレッド」扱いになり遷移が落ちるので、この形では再生量が減る。遷移を落とす向きは安全側なので意図してそのままにしている。通常のturn追加では追記するが、`seedContinuation`と、prompt guardのdedup・compact・summarizeによってmessagesが変わった場合は、`Conversation.rewrite()`でファイル全体を再構築する。
|
||||
|
||||
### 3.4 キャッシュを維持するための変更時ルール
|
||||
|
||||
| 対象 | 維持すべき条件 | 変更時の影響 |
|
||||
|---|---|---|
|
||||
| `tools`配列 | Workspace Tool Policy、task内grant、動的tool module条件が不変なら、同一Piece内で名前、順序、schema、descriptionを安定させる | 1バイトでも変わるとllama.cppで全prompt cache missになり得る |
|
||||
| transition | 遷移先があるPieceだけ追加し、enumはPiece全体の和集合にする | Movementごとの差分がtools配列に入ると全prompt cache missになり得る |
|
||||
| static preamble | 日時、Mission、files、handoff、consoleを入れない | Jobごとの差分が先頭に入り、継続時の共有prefixを失う |
|
||||
| system message | index 0の一つだけにする | 厳格なchat templateで拒否される可能性がある |
|
||||
| dynamic context | task instructionと一つの末尾`user` messageに結合する | 連続した`user` roleに対応しないモデルで失敗し得る |
|
||||
| Movement guidance | 2番目以降は会話末尾へ`user`として追記する | 先頭を書き換えると既存prefixを無効化する |
|
||||
| 同一Piece transition | replay時に回答済みcall/resultを保持する | 中間履歴を削ると、その位置以降のcacheが分岐する |
|
||||
| Error以外のcomplete | replayから除外し、同時出力transitionも除外する | 再生すると継続Jobが即時完了を模倣する可能性がある |
|
||||
|
||||
キャッシュ再利用量は`llm-stream`の`prompt_cache reused=... prompt=... pct=...`ログと、LLMイベントの`cachedPromptTokens`で確認する。構造を変更した場合は、単体テストだけでなく実バックエンドでMovement遷移直後とContinue直後の再利用率を測定する。
|
||||
|
||||
## 4. 待機・再開・通知・UI
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Agent as Agent Loop
|
||||
participant Worker
|
||||
participant DB
|
||||
participant API
|
||||
participant UI as Chat UI
|
||||
participant Notify as Push/Webhook/Inbox
|
||||
|
||||
Agent->>Worker: PieceRunResult(waiting_human)
|
||||
Worker->>DB: status=waiting_human, waitReason, resumeMovement
|
||||
Worker->>Notify: waiting_human event
|
||||
UI->>API: task/tool/package request polling
|
||||
API->>DB: pending request取得
|
||||
API-->>UI: 承認カード / ASK表示
|
||||
|
||||
alt ASK
|
||||
UI->>API: POST comment
|
||||
API->>DB: resumeMovementとaskCountを継承したJob作成
|
||||
else Tool Request
|
||||
UI->>API: approve / deny
|
||||
API->>DB: grantまたはdeny + parked Jobをqueuedへ戻す
|
||||
else Package Request
|
||||
UI->>API: approve / deny
|
||||
API->>DB: CAS決定、必要なら隔離install、parked Jobをqueuedへ戻す
|
||||
end
|
||||
|
||||
DB-->>Worker: 次回pollでclaim
|
||||
Worker->>Agent: 同一Movementから再実行
|
||||
Agent->>Worker: completed / failed / cancelled
|
||||
Worker->>DB: 終端status・comment・audit・event
|
||||
Worker->>Notify: succeeded / failed
|
||||
DB-->>UI: task/comments/activity更新
|
||||
```
|
||||
|
||||
チャットUIでは `ChatPane → ChatMessageFeed → ChatMessage` が永続コメントを表示し、`ChatComposerPanel`がTool RequestとPackage Requestの承認カードを表示する。`useJobStream`は生成中text、tool call、LLM状態、delegate streamを反映する。Activityは`ActivityTimeline`、短期通知はToast、要対応通知はNotification Bell/Centerが担う。
|
||||
|
||||
### 4.1 Auto Prompterの透明性境界
|
||||
|
||||
Auto Prompterが有効なJobでは、ツール実行前に固定済みPolicy Snapshotを評価し、追加指示、拒否、引数に結び付いた一回限りの承認を行う。発火結果は許可リスト形式のPolicy Eventとして記録し、チャットへ通知する。無効なJobではこの経路を短絡し、従来のツール実行経路を変えない。
|
||||
|
||||
Policy Eventは追跡可能性を支援するbest-effort監査であり、hidden chain-of-thought、生のツール引数、認証情報、prompt全文を保存しない。記録失敗だけを理由にエージェント処理を停止する保証型台帳でもない。
|
||||
|
||||
この機構はEU AI Actその他の法令への準拠を自己宣言しない。Article 50だけでchain-of-thought保存や一律5年保持が要求されるとは解釈せず、適用範囲、事業者の役割、保持期間は法務確認の対象とする。保持期間の設定は将来のCompliance Phaseで扱う。詳細は [EU AI Act透明性対応 設計付録](./auto-prompter-eu-ai-act-transparency-design.md) を参照する。
|
||||
|
||||
一次資料: [Regulation (EU) 2024/1689](https://eur-lex.europa.eu/eli/reg/2024/1689/oj/eng)、[European Commission: AI Act](https://digital-strategy.ec.europa.eu/en/policies/regulatory-framework-ai)
|
||||
Reference in New Issue
Block a user