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

feat(阶段策略): 由 Host 注入完整 Phase1 与 Phase2 生命周期

Phase1 RunConfig 显式冻结 phase=1;Phase2 策略描述唯一 Portfolio、Compose 闭包、Structure/Paragraph 作用域和并发上限。补充恢复 RunConfig 与 recovery 消息,要求沿原 Trace 保留完成 Attempt,并细化 adoption closure 的完整分区规则。
SamLee 20 часов назад
Родитель
Сommit
93a55a7807

+ 85 - 5
script_build_host/src/script_build_host/application/mission_factory.py

@@ -93,8 +93,10 @@ class ScriptMissionFactory:
                 "phase": 1,
                 "phase_boundary": "PHASE_ONE_CAPABILITY_BOUNDARY",
                 "instruction": (
-                    "Inspect the ledger and dynamically plan retrieval and direction work. "
-                    "After direction ACCEPT, block Root at the phase-one boundary."
+                    "Create Direction under Root without dispatching it; create Retrieval "
+                    "children under that Direction; dispatch and ACCEPT Retrieval before "
+                    "dispatching Direction. After Direction ACCEPT, block Root with the exact "
+                    "reason PHASE_ONE_CAPABILITY_BOUNDARY."
                 ),
             },
             ensure_ascii=False,
@@ -128,6 +130,7 @@ class ScriptMissionFactory:
             context={
                 "script_build_id": binding.script_build_id,
                 "input_snapshot_id": snapshot.snapshot_id,
+                "phase": 1,
             },
             name=f"Script build {binding.script_build_id}",
         )
@@ -141,9 +144,58 @@ class ScriptMissionFactory:
                 "input_snapshot_ref": f"script-build://inputs/{snapshot.snapshot_id}",
                 "input_sha256": snapshot.canonical_sha256,
                 "instruction": (
-                    "Dynamically create independently verifiable creative increments. "
-                    "Use only controlled phase-two task contracts and stop Root at "
-                    "PHASE_TWO_CANDIDATE_PORTFOLIO_READY."
+                    "Follow the phase-two lifecycle exactly: (1) create the single "
+                    "CandidatePortfolio under Root with a scope_ref below the accepted "
+                    "Direction scope (for example <direction-scope>/portfolio/main); its "
+                    "initial input_decision_refs are "
+                    "empty because the accepted Direction is already frozen in the Phase2 "
+                    "Host context; "
+                    "(2) create a non-executable Compose child; (3) create and ACCEPT "
+                    "Structure, then Paragraph Tasks whose parent_task_id remains the open "
+                    "Compose Task while each Paragraph scope_ref is below the accepted "
+                    "Structure scope (completed Structure Tasks cannot receive framework "
+                    "children), plus "
+                    "optional ElementSet, "
+                    "Compare, or Retrieval increments; (4) REVISE Compose with the exact "
+                    "accepted closure and adoption order; (5) dispatch, validate, and "
+                    "ACCEPT Compose; (6) REVISE CandidatePortfolio with the accepted "
+                    "Compose closure; (7) dispatch, validate, ACCEPT CandidatePortfolio, "
+                    "then BLOCK Root at PHASE_TWO_CANDIDATE_PORTFOLIO_READY. Never "
+                    "dispatch an empty adoption container or cancel the unique portfolio. "
+                    "Keep business hierarchy in scope_ref, but use capability URIs in "
+                    "write_scope: CandidatePortfolio and Compose must use the exact parent "
+                    "capability script-build://writes; every Structure or Paragraph that "
+                    "creates paragraphs must "
+                    "include script-build://writes/paragraphs/<stable-selector>; every "
+                    "ElementSet that creates or links elements must include "
+                    "script-build://writes/elements/<stable-selector>. Never copy scope_ref "
+                    "into write_scope for workspace-writing Tasks. A Paragraph refining an "
+                    "accepted Structure must copy the whole Structure accepted_decision_ref "
+                    "unchanged into input_decision_refs and copy its whole artifact_ref "
+                    "unchanged into base_artifact_ref. "
+                    "Never place a Paragraph as a sibling of its Structure. "
+                    "Each Paragraph write_scope must also be below its Structure write_scope, "
+                    "for example Structure script-build://writes/paragraphs/main and Paragraph "
+                    "script-build://writes/paragraphs/main/opening. "
+                    "Dispatch at most "
+                    "four Tasks in one call because the concurrent Operation limit is four. "
+                    "When revising Compose for execution, include exactly one whole accepted "
+                    "Direction decision in input_decision_refs in addition to the candidate "
+                    "closure. Immediately before that REVISE, inspect the plan again and copy "
+                    "every accepted Structure and Paragraph decision under the Compose into "
+                    "candidate_decision_ids. The union of adopted_decision_ids and "
+                    "held_or_rejected_decision_ids must partition that complete candidate list; "
+                    "when adopting all candidates the held list is empty and compose_order lists "
+                    "every adopted Decision ID in intended script order. "
+                    "When revising CandidatePortfolio, input_decision_refs and the candidate "
+                    "closure contain only accepted Compose decisions, and compose_order must "
+                    "list the adopted Compose decision IDs exactly, including the single-ID "
+                    "case. With one accepted Compose, candidate_decision_ids, "
+                    "adopted_decision_ids, and compose_order are the same one-item list and "
+                    "held_or_rejected_decision_ids is empty; do not add Direction to Portfolio "
+                    "inputs. "
+                    "A Compose adopting any Paragraph must also include and adopt its covering "
+                    "Structure in the same candidate closure."
                 ),
             },
             ensure_ascii=False,
@@ -151,6 +203,34 @@ class ScriptMissionFactory:
         )
         return f"{frozen}\n\n{policy}".strip()
 
+    def build_phase_one_resume_run_config(
+        self,
+        binding: MissionBinding,
+        snapshot: ScriptBuildInputSnapshotV1,
+    ) -> RunConfig:
+        config = self.build_run_config(binding, snapshot)
+        config.new_trace_id = None
+        config.trace_id = binding.root_trace_id
+        config.root_task_spec = None
+        config.name = f"Script build {binding.script_build_id} phase one recovery"
+        return config
+
+    def build_recovery_message(self, *, phase: int, script_build_id: int) -> str:
+        return json.dumps(
+            {
+                "mission": "recover_planner_from_durable_ledger",
+                "script_build_id": script_build_id,
+                "phase": phase,
+                "instruction": (
+                    "Inspect the durable ledger, preserve completed Attempts and ACCEPT "
+                    "decisions, and create new work only for needs_replan Tasks. Never replay "
+                    "a completed Attempt or cross the Host-declared phase boundary."
+                ),
+            },
+            ensure_ascii=False,
+            sort_keys=True,
+        )
+
     def build_phase_two_message(
         self,
         binding: MissionBinding,