|
|
@@ -55,6 +55,7 @@ from script_build_host.tools.gateway import RetrievalResult
|
|
|
|
|
|
ROOT = "phase-two-real-runner-root"
|
|
|
FULL_SCOPE = "script-build://scopes/full"
|
|
|
+DIRECTION_GOAL_ID = "direction-goal"
|
|
|
|
|
|
|
|
|
def _tool(call_id: str, name: str, arguments: Mapping[str, Any]) -> dict[str, Any]:
|
|
|
@@ -135,6 +136,7 @@ def _contract(
|
|
|
compose_order: Sequence[str] = (),
|
|
|
comparison_decision_refs: Sequence[Mapping[str, Any]] = (),
|
|
|
supersedes_decision_ids: Sequence[str] = (),
|
|
|
+ goal_ids: Sequence[str] | None = None,
|
|
|
) -> dict[str, Any]:
|
|
|
output_schema = {
|
|
|
"direction": "script-direction/v1",
|
|
|
@@ -177,9 +179,9 @@ def _contract(
|
|
|
"max_external_queries": 40,
|
|
|
"max_no_improvement": 3,
|
|
|
},
|
|
|
- "goal_ids": (
|
|
|
- [] if task_kind in {"direction", "decode-retrieval"} else ["goal-1"]
|
|
|
- ),
|
|
|
+ "goal_ids": list(goal_ids)
|
|
|
+ if goal_ids is not None
|
|
|
+ else ([] if task_kind in {"direction", "decode-retrieval"} else [DIRECTION_GOAL_ID]),
|
|
|
"supersedes_decision_ids": list(supersedes_decision_ids),
|
|
|
"candidate_closure_decision_refs": list(closure),
|
|
|
"adopted_decision_ids": list(adopted),
|
|
|
@@ -305,6 +307,14 @@ class _PhaseTwoScriptedLLM:
|
|
|
},
|
|
|
)
|
|
|
|
|
|
+ direction_decision, direction_ref = _accepted_ref(ledger, direction)
|
|
|
+ direction_pin = _decision_ref(
|
|
|
+ direction_decision,
|
|
|
+ direction_ref,
|
|
|
+ scope_ref=FULL_SCOPE,
|
|
|
+ task_kind="direction",
|
|
|
+ )
|
|
|
+
|
|
|
portfolio = next(iter(by_kind("candidate-portfolio")), None)
|
|
|
if portfolio is None:
|
|
|
return self._call(
|
|
|
@@ -315,6 +325,7 @@ class _PhaseTwoScriptedLLM:
|
|
|
"candidate-portfolio",
|
|
|
scope_ref=FULL_SCOPE,
|
|
|
write_scope=("script-build://writes",),
|
|
|
+ input_decision_refs=(direction_pin,),
|
|
|
)
|
|
|
]
|
|
|
},
|
|
|
@@ -330,6 +341,7 @@ class _PhaseTwoScriptedLLM:
|
|
|
"compose",
|
|
|
scope_ref=FULL_SCOPE,
|
|
|
write_scope=("script-build://writes",),
|
|
|
+ input_decision_refs=(direction_pin,),
|
|
|
)
|
|
|
],
|
|
|
},
|
|
|
@@ -345,6 +357,7 @@ class _PhaseTwoScriptedLLM:
|
|
|
"structure",
|
|
|
scope_ref="script-build://scopes/full/opening",
|
|
|
write_scope=("script-build://writes/paragraphs/opening",),
|
|
|
+ input_decision_refs=(direction_pin,),
|
|
|
)
|
|
|
],
|
|
|
},
|
|
|
@@ -375,7 +388,7 @@ class _PhaseTwoScriptedLLM:
|
|
|
scope_ref="script-build://scopes/full/opening",
|
|
|
write_scope=("script-build://writes/paragraphs/opening",),
|
|
|
objective=first_paragraph_objective,
|
|
|
- input_decision_refs=(structure_pin,),
|
|
|
+ input_decision_refs=(direction_pin, structure_pin),
|
|
|
base_artifact_ref=_artifact_ref_payload(structure_ref),
|
|
|
)
|
|
|
],
|
|
|
@@ -386,7 +399,6 @@ class _PhaseTwoScriptedLLM:
|
|
|
if paragraph.status is TaskStatus.AWAITING_DECISION:
|
|
|
return self._accept(paragraph, ledger)
|
|
|
|
|
|
- direction_decision, direction_ref = _accepted_ref(ledger, direction)
|
|
|
paragraph_decision, paragraph_ref = _accepted_ref(ledger, paragraph)
|
|
|
if compose.current_spec_version == 1:
|
|
|
structure_pin = _decision_ref(
|
|
|
@@ -411,14 +423,7 @@ class _PhaseTwoScriptedLLM:
|
|
|
"compose",
|
|
|
scope_ref=FULL_SCOPE,
|
|
|
write_scope=("script-build://writes",),
|
|
|
- input_decision_refs=(
|
|
|
- _decision_ref(
|
|
|
- direction_decision,
|
|
|
- direction_ref,
|
|
|
- scope_ref=FULL_SCOPE,
|
|
|
- task_kind="direction",
|
|
|
- ),
|
|
|
- ),
|
|
|
+ input_decision_refs=(direction_pin,),
|
|
|
closure=(structure_pin, paragraph_pin),
|
|
|
adopted=(structure_decision, paragraph_decision),
|
|
|
compose_order=(structure_decision, paragraph_decision),
|
|
|
@@ -445,6 +450,7 @@ class _PhaseTwoScriptedLLM:
|
|
|
write_scope=("script-build://writes/paragraphs/opening",),
|
|
|
objective=replacement_objective,
|
|
|
input_decision_refs=(
|
|
|
+ direction_pin,
|
|
|
_decision_ref(
|
|
|
structure_decision,
|
|
|
structure_ref,
|
|
|
@@ -487,6 +493,7 @@ class _PhaseTwoScriptedLLM:
|
|
|
scope_ref="script-build://scopes/full/opening/evidence",
|
|
|
write_scope=(),
|
|
|
objective="retrieve evidence for the replacement opening",
|
|
|
+ goal_ids=(DIRECTION_GOAL_ID,),
|
|
|
)
|
|
|
],
|
|
|
},
|
|
|
@@ -513,6 +520,7 @@ class _PhaseTwoScriptedLLM:
|
|
|
scope_ref="script-build://scopes/full/opening",
|
|
|
write_scope=(),
|
|
|
objective="compare opening candidates A and B symmetrically",
|
|
|
+ input_decision_refs=(direction_pin,),
|
|
|
comparison_decision_refs=(
|
|
|
_decision_ref(
|
|
|
paragraph_decision,
|
|
|
@@ -566,14 +574,7 @@ class _PhaseTwoScriptedLLM:
|
|
|
"compose",
|
|
|
scope_ref=FULL_SCOPE,
|
|
|
write_scope=("script-build://writes",),
|
|
|
- input_decision_refs=(
|
|
|
- _decision_ref(
|
|
|
- direction_decision,
|
|
|
- direction_ref,
|
|
|
- scope_ref=FULL_SCOPE,
|
|
|
- task_kind="direction",
|
|
|
- ),
|
|
|
- ),
|
|
|
+ input_decision_refs=(direction_pin,),
|
|
|
closure=(structure_pin, paragraph_pin, replacement_pin),
|
|
|
adopted=(structure_decision, replacement_decision),
|
|
|
held=(paragraph_decision,),
|
|
|
@@ -612,6 +613,7 @@ class _PhaseTwoScriptedLLM:
|
|
|
"candidate-portfolio",
|
|
|
scope_ref=FULL_SCOPE,
|
|
|
write_scope=("script-build://writes",),
|
|
|
+ input_decision_refs=(direction_pin,),
|
|
|
closure=(compose_pin,),
|
|
|
adopted=(compose_decision,),
|
|
|
compose_order=(compose_decision,),
|
|
|
@@ -673,7 +675,7 @@ class _PhaseTwoScriptedLLM:
|
|
|
{
|
|
|
"goals": [
|
|
|
{
|
|
|
- "goal_id": "direction-goal",
|
|
|
+ "goal_id": DIRECTION_GOAL_ID,
|
|
|
"statement": "open with one observable reversal",
|
|
|
"rationale": "the frozen topic benefits from a concrete hook",
|
|
|
"success_criteria": [
|
|
|
@@ -767,8 +769,12 @@ class _PhaseTwoScriptedLLM:
|
|
|
return self._call("submit_attempt", {})
|
|
|
if not isinstance(last, list):
|
|
|
return self._call("read_pinned_candidates", {})
|
|
|
- assert len(last) == 2
|
|
|
- candidates = [str(item["artifact_ref"]["uri"]) for item in last]
|
|
|
+ candidates = [
|
|
|
+ str(item["artifact_ref"]["uri"])
|
|
|
+ for item in last
|
|
|
+ if item["task_kind"] == "paragraph"
|
|
|
+ ]
|
|
|
+ assert len(candidates) == 2
|
|
|
return self._call(
|
|
|
"save_comparison_candidate",
|
|
|
{
|
|
|
@@ -811,7 +817,7 @@ class _PhaseTwoScriptedLLM:
|
|
|
return self._call("submit_attempt", {})
|
|
|
if not isinstance(last, list):
|
|
|
return self._call("read_pinned_candidates", {})
|
|
|
- assert len(last) == 1
|
|
|
+ assert sorted(item["task_kind"] for item in last) == ["compose", "direction"]
|
|
|
return self._call(
|
|
|
"save_candidate_portfolio",
|
|
|
{
|
|
|
@@ -956,6 +962,13 @@ class _OrderedExplorationScriptedLLM(_PhaseTwoScriptedLLM):
|
|
|
return await super()._planner()
|
|
|
|
|
|
root = ledger.tasks[ledger.root_task_id]
|
|
|
+ direction_decision, direction_ref = _accepted_ref(ledger, direction)
|
|
|
+ direction_pin = _decision_ref(
|
|
|
+ direction_decision,
|
|
|
+ direction_ref,
|
|
|
+ scope_ref=FULL_SCOPE,
|
|
|
+ task_kind="direction",
|
|
|
+ )
|
|
|
|
|
|
def by_objective(value: str) -> Any | None:
|
|
|
return next((task for task in tasks if task.current_spec.objective == value), None)
|
|
|
@@ -972,6 +985,7 @@ class _OrderedExplorationScriptedLLM(_PhaseTwoScriptedLLM):
|
|
|
"candidate-portfolio",
|
|
|
scope_ref=FULL_SCOPE,
|
|
|
write_scope=("script-build://writes",),
|
|
|
+ input_decision_refs=(direction_pin,),
|
|
|
)
|
|
|
]
|
|
|
},
|
|
|
@@ -987,6 +1001,7 @@ class _OrderedExplorationScriptedLLM(_PhaseTwoScriptedLLM):
|
|
|
"compose",
|
|
|
scope_ref=FULL_SCOPE,
|
|
|
write_scope=("script-build://writes",),
|
|
|
+ input_decision_refs=(direction_pin,),
|
|
|
)
|
|
|
],
|
|
|
},
|
|
|
@@ -994,7 +1009,7 @@ class _OrderedExplorationScriptedLLM(_PhaseTwoScriptedLLM):
|
|
|
|
|
|
exploratory: dict[str, Any] = {}
|
|
|
scopes = {
|
|
|
- "structure": "script-build://scopes/full/opening/structure-sketch",
|
|
|
+ "structure": "script-build://scopes/full/opening",
|
|
|
"paragraph": "script-build://scopes/full/opening",
|
|
|
"element-set": "script-build://scopes/full/opening/elements",
|
|
|
}
|
|
|
@@ -1007,13 +1022,14 @@ class _OrderedExplorationScriptedLLM(_PhaseTwoScriptedLLM):
|
|
|
objective = f"explore {kind} before formal adoption"
|
|
|
task = by_objective(objective)
|
|
|
if task is None:
|
|
|
- inputs: tuple[dict[str, Any], ...] = ()
|
|
|
+ inputs: tuple[dict[str, Any], ...] = (direction_pin,)
|
|
|
base: dict[str, Any] | None = None
|
|
|
if kind == "paragraph":
|
|
|
structure_decision, structure_ref = _accepted_ref(
|
|
|
ledger, exploratory["structure"]
|
|
|
)
|
|
|
inputs = (
|
|
|
+ direction_pin,
|
|
|
_decision_ref(
|
|
|
structure_decision,
|
|
|
structure_ref,
|
|
|
@@ -1062,6 +1078,7 @@ class _OrderedExplorationScriptedLLM(_PhaseTwoScriptedLLM):
|
|
|
write_scope=("script-build://writes/paragraphs/opening",),
|
|
|
objective=paragraph_objective,
|
|
|
input_decision_refs=(
|
|
|
+ direction_pin,
|
|
|
_decision_ref(
|
|
|
structure_decision,
|
|
|
structure_ref,
|
|
|
@@ -1105,6 +1122,7 @@ class _OrderedExplorationScriptedLLM(_PhaseTwoScriptedLLM):
|
|
|
write_scope=("script-build://writes/elements",),
|
|
|
objective=element_objective,
|
|
|
input_decision_refs=(
|
|
|
+ direction_pin,
|
|
|
_decision_ref(
|
|
|
element_decision,
|
|
|
element_ref,
|
|
|
@@ -1130,7 +1148,6 @@ class _OrderedExplorationScriptedLLM(_PhaseTwoScriptedLLM):
|
|
|
return self._accept(element_replacement, ledger)
|
|
|
adopted_element_decision, adopted_element_ref = _accepted_ref(ledger, element_replacement)
|
|
|
|
|
|
- direction_decision, direction_ref = _accepted_ref(ledger, direction)
|
|
|
pins = (
|
|
|
_decision_ref(
|
|
|
structure_decision,
|
|
|
@@ -1174,14 +1191,7 @@ class _OrderedExplorationScriptedLLM(_PhaseTwoScriptedLLM):
|
|
|
"compose",
|
|
|
scope_ref=FULL_SCOPE,
|
|
|
write_scope=("script-build://writes",),
|
|
|
- input_decision_refs=(
|
|
|
- _decision_ref(
|
|
|
- direction_decision,
|
|
|
- direction_ref,
|
|
|
- scope_ref=FULL_SCOPE,
|
|
|
- task_kind="direction",
|
|
|
- ),
|
|
|
- ),
|
|
|
+ input_decision_refs=(direction_pin,),
|
|
|
closure=pins,
|
|
|
adopted=(
|
|
|
structure_decision,
|
|
|
@@ -1214,6 +1224,7 @@ class _OrderedExplorationScriptedLLM(_PhaseTwoScriptedLLM):
|
|
|
"candidate-portfolio",
|
|
|
scope_ref=FULL_SCOPE,
|
|
|
write_scope=("script-build://writes",),
|
|
|
+ input_decision_refs=(direction_pin,),
|
|
|
closure=(
|
|
|
_decision_ref(
|
|
|
compose_decision,
|
|
|
@@ -1958,6 +1969,8 @@ async def test_historical_partial_advances_via_http_and_reenters_after_filestore
|
|
|
assert phase_one_root.status is TaskStatus.BLOCKED
|
|
|
assert phase_one_root.blocked_reason == PHASE_ONE_CAPABILITY_BOUNDARY
|
|
|
assert await build_states.get_status(script_build_id) is BuildStatus.PARTIAL
|
|
|
+ phase_one_traces = FileSystemTraceStore(str(tmp_path / "trace"))
|
|
|
+ assert await phase_one_traces.get_goal_tree(ROOT) is None
|
|
|
|
|
|
# Reopen every file-backed component to represent the first Phase2 process.
|
|
|
transition_store = FileSystemTaskStore(str(tmp_path / "ledger"))
|