diff options
| author | tanaka takashi <isazaka@gmail.com> | 2026-08-09 14:43:23 +0900 |
|---|---|---|
| committer | tanaka takashi <isazaka@gmail.com> | 2026-08-09 14:43:23 +0900 |
| commit | 2fefd29e86c3b926d0cf4a362251d3f119688612 (patch) | |
| tree | a61eb163845b0d7dcf74cb78ce3bf61dbfd57874 | |
First commit.
| -rw-r--r-- | doc/Design.md | 787 | ||||
| -rw-r--r-- | doc/Specifications.md | 559 | ||||
| -rw-r--r-- | plans/ImplementationPlan.md | 757 |
3 files changed, 2103 insertions, 0 deletions
diff --git a/doc/Design.md b/doc/Design.md new file mode 100644 index 0000000..f877e3e --- /dev/null +++ b/doc/Design.md @@ -0,0 +1,787 @@ +# AI Agent Sandbox MCP Server — 設計書 + +**文書名:** `Design.md` +**版:** 0.1 Draft +**上位仕様:** `Specifications.md` +**対象:** Windows 11 x64 / C# 14 / .NET 10 LTS + +--- + +## 1. 設計方針 + +### 1.1 基本原則 + +- 仕様で定義された性質を設計が満たすことを最優先する。 +- LLMを信頼境界に置かない。決定的に検査可能なものはC#とWindows機構で検査する。 +- 外部MCP Tool surfaceを2個に固定し、内部機能を外部へ漏らさない。 +- Windows native security primitiveを薄く組み合わせ、独自Sandbox frameworkを作らない。 +- 設定から緩和するホワイトリスト方式を採用する。 +- 一時的なOS変更はtransactionとして扱い、crash recovery可能にする。 +- AI生成実装が勝手に概念・層・依存を増やさないよう、語彙とmodule boundaryを固定する。 +### 1.2 参照するIPAの記述観点 +IPA資料が示す「構造」「機能」「振る舞い」「非機能」を、本設計では Architecture / Interface / State Transition / Quality & Invariant に対応づける。Verificationは `Specifications.md` のRequirement IDと本書の設計要素をtraceすることで行う。 + +--- + +## 2. 技術スタック +| 区分 | 採用 | 理由 | +| --- | --- | --- | +| OS | Windows 11 x64 | AppContainer、NTFS ACL、Job Object、WFPを直接利用するため | +| Language | C# 14 | Windows interopとMCP/JSON/asyncの両立 | +| Runtime | NET 10 LTS | LTS運用 | +| Editor | VS Code + C# Dev Kit | 既定開発環境 | +| Build | dotnet CLI / MSBuild | 追加build systemを不要にする | +| Package | NuGet | C#標準package管理 | +| MCP | 公式 ModelContextProtocol C# SDK | stdio/Streamable HTTP実装 | +| Win32 binding | Microsoft.Windows.CsWin32 | 必要Win32 APIだけ型付き生成 | +| Ollama | HttpClient + REST API | 専用SDK依存を避ける | +| JSON | System.Text.Json | MCP周辺・locale・audit | +| YAML | 小規模YAML parser library 1つ | 主設定のみ。追加依存はこれ以上増やさない | +| IPC | System.IO.Pipes | Sandbox worker連携 | +| Logging | Microsoft.Extensions.Logging | stderr/file sinkを統一 | +| Test | xUnit | unit/integration/security test | +### 2.1 明示的非採用 +- Python +- Node.js / TypeScript +- CMake +- vcpkg +- Docker +- WSL +- ASP.NET Core application framework(MCP SDKが内部利用する部分を除く) +- Database/ORM +- 独自RPC +- 汎用Workflow engine +- 汎用Graph library +- Ollama専用SDK +- Legacy HTTP+SSE compatibility + +--- + +## 3. 論理アーキテクチャ +```text +MCP Client + │ stdio / Streamable HTTP(loopback) + ▼ +MCP Adapter ───────────── Localization + │ + ▼ +Agent Runtime ─── Session Store (memory) + ├── Prompt Composer ── Skill Selector/Loader + ├── Ollama Client ───── Ollama localhost + ├── Token Planner ───── TaskGraph / PERT / CPM + └── Internal Tool Dispatcher + │ + ▼ + Policy Engine + │ + ▼ + Sandbox Broker + ├── AppContainer + ├── NTFS ACL + ├── Job Object + ├── WFP + └── Named Pipe + │ + ▼ + Sandboxed Process Tree +Audit Writer / Recovery Manager は各副作用境界を横断して記録・復旧する。 +``` +### 3.1 信頼境界 +| 領域 | 信頼 | 備考 | +| --- | --- | --- | +| MCP Client | Untrusted | request、image、temperature、session指定を検証する | +| Ollama output | Untrusted | tool argumentもPolicy検査する | +| Skill/User Prompt | Untrusted configuration content | Fixed PromptやPolicyを上書きできない | +| Agent Runtime | Trusted | 状態管理とdeterministic guard | +| Policy Engine | Trusted | allow/deny決定 | +| Sandbox Broker | Highly Trusted | OS副作用を発生させる唯一の境界 | +| Windows Kernel Security | Trusted enforcement | ACL/AppContainer/Job/WFP | + +--- + +## 4. Project構成 +```text +src/ + Agent.App/ # Program, CLI, composition root, configuration + Agent.Mcp/ # MCP transport and two public tools + Agent.Core/ # Agent loop, session, prompt, ollama abstractions + Agent.Planner/ # TaskGraph, TokenPERT, TokenCPM + Agent.Windows/ # SandboxPolicy enforcement and Win32 interop +tests/ + Agent.Core.Tests/ + Agent.Planner.Tests/ + Agent.Windows.Tests/ +config/ + agent.yaml + locales/en.json + locales/ja.json +prompts/ + user-system.md # optional user prompt; fixed prompt is embedded +skills/ +logs/ +state/ + recovery/ # rollback journal; application-owned +``` +### 4.1 dependency方向 +```text +Agent.App -> Agent.Mcp -> Agent.Core -> Agent.Planner +Agent.App -------------------------> Agent.Windows +Agent.Core -> ISandbox/IToolExecutor interfaces +Agent.Windows implements those interfaces +``` +`Agent.Planner` と `Agent.Core` はWin32型、HANDLE、SID、WFP型を参照してはならない。 + +--- +## 5. MCP詳細設計 +### 5.1 Transport +- defaultはstdio。stdioではstdoutをMCP専用、ログをstderrへ出す。 +- Streamable HTTPは `127.0.0.1` または `::1` だけにbind可能。非loopback設定はvalidation error。 +- Streamable HTTPは1つのMCP endpointを持つ。v1はJSON responseのみ使用し、SSE streamを開始しない。 +- HTTP GETによるSSE listenerは提供せず、GETには405を返す。 +- Legacy HTTP+SSEの旧endpoint検出・fallbackを実装しない。 +- Origin headerが存在するHTTP requestはloopback originとして妥当か検査する。 +### 5.2 agent_run JSON Schema +```json +{ + "type": "object", + "properties": { + "request": { "type": "string", "minLength": 1 }, + "session_id": { "type": "string", "format": "uuid" }, + "temperature": { "type": "number", "minimum": 0.0, "maximum": 2.0 }, + "images": { + "type": "array", + "items": { + "type": "object", + "properties": { + "mime_type": { "type": "string", "enum": ["image/png", "image/jpeg", "image/webp"] }, + "data_base64": { "type": "string", "minLength": 1 } + }, + "required": ["mime_type", "data_base64"], + "additionalProperties": false + } + } + }, + "required": ["request"], + "additionalProperties": false +} +``` +### 5.3 agent_run result +MCP resultはtext content 1件とする。Machine-readable structuredContentはv1では公開しない。本文はlocale templateで次を必ず含める。 +```text +task_id: <UUID> +session_id: <UUID> +status: queued +message: <localized message> +``` +### 5.4 agent_status JSON Schema +```json +{ + "type": "object", + "properties": { + "task_id": { "type": "string", "format": "uuid" }, + "session_id": { "type": "string", "format": "uuid" } + }, + "required": ["task_id"], + "additionalProperties": false +} +``` +### 5.5 agent_status result +```text +task_id: <UUID> +session_id: <UUID> +status: queued|planning|running|completed|failed|cancelled +completed_tasks: <n>/<total> +current_task: <localized summary or empty> +token_usage: input=<n> output=<n> total=<n> +critical_path_tokens: <n> +message: <localized status> +result: <final natural-language answer; completed only> +``` +`result`は選択localeで生成する。内部Tool名、policy internals、chain-of-thoughtは返さない。 +--- +## 6. Ollama統合設計 +### 6.1 APIモデル +- `HttpClient`をsingleton相当で再利用する。 +- Chat APIを会話、Vision、native tool callingに使用する。 +- `stream=false`をv1既定とし、Agent内部でも1call単位の完了responseを扱う。 +- `prompt_eval_count` と `eval_count` を毎callで取得する。 +### 6.2 Option mapping +`OllamaOptions` は既知optionをnullable typed propertyとして持つ。設定されていないpropertyはpayloadへ出さない。`extra_options` は `Dictionary<string, JsonElement>` とし、typed propertyと同名keyがある場合はconfiguration errorとする。 +代表的typed property: +```text +num_ctx, num_keep, num_predict, temperature, seed, +top_k, top_p, min_p, typical_p, tfs_z, +repeat_last_n, repeat_penalty, presence_penalty, frequency_penalty, +mirostat, mirostat_tau, mirostat_eta, stop +``` +Chat API top-levelとして `model`, `think`, `keep_alive`, `format`, `logprobs`, `top_logprobs` を別型で管理する。Ollama API変更時は既知型を更新し、未知optionは `extra_options` で一時対応できる。 +### 6.3 temperature override +```text +effective_temperature = agent_run.temperature ?? config.ollama.options.temperature +``` +overrideはTask objectにcopyし、global configurationを変更しない。Session内の次Taskへも継承しない。 +### 6.4 Vision +- `images[]`をBase64としてOllama messageへ転送する。 +- mime_type、Base64妥当性、設定上限size/countを事前検査する。 +- model capability確認でVision非対応と判定した場合はOllama呼出し前にlocalized error。能力確認不能時は呼出しを行い、Ollama errorを正規化して返す。 +### 6.5 Tool calling +Ollamaに公開するInternal Toolは次の5群に固定する。個々のOS command (`grep.exe`等) をtoolとして増殖させない。 +| 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 | +--- +## 7. Internal Tool Schema設計 +### 7.1 file_search +```json +{"root":"string","mode":"glob|name|text|regex|tail","query":"string","max_results":100,"tail_lines":100} +``` +- `root`はread許可directory/file配下でなければdeny。 +- `tail`はtext file向け。binaryは拒否する。 +- `max_results`にhard upper boundを設け、context爆発を防ぐ。 +### 7.2 file_read +```json +{"path":"string","mode":"whole|range|metadata","start":0,"length":0} +``` +- wholeはsize上限を超えた場合range利用を要求する。 +- read前にcanonical pathとreparse pointを検査する。 +### 7.3 file_edit +```json +{ + "path":"string", + "operation":"overwrite|patch|atomic_replace|delete", + "content":"string|null", + "patch":"string|null", + "expected_sha256":"string|null" +} +``` +- overwrite/patch/atomic_replaceはwrite permissionを要求する。 +- deleteはdelete permissionを要求する。 +- `expected_sha256` 指定時はoptimistic concurrency guardとして利用する。 +### 7.4 process_run +```json +{ + "executable":"string", + "args":["string"], + "cwd":"string", + "timeout_seconds":300, + "stdin":"string|null" +} +``` +- shell command line 1本ではなくexeとargsを分離する。 +- executableはcanonical path + SHA-256 approval必須。 +- shell category disabled時はcmd/powershell/pwshを拒否する。 +- cwdはfilesystem policy内でなければならない。 +### 7.5 task_update +```json +{ + "operation":"add|add_dependency|set_state|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|running|completed|failed|null" +} +``` +PlannerがDAG、不変条件、completed immutable、max_tasksを再検査してから適用する。 +### 7.6 ToolUseGuard +Taskには `requires_external_effect` をPlanner内部属性として持たせる。trueのTaskで、当該iteration中のtool callが0かつ完了証拠がない場合、LLMへ「未実行」を示すsystem-generated observationを追加して再試行する。同一失敗fingerprintが5回に達したらTaskをfailedにする。 +--- +## 8. Token Planner設計 +### 8.1 Task model +```text +Task + Id: UUID + Description: string + Dependencies: Set<TaskId> + State: queued|running|completed|failed + BudgetClass: TokenBudgetClass + O, M, P: long + ExpectedTokens: double + ActualInputTokens: long + ActualOutputTokens: long + ActualTotalTokens: long + RequiresExternalEffect: bool +``` +### 8.2 PERT計算 +```text +ExpectedTokens = (O + 4*M + P) / 6.0 +VarianceTokens = ((P - O) / 6.0)^2 # 診断値。v1ではscheduler判断に必須ではない +``` +validation: `0 < O <= M <= P <= BudgetClass.MaxTokens`. +### 8.3 CPM +topological sort後にforward passで各Taskの累積expected token costを計算し、最大経路をCritical Pathとする。時間のearliest/latest startという語をそのままUIへ出さず、`cumulative_token_cost`、`critical_path` と表記する。 +### 8.4 再計画 +- 未完了Taskの追加/dependency追加後にDAG validationとCPMを再計算。 +- completed Taskは変更しない。 +- 実績がPを超過しても即失敗にはせず、remaining Taskのestimate見直しをLLMへ要求できる。 +- `max_tasks=32`超過提案は拒否し、既存Taskの統合をLLMへ求める。 +- Budget Classは意味的Taskを分割する唯一の理由にしない。Taskが複数独立成果物を含む場合に分割する。 +### 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として別集計する。 +--- +## 9. Session・Context設計 +### 9.1 In-memory store +`ConcurrentDictionary<SessionId, AgentSession>` 相当で保持する。永続化しない。Taskは必ず1 Sessionに所属する。 +```text +AgentSession + SessionId + Conversation + TaskGraph + ExecutionResults + Summary + CreatedAt / LastAccessAt +``` +### 9.2 Context assembly +順序を次に固定する。 +1. Fixed System Prompt +2. User System Prompt +3. locale instruction +4. selected Skills +5. Sandbox capability summary +6. current TaskGraph / current Task +7. previous Summary +8. recent Conversation / Execution Result +### 9.3 Summary policy +`num_ctx`に対する利用率が設定閾値を超えたとき、古いConversation/Execution Resultを要約する。次は削除・曖昧化してはならない。 +- 利用者が明示した制約 +- 未完了Taskとdependency +- completed Taskの重要成果 +- 失敗原因と再試行回数 +- 変更済fileと検証結果 +- security denial +- 承認/Policyそのものではなく現在利用可能なcapability summary +raw chain-of-thoughtは保存・要約対象としない。 +--- +## 10. SandboxPolicy YAML設計 +### 10.1 schema概要 +```yaml +schema_version: 1 +application: + language: en +mcp: + transport: stdio + http: + host: 127.0.0.1 + port: 8080 +agent: + user_system_prompt: prompts/user-system.md + max_iterations: 128 + same_failure_limit: 5 +ollama: + endpoint: http://localhost:11434 + model: qwen3-coder + think: true + keep_alive: 5m + options: + num_ctx: 32768 + temperature: 0.4 + extra_options: {} +planner: + max_tasks: 32 +sandbox: + filesystem: + read: [] + write: [] + execute: [] + delete: [] + process: + allow_shell: true + approvals: [] + max_processes: 16 + network: + mode: deny + allow: [] + resources: + memory_mb: 4096 + process_timeout_seconds: 1800 +file_edit: + memory_backup_limit_mb: 16 +localization: + directory: config/locales + fallback: en +skills: + directory: skills +logging: + directory: logs +``` +### 10.2 Filesystem entry +各list itemはpath文字列とする。起動時に絶対canonical pathへ正規化して保持する。file/directoryは実在時に種別を記録し、未作成write targetは最も近い既存親directoryまで検査する。 +### 10.3 Process approval entry +```yaml +approvals: + - path: C:/Program Files/Git/cmd/git.exe + sha256: "<64 hex chars>" + - path: C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe + sha256: "<64 hex chars>" +``` +署名はaudit metadataとして取得可能だが、v1のallow判定はpath + SHA-256を必須条件とする。 +### 10.4 Network entry +```yaml +network: + mode: allow + allow: + - host: github.com + ports: [443] + - host: api.github.com + ports: [443] +``` +`allow` modeでもlist外はdeny。`deny`ではlistを無視して全denyする。localhostも特別扱いしない。 +--- +## 11. Windows強制設計 +### 11.1 AppContainer +- Application Profileを固定名で作成/取得する。 +- 起動時にprofile SIDを解決する。 +- Taskごとにprofileを作り直さない。 +- AppContainer外の通常user tokenに戻るbreakawayを許可しない。 +### 11.2 NTFS ACL +- Policy Engineが許可pathから必要ACEを導出する。 +- 既存DACL全体を書き換えず、アプリケーションSID向けの必要ACEだけをtransactionalに追加する。 +- 元security descriptorまたは追加ACEの逆操作情報をRecovery Journalへ記録する。 +- Task終了で追加分を除去し、元状態との整合を検査する。 +### 11.3 Job Object +- TaskごとにJob Objectを1つ作成する。 +- root sandbox processをJobへ割り当てる。descendantを同一Jobへ継承させる。 +- breakawayを許可しない。 +- process count / memory limitをJobへ設定する。 +- `KILL_ON_JOB_CLOSE`相当を利用し、application終了時にprocess treeを残さない。 +### 11.4 Process approval +Sandbox Brokerは実行直前にcanonical pathを取得し、ファイルを開いた状態でSHA-256を計算し、approvalと一致確認してから起動する。TOCTOU低減のため、検証対象と実行対象のpath解決がずれないよう実装時にWin32のfile identity確認を追加する。具体API選択は実装時に確定する。 +### 11.5 WFP方針 +WFP実装は複雑な汎用Firewallにしない。設計上の変換規則だけを固定する。 +1. `deny`ならApplication Profile/Task processに対するoutbound blockを作成する。 +2. `allow`ならdefault blockを置き、列挙hostをTask開始時にDNS解決する。 +3. 解決したIP集合とportの組にだけallow filterを作成する。 +4. Task実行中はそのIP snapshotを使用し、複雑な動的DNS追随は行わない。 +5. DNS解決失敗はdeny。 +6. Task終了でTask固有WFP filterを削除する。 +7. localhostはallow-listに明示されない限り許可しない。 +具体的なWFP layer、sublayer、filter condition、transaction APIは実装時にCodexがWindows SDKを確認して決定し、Security Integration Testで仕様を検証する。 +### 11.6 Named Pipe +Sandbox workerとのIPCが必要な場合はtask固有Named Pipeを使用し、DACLをApplication SIDとBrokerだけに限定する。TCP localhostを内部IPCに使わない。 +--- +## 12. ACL / Resource Transaction設計 +### 12.1 ACIDから借用する性質 +| 性質 | 本システムでの意味 | +| --- | --- | +| Atomicity | Task Resource適用が途中失敗した場合、適用済み変更をrollbackする。 | +| Consistency | SandboxPolicyとSecurity Invariantを満たす状態だけを実行可能状態とする。 | +| Isolation | Task固有ResourceをTask IDで識別し、他Task cleanupで誤削除しない。 | +| Durability | Task Resource自体の永続化ではなく、cleanupに必要なjournalをcrashに耐えて保持する。 | +### 12.2 状態機械 +```text +CLEAN + -> PREPARING journal create + -> APPLIED ACL/WFP/Job ready + -> RUNNING sandbox process start + -> CLEANING process stopped / task terminal + -> CLEAN all task resources removed +PREPARING/APPLIED/RUNNING/CLEANING --crash--> RECOVERY_REQUIRED +RECOVERY_REQUIRED -> CLEANING -> CLEAN +``` +### 12.3 Recovery Journal +JournalはTaskごとのJSONとし、操作を実行する**前**にundoに必要な情報をflushする。例: +```json +{ + "schema_version": 1, + "task_id": "...", + "state": "APPLIED", + "acl_changes": [{"path":"...","change_id":"..."}], + "wfp_filter_ids": [123], + "temp_paths": ["..."], + "created_at": "..." +} +``` +起動時にjournalが存在する場合、MCP transport開始前にRecovery Managerが逆順でcleanupし、全項目の不存在/復元を検査してからjournalを削除する。 +--- +## 13. File Transaction設計 +### 13.1 基本フロー +```text +canonicalize + policy check + -> read old identity/hash + -> old content snapshot (memory or temp) + -> edit temp representation + -> syntax/basic validation if available + -> atomic replace when possible + -> post-write hash/readback validation + -> commit: discard snapshot +failure -> rollback snapshot -> verify original hash +``` +### 13.2 backup threshold +`memory_backup_limit_mb`以下はメモリsnapshot、それより大きい場合はTask専用temp directoryへbackupする。16MBをdefault候補とするが、実装時benchmarkで変更可能。これは仕様上の固定値ではない。 +### 13.3 Patch +patchは適用前にtarget hashまたはcontext一致を検査する。曖昧適用を禁止し、複数候補に一致する場合は失敗としてLLMへ返す。 +--- +## 14. Localization設計 +### 14.1 Locale file +`config/locales/en.json` と `ja.json` を完全key集合として配布する。flat objectを採用する。 +```json +{ + "app.starting": "Starting agent.", + "mcp.task_queued": "Task {task} was queued.", + "sandbox.access_denied": "Access denied: {path}", + "ollama.vision_unsupported": "The selected model does not support image input." +} +``` +### 14.2 validation +- JSON parse failure: fatal。 +- baseline key集合にないunknown key: fatal。 +- missing key: 起動は継続し、runtimeでenへfallback。 +- enにもない場合はkey自体を表示する。 +- placeholder名はen baselineと一致しなければfatal。 +### 14.3 Language propagation +`LanguageContext`をrequest/sessionへ渡し、CLI/diagnostic/MCP templateだけでなくPrompt Composerのlocale instructionにも利用する。LLMに入力言語自動判定をさせない。 +--- +## 15. Logging・Audit設計 +### 15.1 Application log +- stdio時はstderr + rolling file。 +- 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にする。 +### 15.3 Audit JSONL +Auditはappend-only JSONLを採用する。1 event = 1 line。 +```json +{"ts":"...","event":"process.start","session_id":"...","task_id":"...","exe":"...","sha256":"...","args":["..."],"decision":"allow"} +{"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`. +--- +## 16. Recovery・終了設計 +### 16.1 graceful stop +1. 新規agent_run受付停止。 +2. 実行中Taskをcancelledへ遷移予定としてマーク。 +3. Job Objectを終了しprocess tree停止。 +4. File transaction rollbackが必要なら実施。 +5. WFP filter/ACL/temp resource cleanup。 +6. journal clean確認。 +7. transport終了。 +### 16.2 client disconnect +- stdio: EOFまたはparent process消失をClient切断とみなし、所有Taskをsafe stop。 +- Streamable HTTP: 1回のHTTP response完了は切断ではない。MCP sessionの明示終了、session失効、server shutdownをsafe stop triggerとする。 +### 16.3 Ollama retry +network/temporary errorだけを最大3回retryする。validation error、Vision unsupported、invalid model等の恒久errorは即failed。backoffの具体値は実装時に小さく固定し、汎用retry frameworkを導入しない。 +--- +## 17. 状態遷移 +### 17.1 Task +```text +queued -> planning -> running -> completed + -> planning # replan +queued/planning/running -> failed +queued/planning/running -> cancelled +completed/failed/cancelled are terminal +``` +### 17.2 Session +```text +active -> closing -> closed +``` +closed Sessionは再利用しない。プロセス再起動後に以前のSession IDが指定された場合はnot found。 +--- +## 18. Validation / Verification設計 +### 18.1 起動時validation +- YAML schema_version +- MCP transport value +- HTTP hostがloopback +- locale baseline/placeholder +- Ollama endpoint URI +- Sandbox path canonicalization +- process approval path/hash format +- network host/port syntax +- resource limit range +- Fixed/User prompt file state +- Skill directory +### 18.2 deterministic verification +| 対象 | 検証 | +| --- | --- | +| TaskGraph | cycle、max_tasks、completed immutable | +| TokenPERT | O<=M<=P<=budget、式のunit test | +| TokenCPM | 既知DAGに対するcritical path unit test | +| Filesystem | allow/deny/reparse point integration test | +| Process | hash mismatch、path mismatch、shell toggle | +| Network | deny loopback、allow-list host/port | +| Recovery | 各transaction stateで強制crashして再起動cleanup | +| MCP | stdio purity、Streamable HTTP loopback、GET 405 | +| Localization | fallback、unknown key fatal、placeholder validation | +--- +## 19. Security Test Matrix +| ID | ケース | 期待 | +| --- | --- | --- | +| ST-01 | read許可file | 成功 | +| ST-02 | read未許可file | ACCESS_DENIED | +| ST-03 | write許可file | 成功 | +| ST-04 | delete権限なしdelete | 拒否 | +| ST-05 | junctionで許可外へ脱出 | 拒否 | +| ST-06 | symlink chainで許可外へ脱出 | 拒否 | +| ST-07 | 承認exe/hash一致 | 成功 | +| ST-08 | exe更新/hash不一致 | 拒否 | +| ST-09 | shell disabledでPowerShell | 拒否 | +| ST-10 | 子が未承認exe起動 | 拒否 | +| ST-11 | Job close | 全descendant終了 | +| ST-12 | network denyで127.0.0.1 | 拒否 | +| ST-13 | network allowで許可host:port | 成功 | +| ST-14 | network allowで未許可port | 拒否 | +| ST-15 | MCPからpolicy変更試行 | schema/機能上不可能 | +| ST-16 | Ollama tool arg path脱出 | Policyで拒否 | +| ST-17 | crash after ACL apply | 再起動cleanup | +| ST-18 | crash after WFP apply | 再起動cleanup | +| ST-19 | malformed locale | 起動失敗 | +| ST-20 | non-loopback HTTP bind | 起動失敗 | +--- +## 20. エラー分類 +| Category | 例 | Task結果 | Retry | +| --- | --- | --- | --- | +| validation | invalid config/schema/tool args | failed | No | +| policy_denied | path/network/exe denial | LLMへobservation。回復不能ならfailed | LLM再計画のみ | +| ollama_transient | connection reset/temporary unavailable | running維持 | 最大3 | +| ollama_permanent | model not found/vision unsupported | failed | No | +| tool_failure | process nonzero/patch mismatch | running→replan | 最大同一5 | +| resource_limit | timeout/memory/process limit | failedまたはreplan | 原則No | +| recovery_failure | ACL/WFP cleanup不能 | application fatal | No | +errorは内部codeとlocalized messageを分離し、ログ/auditにはcode、MCPにはlocalized textを返す。 +--- +## 21. 実装順序 +| Phase | 実装 | 完了条件 | +| --- | --- | --- | +| 1 | Config/Locale/MCP stdio skeleton | agent_run/statusのstubが動作 | +| 2 | Session/Ollama/Prompt | text-only会話とtoken取得 | +| 3 | Planner | TaskGraph + TokenPERT/CPM unit test | +| 4 | Internal Tool dispatcher | tool schemaとToolUseGuard | +| 5 | Filesystem/Process Sandbox | ACL/AppContainer/Job integration test | +| 6 | Resource Transaction/Recovery | 強制crash recovery test | +| 7 | WFP | deny/allow-list integration test | +| 8 | Vision/Streamable HTTP | image optional、loopback HTTP | +| 9 | Audit/Hardening | security matrix全PASS | +--- +## 22. Codex実装制約 +- 新規NuGet dependencyを勝手に追加しない。追加時は標準ライブラリで不能な理由を示す。 +- MCP Toolを `agent_run` / `agent_status` 以外に増やさない。 +- Internal ToolをOSコマンド名ごとに増やさず、定義済み5群に収める。 +- Legacy HTTP+SSE transport、WebSocket、独自transportを追加しない。 +- Streamable HTTPをnon-loopbackへbind可能にしない。 +- 認証/TLSを「便利だから」という理由でv1へ追加しない。 +- SandboxPolicyをMCP/LLMから変更できるI/Fを作らない。 +- Fixed System Promptを外部ファイルへ移動しない。 +- AppContainer profileをTaskごとに作成・削除しない。 +- WFPを汎用Firewall rule engineへ拡張しない。 +- DatabaseをSession/Journal目的で導入しない。Journalは小さなfile transactionで実装する。 +- Graph library/Workflow engineを導入しない。 +- `Utils`, `Common`, `Infrastructure`, `Manager`等の曖昧な巨大moduleを作らない。 +- 仕様語彙と異なる新名称を導入する場合はDesign.mdを先に更新する。 +- セキュリティ判定をLLM出力だけに依存させない。 +--- +## 23. 未固定の実装詳細 +次は設計方針のみを固定し、実装時にWindows SDK/APIの実状を確認して選択する。仕様変更を意味しない。 +| 項目 | 固定済み方針 | 実装時に決めること | +| --- | --- | --- | +| WFP | deny/default block + hostname resolve + IP/port allow | layer/sublayer/filter condition/API sequence | +| File backup threshold | memory超過時temp rollback | default閾値benchmark | +| Process TOCTOU | path+SHA必須 | file identity handleを用いた最適API | +| Context summary | 重要情報保持 | 要約promptとthreshold | +| Retry backoff | Ollama最大3 | 具体interval | +--- +## 24. 仕様トレーサビリティ +| Specifications.md | Design.md | 主検証 | +| --- | --- | --- | +| 5章 MCP | 5章 | AT-01〜06 | +| 6章 Ollama | 6〜7章 | Ollama integration tests | +| 7章 Agent | 7章/17章 | ToolUseGuard/loop tests | +| 8章 Planner | 8章 | AT-14〜17 | +| 9章 Session | 9章 | session/context tests | +| 11章 Sandbox | 10〜13章 | ST-01〜18 | +| 14章 i18n | 14章 | AT-18〜20 | +| 16〜17章 Audit/Recovery | 15〜16章 | recovery/audit tests | +| 18章 Security Invariant | 11〜19章 | Security Test Matrix | +--- +## 25. 参考資料 +- IPA/SEC「実務家のための形式手法 厳密な仕様記述を志すための形式手法入門 厳密な仕様記述入門」2013年。 +- Model Context Protocol Specification, Transports。stdio / Streamable HTTP、旧HTTP+SSE置換、loopback推奨等を参照。 +- Ollama API Reference, Chat / Generate。tools、images、options、think、keep_alive、prompt/eval token countを参照。 +--- +## 26. 設計変更ルール +- `Specifications.md` と矛盾する設計変更は禁止。 +- Security Invariant、MCP schema、SandboxPolicy schema、Task state transitionを変える場合は仕様書も同時更新する。 +- 実装時にWindows API制約が判明しても、仕様を暗黙緩和しない。実現不能なら明示的に設計レビューへ戻す。 +- 語彙を追加する前に既存用語で表現できないか確認する。 +--- +## 27. Configuration key索引 +| Key | 意味 | +| --- | --- | +| schema_version | 設定schema版 | +| application.language | 既定locale | +| mcp.transport | stdio/http | +| mcp.http.host | loopback address only | +| mcp.http.port | listen port | +| agent.user_system_prompt | 追加prompt path | +| agent.max_iterations | 128 default | +| agent.same_failure_limit | 5 default | +| ollama.endpoint | Ollama URL | +| ollama.model | model name | +| ollama.think | thinking option | +| ollama.keep_alive | model keep alive | +| ollama.options.* | typed runtime options | +| ollama.extra_options.* | future passthrough options | +| planner.max_tasks | 32 default | +| sandbox.filesystem.read | read allow-list | +| sandbox.filesystem.write | write allow-list | +| sandbox.filesystem.execute | execute path allow-list | +| sandbox.filesystem.delete | delete allow-list | +| sandbox.process.allow_shell | shell toggle | +| sandbox.process.approvals | path+sha256 approvals | +| sandbox.process.max_processes | Job process limit | +| sandbox.network.mode | deny/allow | +| sandbox.network.allow | host/port list | +| sandbox.resources.memory_mb | Job memory limit | +| sandbox.resources.process_timeout_seconds | process timeout | +| file_edit.memory_backup_limit_mb | memory/temp threshold | +| localization.directory | locale directory | +| localization.fallback | en | +| skills.directory | Skill directory | +| logging.directory | log directory | +## 28. 主要データ型索引 +- `AgentSession` +- `AgentTask` +- `TaskGraph` +- `TokenEstimate` +- `TokenBudgetClass` +- `OllamaOptions` +- `OllamaChatRequest` +- `OllamaChatResponse` +- `SandboxPolicy` +- `FilesystemPolicy` +- `ProcessPolicy` +- `NetworkPolicy` +- `ResourcePolicy` +- `ExecutableApproval` +- `TaskResourceJournal` +- `AuditEvent` +- `LanguageContext` +- `SkillDescriptor` +- `ToolCallRecord` +## 29. 実装レビュー用チェックリスト +- [ ] public MCP toolは2個だけか。 +- [ ] Legacy SSE endpointが生成されていないか。 +- [ ] HTTPはloopback検証されているか。 +- [ ] Fixed Promptがresource埋め込み等で変更不能か。 +- [ ] Internal Tool argumentが必ずPolicy Engineを通るか。 +- [ ] pathはcanonicalize/reparse検査後に評価しているか。 +- [ ] process hashは実行直前に再計算しているか。 +- [ ] shell有効でもFilesystem/Network policyを迂回できないか。 +- [ ] Job breakawayがないか。 +- [ ] Network allow-list外がdefault denyか。 +- [ ] WFP/ACL変更前にjournalを書いているか。 +- [ ] 起動時Recoveryがserveより前か。 +- [ ] file rollback後にhash検証しているか。 +- [ ] completed Taskを更新するpathがないか。 +- [ ] TokenPERT式がdeterministicか。 +- [ ] Ollama token countsがcallごとに集計されるか。 +- [ ] context summaryが重要情報を保持するか。 +- [ ] locale unknown keyがfatalか。 +- [ ] stdio stdoutがMCP messageだけか。 +- [ ] AuditとApplication Logが分離されているか。 diff --git a/doc/Specifications.md b/doc/Specifications.md new file mode 100644 index 0000000..9d13343 --- /dev/null +++ b/doc/Specifications.md @@ -0,0 +1,559 @@ +# AI Agent Sandbox MCP Server — 仕様書 + +**文書名:** `Specifications.md` +**版:** 0.1 Draft +**対象OS:** Windows 11 x64 +**主実装:** C# / .NET 10 LTS +**目的:** 実装前に、外部から観測可能な性質・制約・安全条件を一意に定義する。 + +--- + +## 1. 文書の位置付け + +### 1.1 仕様と設計の分離 + +本書は「システムが何を満たすか」を定義する。実現手段、モジュール構成、Win32 APIの使い方などは `Design.md` に定義する。 +IPA「厳密な仕様記述入門」の考え方に従い、課題・仕様・設計を分離し、仕様は設計より上位の性質として扱う。 + +| 文書 | 責務 | 主な読者 | +| --- | --- | --- | +| Specifications.md | 外部性質、機能、状態、制約、非機能、安全条件を定義 | 利用者、レビュー担当、実装担当 | +| Design.md | 仕様を満たすための構造、データ、アルゴリズム、Windows強制方式を定義 | 実装担当、Codex、保守担当 | + +### 1.2 記述規則 + +- **MUST / 必須**: 実装が必ず満たす。 +- **MUST NOT / 禁止**: 実装が行ってはならない。 +- **SHOULD / 推奨**: 原則として満たす。逸脱時は根拠を記録する。 +- **MAY / 任意**: 実装上の選択肢である。 +- 同一概念には必ず同一の用語を使用する。類義語を新しい概念として導入しない。 + +### 1.3 仕様品質の観点 + +本書は、完全性、一貫性、検証容易性、修正容易性、追跡性を重視する。妥当性確認は「この仕様がAIエージェントの安全な作業実行という目的に適合するか」、正当性検証は「設計・実装が本仕様を満たすか」と定義する。 + +--- + +## 2. 目的・課題・範囲 + +### 2.1 解くべき課題 + +外部AIエージェントから自然言語で作業依頼を受け、ローカルLLMで計画・判断し、Windows上で許可された操作だけを実行し、結果をテキストで返す。LLMの判断をセキュリティ境界として信用せず、OSとアプリケーションのポリシーで能力を制限する。 + +### 2.2 システム境界 + +| 境界内 | 境界外 | +| --- | --- | +| MCP Server、Agent Runtime、Ollama制御、Planner、Session、Skill、Policy Engine、Sandbox Broker、監査 | Ollamaサーバ本体、MCP Client、利用対象リポジトリ、外部ネットワーク | +| Windows上の一時ACL/WFP/Job/AppContainer利用 | OS自体の完全仮想化、Hyper-V、WSL、Docker | + +### 2.3 v1の非対象 + +- Legacy HTTP+SSE transportの後方互換対応。 +- WebSocketや独自TCP等の独自MCP transport。 +- 外部ネットワークからのStreamable HTTP接続。 +- Streamable HTTPのアプリ内TLS終端・HTTP認証。 +- SandboxPolicyのMCP経由での変更。 +- 固定System PromptのMCP/CLI/設定からの置換。 +- Hot Reload。 +- 永続Sessionデータベース。 +- WSL、Docker、VMを安全境界として利用すること。 +- Credential Manager、SSH key、API token等のSandboxへの継承。 + +--- + +## 3. 用語 + +| 用語 | 定義 | +| --- | --- | +| MCP Client | 本システムをMCP Serverとして呼び出す外部AIエージェントまたはホスト。 | +| MCP Tool | MCP Clientに公開する `agent_run` と `agent_status`。 | +| Agent | Ollama、Planner、Internal Toolを用いてTaskを遂行する内部実行主体。 | +| Agent Runtime | Agent Loop、Session、Ollama呼出し、Internal Tool調停を行う中核。 | +| Internal Tool | Ollamaのnative tool callingにだけ公開され、MCP Clientには公開されない内部操作。 | +| Task | 依頼を分割した意味的な作業単位。 | +| TaskGraph | Taskとdependencyから成る有向非巡回グラフ。 | +| Token PERT | TaskのLLM消費量をO/M/Pのtoken値で推定するPERT派生モデル。 | +| Token CPM | TaskGraph上でexpected token costを重みとしてcritical pathを求めるモデル。 | +| Token Budget Class | 1K~128KのTask単位token予算階級。Ollama `num_ctx`とは別概念。 | +| Session | 会話、TaskGraph、Execution Resultをメモリ上に保持する論理単位。 | +| SandboxPolicy | Filesystem、Process、Network、Resourceの許可範囲を表すホワイトリスト型ポリシー。 | +| Sandbox | SandboxPolicyをWindows機構で強制したプロセス実行環境。 | +| Sandbox Broker | プロセス起動・許可判定・Windows強制機構の調停を担当する信頼境界。 | +| Application Profile | アプリケーション固定のAppContainer profile。Taskごとには作成・削除しない。 | +| Task Resource | Task中だけ存在するACL、WFP filter、Job Object、一時ファイル等。 | +| Approval | 実行ファイルのcanonical pathとSHA-256を信頼対象として登録する操作。 | +| Fixed System Prompt | 実行ファイルに組み込まれ、利用者が変更できない最上位指示。 | +| User System Prompt | 設定で指定可能だがFixed System Promptを上書きできない追加指示。 | +| Skill | LLMへの補助指示を記述したMarkdown。実行権限そのものを与えない。 | +| Locale | BCP 47形式を推奨する言語識別子。標準は `en` と `ja`。 | +| Audit Log | セキュリティに関係する操作を通常ログと分離して記録する監査記録。 | +| Recovery Journal | Task Resourceの適用・解除を復旧可能にする永続的な最小ジャーナル。 | + +--- + +## 4. 利用者と主要利用シナリオ + +| ID | 主体 | シナリオ | 成功条件 | +| --- | --- | --- | --- | +| UC-01 | MCP Client | 自然言語の依頼を送信する | Task IDとSession IDを受領する | +| UC-02 | MCP Client | Task状態を照会する | 状態と、完了時には最終回答をテキストで得る | +| UC-03 | 利用者 | 画像付き依頼を送信する | Vision対応modelなら処理される | +| UC-04 | 利用者 | 言語を指定して起動する | CLI/診断/MCP応答/LLM最終回答が指定言語になる | +| UC-05 | 管理者 | SandboxPolicyを設定する | 未許可能力はdenyされる | +| UC-06 | 管理者 | 実行ファイルを承認する | pathとSHA-256一致時だけ起動できる | +| UC-07 | Agent | 計画を作成・更新する | TaskGraphがDAGを維持しToken CPMを再計算する | +| UC-08 | Agent | Internal Toolを呼ぶ | Policy検査後にのみ副作用が発生する | +| UC-09 | システム | 異常終了から復旧する | 残留Task Resourceを除去してから受付開始する | + +--- + +## 5. 外部インターフェース仕様 + +### 5.1 MCP Transport + +| ID | Transport | 要件 | +| --- | --- | --- | +| MCP-TR-01 | stdio | MUST対応。既定transportとする。 | +| MCP-TR-02 | Streamable HTTP | MUST対応。loopbackのみlisten可能とする。 | +| MCP-TR-03 | Legacy HTTP+SSE | MUST NOT対応。後方互換fallbackも実装しない。 | +| MCP-TR-04 | Streamable HTTP SSE stream | v1では提供しない。GETによるevent streamは提供しない。 | +| MCP-TR-05 | 独自transport | MUST NOT実装。 | + +### 5.2 MCP Tool + +| Tool | 用途 | 処理モデル | 返却 | +| --- | --- | --- | --- | +| agent_run | 新規または既存Sessionに依頼を登録 | 非同期 | Task ID、Session IDを含むテキスト | +| agent_status | Task状態を取得 | 同期照会 | 状態、進捗要約、完了時最終回答を含むテキスト | + +### 5.3 agent_run入力要件 + +| ID | 項目 | 必須 | 要件 | +| --- | --- | --- | --- | +| MCP-RUN-01 | request | Yes | 空でないUTF-8テキスト。主I/F。 | +| MCP-RUN-02 | session_id | No | 指定時は存在するSessionへ継続。未指定時は新規Session。 | +| MCP-RUN-03 | temperature | No | 当該TaskのOllama呼出しにのみ適用する一時override。設定を書き換えない。 | +| MCP-RUN-04 | images | No | 画像0件以上。Vision対応model利用時のみ処理。 | +| MCP-RUN-05 | その他LLM設定 | No | model、system prompt、context等をMCPから変更してはならない。 | + +### 5.4 agent_status入力要件 + +| ID | 項目 | 必須 | 要件 | +| --- | --- | --- | --- | +| MCP-STS-01 | task_id | Yes | agent_runが返したTask ID。 | +| MCP-STS-02 | session_id | No | 指定時はTaskとの整合を検査する。 | + +### 5.5 Task状態 + +| 状態 | 意味 | 遷移先 | +| --- | --- | --- | +| queued | 受付済み、未開始 | planning / cancelled / failed | +| planning | TaskGraph作成・更新中 | running / failed | +| running | Internal ToolまたはLLM処理中 | planning / completed / failed / cancelled | +| completed | TaskGraph全ノード完了 | 終端 | +| failed | 回復不能な失敗 | 終端 | +| cancelled | 安全停止完了 | 終端 | + +### 5.6 CLI + +v1のCLI surfaceは次に限定する。 + +```text +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にしない。 + +--- + +## 6. Ollama機能仕様 + +| ID | 対象 | 仕様 | +| --- | --- | --- | +| OLL-01 | Backend | LLM backendはOllamaのみに限定する。 | +| OLL-02 | API | 会話とtool callingはOllama Chat APIを使用可能とする。 | +| OLL-03 | Options | Ollamaが提供する生成optionを設定ファイルから変更可能にする。 | +| OLL-04 | Typed Options | 既知optionは型付きで検証する。 | +| OLL-05 | Extra Options | 将来追加optionのため `extra_options` を許可する。既知optionとの競合は既知optionを優先する。 | +| OLL-06 | Temperature | 設定値を既定とし、agent_runのoptional値だけTask scopeで上書き可能。 | +| OLL-07 | Model | MCPから変更不可。 | +| OLL-08 | System Prompt | MCPから変更不可。Fixed System Promptは設定からも変更不可。 | +| OLL-09 | Vision | MCPから画像をoptional入力可能。非対応modelではlocalized error。 | +| OLL-10 | Tool Calling | Internal ToolにOllama native tool callingを使用する。 | +| OLL-11 | Tool Guard | 実行が必要なTaskでtool callが行われない場合、未実行を検出して再試行する。 | +| OLL-12 | Retry | Ollama通信失敗は既定3回まで再試行する。 | +| OLL-13 | Usage | `prompt_eval_count` と `eval_count` をTask実測tokenとして記録する。 | + +--- + +## 7. Agent Runtime仕様 + +### 7.1 Agent Loop + +| ID | 要件 | +| --- | --- | +| AGT-01 | 正常終了条件はTaskGraphの全Taskがcompletedであること。 | +| AGT-02 | 既定 `max_iterations` は128。超過時はfailed。 | +| AGT-03 | 同一原因と判定した失敗が5回連続した場合はfailed。 | +| AGT-04 | Taskが外部操作を必要とする場合、LLMの文章上の「実施した」という主張だけを完了根拠にしない。 | +| AGT-05 | 副作用はInternal Tool経由でのみ実行する。 | +| AGT-06 | Internal ToolはMCP Clientに列挙・公開しない。 | + +### 7.2 Tool未使用検出 + +AgentはTaskの期待副作用と観測結果を比較し、実行が必要なのにtool callが0件の場合はTaskをcompletedにしない。再試行はAgent Loopの失敗回数へ算入する。純粋な説明・分析Taskにはtool callを強制しない。 + +--- + +## 8. Planner仕様 + +### 8.1 TaskGraph + +| ID | 要件 | +| --- | --- | +| PLN-01 | TaskGraphはDAGでなければならない。cycleを検出した更新は拒否する。 | +| PLN-02 | 既定 `max_tasks` は32。 | +| PLN-03 | completed Taskはimmutable。 | +| PLN-04 | 未完了Taskの追加とdependency追加を許可する。 | +| PLN-05 | TaskGraph変更後はToken CPMを再計算する。 | +| PLN-06 | Taskは意味的作業単位とし、Token Budget Classとは分離する。 | + +### 8.2 Token Budget Class + +| Class | Token上限 | +| --- | --- | +| 1K | 1,024 | +| 2K | 2,048 | +| 4K | 4,096 | +| 8K | 8,192 | +| 16K | 16,384 | +| 32K | 32,768 | +| 64K | 65,536 | +| 128K | 131,072 | + +Token Budget ClassはTask全体に許されるLLM token消費の計画値であり、単一Ollama callのcontext window (`num_ctx`) ではない。複数callの合計がTask実績となる。 + +### 8.3 Token PERT + +- 各Taskは `optimistic_tokens (O)`、`most_likely_tokens (M)`、`pessimistic_tokens (P)` を持つ。 +- 不変条件は `0 < O <= M <= P <= token_budget` とする。 +- 期待token costは `E = (O + 4M + P) / 6` とする。 +- Critical Pathは依存経路上の `E` の合計が最大の経路とする。 +- Token CPMは実行時間を予測しない。依存連鎖のLLMコストと優先度を可視化するために使用する。 +- 全Taskの総token予算はCritical Pathとは別に合計して管理する。 + +### 8.4 実測 + +Task実績はOllama応答の `prompt_eval_count` をinput token、`eval_count` をoutput tokenとして累積し、`actual_total_tokens = input + output` を保持する。v1では実績による自動学習補正は行わず、将来の推定改善に利用可能な記録だけを残す。 + +--- + +## 9. Session・Context仕様 + +| ID | 要件 | +| --- | --- | +| SES-01 | Sessionを持つ。完全statelessにはしない。 | +| SES-02 | Session IDをMCP I/Fへ公開する。 | +| SES-03 | Sessionはプロセスメモリにのみ保持し、アプリ終了時に消失してよい。 | +| SES-04 | Sessionはconversation、TaskGraph、Execution Resultを保持する。 | +| SES-05 | context上限接近時は古い情報を単純削除せず要約する。 | +| SES-06 | 要約後も未完了Task、security decision、重要なexecution result、利用者制約を保持する。 | + +--- + +## 10. Skill・Prompt仕様 + +### 10.1 Prompt優先順位 + +優先順位は `Fixed System Prompt > User System Prompt > Runtime Context > Conversation` とする。下位層は上位層の禁止事項・安全条件を上書きできない。 + +| 層 | 変更主体 | 内容 | +| --- | --- | --- | +| Fixed System Prompt | アプリケーションのみ | 安全不変条件、tool利用規則、完了判定 | +| User System Prompt | 設定所有者 | プロジェクト固有の追加指示 | +| Runtime Context | Agent Runtime | locale、選択Skill、Sandbox capability、TaskGraph | +| Conversation | MCP Client/Agent | 依頼と対話履歴 | + +### 10.2 Skill + +- SkillはMarkdown instructionである。 +- Skillロードは権限付与を意味しない。 +- 必要なSkillだけを選択する。 +- Skill選択はLLMにより行うが、選択可能集合は設定されたSkill directoryに限定する。 + +--- + +## 11. SandboxPolicy仕様 + +### 11.1 基本原則 + +- **ホワイトリスト方式**を採用する。未指定能力はdenyする。 +- 子・孫プロセスは親より強い権限を取得できない。 +- LLMはSandboxPolicyを変更できない。 +- Policy変更は設定変更とアプリ再起動を必要とする。 +- v1で開放可能なのはFilesystem、Process、Network、Resourceとする。その他能力はdenyとする。 + +### 11.2 Filesystem Policy + +| 権限 | 意味 | +| --- | --- | +| read | ファイル内容読取、directory列挙。 | +| write | create、overwrite、renameを含む。deleteは含まない。 | +| execute | 対象ファイルを実行対象として利用できる。Process approvalも別途必要。 | +| delete | ファイルまたはdirectoryを削除できる。 | + +| ID | 要件 | +| --- | --- | +| FS-01 | 指定粒度はdirectoryまたはfile。workspaceという特別な権限単位は持たない。 | +| FS-02 | pathはcanonicalize後にPolicy評価する。 | +| FS-03 | symlink、junction、その他reparse pointを経由した許可範囲外への脱出を禁止する。 | +| FS-04 | write権限だけではdeleteできない。 | +| FS-05 | ACLとAppContainerの両方で強制可能な形にする。 | + +### 11.3 Process Policy + +| ID | 要件 | +| --- | --- | +| PRC-01 | 実行対象はcanonical pathとSHA-256が承認記録と一致しなければならない。 | +| PRC-02 | 実行ファイル更新でhashが変化した場合は自動許可せず再承認を要求する。 | +| PRC-03 | path変更も再承認を要求する。 | +| PRC-04 | cmd.exe、powershell.exe、pwsh.exeは機能上デフォルト許可とするが、承認照合を免除しない。 | +| PRC-05 | shell categoryは設定で禁止可能。 | +| PRC-06 | すべてのdescendant processに同等以下のSandboxPolicyを適用する。 | +| PRC-07 | 実行前判定はSandbox Brokerが行う。 | + +### 11.4 Network Policy + +- Network modeは `deny` と `allow` の2値とする。 +- `deny` はlocalhostを含む全通信を拒否する。 +- `allow` はhost/port allow-listに一致するoutboundだけを許可する。 +- allow-listが空の `allow` は実質denyとして扱い、全開放を意味しない。 +- host名はhostsファイルに近い単純な列挙思想で扱い、汎用Firewall言語は実装しない。 + +### 11.5 Resource Policy + +| 資源 | 要件 | +| --- | --- | +| process count | 上限を設定可能。Job配下全体に適用。 | +| memory | 上限を設定可能。 | +| wall-clock timeout | TaskまたはProcessの停止条件として設定可能。 | +| child process | 親と同等以下の制約下でのみ許可。 | + +### 11.6 v1で明示denyする能力 + +- Registry write +- 任意COM/Automation +- Device直接アクセス +- Camera/Microphone +- Credential Manager +- SSH keyの自動継承 +- API token/secretの自動継承 +- Sandbox外のNamed Pipe/IPC + +--- + +## 12. File Editing仕様 + +- overwrite、patch、atomic replaceを併用できる。 +- 通常は変更前内容をメモリに保持し、編集後検証に失敗した場合にrollbackする。 +- 設定されたmemory backup閾値を超える大容量ファイルでは、Sandbox管理下の一時backupを使用できる。 +- 利用者向け恒久 `.bak` ファイルは既定で作成しない。 +- atomic replaceが適用可能な操作では、部分書込み状態を利用者から観測させないことを優先する。 + +--- + +## 13. Application Profile・Task Resource仕様 + +- AppContainer profileはapplication固定とする。 +- Task終了時にApplication Profileを削除しない。 +- Task固有ACL、WFP filter、Job Object、一時ファイル等はTask Resourceとして管理する。 +- Task Resourceは正常終了・失敗・cancelのいずれでも残留させない。 +- crashで残留可能性がある変更はRecovery Journalにより次回起動時に回収する。 +- MCP受付開始前にRecoveryを完了し、clean stateを確認しなければならない。 + +--- + +## 14. 国際化仕様 + +| ID | 要件 | +| --- | --- | +| I18N-01 | アプリケーション管理メッセージをソースコードへハードコードしない。 | +| I18N-02 | 標準localeとして `locales/en.json` と `locales/ja.json` を配布する。 | +| I18N-03 | ユーザーは `zh-CN.json` 等を追加し、アプリ変更なしでlocaleを追加できる。 | +| I18N-04 | locale識別子はBCP 47形式を推奨する。 | +| I18N-05 | `--lang <locale>` で起動時に選択可能。 | +| I18N-06 | 優先順位は CLI > config > built-in default(en)。 | +| I18N-07 | 選択言語はCLI、診断、MCPテキスト応答、LLM最終回答へ適用する。 | +| I18N-08 | 入力言語の自動検出による切替は行わない。 | +| I18N-09 | placeholderは `{task}` のようなnamed placeholderを使う。 | +| I18N-10 | missing keyは 選択locale → en → key文字列 の順にfallbackする。 | +| I18N-11 | 壊れたJSONまたは未知keyを含むlocale fileはfatal errorとする。 | + +--- + +## 15. Configuration仕様 + +- 主設定形式はYAML。 +- `schema_version` を必須とする。 +- 設定変更の反映には再起動を必須とする。 +- Hot Reloadは明示的に非対応。 +- CLIの `--config` で設定ファイルpathを選択可能。 +- 起動時にschema、path、hash approval、locale、policyの静的validationを行う。 + +--- + +## 16. Logging・Audit仕様 + +| 種別 | 要件 | +| --- | --- | +| Application Log | stderrに出力可能。stdio時stdoutへログを出してはならない。ファイルにも保存する。 | +| LLM Log | promptとresponseを記録する。secretを継承しない前提でも、ログ出力先は保護する。 | +| Audit Log | 通常ログと分離する。process、args、exit code、file write、delete、denied access等を記録する。 | +| Token Metrics | Task/Call単位のinput/output/total tokenを記録する。 | + +--- + +## 17. Recovery・異常系仕様 + +| ID | 異常 | 要求動作 | +| --- | --- | --- | +| REC-01 | Ollama unavailable | 既定3回retry後、Taskをfailed。 | +| REC-02 | Process hang | timeout後、安全にJob配下を停止。 | +| REC-03 | Application終了 | Job Object配下を必ずkillする。 | +| REC-04 | stdio EOF/Client消失 | 当該Client所有のTaskを安全停止する。 | +| REC-05 | Streamable HTTP session終了 | 当該Session所有のTaskを安全停止する。通常のHTTP request完了は切断とみなさない。 | +| REC-06 | crash後起動 | Recovery Journalに基づき残留Task Resourceをcleanにしてからserveする。 | +| REC-07 | cleanup失敗 | serveを開始せずfatal errorとする。 | + +--- + +## 18. セキュリティ不変条件 + +| ID | 不変条件 | +| --- | --- | +| SEC-INV-01 | LLMの出力だけでは権限を増加できない。 | +| SEC-INV-02 | MCP ClientはSandboxPolicyを変更できない。 | +| SEC-INV-03 | descendant processは親より強い権限を持てない。 | +| SEC-INV-04 | 未許可Filesystem pathへR/W/E/Deleteできない。 | +| SEC-INV-05 | 承認hashと一致しない実行ファイルを起動できない。 | +| SEC-INV-06 | Network denyではlocalhostを含め通信できない。 | +| SEC-INV-07 | Network allowでもallow-list外host/portへ通信できない。 | +| SEC-INV-08 | CredentialをSandboxへ暗黙継承しない。 | +| SEC-INV-09 | Fixed System Promptは利用者入力で置換できない。 | +| SEC-INV-10 | Task終了後にTask Resourceを残さない。 | +| SEC-INV-11 | Recovery未完了状態でMCP受付を開始しない。 | +| SEC-INV-12 | stdio stdoutにはMCP protocol以外を書かない。 | + +--- + +## 19. 非機能要求 + +| ID | 品質 | 要求 | +| --- | --- | --- | +| NFR-01 | Security | default deny、least privilege、explicit approvalを優先する。 | +| NFR-02 | Determinism | Policy評価、TaskGraph検証、PERT/CPM計算はLLMに依存せず決定的に実行する。 | +| NFR-03 | Recoverability | crash後にclean stateへ復帰できる。 | +| NFR-04 | Maintainability | 外部MCP Toolを2個に固定し、内部責務を分離する。 | +| NFR-05 | Dependency Control | 標準ライブラリで実現可能な機能に新規依存を追加しない。 | +| NFR-06 | Portability | v1はWindows 11 x64専用。Windows機構を抽象化し過ぎない。 | +| NFR-07 | Observability | Task、Tool、Process、Token、Policy denialを追跡可能にする。 | +| NFR-08 | Localization | 英語・日本語を標準提供し、追加localeをコード変更なしで導入可能。 | +| NFR-09 | Readability | 設定、ログ、仕様語彙を一貫させる。 | + +--- + +## 20. 受入基準 + +| ID | 検証条件 | +| --- | --- | +| AT-01 | stdioでinitialize→agent_run→agent_statusが成立する。 | +| AT-02 | Streamable HTTPを127.0.0.1/::1で利用でき、非loopback bindは拒否される。 | +| AT-03 | Legacy HTTP+SSE endpointを提供しない。 | +| AT-04 | agent_runがTask ID/Session IDを返し、完了前にblockingし続けない。 | +| AT-05 | MCP temperature overrideがTask scopeのみで有効。 | +| AT-06 | 非Vision modelへ画像指定時、選択localeのerrorが返る。 | +| AT-07 | 未許可file read/write/deleteがOSまたはBrokerで拒否されAuditに残る。 | +| AT-08 | reparse point経由で許可path外へ到達できない。 | +| AT-09 | 承認hash変更後のexe実行が拒否される。 | +| AT-10 | Network denyでloopbackを含む通信が拒否される。 | +| AT-11 | allow-list外host/portへの通信が拒否される。 | +| AT-12 | 子プロセス・孫プロセスがJobとSandbox制約から逸脱できない。 | +| AT-13 | Task crash後、次回起動RecoveryでTask Resourceが除去される。 | +| AT-14 | TaskGraph cycle追加が拒否される。 | +| AT-15 | completed Taskが変更されない。 | +| AT-16 | O/M/Pからexpected tokenが決定的に計算される。 | +| AT-17 | Ollama実測token数がTask実績へ累積される。 | +| AT-18 | ja/en切替がCLI、MCP応答、LLM回答へ反映される。 | +| AT-19 | 追加localeがコード変更なしでロードされる。 | +| AT-20 | 未知locale keyまたは壊れたJSONで起動/checkが失敗する。 | + +--- + +## 21. 要求トレーサビリティ + +| 仕様領域 | 主要Requirement | Design.md対応章 | +| --- | --- | --- | +| MCP | MCP-TR / MCP-RUN / MCP-STS | 5章 | +| Ollama | OLL-* | 6章 | +| Agent | AGT-* | 7章 | +| Planner | PLN-* | 8章 | +| Session | SES-* | 9章 | +| Sandbox | FS-* / PRC-* / SEC-INV-* | 10〜13章 | +| i18n | I18N-* | 14章 | +| Recovery | REC-* | 16章 | +| NFR | NFR-* | 全章横断 | + +--- + +## 22. 参考資料 + +- IPA/SEC「実務家のための形式手法 厳密な仕様記述を志すための形式手法入門 厳密な仕様記述入門」2013年。仕様と設計の分離、構造・機能・振る舞い・非機能、Validation/Verification、完全性・一貫性等の記述原則を参考にした。 +- Model Context Protocol Specification: standard transportsとしてstdioとStreamable HTTPを参照し、旧HTTP+SSE transportは非対応とした。 +- Ollama API Reference: Chat APIのtools/images/optionsおよび `prompt_eval_count` / `eval_count` を参照した。 + +--- + +## 23. 変更管理 + +- 本仕様の変更は `schema_version`、MCP Tool schema、SandboxPolicy、安全不変条件への影響を必ず確認する。 +- Design.mdが本仕様と矛盾した場合は本仕様を優先し、Design.mdを修正する。 +- 実装都合で仕様を暗黙変更してはならない。必要な場合は先に仕様を変更する。 + +--- + +## 24. Requirement ID索引 + +- `MCP-TR-*`: MCP transport +- `MCP-RUN-*`: agent_run +- `MCP-STS-*`: agent_status +- `OLL-*`: Ollama +- `AGT-*`: Agent Loop +- `PLN-*`: Planner +- `SES-*`: Session +- `FS-*`: Filesystem +- `PRC-*`: Process +- `I18N-*`: Localization +- `REC-*`: Recovery +- `SEC-INV-*`: Security invariant +- `NFR-*`: Non-functional +- `AT-*`: Acceptance + +## 25. 仕様上の禁止事項一覧 + +- MCP ClientへInternal Toolを公開すること。 +- MCP requestでSystem Prompt、model、SandboxPolicyを変更すること。 +- `temperature` overrideを永続設定へ書き戻すこと。 +- Legacy HTTP+SSEを互換目的で自動有効化すること。 +- Streamable HTTPをloopback外にbindすること。 +- write permissionだけでdeleteを許可すること。 +- reparse point解決前の文字列pathだけでallow判定すること。 +- hash不一致の実行ファイルを自動再承認すること。 +- Network `allow`をunrestricted outboundとして解釈すること。 +- 子プロセスに親より広いcapabilityを付与すること。 +- Skill選択を権限付与として扱うこと。 +- completed Taskを書き換えること。 +- Token Budget ClassをOllama context lengthと同一視すること。 +- context要約で未完了Taskや利用者制約を消すこと。 +- cleanup失敗状態でserveを開始すること。 diff --git a/plans/ImplementationPlan.md b/plans/ImplementationPlan.md new file mode 100644 index 0000000..c31f178 --- /dev/null +++ b/plans/ImplementationPlan.md @@ -0,0 +1,757 @@ +# AI Agent Sandbox MCP Server — 実装・監査作業計画 +**文書名:** `ImplementationPlan.md` +**版:** 0.1 Draft +**上位文書:** `Specifications.md` / `Design.md` +**目的:** Codex等のAIコーディングエージェントへ実装作業を委任しつつ、各段階の成果・差分・テスト・未完了事項を後から人間が監査できる形で管理する。 +--- +## 1. 文書の位置付け +### 1.1 文書間の優先順位 +実装判断の優先順位を次に固定する。 +1. `Specifications.md` +2. `Design.md` +3. `ImplementationPlan.md` +4. 実装コード・テスト・設定 +5. Codexの作業上の判断 +下位成果物が上位文書と矛盾する場合、下位成果物を修正する。実装都合で仕様を暗黙変更してはならない。 +### 1.2 本計画の役割 +本計画は次を定義する。 +- 実装フェーズと依存順序 +- 各フェーズの実装対象と非対象 +- 完了条件 +- 必須テスト +- Codexが提出すべき監査証跡 +- 人間が後から確認する監査観点 +- 次フェーズへ進むためのGate +- 仕様変更が必要になった場合の停止条件 +### 1.3 本計画が定義しないもの +以下は上位文書または実装時の詳細設計に従う。 +- 仕様そのものの変更 +- Security Invariantの緩和 +- 新しいMCP Toolの追加 +- Windows APIの具体的なAPI呼出し系列のうち `Design.md` で実装時選択としている部分 +- 未承認依存ライブラリの追加 +--- +## 2. 実装・監査の基本原則 +| ID | 原則 | 内容 | +| --- | --- | --- | +| PLAN-01 | Traceability | すべての実装項目を仕様ID・設計章・テストへ結び付ける。 | +| PLAN-02 | Evidence First | 「実装した」という報告だけを完了根拠にしない。コード、テスト結果、ログ等の証跡を要求する。 | +| PLAN-03 | Small Change | 1フェーズ内でも責務単位の小さい変更に分割する。 | +| PLAN-04 | No Silent Scope Growth | Codexが独自に機能・層・ライブラリ・MCP Toolを増やすことを禁止する。 | +| PLAN-05 | Security Gate | Security Invariantに関係する失敗を残したまま後続フェーズへ進まない。 | +| PLAN-06 | Deterministic Verification | Policy、Planner、State Transition等はLLM評価ではなく自動テストで確認する。 | +| PLAN-07 | Negative Test | セキュリティ機能は成功ケースだけでなく拒否ケースを必須とする。 | +| PLAN-08 | Recovery Test | ACL/WFP/File transaction等の一時副作用は異常終了からの回復まで検証する。 | +| PLAN-09 | No Hidden Completion | TODO、stub、skip、未実行テストを残した状態をPASSと報告しない。 | +| PLAN-10 | Auditability | 各Gateで、第三者が再実行できるコマンドと結果を保存する。 | +--- +## 3. Codex提出物の共通形式 +各フェーズ完了時にCodexは以下を提出する。 +### 3.1 必須作業報告 +```markdown +## Phase <n> Completion Report + +### 実施内容 +- ... + +### 変更ファイル +- path/to/file: 変更理由 + +### 対応Requirement / Design +- Requirement: ... +- Design section: ... + +### 実行した検証 +- command: `...` +- result: PASS / FAIL +- summary: ... + +### 新規・更新テスト +- test name: 対象 + +### 監査証跡 +- build log: ... +- test log: ... +- audit/security log: ... + +### 未完了・既知問題 +- None / ... + +### 仕様・設計からの逸脱 +- None / ... + +### 次フェーズへの前提 +- ... +``` +### 3.2 必須証跡 +| 証跡 | 必須 | 内容 | +| --- | :---: | --- | +| Git diff / commit | Yes | そのフェーズの変更範囲を特定できること。 | +| Build結果 | Yes | `dotnet build` の成功。 | +| Test結果 | Yes | 対象unit/integration testの件数と結果。 | +| 新規テスト一覧 | Yes | 追加したテスト名と対応仕様。 | +| Skip一覧 | Yes | 0件であることを原則とする。存在する場合は理由を明記。 | +| TODO/FIXME一覧 | Yes | 新規に残したものを列挙。 | +| Dependency差分 | Yes | NuGet追加・更新がないこと、または承認根拠。 | +| Security evidence | 該当時 | deny結果、cleanup結果、process tree等。 | +| Audit Log sample | 該当時 | 仕様どおりのeventが出ていること。 | +### 3.3 禁止する完了根拠 +以下だけでは完了と認めない。 +- 「コードを確認したので問題ない」 +- 「コンパイルできるはず」 +- 「既存テストは影響しない」 +- 「手元ではおそらく動作する」 +- LLM自身によるコードレビューのみ +- テストを実行していない状態でのPASS宣言 +--- +## 4. 全体フェーズ +| Phase | 名称 | 主成果 | Gate | +| ---: | --- | --- | --- | +| 0 | Baseline / Skeleton Lock | solution、依存、CI相当のローカル検証基盤 | G0 | +| 1 | Configuration / Localization / Logging | YAML、locale、固定Prompt基盤 | G1 | +| 2 | MCP Public Interface | stdio、非同期Task受付、`agent_run/status` | G2 | +| 3 | Session / Ollama / Prompt | text会話、Session、token usage、Prompt優先順位 | G3 | +| 4 | Token Planner | TaskGraph、Token PERT/CPM、再計画 | G4 | +| 5 | Internal Tool / Policy Boundary | 5 Internal Tool、ToolUseGuard、Policy Engine | G5 | +| 6 | Filesystem / Process Sandbox | AppContainer、ACL、Job、hash approval | G6 | +| 7 | Transaction / Recovery | ACL Resource Transaction、File rollback、Recovery Journal | G7 | +| 8 | Network Sandbox | WFP deny / host-port allow-list | G8 | +| 9 | Vision / Streamable HTTP | optional画像、loopback HTTP | G9 | +| 10 | Audit / Security Hardening | Audit JSONL、全Security Matrix | G10 | +| 11 | Acceptance / Release Audit | AT全件、文書整合、未完了ゼロ確認 | G11 | +依存順は原則として `0 → 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9 → 10 → 11` とする。 +Security境界を後回しにした状態で、実際の任意Process実行を先行実装してはならない。 +--- +# 5. Phase 0 — Baseline / Skeleton Lock +## 5.1 目的 +実装開始前にsolution構造、ビルド、テスト、依存追加ルールを固定し、以降の差分を監査可能にする。 +## 5.2 実装対象 +- .NET 10 / C# 14 solution +- `Agent.App` +- `Agent.Mcp` +- `Agent.Core` +- `Agent.Planner` +- `Agent.Windows` +- 対応Test project +- `Directory.Build.props` 等の共通設定 +- warning方針 +- Git ignore +- 最小README +## 5.3 非対象 +- MCP実処理 +- Ollama通信 +- Sandbox実装 +- Planner実装 +## 5.4 完了条件 +- [ ] `dotnet restore` 成功 +- [ ] `dotnet build` 成功 +- [ ] `dotnet test` 成功 +- [ ] Project dependencyが `Design.md` の方向と一致 +- [ ] `Agent.Core` / `Agent.Planner` がWin32型を参照していない +- [ ] 不要なProject・Utility層が作成されていない +- [ ] 未承認NuGet dependencyがない +## 5.5 必須監査 +| 監査 | 確認内容 | +| --- | --- | +| Project graph | Design 4章と一致するか | +| Package list | 許可されたpackageだけか | +| Build | warning/errorの状態 | +| Naming | `Utils/Common/Infrastructure/Manager`等の曖昧な巨大層がないか | +### Gate G0 +全完了条件PASS。構造上の逸脱がある場合はPhase 1へ進まない。 +--- +# 6. Phase 1 — Configuration / Localization / Logging +## 6.1 対応仕様 +- Specifications 14章、15章、16章 +- I18N-01〜11 +- NFR-05、NFR-08、NFR-09 +## 6.2 実装対象 +- `agent.yaml` +- `schema_version` +- typed configuration +- `en.json` / `ja.json` +- locale loader / validator +- named placeholder +- CLI `--config` / `--lang` +- fallback `selected locale → en → key` +- Fixed System Promptの埋め込み基盤 +- User System Prompt path +- Application Logのstderr/file基盤 +## 6.3 重要制約 +- Fixed System Promptを外部ファイルへ移動しない。 +- locale messageをコード中に直接ハードコードしない。 +- unknown locale keyまたは壊れたJSONはfatal。 +- Hot Reloadを実装しない。 +## 6.4 必須テスト +- [ ] `en` 起動 +- [ ] `ja` 起動 +- [ ] `--lang` がconfigより優先 +- [ ] 追加locale fileをコード変更なしで読める +- [ ] missing keyはfallbackする +- [ ] unknown keyでfatal +- [ ] malformed JSONでfatal +- [ ] placeholder不一致でfatal +- [ ] invalid YAML/schemaでfatal +## 6.5 監査証跡 +- locale key一覧比較結果 +- `agent-mcp check --lang en/ja` の結果 +- stderr/file log sample +- Fixed Promptの格納場所 +### Gate G1 +LocalizationとConfigurationのnegative testを含め全PASS。 +--- +# 7. Phase 2 — MCP Public Interface +## 7.1 対応仕様 +- MCP-TR-01〜05 +- MCP-RUN-01〜05 +- MCP-STS-01〜02 +- AT-01〜05 +- SEC-INV-12 +## 7.2 実装対象 +- MCP公式C# SDK +- stdio transport +- public Toolを `agent_run` / `agent_status` の2個だけ登録 +- 非同期Task受付の最小Task registry +- UUID Task ID / Session ID +- `agent_run` Schema +- `agent_status` Schema +- text content response +- optional `temperature` +## 7.3 このPhaseではstubでよい部分 +Agent本体はまだ未実装のため、Task workerは決定的なstubでもよい。ただしMCP I/Fと状態遷移の外形を固定する。 +## 7.4 必須テスト +- [ ] initialize成功 +- [ ] tool listが2個のみ +- [ ] `agent_run` がblockingせずTask ID/Session IDを返す +- [ ] `agent_status` がTaskを取得できる +- [ ] invalid schemaを拒否 +- [ ] model/system prompt/policyを指定する余分なpropertyを拒否 +- [ ] stdio stdoutにMCP protocol以外が出ない +- [ ] Legacy SSE endpointが存在しない +## 7.5 監査ポイント +Codexが「便利な補助MCP Tool」を追加していないことを明示確認する。 +### Gate G2 +MCP surfaceが仕様どおり2 Toolのみで固定されていること。 +--- +# 8. Phase 3 — Session / Ollama / Prompt +## 8.1 対応仕様 +- OLL-01〜13 +- SES-01〜06 +- Specifications 10章 +## 8.2 実装対象 +- Ollama `HttpClient` +- Chat API +- typed `OllamaOptions` +- `extra_options` +- temperature Task-scope override +- `prompt_eval_count` / `eval_count` +- in-memory Session Store +- Conversation / ExecutionResults +- Prompt Composer +- Prompt優先順位 +- Ollama transient retry 3回 +## 8.3 Prompt順序 +1. Fixed System Prompt +2. User System Prompt +3. Locale instruction +4. Skill +5. Sandbox capability summary +6. TaskGraph / current Task +7. Summary +8. Conversation / Execution Result +このPhaseではSkill選択やTaskGraphが未実装の場合、空要素として合成可能にする。 +## 8.4 必須テスト +- [ ] text-only Ollama call成功 +- [ ] Session継続でconversationが保持される +- [ ] process再起動後Sessionが消失する +- [ ] temperature overrideが当該Taskだけに作用 +- [ ] typed optionと`extra_options`競合を拒否 +- [ ] prompt/eval tokenを取得 +- [ ] transient errorだけ最大3回retry +- [ ] permanent errorを無駄にretryしない +- [ ] Fixed PromptをUser Promptが置換できない +## 8.5 監査証跡 +- 実際にOllamaへ送信したpayloadのsanitized sample +- token usage sample +- Session IDを跨いだ2回以上の会話テスト +### Gate G3 +Ollama通信とSessionがMCP I/Fに統合され、global設定をTaskから変更できないこと。 +--- +# 9. Phase 4 — Token Planner +## 9.1 対応仕様 +- PLN-01〜06 +- Specifications 8章 +- AT-14〜17 +## 9.2 実装対象 +- `AgentTask` +- `TaskGraph` +- DAG validation +- max_tasks=32 +- completed immutable +- Token Budget Class 1K〜128K +- O/M/P Token PERT +- Token CPM +- Task追加 / dependency追加 +- 実測input/output/total token +## 9.3 不変条件 +```text +0 < O <= M <= P <= TokenBudgetClass.MaxTokens +ExpectedTokens = (O + 4M + P) / 6 +TaskGraph is DAG +completed Task is immutable +``` +## 9.4 必須テスト +- [ ] cycle拒否 +- [ ] max_tasks超過拒否 +- [ ] completed変更拒否 +- [ ] O/M/P invalid ordering拒否 +- [ ] Budget超過拒否 +- [ ] 既知DAGでcritical path一致 +- [ ] graph変更でCPM再計算 +- [ ] Ollama実測tokenがTaskへ累積 +## 9.5 監査 +Known-answer testを用意し、LLMを使わず同一入力で同一結果になることを確認する。 +### Gate G4 +Planner deterministic test全PASS。 +--- +# 10. Phase 5 — Internal Tool / Policy Boundary +## 10.1 対応仕様 +- AGT-01〜06 +- OLL-10〜11 +- SEC-INV-01〜02 +## 10.2 Internal Toolを5群に固定 +| Tool | Operation | +| --- | --- | +| `file_search` | glob / name / text / regex / tail | +| `file_read` | whole / range / metadata | +| `file_edit` | overwrite / patch / atomic_replace / delete | +| `process_run` | exe + args + cwd + timeout | +| `task_update` | add / dependency / state / estimate | +個々の `grep`、`find`、`tail` 等を独立Toolにしない。 +## 10.3 実装対象 +- JSON Schema +- Ollama native tool calling +- Internal Tool Dispatcher +- Policy Engine I/F +- Tool argument validation +- ToolUseGuard +- `requires_external_effect` +- same failure fingerprint limit=5 +## 10.4 重要な段階制約 +このPhaseの副作用backendはfake/in-memory実装を使用可能とし、Windows sandboxを迂回した本物の無制限file/process操作を実装してはならない。 +## 10.5 必須テスト +- [ ] MCP ClientからInternal Toolが見えない +- [ ] Ollamaには5群のみ公開 +- [ ] malformed tool args拒否 +- [ ] Policy deny時に副作用なし +- [ ] external effect必須Taskでtool未使用ならcompletedにならない +- [ ] 同一失敗5回でfailed +- [ ] pure analysis TaskにはToolを強制しない +### Gate G5 +LLM→Tool→Policyの境界が固定され、Policyを通らない副作用経路が存在しないこと。 +--- +# 11. Phase 6 — Filesystem / Process Sandbox +## 11.1 対応仕様 +- Specifications 11.1〜11.3 +- SEC-INV-03〜05、08 +- ST-01〜11、ST-16 +## 11.2 実装対象 +- Application固定AppContainer Profile +- Sandbox Broker +- FilesystemPolicy R/W/E/Delete +- canonical path +- reparse point防御 +- NTFS ACL +- Process approval canonical path + SHA-256 +- shell toggle +- Job Object +- descendant制御 +- process count / memory limit +- KILL_ON_JOB_CLOSE +- Named Pipeが必要ならtask固有DACL +## 11.3 Process approval +承認条件は以下を両方満たすこと。 +```text +canonical path == approval.path +SHA-256 == approval.sha256 +``` +hash変更、path変更は再承認を必要とする。 +## 11.4 必須Security Test +- [ ] ST-01 read許可成功 +- [ ] ST-02 read未許可拒否 +- [ ] ST-03 write許可成功 +- [ ] ST-04 delete権限なし拒否 +- [ ] ST-05 junction脱出拒否 +- [ ] ST-06 symlink chain脱出拒否 +- [ ] ST-07 approved exe成功 +- [ ] ST-08 hash mismatch拒否 +- [ ] ST-09 shell disabled拒否 +- [ ] ST-10 descendant未承認exe拒否 +- [ ] ST-11 Job closeで全descendant終了 +- [ ] ST-16 Ollama tool path脱出拒否 +## 11.5 監査証跡 +Security testでは「例外になった」だけでなく、OS/Brokerで実際に対象資源へ副作用が発生していない証跡を残す。 +### Gate G6 +ST-01〜11、16全PASS。Security不具合を残したまま進行禁止。 +--- +# 12. Phase 7 — Resource Transaction / Recovery +## 12.1 対応仕様 +- Specifications 12〜13章、17章 +- SEC-INV-10〜11 +- REC-02、03、06、07 +- ST-17、18のうちACL側 +## 12.2 実装対象 +- Recovery Journal +- CLEAN / PREPARING / APPLIED / RUNNING / CLEANING / RECOVERY_REQUIRED +- ACL適用前journal flush +- Task Resource ownership +- cleanup逆順処理 +- 起動前Recovery +- File Transaction +- memory snapshot / temp backup +- patch guard +- atomic replace +- rollback後hash検証 +## 12.3 ACID対応 +| 性質 | 実装上の確認 | +| --- | --- | +| Atomicity | ACL/File変更途中失敗時にrollbackされる | +| Consistency | Policyを満たさない状態でprocessを開始しない | +| Isolation | Task ID違いのResourceを誤cleanupしない | +| Durability | cleanupに必要なJournalがcrash後も残る | +## 12.4 強制Crash Test +最低限次の地点でProcessを意図的に終了させ、次回起動時にRecoveryを確認する。 +- [ ] journal作成後、ACL前 +- [ ] ACL適用直後 +- [ ] sandbox process起動後 +- [ ] File temp作成後 +- [ ] replace直後、commit前 +- [ ] cleanup途中 +## 12.5 完了条件 +- [ ] crash後に元ACLへ復旧 +- [ ] temp resourceなし +- [ ] orphan processなし +- [ ] recovery完了前にMCP serveしない +- [ ] cleanup不能ならfatal +### Gate G7 +全Recovery test PASS。残留Resourceゼロを証跡で確認する。 +--- +# 13. Phase 8 — Network Sandbox / WFP +## 13.1 対応仕様 +- Specifications 11.4 +- SEC-INV-06〜07 +- ST-12〜14、ST-18 +## 13.2 固定方針 +```text +mode=deny + -> localhostを含むoutbound全拒否 + +mode=allow + -> default deny + -> allow-list hostをTask開始時にDNS resolve + -> IP snapshot + portだけallow +``` +## 13.3 実装時にCodexが選択してよい範囲 +- WFP layer +- sublayer +- filter condition +- transaction API sequence +ただし仕様を変更する選択は不可。 +## 13.4 必須テスト +- [ ] denyで127.0.0.1拒否 +- [ ] denyで外部host拒否 +- [ ] allowで許可host:port成功 +- [ ] allowで未許可port拒否 +- [ ] allowで未許可host拒否 +- [ ] DNS失敗時deny +- [ ] Task終了時WFP filter削除 +- [ ] WFP適用直後crash→次回Recovery +## 13.5 Codex必須報告 +WFP API選択理由を短く報告し、Windows SDK/APIの根拠と、どのSecurity Testで保証するかを記録する。 +### Gate G8 +Network Security Test全PASS、filter残留なし。 +--- +# 14. Phase 9 — Vision / Streamable HTTP +## 14.1 対応仕様 +- OLL-09 +- MCP-TR-02〜04 +- AT-02、03、06 +- ST-20 +## 14.2 Vision +- `images` optional +- PNG/JPEG/WebP +- Base64 validation +- size/count上限 +- Vision非対応modelはlocalized error +## 14.3 Streamable HTTP +- loopbackのみ +- `127.0.0.1` / `::1` +- non-loopback bindはfatal validation +- v1はTLSなし +- v1はHTTP認証なし +- 外部公開不可 +- Legacy HTTP+SSEなし +- GET SSE listenerなし +## 14.4 必須テスト +- [ ] text-only requestは画像なしで従来どおり動作 +- [ ] Vision対応modelで画像成功 +- [ ] Vision非対応modelでlocalized error +- [ ] invalid Base64拒否 +- [ ] loopback Streamable HTTP成功 +- [ ] `0.0.0.0`等のbind拒否 +- [ ] Legacy SSE endpointなし +- [ ] HTTP GET SSE開始なし +### Gate G9 +Vision optional性とHTTP非公開性を確認。 +--- +# 15. Phase 10 — Audit / Security Hardening +## 15.1 対応仕様 +- Specifications 16章、18〜20章 +- NFR-01〜09 +## 15.2 実装対象 +- Application Log +- LLM Log +- Audit JSONL +- user-only log ACL +- error code / localized message分離 +- audit event completeness +- testでstdio stdout purity保証 +## 15.3 Audit最低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` +## 15.4 Security Matrix全件再実行 +ST-01〜ST-20をクリーン環境から再実行する。 +各テストは以下を記録する。 +| 項目 | 内容 | +| --- | --- | +| Test ID | ST-* | +| Setup | ACL/Config/fixture | +| Action | 実行内容 | +| Expected | 仕様上の期待 | +| Actual | 実測 | +| Result | PASS/FAIL | +| Evidence | log/audit/file/process state | +### Gate G10 +ST-01〜20全PASS。skip 0。Security関連TODO 0。 +--- +# 16. Phase 11 — Acceptance / Release Audit +## 16.1 目的 +Codexの自己申告ではなく、仕様書のAcceptance IDと実成果を1対1で監査する。 +## 16.2 Acceptance Test +AT-01〜AT-20をすべて再実行する。 +## 16.3 Requirement Traceability監査 +最低限次のマトリクスを完成させる。 +| Requirement | Implementation | Test | Result | Evidence | +| --- | --- | --- | --- | --- | +| MCP-TR-* | `<file/class>` | `<test>` | PASS/FAIL | `<log>` | +| OLL-* | ... | ... | ... | ... | +| AGT-* | ... | ... | ... | ... | +| PLN-* | ... | ... | ... | ... | +| SES-* | ... | ... | ... | ... | +| FS-* | ... | ... | ... | ... | +| PRC-* | ... | ... | ... | ... | +| I18N-* | ... | ... | ... | ... | +| REC-* | ... | ... | ... | ... | +| SEC-INV-* | ... | ... | ... | ... | +| NFR-* | ... | ... | ... | ... | +## 16.4 最終静的監査 +- [ ] public MCP Toolが2個だけ +- [ ] Legacy SSEなし +- [ ] non-loopback HTTPなし +- [ ] Fixed Prompt変更I/Fなし +- [ ] MCP/LLMによるPolicy変更I/Fなし +- [ ] Internal Toolが5群から増えていない +- [ ] AppContainer profileをTaskごとに作成していない +- [ ] WFPが汎用Firewall engine化していない +- [ ] Database/ORMなし +- [ ] Workflow/Graph frameworkなし +- [ ] 未承認NuGet追加なし +- [ ] ambiguous巨大moduleなし +- [ ] test skipなし +- [ ] security TODO/FIXMEなし +- [ ] cleanup journal残留なし +## 16.5 文書監査 +- [ ] 実装語彙がSpecifications/Designと一致 +- [ ] 実装で追加された概念がDesignへ未記載ではない +- [ ] 実装制約が現在のコードと一致 +- [ ] Configuration key索引と実際のkeyが一致 +- [ ] Internal Tool Schemaと実装が一致 +- [ ] MCP Schemaと実装が一致 +### Gate G11 — Release Candidate +次をすべて満たした場合のみRelease Candidateとする。 +1. Build PASS +2. Unit Test PASS +3. Integration Test PASS +4. ST-01〜20 PASS +5. AT-01〜20 PASS +6. Requirement traceability完成 +7. 未承認依存0 +8. Security関連未完了0 +9. 仕様・設計逸脱0、または承認済み文書更新済み +10. Recovery後のclean state確認 +--- +# 17. フェーズ横断テスト分類 +| 種別 | 目的 | 実行タイミング | +| --- | --- | --- | +| Unit | 純粋ロジック検証 | 毎Phase | +| Integration | Ollama/MCP/Windows API境界 | 対象Phase以降 | +| Security | deny、escape、hash、network | Phase 6以降 | +| Recovery | crash後cleanup | Phase 7以降 | +| Acceptance | 仕様の外部性質 | Phase 11 | +| Regression | 既存Gate破壊の検出 | 全Phase | +各Phase完了時は、そのPhaseの新規テストだけでなく**それ以前の全自動テスト**を再実行する。 +--- +# 18. Codexが作業を停止して設計レビューへ戻す条件 +Codexは次の場合、独自判断で迂回実装せず作業を停止し報告する。 +| 条件 | 禁止される対応 | +| --- | --- | +| Windows API制約でSecurity Invariantを満たせない | Policyを暗黙緩和する | +| MCP SDKが想定transportを提供しない | 独自transportを作る | +| CsWin32でAPIを扱いにくい | 無断で大規模native layerを導入する | +| WFP host/port実装が複雑 | unrestricted networkへ変更する | +| Recoveryが難しい | cleanupをbest-effortに変更する | +| Ollama option/API差異 | optionを silently ignoreする | +| dependency不足 | 無断でNuGetを追加する | +| Design語彙で表現不能 | 独自概念を勝手に作る | +報告には次を含める。 +1. 該当Requirement +2. 該当Design +3. 技術的制約 +4. 再現手順 +5. 仕様を変更しない代替案 +6. 仕様変更が必要な場合はその影響範囲 +--- +# 19. Codex向け変更管理ルール +## 19.1 1フェーズ1主目的 +無関係なrefactorを同じ差分へ混ぜない。 +## 19.2 Dependency追加 +新しいNuGet packageを追加する前に作業を止め、以下を報告する。 +- package名/version +- 必要理由 +- .NET標準/CsWin32/MCP SDKで代替不能な理由 +- runtime dependencyかbuild-time dependencyか +- security/maintenance影響 +## 19.3 文書変更 +以下を変更する場合はコードより先に `Specifications.md` / `Design.md` の変更案を提示する。 +- MCP Schema +- SandboxPolicy Schema +- Task state +- Security Invariant +- public CLI surface +- Internal Toolの追加・削除 +- HTTP公開範囲 +- Prompt優先順位 +--- +# 20. 監査用進捗台帳 +Codex作業後、人間はこの表を更新する。 +| Phase | Gate | Codex報告 | Build | Tests | Security | Evidence確認 | 人間監査 | 備考 | +| ---: | --- | --- | --- | --- | --- | --- | --- | --- | +| 0 | G0 | ☐ | ☐ | ☐ | N/A | ☐ | ☐ | | +| 1 | G1 | ☐ | ☐ | ☐ | N/A | ☐ | ☐ | | +| 2 | G2 | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | | +| 3 | G3 | ☐ | ☐ | ☐ | N/A | ☐ | ☐ | | +| 4 | G4 | ☐ | ☐ | ☐ | N/A | ☐ | ☐ | | +| 5 | G5 | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | | +| 6 | G6 | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | | +| 7 | G7 | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | | +| 8 | G8 | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | | +| 9 | G9 | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | | +| 10 | G10 | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | | +| 11 | G11 | ☐ | ☐ | ☐ | ☐ | ☐ | ☐ | | +--- +# 21. Phase監査記録テンプレート +各Phaseについて以下をコピーして使用する。 +```markdown +## Audit Record — Phase X + +- Codex実施日時: +- 対象commit: +- 前提commit: +- Reviewer: + +### 1. Scope +- 計画内の変更: PASS / FAIL +- 計画外変更: None / ... + +### 2. Build +- command: +- result: + +### 3. Tests +- unit: <passed>/<failed>/<skipped> +- integration: <passed>/<failed>/<skipped> +- security: <passed>/<failed>/<skipped> + +### 4. Requirement Trace +- Requirement IDs: +- Implementation files: +- Test IDs: + +### 5. Diff Review +- 不要な抽象化: None / ... +- 新規dependency: None / ... +- 新規public surface: None / ... +- TODO/FIXME: None / ... + +### 6. Security Review +- Policy bypass path: None / ... +- negative test evidence: +- cleanup evidence: + +### 7. Evidence +- build log: +- test log: +- audit log: +- other: + +### 8. Result +- Gate: PASS / FAIL +- Rework required: +- Notes: +``` +--- +# 22. 最終監査でCodexに提出させる一覧 +- [ ] 最終変更ファイル一覧 +- [ ] 最終Project dependency graph +- [ ] 最終NuGet package一覧 +- [ ] MCP Tool一覧 +- [ ] Internal Tool一覧 +- [ ] Configuration key一覧 +- [ ] Locale key一覧 +- [ ] Test一覧 +- [ ] ST-01〜20結果表 +- [ ] AT-01〜20結果表 +- [ ] Requirement Traceability Matrix +- [ ] TODO/FIXME/Skip一覧 +- [ ] Recovery crash test結果 +- [ ] Audit Log sample +- [ ] Known limitations +- [ ] Specifications/Designからの逸脱一覧(原則0件) +--- +# 23. Definition of Done +本アプリケーションのv1実装完了は、単に機能が動作することではなく、次をすべて満たすこととする。 +- 仕様の外部性質を満たす。 +- Designの責務境界を維持する。 +- MCP public surfaceが2 Toolに限定される。 +- OllamaだけをLLM backendとして使用する。 +- SandboxPolicyをLLM/MCPから緩和できない。 +- Filesystem / Process / Networkのnegative testが成立する。 +- descendantが権限を拡大できない。 +- crash後にTask Resourceを残さない。 +- Token Plannerが決定的に検証できる。 +- en/jaおよび追加Localeの仕組みが成立する。 +- Audit Logから重要な副作用を追跡できる。 +- 全Acceptance TestがPASSする。 +- 全Security TestがPASSする。 +- skipped test、Security TODO、未承認dependencyが0である。 +- Codexの主張ではなく、再実行可能な証跡によって上記を確認できる。 |
