فهرست منبع

修复(脚本构建): 统一 Portfolio 与 Direction 输入规则

允许 CandidatePortfolio 通过显式 DecisionRef 钉住当前已接受 Direction,使 Goal 守卫与 accepted-input 权威矩阵保持一致。\n\n补充纯领域规则测试,并清除测试 TaskRecord 对已废弃 goal_id 构造参数的依赖。
SamLee 12 ساعت پیش
والد
کامیت
a327d29777

+ 3 - 1
script_build_host/src/script_build_host/domain/input_compatibility.py

@@ -43,7 +43,9 @@ _DIRECT_ALLOWED = {
 }
 _EXPLICIT_ALLOWED = {
     **_DIRECT_ALLOWED,
-    ScriptTaskKind.CANDIDATE_PORTFOLIO: frozenset({ScriptTaskKind.COMPOSE, ScriptTaskKind.COMPARE}),
+    ScriptTaskKind.CANDIDATE_PORTFOLIO: frozenset(
+        {ScriptTaskKind.DIRECTION, ScriptTaskKind.COMPOSE, ScriptTaskKind.COMPARE}
+    ),
     ScriptTaskKind.COMPOSE: _CREATIVE | _RETRIEVAL | {ScriptTaskKind.DIRECTION},
     ScriptTaskKind.STRUCTURE: _CREATIVE | _RETRIEVAL | {ScriptTaskKind.DIRECTION},
     ScriptTaskKind.PARAGRAPH: _CREATIVE | _RETRIEVAL | {ScriptTaskKind.DIRECTION},

+ 14 - 1
script_build_host/tests/test_phase_two_inputs_validation.py

@@ -41,6 +41,10 @@ from script_build_host.domain.artifacts import (
     ArtifactVersion,
     EvidenceRecordV1,
 )
+from script_build_host.domain.input_compatibility import (
+    AcceptedInputSource,
+    validate_accepted_input,
+)
 from script_build_host.domain.phase_two_artifacts import (
     CandidateLineageV1,
     ParagraphArtifactV1,
@@ -64,6 +68,16 @@ SCOPE = "script-build://scopes/opening"
 WRITE = "script-build://writes/paragraphs/1"
 
 
+def test_candidate_portfolio_can_pin_the_active_direction_explicitly() -> None:
+    validate_accepted_input(
+        consumer_kind=ScriptTaskKind.CANDIDATE_PORTFOLIO,
+        consumer_scope="script-build://scopes/full",
+        producer_kind=ScriptTaskKind.DIRECTION,
+        producer_scope="script-build://scopes/full",
+        source=AcceptedInputSource.EXPLICIT,
+    )
+
+
 def _contract(
     *,
     kind: ScriptTaskKind = ScriptTaskKind.PARAGRAPH,
@@ -120,7 +134,6 @@ def _paragraph_artifact(*, text: str = "specific opening") -> ParagraphArtifactV
 def _task(task_id: str, *, parent: str | None, kind: str, status: TaskStatus) -> TaskRecord:
     return TaskRecord(
         task_id=task_id,
-        goal_id=None,
         parent_task_id=parent,
         display_path=task_id,
         specs=[