| Age | Commit message (Collapse) | Author |
|
Two runtime bugs discovered during MCP integration testing:
1. PlannerService.BuildTaskGraph fallback: If the LLM-generated plan
contains invalid tasks (bad estimates, cycles, etc.), graph.AddTask
throws PlannerValidationException. Previously this propagated up and
caused "No tasks were executed." or "Planning failed" errors.
Fix: wrap BuildTaskGraph in try/catch, fall back to single-task
graph. Also handle graph.Count == 0 after filtering.
2. TaskGraphToolHandler.BeginTask conflict: PlanAsync stores the
planned TaskGraph in session.TaskGraphs[taskId] before RunAsync
calls BeginTaskAsync. BeginTask then tried TryAdd which failed
because the key already existed, throwing
"TaskGraph for '...' already exists in session".
Fix: use TryAdd without throwing on conflict — if PlanAsync already
created the graph, keep it; otherwise add a new empty one.
Test results: Core 61/61, Planner 10/10, Windows 41/41 (elevated).
MCP integration: agent_run/agent_status verified via HTTP transport.
ACL boundary: C:\Windows\System32 access correctly denied by sandbox.
ToolUseGuard: "Required external effect was not completed" fires
correctly when LLM does not produce verifiable external effect.
|
|
fixes
## P3: Session/Planning Foundation
### PlanAsync / RunAsync flow separation (Design §8.4)
- AgentRuntime.ExecuteAsync now follows a two-phase lifecycle:
1. Planning: generate Initial TaskGraph via Ollama structured output
2. Running: execute ready Tasks (dependencies satisfied) in
critical-path then creation order
- Sandbox Task Resource (BeginTask/EndTask) is applied at RunAsync
time, not PlanAsync time (Design constraint)
- QueuedTaskWorker transitions to Planning; ExecuteAsync transitions
to Running internally
### PlannerService (new: src/Agent.Core/Runtime/PlannerService.cs)
- PlanAsync: uses Ollama ChatStructuredAsync with JSON Schema to
generate a TaskGraph with per-Task requires_external_effect
- ReplanAsync: rebuilds TaskGraph after policy deny, preserving
completed tasks (Design §8.4)
- Fallback: single-task plan with conservative estimates when
structured output fails or returns empty
- Pure analysis tasks get RequiresExternalEffect=false with at
least 1 Task (Design constraint)
### PlanResult / PlanSchema (new: src/Agent.Core/Runtime/PlanResult.cs)
- JSON model for LLM structured output during Planning
- JSON Schema with tasks array: description, dependencies (by index),
budget_class, PERT estimates, requires_external_effect
### requires_external_effect integration (P2 + P3)
- Removed keyword heuristic RequiresExternalEffect() from AgentRuntime
- Removed tool-name-counting RequiredToolCalls() from AgentRuntime
- ToolUseGuard now receives PlannerTask.RequiresExternalEffect
(set by Planner during Planning, not by keyword matching)
- requires_external_effect is NOT always true; it is a per-Task
attribute determined by the Planner (Design constraint)
### RunAsync / ready Task execution
- SelectNextReadyTask: dependencies satisfied, not completed/failed,
critical path first then creation order
- Each PlannerTask executed via ExecutePlannerTaskAsync (LLM
chat-with-tools iteration loop)
- TaskGraph.AddUsage records per-Task token usage for CPM tracking
### Replan implementation
- Policy deny (InvalidOperationException with "denied by sandbox
policy") triggers ReplanAsync, up to max 3 replan attempts
- Failed task is marked Failed in TaskGraph before replan
- Registry transitions back to Running for replan iteration
## P3-A: AgentSession + TaskGraph ownership
### AgentSession expansion (src/Agent.Core/Sessions/AgentSession.cs)
- Added Summary, ExecutionResults, TaskGraphs
(ConcurrentDictionary<Guid, TaskGraph>)
- TaskGraph is per-MCP-Task (1 agent_run = 1 TaskGraph), NOT shared
per-Session (Design constraint)
- Added CompactConversation, CompactExecutionResults, SetSummary
methods for context summary compaction
### ExecutionResult (new: src/Agent.Core/Sessions/ExecutionResult.cs)
- Records tool execution results in session for context summary
- Fields: TaskId, ToolName, Success, Output
### SessionStore (src/Agent.Core/Sessions/SessionStore.cs)
- Added Sessions property for TaskGraphToolHandler to resolve graphs
by TaskId across sessions
### sessionId threading
- IInternalToolBackend.BeginTaskAsync signature changed to include
sessionId parameter
- InternalToolDispatcher, WindowsToolBackend, TaskGraphToolHandler
updated to thread sessionId through
- task_update schema includes requires_external_effect property
- McpHost and Program.cs pass SessionStore to TaskRegistry
## P3: Context Summary (Design §9.3)
- Context utilization = latest prompt_eval_count / num_ctx
(NOT cumulative InputTokens) (Design constraint)
- TryContextSummary: compacts old Conversation/ExecutionResults when
utilization exceeds 80% threshold
- AgentRuntimeSettings: added NumCtx, ContextSummaryThreshold,
ConversationKeepLastN, ExecutionResultsKeepLastN
- OllamaResult: added PromptEvalCount field
- OllamaClient: passes PromptEvalCount from OllamaChatResponse
## P3: ExecutionResults Session recording
- ExecutePlannerTaskAsync records each tool execution result via
session.AppendExecutionResult for context summary and audit
## Windows test fixes
### SandboxPolicyException catch (src/Agent.Windows/Tools/WindowsToolBackend.cs)
- ExecuteAsync now catches SandboxPolicyException and returns
ToolExecutionResult(false, ..., RetryAllowed: false) instead of
propagating the exception
- Fixes Dir_mkdir_outside_approved_root_is_denied and
File_edit_rename_rejects_outside_approved_root tests
### LoopbackExemption cleanup (tests/Agent.Windows.Tests/SecurityPolicyTests.cs)
- Recovery_after_crash: added pre-clean and try/finally to ensure
LoopbackExemption is always removed, even on assertion failure
- Independent_process_crash: added pre-clean to remove residual
loopback exemption from prior test failures
- Fixes 7 Independent_process_crash scenarios that were failing due
to LoopbackExemption residue from Recovery_after_crash
## Test updates (tests/Agent.Core.Tests/PromptAndRuntimeTests.cs)
- FakeOllamaClient implementations updated with ChatStructuredAsync
and ChatWithToolsAsync overrides to support Plan/Run flow
- RecordingOllamaClient: returns single-task plan JSON for
ChatStructuredAsync, tracks all call types
- ToolCallingOllamaClient: returns plan with
requires_external_effect=true for file edit tasks
- Test expectations updated for Plan+Run call counts and token
accounting (Plan tokens not added to registry usage)
## Documentation updates
- Design.md §7.7: requires_external_effect is set by Planner during
Planning, not keyword heuristic
- Design.md §8.4: Plan/Run phase separation, replan after policy deny
- Design.md §9.3: context utilization formula clarified
- ImplementationPlan.md §10.3: Plan/Run flow, replan, Context Summary
## Test results (all passing)
- Agent.Core.Tests: 61/61
- Agent.Planner.Tests: 10/10
- Agent.Windows.Tests (elevated): 41/41
- Build: 0 errors, 0 warnings
|
|
P5残件3項目を実装:
1. Ollama structured output (format param):
- OllamaChatRequestへFormat プロパティ追加 (JsonElement?)
- IOllamaClientへChatStructuredAsync メソッド追加
- OllamaClient.ChatCoreAsync へformat パラメータ追加
- ChatStructuredAsync はtoolsなし、format指定でJSON構造化出力を要求
2. AgentRuntime skill selection step:
- SelectSkillsAsync メソッド追加: メインループ前にOllamaへskill catalogを送信
- structured output で {"selected_skills": ["name"]} を取得
- ParseSelectedSkills: JSON解析、unknown skill名排除、重複排除、最大10件
- structured output非対応モデルはfallback空リスト
- 選択されたskillのInstructionsのみPromptContext.SelectedSkillsへ設定
- Progressive Disclosure Stage 2→3 が完了
3. Skill security/path validation:
- SelectSkillsAsync でsettings.Skillsからのみ選択(unknown name排除)
- SkillLoader でreparse point skip済み(既存実装)
- 選択数上限10件でDoS防止
- Skill load != permission grant 維持: allowed-toolsはSandbox permissionに影響しない
変更対象:
- OllamaModels.cs: OllamaChatRequest.Format プロパティ追加
- IOllamaClient.cs: ChatStructuredAsync メソッド追加
- OllamaClient.cs: ChatCoreAsync へformat パラメータ追加、ChatStructuredAsync 実装
- AgentRuntime.cs: SelectSkillsAsync + ParseSelectedSkills、メインループ前の選択ステップ
検証結果:
- Release build: 警告0、エラー0
- Core tests: 61/61 PASS、skip 0
- Planner tests: 10/10 PASS、skip 0
|
|
P1: Tool小改善
1. tailバイナリ判定 (TextFileDetector):
- file_search tailモードでtext/binary判定を追加
- 先頭4KBのみ読み、BOM確認(UTF-8/UTF-16 LE/BE)→UTF-8 strict byte検証
- NULバイトのみ判定不可(UTF-16でNULが正常出現するため)
- binaryファイルはToolValidationExceptionで拒否
- TextFileDetectorクラスへ判定ロジックを分離
2. file_edit rename機能:
- file_edit.operation=renameを追加(新規toolではない)
- new_path property追加、Write capability要求(source/destination双方)
- destination既存時は禁止(overwrite不可)
- cross-volume renameは不支持、Tool failureとして拒否
- FileRenameTransaction + RecoveryManager file.rename recovery追加
- crash recovery: destination hash == journal記録の場合のみ戻す
P5: Agent Skills open standard準拠
3. Skill形式をagentskills.io標準へ移行:
- legacy単一Markdown形式(skills/*.md)を廃止
- <skill-name>/SKILL.md標準directory形式のみ対応
- YAML frontmatter必須(name/description)、YamlDotNetで解析
- validation: name必須(1-64文字,lowercase英数字+hyphen,親dir名一致),
description必須(1-1024文字), malformed YAML reject, duplicate fatal
4. Progressive Disclosure:
- Stage 1 Discovery: name+descriptionのみをsystem messageへ(name+desc一覧)
- Stage 3 Instructions: 選択Skillの本文のみ注入
- PromptComposer: 全文埋め込みを廃止、カタログ形式へ変更
- PromptContext: Skills→AvailableSkills+SelectedSkillsへ分割
- 未選択Skill本文はpromptへ入らない
5. Internal Tool境界維持:
- skill_read等のInternal Tool追加なし
- Internal Toolは6群(file_search/file_read/file_edit/process_run/task_update/dir)のまま
- Skill選択・本文ロードはAgent Runtime/Prompt Context Managementの責務
6. AgentSkill data model (Agent.Core/Skills/AgentSkill.cs):
- RootPath, Name, Description, Instructions, License?, Compatibility?, Metadata?, AllowedTools?
- SkillLoader(Agent.App)がYamlDotNetでfrontmatter解析→AgentSkill構築
設計判断:
- renameはfile_edit operation拡張(新規toolではない)
- rmdir空dirのみ制約は維持
- Skill load != permission grant維持
- allowed-toolsはSandbox permissionとして解釈しない
- YamlDotNetはAgent.App側のみ使用(Agent.Coreへ依存追加なし)
変更対象:
- TextFileDetector.cs: 新規、text/binary判定
- WindowsToolBackend.cs: tail binary判定統合、rename case追加
- InternalToolCatalog.cs: file_edit operation enum に rename 追加、new_path property
- InternalToolValidator.cs: rename時new_path必須検証
- TransactionalFileEditor.cs: Rename() + FileRenameTransaction
- RecoveryManager.cs: file.rename recovery
- AgentSkill.cs: 新規data model
- SkillLoader.cs: 全面書き換え、YamlDotNet frontmatter解析、validation
- PromptComposer.cs: Progressive Disclosure、AvailableSkills+SelectedSkills
- AgentRuntimeSettings.cs: Skills型変更
- AgentRuntime.cs: SelectedSkills=[]で初期化
- Program.cs: SkillLoader戻り値型対応
- Specifications.md: FS-07 rename、Skill節Agent Skills standard準拠
- Design.md: §7.1 tail binary判定、§7.3 rename、AgentSkill model
- ImplementationPlan.md: Prompt順序更新、Skill標準準拠
テスト:
- SecurityPolicyTests.cs: tail binary拒否/UTF-8/UTF-16 text許可、rename正常/dest既存拒否/許可外拒否
- InternalToolTests.cs: rename validationテスト追加
- ConfigurationTests.cs: SkillLoader標準形式/missing frontmatter/name mismatch/duplicate tests
- PromptAndRuntimeTests.cs: PromptContext型変更対応、skill catalog検証
検証結果:
- Release build: 警告0、エラー0
- Core tests: 61/61 PASS、skip 0
- Planner tests: 10/10 PASS、skip 0
- Internal Tool 6群固定: 確認済み
|
|
新規Internal Tool `dir` を追加し、ディレクトリの作成・削除・一覧取得を
可能にした。file_editの拡張ではなく独立toolとして実装し、LLMが
「ディレクトリ操作はdir tool」と直感的に判断できるようにした。
追加した機能:
- dir tool (6番目のInternal Tool、MCP非公開)
- mkdir: Write capability要求、Directory.CreateDirectory()で親ディレクトリも含めて作成
- rmdir: Delete capability要求、空ディレクトリのみ削除(非空はToolValidationExceptionで拒否)
- list: Read capability要求、直下エントリ一覧を返す
設計判断:
- file_edit拡張ではなく新規toolとした理由: ツール名から機能が推測しやすく、
LLMが直感的に選択できるため
- rmdirを空ディレクトリのみに制限した理由: rollback時の内容復元の複雑さを排除、
MemoryBackupLimit超過リスクなし、安全側
- mkdir/rmdirは既存のPathPolicy/ACL/Journal/Recovery枠組みを利用
- root継承ACE方式のため新規作成ディレクトリは自動的に親のACEを継承、追加ACL操作不要
変更対象:
- InternalToolCatalog.cs: dir定義追加 (5→6 tool)
- InternalToolDispatcher.cs: FakeInternalToolBackendの効果判定にdir追加
- InternalToolValidator.cs: dir用コメント追記
- WindowsToolBackend.cs: DirectoryOp()メソッド実装
- TransactionalFileEditor.cs: Mkdir()/Rmdir() transaction +
DirectoryMkdirTransaction/DirectoryRmdirTransaction クラス追加
- RecoveryManager.cs: dir.mkdir/dir.rmdir crash recovery追加
- Specifications.md: FS-06追加
- Design.md: 6群表更新、§7.6 dir追加、5群→6群参照更新
テスト:
- InternalToolTests.cs: dir単体テスト、catalog 6群検証、malformed args拒否
- SecurityPolicyTests.cs: mkdir/rmdir/list/許可外deny テスト追加
- PromptAndRuntimeTests.cs: tool count 5→6
- OllamaClientTests.cs: tool catalog配列長 5→6
検証結果:
- Release build: 警告0、エラー0
- Planner tests: 10/10 PASS、skip 0
- Core tests: 56/56 PASS、skip 0
- MCP経由での動作確認: mkdir/list/rmdir/file_edit すべて正常
- Python実行確認: dir mkdir + file_edit + process_run でfib(1)〜fib(10)が正常出力
- Release Bundle publish済み
既知の運用上の知見:
- uv venvのpyvenv.cfgのhomeがjunctionを指す場合、CanonicalPath.Resolveが
reparse pointとして拒否する。実体パスへ書き換えるか、実体ディレクトリを
agent.yamlのread/executeに追加する必要がある
- venvのpython.exeはuv trampolineで子プロセスを生成するため、
sandboxのchild-process制限で拒否される。pyvenv.cfgが指す実体python.exeを
直接起動する必要がある
|
|
Replace per-descendant ACL enumeration, security descriptor snapshots, journal entries, audit events, and cleanup rewrites with one inheritable ACE and one snapshot per approved directory root. Exact file approvals continue to receive non-inheritable file ACEs, and nested roots retain independent least-privilege scopes cleaned in reverse order.
Keep protected descendant DACLs protected instead of disabling inheritance protection. Such paths remain OS-denied, preserving fail-safe behavior without silently expanding the SandboxPolicy.
Remove the obsolete descendant normalization pass. Restoring the root security descriptor removes inherited Application SID ACEs from existing and Task-created descendants; crash recovery performs the same root descriptor restoration from the journal.
Add tests for existing-child inheritance, newly-created-child inheritance, protected descendants, one journal entry per root, exact descriptor restoration, no residual Application SID ACE, and independent-process crash recovery. Extend the existing elevated recovery and backend tests to validate inherited child cleanup and one ACL apply/restore event per root.
Verification: Release build passed with 0 warnings and 0 errors; Core 50/50 passed; Planner 10/10 passed; focused ACL/recovery 3/3 passed; elevated Windows Security 28/28 passed; all reported skip 0.
Operational evidence: the updated Release Bundle completed MCP Task 9b4a59a9-1f9b-4362-85f4-7b858899b488. ACL apply/restore decreased from 3,583/3,583 events taking 72/57 seconds to 3/3 root_inheritance events completing within the same second. WFP residual filters were 0 and the Task journal was removed.
Release: refreshed the win-x64 self-contained folder bundle, clean ZIP, manifest, and checksum while preserving the local agent.yaml. Agent.Windows.dll SHA-256 is 24FDDD5727D5455170B6742B1D21E023A0BD70F92C225A2681BB5832C7AC0824; ZIP SHA-256 is EF7684C1A5A6155B774F4DF23CB08E9D1CF676351BF2B7D0F57915304495F456. No dependencies were added.
|
|
Treat Policy Engine denials and UnauthorizedAccessException results as terminal tool failures by adding RetryAllowed metadata to ToolExecutionResult.
Stop the Agent loop immediately after recording the denied tool result, transition the Task to failed, and run normal Task resource cleanup instead of returning the same failure to the LLM for another iteration. Correctable validation and process failures retain the existing bounded retry behavior.
Expose RetryAllowed in llm.jsonl and document the fail-fast security invariant in Specifications, Design, and ImplementationPlan.
Tests: Agent.Core.Tests 50/50 passed with skip 0; Release build passed with 0 warnings and 0 errors. The full Windows suite remained environment-blocked outside an elevated token: 14 tests failed while creating/deriving the fixed AppContainer or creating symlinks; 11 passed and none were skipped.
Release: refreshed the win-x64 self-contained folder binaries, publish manifest, ZIP, and checksum while preserving the local agent.yaml. The clean ZIP contains no runtime logs or Task state.
|
|
Add a concise Japanese companion prompt that asks the model to be approachable, clarify uncertainty, select available skills and tools, verify results, and report the next useful action without adding excessive context.
Add the standard skills/python-via-uv/SKILL.md package and UI metadata. The workflow uses uv python find offline to resolve an interpreter, then asks the Broker to launch the separately approved Python executable. It deliberately avoids uv run because the v1 OS child-process restriction must reject descendants created directly by uv.
Support standard skills/<name>/SKILL.md directories while retaining legacy top-level Markdown loading. Skip reparse-point skill directories, load deterministically, package the complete skills tree, and avoid loading nested reference Markdown as independent skills.
Validation: skill-creator quick_validate PASS; uv 0.11.23 resolved Python and the two-stage Python execution printed UV_BROKER_TWO_STAGE_OK. Release build passed with 0 warnings/errors; Core tests passed 49/49 with skip 0. The 1.0.0 Bundle and manifest were regenerated with the prompt and Skill.
|
|
HTTP observability callbacks previously called RollingFileLog synchronously. RollingFileLog writes to Console.Error before the application file, so a paused console or an undrained redirected stderr pipe could block Kestrel request threads for minutes and cause otherwise valid MCP clients to time out.
Route ready, connection, request-started, request-completed, and HTTP JSONL work through a bounded 4,096-entry Channel. Request callbacks use TryWrite and never wait for console or file I/O. A dedicated single-reader background task preserves log ordering, performs rotation, reports dropped entries after queue pressure, and contains non-fatal sink failures.
Keep the queue bounded so a stalled console cannot cause unbounded memory growth. When capacity is exhausted, request availability takes precedence over observability and the dropped count is emitted as an application warning after the writer resumes.
Add a regression test with a deliberately blocked console writer. The background writer remains blocked while the HTTP completion callback returns within 250 ms. Release build passed with zero warnings and errors; Core tests passed 48/48 with skip 0.
Regenerate the win-x64 self-contained 1.0.0 Bundle and ZIP. ZIP SHA-256: 62E28C903880A51614EC0C3CE23409580F803C7C124764CA7E1CB0EB2CCAA7A9.
|
|
Replace the MCP 1.4.1 stateful HTTP design with the official C# SDK 2.0.0 stateless transport. The SDK now owns protocol negotiation, server/discover, standard MCP headers, GET and DELETE handling, error serialization, caching hints, and legacy initialize compatibility; production code no longer maintains a custom wire-protocol workaround for MCP Inspector.
Separate transport state from application conversation state. HTTP does not issue Mcp-Session-Id, while the existing session_id remains an Agent conversation identifier. Preserve agent_run and agent_status for clients without Tasks support and add the official ModelContextProtocol.Extensions.Tasks 2.0.0 path for capable clients.
Add persistent MCP Task storage with atomic JSON replacement, user-only state location, configurable TTL and poll interval, restart recovery, cancellation correlation, and public Agent-to-MCP state mapping. Keep conformance-only tools and protocol exception fixtures in a test host so they cannot enter the Release Bundle.
Run administrator, BFE, WFP transaction, and filter add/delete preflight before binding. Fail fast with exit code 2 and actionable localized diagnostics when sandbox enforcement is unavailable. Emit ready only after the listener starts and keep stdio stdout protocol-pure.
Add shared rotating application and HTTP request logs. Record real socket endpoints, connection and trace identifiers, method, path, result, timing, media metadata, User-Agent, and MCP metadata. Do not trust X-Forwarded-For and do not log authorization, cookies, query data, request or response bodies, prompts, images, or Base64 payloads.
Add typed logging and Tasks configuration, Japanese and English messages, protocol and operations documentation, design/specification deltas, traceability, and exact conformance acquisition/offline runner scripts for @modelcontextprotocol/conformance 0.2.0-alpha.11. Node remains test-only and is not a runtime dependency.
Conformance evidence: server-stateless passed 28 of 28 checks with zero unexpected failures; DNS rebinding and multiple POST stream scenarios passed. The alpha Tasks lifecycle/cancel/error/required-task checks passed, while its wire-schema validator misclassifies CreateTaskResult and its MRTR composition remains incompatible with SDK 2.0.0. The aggregate conformance Gate is therefore recorded as PARTIAL, not PASS. Test-host fixture gaps for tools-list descriptions, JSON Schema diagnostics, caching fixtures, and a header-validation/required-Task capability conflict are also recorded without expected-failure masking.
Verification: Release build passed with 0 warnings and 0 errors; Planner tests 10/10 and Core tests 47/47 passed with skip 0. The last Windows suite run passed 19/25; five WFP cases require an elevated token and one symlink case requires unavailable host privilege, so the elevated security Gate remains open. A win-x64 self-contained 1.0.0 Bundle and ZIP were regenerated under build/Release/publish; runtime check was intentionally skipped in this non-elevated session. Evidence remains under ignored artifacts/evidence/mcp-2026-07-28.
Harden release regeneration when another shell holds the previous Bundle directory as its current directory: validate the target and remove only its children instead of deleting the directory itself. build/ and artifacts/ remain excluded from Git.
|
|
Specifications、Design、ImplementationPlanの優先順位を整理し、単一Task実行モデル、typed option優先、設定可能なresource上限、local Ollamaを必須とするRelease Gateを文書化。
.NET 10/C# 14の5 production project、3 test project、E2E Clientを構築。typed YAML、en/ja locale、fixed/user prompt、stdioおよびloopback限定Streamable HTTP、agent_run/agent_status、Session、Ollama text/tool/Vision、TaskGraphとtoken accountingを実装。
Windows sandboxとしてfixed AppContainer、canonical/reparse検査、能力別ACL、path+SHA-256 executable approval、child-process restriction、Job Object、task journal、atomic file transaction、crash recoveryを実装。WFPのIPv4/IPv6 default denyとexact allow、dynamic session、temporary loopback exemption、管理者/BFE診断を追加。
Security/Recovery test、MCP/Ollama integration test、stdio/HTTP Operational E2E、Release Bundle生成・checksum・manifest・fresh extraction検査を追加。Requirement TraceabilityとPhase 0〜11の進捗、初回セットアップ可能なREADMEを整備。
Debug/Release/publish/objをrepository rootのbuild/へ集約し、旧project-local bin/objへの依存を除去。artifacts/とbuild/をGit管理外に設定し、clean checkoutでもsolution buildからE2E Clientまで生成可能にした。
|