Просмотр исходного кода

接入子报告聚合与审核门禁

SamLee 21 часов назад
Родитель
Сommit
24ab2744d3
2 измененных файлов с 36 добавлено и 38 удалено
  1. 22 38
      cyber_agent/tools/builtin/subagent.py
  2. 14 0
      cyber_agent/tools/builtin/task_protocol.py

+ 22 - 38
cyber_agent/tools/builtin/subagent.py

@@ -50,7 +50,6 @@ from cyber_agent.core.resource_budget import (
     ResourceBudgetExceeded,
     ResourceBudgetExceeded,
     ResourceBudgetStateError,
     ResourceBudgetStateError,
 )
 )
-from cyber_agent.core.validation import ValidationResult
 from cyber_agent.trace.models import Trace, Messages
 from cyber_agent.trace.models import Trace, Messages
 from cyber_agent.trace.trace_id import generate_sub_trace_id
 from cyber_agent.trace.trace_id import generate_sub_trace_id
 from cyber_agent.trace.goal_models import GoalTree
 from cyber_agent.trace.goal_models import GoalTree
@@ -322,43 +321,28 @@ async def _record_pending_task_reports(
         child_state = ensure_task_protocol(child_trace.context)
         child_state = ensure_task_protocol(child_trace.context)
         task_brief = child_state.get("task_brief")
         task_brief = child_state.get("task_brief")
         report_payload = report.model_dump()
         report_payload = report.model_dump()
-        cached = child_state.get("task_report_validation")
-        validation_result = None
-        if isinstance(cached, dict) and cached.get("task_report") == report_payload:
-            try:
-                validation_result = ValidationResult.model_validate(
-                    cached.get("validation_result")
-                )
-                if validation_result.evaluated_trace_id != child_trace_id:
-                    validation_result = None
-            except ValidationError:
-                validation_result = None
-        if validation_result is None:
-            if report.outcome in {"satisfied", "partial"}:
-                validation_run = await runner.validate_recursive_trace(
-                    child_trace_id,
-                    scope="task",
-                    task_brief=task_brief,
-                    task_report=report_payload,
-                )
-            else:
-                is_protocol_error = report.outcome == "protocol_error"
-                validation_run = await runner.validate_recursive_trace(
-                    child_trace_id,
-                    scope="task",
-                    deterministic_failure={
-                        "outcome": "error" if is_protocol_error else "failed",
-                        "reason": report.summary,
-                        "issues": report.remaining_issues or [report.summary],
-                        "retry_from": None if is_protocol_error else "task_definition",
-                    },
-                )
-            validation_result = validation_run.result
-            child_state["task_report_validation"] = {
-                "task_report": report_payload,
-                "validation_result": validation_result.model_dump(),
-            }
-            await store.update_trace(child_trace_id, context=child_trace.context)
+        if report.outcome in {"satisfied", "partial"}:
+            validation_run = await runner.validate_recursive_trace(
+                child_trace_id,
+                scope="task",
+                task_brief=task_brief,
+                task_report=report_payload,
+            )
+        else:
+            is_protocol_error = report.outcome == "protocol_error"
+            validation_run = await runner.validate_recursive_trace(
+                child_trace_id,
+                scope="task",
+                task_brief=task_brief,
+                task_report=report_payload,
+                deterministic_failure={
+                    "outcome": "error" if is_protocol_error else "failed",
+                    "reason": report.summary,
+                    "issues": report.remaining_issues or [report.summary],
+                    "retry_from": None if is_protocol_error else "task_definition",
+                },
+            )
+        validation_result = validation_run.result
         state["pending_reviews"][child_trace_id] = pending_review_entry(
         state["pending_reviews"][child_trace_id] = pending_review_entry(
             goal_id=goal_id,
             goal_id=goal_id,
             report=report,
             report=report,

+ 14 - 0
cyber_agent/tools/builtin/task_protocol.py

@@ -45,6 +45,7 @@ _ALLOWED_REVIEW_DECISIONS_BY_VALIDATION: dict[str, set[ReviewDecision]] = {
         "FAIL",
         "FAIL",
     },
     },
     "failed": {"REVISE_CHILD", "REPLAN_CURRENT", "FAIL"},
     "failed": {"REVISE_CHILD", "REPLAN_CURRENT", "FAIL"},
+    "unknown": {"REVISE_CHILD", "REPLAN_CURRENT", "FAIL"},
     "error": {"REVISE_CHILD", "FAIL"},
     "error": {"REVISE_CHILD", "FAIL"},
 }
 }
 
 
@@ -215,6 +216,19 @@ async def review_task_result(
             return _error(
             return _error(
                 "ValidationResult evaluated_trace_id does not match the direct child"
                 "ValidationResult evaluated_trace_id does not match the direct child"
             )
             )
+        child_validation_state = ensure_task_protocol(child.context).get(
+            "task_report_validation"
+        )
+        if not isinstance(child_validation_state, dict):
+            return _error("Child has no persisted framework validation cache")
+        if (
+            child_validation_state.get("plan_hash") != validation_result.plan_hash
+            or child_validation_state.get("aggregate_result")
+            != validation_result.model_dump(mode="json")
+        ):
+            return _error(
+                "Pending ValidationResult does not match the child's authoritative cache"
+            )
         allowed_decisions = _ALLOWED_REVIEW_DECISIONS_BY_VALIDATION[
         allowed_decisions = _ALLOWED_REVIEW_DECISIONS_BY_VALIDATION[
             validation_result.outcome
             validation_result.outcome
         ]
         ]