diff options
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/Design.md | 787 | ||||
| -rw-r--r-- | doc/Specifications.md | 559 |
2 files changed, 1346 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を開始すること。 |
