|
@@ -3,6 +3,7 @@
|
|
|
from __future__ import annotations
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
import json
|
|
import json
|
|
|
|
|
+from hashlib import sha256
|
|
|
from math import isfinite
|
|
from math import isfinite
|
|
|
|
|
|
|
|
from agent import CompletionPolicy, RunConfig
|
|
from agent import CompletionPolicy, RunConfig
|
|
@@ -111,6 +112,7 @@ class ScriptMissionFactory:
|
|
|
model=planner_config["model"],
|
|
model=planner_config["model"],
|
|
|
temperature=planner_config["temperature"],
|
|
temperature=planner_config["temperature"],
|
|
|
max_iterations=planner_config["max_iterations"],
|
|
max_iterations=planner_config["max_iterations"],
|
|
|
|
|
+ system_prompt=_frozen_prompt(snapshot, "script_planner"),
|
|
|
completion_policy=CompletionPolicy.EXPLICIT_VALIDATION,
|
|
completion_policy=CompletionPolicy.EXPLICIT_VALIDATION,
|
|
|
new_trace_id=binding.root_trace_id,
|
|
new_trace_id=binding.root_trace_id,
|
|
|
root_task_spec=self.build_root_task_spec(snapshot),
|
|
root_task_spec=self.build_root_task_spec(snapshot),
|
|
@@ -130,6 +132,79 @@ class ScriptMissionFactory:
|
|
|
name=f"Script build {binding.script_build_id}",
|
|
name=f"Script build {binding.script_build_id}",
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+ def build_phase_two_policy(self, snapshot: ScriptBuildInputSnapshotV1) -> str:
|
|
|
|
|
+ frozen = _frozen_prompt(snapshot, "script_planner") or ""
|
|
|
|
|
+ policy = json.dumps(
|
|
|
|
|
+ {
|
|
|
|
|
+ "policy": "script-build-phase-two/v1",
|
|
|
|
|
+ "phase": 2,
|
|
|
|
|
+ "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."
|
|
|
|
|
+ ),
|
|
|
|
|
+ },
|
|
|
|
|
+ ensure_ascii=False,
|
|
|
|
|
+ sort_keys=True,
|
|
|
|
|
+ )
|
|
|
|
|
+ return f"{frozen}\n\n{policy}".strip()
|
|
|
|
|
+
|
|
|
|
|
+ def build_phase_two_message(
|
|
|
|
|
+ self,
|
|
|
|
|
+ binding: MissionBinding,
|
|
|
|
|
+ snapshot: ScriptBuildInputSnapshotV1,
|
|
|
|
|
+ *,
|
|
|
|
|
+ direction_artifact_version_id: int,
|
|
|
|
|
+ ) -> str:
|
|
|
|
|
+ return json.dumps(
|
|
|
|
|
+ {
|
|
|
|
|
+ "mission": "continue_toward_root",
|
|
|
|
|
+ "script_build_id": binding.script_build_id,
|
|
|
|
|
+ "phase": 2,
|
|
|
|
|
+ "input_snapshot_ref": f"script-build://inputs/{snapshot.snapshot_id}",
|
|
|
|
|
+ "input_sha256": snapshot.canonical_sha256,
|
|
|
|
|
+ "accepted_direction_ref": (
|
|
|
|
|
+ f"script-build://artifact-versions/{direction_artifact_version_id}"
|
|
|
|
|
+ ),
|
|
|
|
|
+ "phase_boundary": "PHASE_TWO_CANDIDATE_PORTFOLIO_READY",
|
|
|
|
|
+ },
|
|
|
|
|
+ ensure_ascii=False,
|
|
|
|
|
+ sort_keys=True,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ def build_phase_two_run_config(
|
|
|
|
|
+ self,
|
|
|
|
|
+ binding: MissionBinding,
|
|
|
|
|
+ snapshot: ScriptBuildInputSnapshotV1,
|
|
|
|
|
+ ) -> RunConfig:
|
|
|
|
|
+ planner_config = _planner_model_config(snapshot.model_manifest)
|
|
|
|
|
+ return RunConfig(
|
|
|
|
|
+ agent_type="script_planner",
|
|
|
|
|
+ model=planner_config["model"],
|
|
|
|
|
+ temperature=planner_config["temperature"],
|
|
|
|
|
+ max_iterations=planner_config["max_iterations"],
|
|
|
|
|
+ completion_policy=CompletionPolicy.EXPLICIT_VALIDATION,
|
|
|
|
|
+ trace_id=binding.root_trace_id,
|
|
|
|
|
+ root_task_spec=None,
|
|
|
|
|
+ tool_groups=None,
|
|
|
|
|
+ parallel_tool_execution=False,
|
|
|
|
|
+ enable_memory=False,
|
|
|
|
|
+ enable_research_flow=False,
|
|
|
|
|
+ knowledge=KnowledgeConfig(
|
|
|
|
|
+ enable_extraction=False,
|
|
|
|
|
+ enable_completion_extraction=False,
|
|
|
|
|
+ enable_injection=False,
|
|
|
|
|
+ ),
|
|
|
|
|
+ context={
|
|
|
|
|
+ "script_build_id": binding.script_build_id,
|
|
|
|
|
+ "input_snapshot_id": snapshot.snapshot_id,
|
|
|
|
|
+ "phase": 2,
|
|
|
|
|
+ },
|
|
|
|
|
+ name=f"Script build {binding.script_build_id} phase two",
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
|
|
|
def _planner_model_config(manifest: dict[str, object]) -> dict[str, object]:
|
|
def _planner_model_config(manifest: dict[str, object]) -> dict[str, object]:
|
|
|
raw_presets = manifest.get("presets", manifest)
|
|
raw_presets = manifest.get("presets", manifest)
|
|
@@ -148,4 +223,20 @@ def _planner_model_config(manifest: dict[str, object]) -> dict[str, object]:
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+def _frozen_prompt(snapshot: ScriptBuildInputSnapshotV1, preset: str) -> str | None:
|
|
|
|
|
+ matches = [item for item in snapshot.prompt_manifest if item.get("preset") == preset]
|
|
|
|
|
+ if not matches:
|
|
|
|
|
+ return None
|
|
|
|
|
+ if len(matches) != 1:
|
|
|
|
|
+ raise ValueError(f"frozen prompt manifest has duplicate preset: {preset}")
|
|
|
|
|
+ value = matches[0]
|
|
|
|
|
+ content = value.get("content")
|
|
|
|
|
+ digest = value.get("content_sha256")
|
|
|
|
|
+ if not isinstance(content, str) or not isinstance(digest, str):
|
|
|
|
|
+ raise ValueError(f"frozen prompt manifest is incomplete: {preset}")
|
|
|
|
|
+ if f"sha256:{sha256(content.encode('utf-8')).hexdigest()}" != digest:
|
|
|
|
|
+ raise ValueError(f"frozen prompt manifest digest mismatch: {preset}")
|
|
|
|
|
+ return content
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
__all__ = ["ScriptMissionFactory", "normalize_topic_summary"]
|
|
__all__ = ["ScriptMissionFactory", "normalize_topic_summary"]
|