Переглянути джерело

阶段边界:阻止未覆盖 Goal 的 Portfolio 提交

Phase 2 boundary 读取 active Direction 和唯一 adopted StructuredScript,核对 Direction 引用、全部父子 Goal 覆盖及来源闭包。

Goal 没有闭合时禁止提交 PHASE_TWO_CANDIDATE_PORTFOLIO_READY。
SamLee 1 день тому
батько
коміт
6edefdd364

+ 21 - 1
script_build_host/src/script_build_host/application/phase_two_boundary.py

@@ -6,8 +6,9 @@ from typing import Any
 
 from agent.orchestration import DecisionAction, OperationStatus, TaskStatus
 
-from script_build_host.domain.artifacts import ArtifactKind, ArtifactState
+from script_build_host.domain.artifacts import ArtifactKind, ArtifactState, DirectionArtifact
 from script_build_host.domain.errors import PhaseTwoBoundaryNotReady, ScriptBuildError
+from script_build_host.domain.goal_coverage import validate_goal_coverage
 from script_build_host.domain.phase_two_artifacts import (
     CandidatePortfolioArtifactV1,
     StructuredScriptArtifactV1,
@@ -205,6 +206,25 @@ class ScriptPhaseTwoBoundaryVerifier:
             raise PhaseTwoBoundaryNotReady(
                 "adopted StructuredScript is not backed by an adopted ACCEPT decision"
             )
+        binding = await self._bindings.get_by_build(script_build_id)
+        direction_version_id = binding.active_direction_artifact_version_id
+        if direction_version_id is None:
+            raise PhaseTwoBoundaryNotReady("active Direction is missing")
+        direction_version = await self._artifacts.get_by_id(
+            direction_version_id, script_build_id=script_build_id
+        )
+        if not isinstance(direction_version.artifact, DirectionArtifact):
+            raise PhaseTwoBoundaryNotReady("active Direction has the wrong artifact type")
+        structured = adopted[0].artifact
+        if not isinstance(structured, StructuredScriptArtifactV1):
+            raise PhaseTwoBoundaryNotReady("adopted StructuredScript has the wrong type")
+        if structured.direction_ref != _artifact_uri(direction_version_id):
+            raise PhaseTwoBoundaryNotReady("StructuredScript uses a stale Direction")
+        validate_goal_coverage(
+            direction_goal_ids=tuple(item.goal_id for item in direction_version.artifact.goals),
+            coverage=structured.goal_coverage,
+            adopted_source_refs=structured.source_artifact_refs,
+        )
         if any(item.status in _ACTIVE_OPERATIONS for item in ledger.operations.values()):
             raise PhaseTwoBoundaryNotReady("active or stopping Operations prevent checkpoint")