From 842e55654db060c84448f3a0deddb24f77fad5a7 Mon Sep 17 00:00:00 2001 From: tanaka takashi Date: Tue, 11 Aug 2026 22:20:25 +0900 Subject: Verify task-specific external effect evidence --- src/Agent.Planner/TaskGraph.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/Agent.Planner/TaskGraph.cs') diff --git a/src/Agent.Planner/TaskGraph.cs b/src/Agent.Planner/TaskGraph.cs index 7a4d45b..729f646 100644 --- a/src/Agent.Planner/TaskGraph.cs +++ b/src/Agent.Planner/TaskGraph.cs @@ -18,7 +18,8 @@ public sealed class TaskGraph(int maxTasks = 32) TokenEstimate estimate, IEnumerable? dependencies = null, bool requiresExternalEffect = false, - Guid? id = null) + Guid? id = null, + IEnumerable? requiredEffectTools = null) { if (string.IsNullOrWhiteSpace(description)) throw new PlannerValidationException("Task description is required."); if (_tasks.Count >= MaxTasks) throw new PlannerValidationException($"Task limit of {MaxTasks} exceeded."); @@ -26,10 +27,13 @@ public sealed class TaskGraph(int maxTasks = 32) Guid taskId = id ?? Guid.NewGuid(); if (_tasks.ContainsKey(taskId)) throw new PlannerValidationException($"Task '{taskId}' already exists."); HashSet dependencySet = dependencies?.ToHashSet() ?? []; + HashSet effectTools = requiredEffectTools?.ToHashSet(StringComparer.Ordinal) ?? []; + if (requiresExternalEffect && effectTools.Count == 0) throw new PlannerValidationException("An external-effect Task must name at least one required effect tool."); + if (!requiresExternalEffect && effectTools.Count != 0) throw new PlannerValidationException("A non-effect Task cannot require an effect tool."); EnsureDependenciesExist(dependencySet); if (dependencySet.Contains(taskId)) throw new PlannerValidationException("A task cannot depend on itself."); - _tasks.Add(taskId, new MutableTask(taskId, description, dependencySet, budgetClass, estimate, requiresExternalEffect)); + _tasks.Add(taskId, new MutableTask(taskId, description, dependencySet, budgetClass, estimate, requiresExternalEffect, effectTools)); _insertionOrder.Add(taskId); try { @@ -163,7 +167,7 @@ public sealed class TaskGraph(int maxTasks = 32) if (task.State == PlannerTaskState.Completed) throw new PlannerValidationException("Completed tasks are immutable."); } - private sealed class MutableTask(Guid id, string description, HashSet dependencies, TokenBudgetClass budgetClass, TokenEstimate estimate, bool requiresExternalEffect) + private sealed class MutableTask(Guid id, string description, HashSet dependencies, TokenBudgetClass budgetClass, TokenEstimate estimate, bool requiresExternalEffect, HashSet requiredEffectTools) { public Guid Id { get; } = id; public string Description { get; } = description; @@ -174,6 +178,7 @@ public sealed class TaskGraph(int maxTasks = 32) public long ActualInputTokens { get; set; } public long ActualOutputTokens { get; set; } public bool RequiresExternalEffect { get; } = requiresExternalEffect; - public PlannerTask Snapshot() => new(Id, Description, Dependencies.ToHashSet(), State, BudgetClass, Estimate, ActualInputTokens, ActualOutputTokens, RequiresExternalEffect); + public HashSet RequiredEffectTools { get; } = requiredEffectTools; + public PlannerTask Snapshot() => new(Id, Description, Dependencies.ToHashSet(), State, BudgetClass, Estimate, ActualInputTokens, ActualOutputTokens, RequiresExternalEffect, RequiredEffectTools.ToHashSet(StringComparer.Ordinal)); } } -- cgit v1.2.3