| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- from __future__ import annotations
- from types import SimpleNamespace
- import pytest
- from agent.orchestration import TaskLedger, TaskRecord, TaskSpec
- from agent.orchestration.models import AcceptanceCriterion
- from script_build_host.application.task_planning_v2 import TaskPlanningServiceV2
- from script_build_host.tools.registry import _planner_task_input_schema
- class Store:
- def __init__(self, ledger: TaskLedger) -> None:
- self.ledger = ledger
- async def load(self, root_trace_id: str) -> TaskLedger:
- assert root_trace_id == self.ledger.root_trace_id
- return self.ledger
- class Coordinator:
- def __init__(self, ledger: TaskLedger) -> None:
- self.task_store = Store(ledger)
- self.call = None
- async def replay_command(self, *_args, **_kwargs):
- return None
- async def create_task_graph(self, root_trace_id: str, drafts, **kwargs):
- self.call = (root_trace_id, drafts, kwargs)
- for document in kwargs["context_documents"]:
- self.task_store.ledger.context_documents[document.uri] = document
- for draft in drafts:
- task_id = draft["_task_id"]
- self.task_store.ledger.tasks[task_id] = TaskRecord(
- task_id,
- draft["_parent_task_id"],
- "1.1",
- [
- TaskSpec(
- 1,
- draft["objective"],
- tuple(
- AcceptanceCriterion(
- item["criterion_id"],
- item["description"],
- item["hard"],
- )
- for item in draft["acceptance_criteria"]
- ),
- tuple(draft["context_refs"]),
- )
- ],
- )
- return {"tasks": [{"task_id": drafts[0]["_task_id"]}]}
- async def get_tasks(self, _root_trace_id: str, task_ids):
- return {"tasks": [{"task_id": item} for item in task_ids]}
- @pytest.mark.asyncio
- async def test_v2_planning_passes_contract_documents_in_same_task_mutation() -> None:
- root = TaskRecord(
- "root-task",
- None,
- "1",
- [
- TaskSpec(
- 1,
- "mission",
- (AcceptanceCriterion("done", "done"),),
- )
- ],
- )
- ledger = TaskLedger("root", "mission", "root-task", tasks={"root-task": root})
- coordinator = Coordinator(ledger)
- service = TaskPlanningServiceV2(
- coordinator=coordinator,
- bindings=SimpleNamespace(
- get_by_root=lambda _: None,
- ),
- artifacts=SimpleNamespace(),
- input_snapshots=SimpleNamespace(),
- )
- async def binding(_: str):
- return SimpleNamespace(
- script_build_id=1,
- input_snapshot_id="snapshot",
- active_direction_artifact_version_id=None,
- )
- service.bindings.get_by_root = binding
- async def input_snapshot(*_args, **_kwargs):
- return SimpleNamespace(
- snapshot_id="snapshot",
- account={},
- persona_points=(),
- section_patterns=({"pattern": "opening"},),
- )
- service.input_snapshots.get = input_snapshot
- result = await service.plan(
- intents=[{"task_kind": "direction", "objective": "choose direction"}],
- context={"root_trace_id": "root", "tool_call_id": "call-1"},
- )
- assert result["task_ids"]
- assert coordinator.call is not None
- _, drafts, kwargs = coordinator.call
- documents = kwargs["context_documents"]
- assert len(documents) == len(drafts) == 1
- assert documents[0].uri in drafts[0]["context_refs"]
- assert documents[0].payload["schema_version"] == "script-task-contract/v2"
- def test_planner_schema_exposes_business_intent_only() -> None:
- properties = _planner_task_input_schema()["properties"]
- assert "decision_ids" in properties
- assert "scope_selector" not in properties
- assert "criteria" not in properties
- assert "parent_task_id" not in properties
|