diff options
| author | tanaka takashi <isazaka@gmail.com> | 2026-08-11 21:44:53 +0900 |
|---|---|---|
| committer | tanaka takashi <isazaka@gmail.com> | 2026-08-11 21:44:53 +0900 |
| commit | 6c3458a5ec37a5b69957ad17c84de58984698f25 (patch) | |
| tree | be5c5716e7488fcf1bc1a58de0ded0b9238f34cb /doc | |
| parent | b5ccecca01007f2a2459265df6d749fbfd31aa84 (diff) | |
Audit and align v1 runtime design
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/AuditReport.md | 28 | ||||
| -rw-r--r-- | doc/Design.md | 40 | ||||
| -rw-r--r-- | doc/Specifications.md | 19 |
3 files changed, 67 insertions, 20 deletions
diff --git a/doc/AuditReport.md b/doc/AuditReport.md new file mode 100644 index 0000000..937c155 --- /dev/null +++ b/doc/AuditReport.md @@ -0,0 +1,28 @@ +# v1再監査報告 + +## 基準 + +2026-08-11、commit `b5ccecc`を起点とする現行working treeを対象とした。2026-08-09のPhase/Release証跡は履歴として扱い、現行PASS判定には流用していない。 + +## 確認した矛盾と是正 + +| 観点 | 監査時の状態 | 是正 | +|---|---|---| +| Internal Tool | 仕様・設計・計画で5群/6群が混在 | 仕様から数とcatalogを除去。外部性質だけを残し、名前/schemaをDesignのTool catalogへ移管 | +| policy deny | 初回failedと最大3回replanが混在 | 同一呼出しへ再投入しない条件付きreplanへ統一。同一deny、計画未変更、実行不能、replan失敗でfailed | +| Skill形式 | READMEにlegacy互換記述 | `<skill-name>/SKILL.md`だけに統一 | +| Task完了 | 実行Taskなしでもcompletedになり得た | TaskGraph全件completedだけを完了条件とし、実行不能は理由付きfailedへ変更 | +| Planner fallback | 空/不正planから曖昧なfallback graphを生成 | `think=false`で1回だけ再試行し、再失敗はplanning failureへ変更 | +| task_update | LLMが状態遷移可能 | Tool catalogには維持し、Task追加/dependency追加/estimate変更だけに限定 | +| cancel | CancellationToken通知時点でterminal | Task Resource cleanup完了後だけcancelled。cleanup失敗はfailed | +| progress/token | progress固定値、phase別token欠落 | TaskGraph同期、critical path実値、全Ollama phase集計へ変更 | +| context | 閾値超過時に単純削除 | structured要約成功後だけcompactし、失敗時は原文保持 | +| Configuration | validationのみでruntime未接続、local overrideなし | max_tasks/num_ctx/ratio/timeoutを接続し、`agent.local.yaml` mergeを追加 | +| CLI/運用 | `serve`必須、publish後の環境値復旧が必要 | 引数なし/先頭optionをserve化。local prompt/Skill/configをBundle対象外に分離 | +| Logging/Audit | 相関field・iteration・event名が不一致 | LLM相関/rotationとAudit必須eventへ統一。read-only JSONL viewerを追加 | + +## 現在の判定 + +Release buildはwarning 0/error 0、Core 78件とPlanner 10件はPASS/skip 0となった。self-contained Bundle、ZIP、checksumも生成し、local overrideが非同梱であることを確認した。Windows suiteは22/41件がPASSしたが、残り19件はWFP/loopbackのWin32 error 5またはsymlink privilege不足で、実際の管理者tokenでは再検証できていない。AppContainer、ACL、Job、WFP、Recovery crash matrix、Bundle runtime check、stdio/HTTP Operational E2Eは`PARTIAL`または`NOT REVERIFIED`のままとする。詳細は`plans/RequirementTraceability.md`を正本とする。 + +既存の仕様語彙で表現できない独立概念は実装へ追加していない。今回追加したlocal override、status診断field、ログ相関fieldは実装前にSpecifications/Designへ定義した。 diff --git a/doc/Design.md b/doc/Design.md index 798a134..dfce7f3 100644 --- a/doc/Design.md +++ b/doc/Design.md @@ -194,6 +194,10 @@ completed_tasks: <n>/<total> current_task: <localized summary or empty> token_usage: input=<n> output=<n> total=<n> critical_path_tokens: <n> +iterations: <n> +replans: <n> +last_error_code: <stable code or empty> +last_error: <localized message or empty> message: <localized status> result: <final natural-language answer; completed only> ``` @@ -249,14 +253,14 @@ overrideはTask objectにcopyし、global configurationを変更しない。Sess - 既定上限は4画像、1画像10 MiB、request合計20 MiBとする。 - model capability確認でVision非対応と判定した場合はOllama呼出し前にlocalized error。能力確認不能時は呼出しを行い、Ollama errorを正規化して返す。 ### 6.5 Tool calling -Ollamaに公開するInternal Toolは次の6群に固定する。個々のOS command (`grep.exe`等) をtoolとして増殖させない。 +Ollamaに公開する現行Internal Tool catalogは次のとおりとする。個々のOS command (`grep.exe`等) をtoolとして増殖させない。catalogの構成は設計事項であり、仕様上の固定数として扱わない。 | Tool | 責務 | 主なoperation | | --- | --- | --- | | file_search | 検索 | glob / name / text / regex / tail相当 | | file_read | 読取 | whole / range / metadata | | file_edit | 編集 | overwrite / patch / atomic_replace / delete | | process_run | 承認済Process実行 | exe + args + cwd + timeout | -| task_update | TaskGraph更新 | add / dependency / state / estimate | +| task_update | TaskGraph更新 | add / dependency / estimate | | dir | ディレクトリ操作 | mkdir / rmdir / list | --- ## 7. Internal Tool Schema設計 @@ -308,17 +312,17 @@ Ollamaに公開するInternal Toolは次の6群に固定する。個々のOS com ### 7.5 task_update ```json { - "operation":"add|add_dependency|set_state|set_estimate", + "operation":"add|add_dependency|set_estimate", "task_id":"string|null", "description":"string|null", "depends_on":["string"], "budget_class":"1K|2K|4K|8K|16K|32K|64K|128K|null", "optimistic_tokens":0, "most_likely_tokens":0, - "pessimistic_tokens":0, - "state":"queued|planning|running|completed|failed|cancelled|null" + "pessimistic_tokens":0 } ``` +Task状態遷移はAgent Runtimeだけが行う。`task_update` はTask追加、dependency追加、estimate変更に限定し、LLMから状態を変更するschemaを公開しない。 PlannerがDAG、不変条件、completed immutable、max_tasksを再検査してから適用する。 ### 7.6 dir ```json @@ -330,7 +334,7 @@ PlannerがDAG、不変条件、completed immutable、max_tasksを再検査して - 既存の PathPolicy / CanonicalPath / TaskAclManager (root継承ACE) / TaskResourceJournal / RecoveryManager 枠組みを利用する。新規作成ディレクトリは親の継承ACEを自動取得するため追加ACL操作は不要。 - mkdir後crash → ディレクトリ削除、rmdir後crash → 空ディレクトリ再作成、でRecoveryする。 ### 7.7 ToolUseGuard -Taskには `requires_external_effect` をPlanner内部属性として持たせる。**Planning フェーズで LLM structured output により Task ごとに判定・設定される**(keyword heuristic ではない)。trueのTaskで、当該iteration中のtool callが0かつ完了証拠がない場合、LLMへ「未実行」を示すsystem-generated observationを追加して再試行する。同一失敗fingerprintが5回に達したらTaskをfailedにする。ただし、Policy EngineのdenyおよびSandbox backendの`UnauthorizedAccessException`は`RetryAllowed=false`のterminal Tool resultへ変換する。Runtimeはobserverへ結果を1回記録した直後にTaskをfailedへ遷移させ、LLMへ再投入しない。Policy deny後は再計画(replan)が可能(§8.4)。 +Taskには `requires_external_effect` をPlanner内部属性として持たせる。**Planning フェーズで LLM structured output により Task ごとに判定・設定される**(keyword heuristic ではない)。trueのTaskで、当該iteration中のtool callが0かつ完了証拠がない場合、LLMへ「未実行」を示すsystem-generated observationを追加して再試行する。同一失敗fingerprintが5回に達したらTaskをfailedにする。ただし、Policy EngineのdenyおよびSandbox backendの`UnauthorizedAccessException`は`RetryAllowed=false`のterminal Tool resultへ変換する。Runtimeはobserverへ結果を1回記録した後、同一Tool呼出しへ再投入せず、§8.4の条件付きreplanへ遷移する。 --- ## 8. Token Planner設計 ### 8.1 Task model @@ -364,7 +368,10 @@ topological sort後にforward passで各Taskの累積expected token costを計ç® - 実績がPを超過しても即失敗にはせず、remaining Taskのestimate見直しをLLMへ要求できる。 - `max_tasks=32`超過提案は拒否し、既存Taskの統合をLLMへ求める。 - Budget Classは意味的Taskを分割する唯一の理由にしない。Taskが複数独立成果物を含む場合に分割する。 -- Policy deny時は replan を最大3回まで試行可能。同一 deny が繰り返される場合は Failed へ遷移。 +- Policy denyは同一Tool呼出しへ再投入しない。許可済み能力だけで代替できる可能性がある場合、`running -> planning -> running` と遷移してreplanを最大3回まで試行できる。 +- completed TaskのID、状態、usageを保持する。failed Taskをdependency解決済みとして扱わない。 +- 同一deny fingerprintの再発、計画未変更、実行可能Taskなし、structured replan失敗は即Failedとする。全Taskがcompletedの場合だけAgent Taskをcompletedにする。 +- structured planが空または不正な場合は`think=false`で1回だけ再試行し、それでも失敗した場合はplanning failureとする。外部効果要否が不明なfallback graphは作成しない。 ### 8.5 Ollama usage集計 1 Ollama callの `prompt_eval_count` をTask inputへ、`eval_count` をTask outputへ加算する。tool実行そのものにはtoken costを加算しない。context summary生成に使ったtokenはSession maintenance Taskとして別集計する。 --- @@ -462,6 +469,7 @@ skills: logging: directory: logs ``` +base YAMLと同じdirectoryに`agent.local.yaml`が存在する場合、YAML nodeを読み取ってmapを再帰mergeし、scalarとsequenceはlocal nodeで置換してからtyped configurationへdeserializeする。unknown propertyを含むvalidationはmerge後に行い、全相対pathのbaseはbase YAMLのdirectoryとする。local file、そこから参照するUser System PromptおよびSkill directoryはRelease Bundleのpublish入力に含めない。 ### 10.2 Filesystem entry 各list itemはpath文字列とする。起動時に絶対canonical pathへ正規化して保持する。file/directoryは実在時に種別を記録し、未作成write targetは最も近い既存親directoryまで検査する。 ### 10.3 Process approval entry @@ -599,7 +607,7 @@ patchは適用前にtarget hashまたはcontext一致を検査する。曖昧適 - log levelは設定可能だがCLI optionにはしない。 - stdoutへ通常ログを出すコードはtestで禁止する。 ### 15.2 LLM log -call ID、session ID、task ID、model、request metadata、prompt、response、tool_calls、token usageを記録する。秘密情報の自動継承は禁止だが、利用者入力にsecretが含まれる可能性はあるためlog directoryはuser-only ACLにする。 +call ID、session ID、task ID、Planner Task ID、phase、iteration、replan番号、model、request metadata、prompt、response、tool_calls、token usageを記録する。Planning、Skill選択、再計画、実行、context要約を同じ相関形式で記録し、Tool resultにもcall IDとiterationを付ける。秘密情報の自動継承は禁止だが、利用者入力にsecretが含まれる可能性はあるためlog directoryはuser-only ACLにする。既存rotation設定はLLM logにも適用する。 ### 15.3 Audit JSONL Auditはappend-only JSONLを採用する。1 event = 1 line。 ```json @@ -607,7 +615,7 @@ Auditはappend-only JSONLを採用する。1 event = 1 line。 {"ts":"...","event":"file.write","task_id":"...","path":"...","before_sha256":"...","after_sha256":"..."} {"ts":"...","event":"policy.deny","task_id":"...","kind":"network","target":"example.com:443","reason":"not_allowlisted"} ``` -最低event集合: `task.start`, `task.end`, `tool.call`, `process.start`, `process.exit`, `file.write`, `file.delete`, `policy.deny`, `network.rule.apply`, `network.rule.remove`, `recovery.start`, `recovery.end`. +最低event集合: `task.start`, `task.end`, `tool.call`, `process.start`, `process.exit`, `file.write`, `file.delete`, `policy.deny`, `network.rule.apply`, `network.rule.remove`, `recovery.start`, `recovery.end`。各eventは可能な限りsession ID、task ID、内部error codeを持つ。 --- ## 16. Recovery・終了設計 ### 16.1 graceful stop @@ -727,7 +735,7 @@ errorは内部codeとlocalized messageを分離し、ログ/auditにはcode、MC ## 22. Codex実装制約 - 新規NuGet dependencyを勝手に追加しない。追加時は標準ライブラリで不能な理由を示す。 - MCP Toolを `agent_run` / `agent_status` 以外に増やさない。 -- Internal ToolをOSコマンド名ごとに増やさず、定義済み6群に収める。 +- Internal ToolをOSコマンド名ごとに増やさず、本章のTool catalogとschemaを変更管理の単位にする。 - Legacy HTTP+SSE transport、WebSocket、独自transportを追加しない。 - Streamable HTTPをnon-loopbackへbind可能にしない。 - 認証/TLSを「便利だから」という理由でv1へ追加しない。 @@ -783,6 +791,11 @@ errorは内部codeとlocalized messageを分離し、ログ/auditにはcode、MC | mcp.transport | stdio/http | | mcp.http.host | loopback address only | | mcp.http.port | listen port | +| mcp.images.max_count | 画像数上限 | +| mcp.images.max_bytes_each | 1画像byte上限 | +| mcp.images.max_total_bytes | request画像合計byte上限 | +| mcp.tasks.time_to_live_hours | 永続MCP Task保持時間 | +| mcp.tasks.poll_interval_ms | Task poll間隔 | | agent.user_system_prompt | 追加prompt path | | agent.max_iterations | 128 default | | agent.same_failure_limit | 5 default | @@ -809,13 +822,14 @@ errorは内部codeとlocalized messageを分離し、ログ/auditにはcode、MC | localization.fallback | en | | skills.directory | Skill directory | | logging.directory | log directory | +| logging.level | Application log閾値 | +| logging.http_requests | HTTP request log有効化 | +| logging.max_file_bytes | rotation size | +| logging.retained_files | rotation保持数 | | limits.whole_read_bytes | whole read上限 | | limits.search_max_results | search結果上限 | | limits.tail_max_lines | tail行数上限 | | limits.context_summary_ratio | context要約開始比率 | -| mcp.images.max_count | 画像数上限 | -| mcp.images.max_bytes_each | 1画像byte上限 | -| mcp.images.max_total_bytes | request画像合計byte上限 | ## 28. 主要データ型索引 - `AgentSession` - `AgentTask` diff --git a/doc/Specifications.md b/doc/Specifications.md index 007ce51..92dc176 100644 --- a/doc/Specifications.md +++ b/doc/Specifications.md @@ -1,7 +1,7 @@ # AI Agent Sandbox MCP Server — 仕様書 **文書名:** `Specifications.md` -**版:** 0.1 Draft +**版:** 0.2 Audit Revision **対象OS:** Windows 11 x64 **主実装:** C# / .NET 10 LTS **目的:** 実装前に、外部から観測可能な性質・制約・安全条件を一意に定義する。 @@ -144,6 +144,8 @@ IPA「厳密な仕様記述入門」の考え方に従い、課題・仕様・è¨ | MCP-STS-01 | task_id | Yes | agent_runが返したTask ID。 | | MCP-STS-02 | session_id | No | 指定時はTaskとの整合を検査する。 | +`agent_status` のtext resultは既存のTask/Session ID、状態、進捗、token実績、最終結果に加え、実行iteration数、再計画回数、最後のerror codeと選択localeのerror messageを返す。内部Tool名、Sandbox実装詳細、chain-of-thoughtは返してはならない。 + ### 5.5 Task状態 | 状態 | 意味 | 遷移先 | @@ -167,11 +169,11 @@ IPA「厳密な仕様記述入門」の考え方に従い、課題・仕様・è¨ v1のCLI surfaceは次に限定する。 ```text -agent-mcp serve [--config <path>] [--lang <locale>] [--transport <stdio|http>] +agent-mcp [serve] [--config <path>] [--lang <locale>] [--transport <stdio|http>] agent-mcp check [--config <path>] [--lang <locale>] ``` -CLIは起動方式と表示言語を変更するためのI/Fであり、SandboxPolicyやOllama sampling値を個別overrideするI/Fにしない。 +command省略時、および先頭引数がoptionの場合は `serve` として扱う。CLIは起動方式と表示言語を変更するためのI/Fであり、SandboxPolicyやOllama sampling値を個別overrideするI/Fにしない。 ### 5.7 MCP 2026-07-28とTasks Extension @@ -231,7 +233,7 @@ Vision入力は設定可能な画像数、1画像あたりのsize、request合è¨ ### 7.2 Tool未使用検出 -AgentはTaskの期待副作用と観測結果を比較し、実行が必要なのにtool callが0件の場合はTaskをcompletedにしない。再試行はAgent Loopの失敗回数へ算入する。純粋な説明・分析Taskにはtool callを強制しない。Sandbox Policyによる未許可操作は修正可能なTool失敗としてLLMへ再試行させず、初回のdenyでTaskをfailedにしてcleanupを実行する。 +AgentはTaskの期待副作用と観測結果を比較し、実行が必要なのにtool callが0件の場合はTaskをcompletedにしない。再試行はAgent Loopの失敗回数へ算入する。純粋な説明・分析Taskにはtool callを強制しない。Sandbox Policyによる未許可操作は同一Tool呼出しへ再投入しない。許可済み能力だけで代替できる可能性がある場合に限り再計画でき、同一denyの再発、計画未変更、実行可能Taskなし、再計画失敗、または既定最大3回への到達でTaskをfailedにしてcleanupする。 Internal Toolが返す読取・検索・tail結果は設定可能な上限を持ち、contextを無制限に消費してはならない。上限値は設計および設定schemaで定義する。 @@ -319,7 +321,8 @@ Context要約を開始する利用率閾値は設定可能でなければならã - Skillロードは権限付与を意味しない。`allowed-tools` metadataはSandbox permissionとして解釈しない。 - Skillに `scripts/` が含まれていても自動実行許可しない。実行には通常どおりFilesystem execute capability、Process Approval、path + SHA-256、Sandbox Brokerを必須とする。 - Skill directory内resourceについてcanonicalization、reparse point検査、Skill root外へのescape禁止を行う。 -- Skill選択・本文ロードはInternal Toolとして公開せず、Agent Runtime / Prompt Context Managementの責務として実装する。Internal Toolは既存5群+dir=6群に固定する。 +- Skill選択・本文ロードはInternal Toolとして公開せず、Agent Runtime / Prompt Context Managementの責務として実装する。 +- Internal Toolの具体的なcatalogとschemaは設計事項とする。MCP Clientへ公開せず、Internal Toolによる副作用は必ずPolicy検査を通過しなければならない。 --- @@ -441,6 +444,8 @@ Context要約を開始する利用率閾値は設定可能でなければならã - 設定変更の反映には再起動を必須とする。 - Hot Reloadは明示的に非対応。 - CLIの `--config` で設定ファイルpathを選択可能。 +- base設定と同じdirectoryに `agent.local.yaml` が存在する場合は任意overrideとして読み込む。mapは再帰mergeし、scalarと配列はlocal側で置換する。merge後の設定全体をvalidationし、相対pathはbase設定directoryを基準に解決する。 +- Release Bundleは既定設定だけを配布し、利用者のlocal設定、User System Prompt、Skillをpublishで上書きしてはならない。 - 起動時にschema、path、hash approval、locale、policyの静的validationを行う。 --- @@ -450,8 +455,8 @@ Context要約を開始する利用率閾値は設定可能でなければならã | 種別 | 要件 | | --- | --- | | Application Log | stderrに出力可能。stdio時stdoutへログを出してはならない。ファイルにも保存する。 | -| LLM Log | promptとresponseを記録する。secretを継承しない前提でも、ログ出力先は保護する。 | -| Audit Log | 通常ログと分離する。process、args、exit code、file write、delete、denied access等を記録する。 | +| LLM Log | promptとresponseを記録する。call、Session、Task、Planner Task、phase、iteration、replan、model、token usageを相関できなければならない。secretを継承しない前提でも、ログ出力先は保護する。 | +| Audit Log | 通常ログと分離する。Task lifecycle、Tool、process、args、exit code、file write、delete、denied access、network rule、recoveryをSession/Taskと相関して記録する。 | | Token Metrics | Task/Call単位のinput/output/total tokenを記録する。 | --- |
