@@ -8,6 +8,7 @@ from datetime import UTC, datetime |
| 8 | 8 | from pathlib import Path |
| 9 | 9 | |
| 10 | 10 | from ..llm.base import Message, Role, ToolCall |
| 11 | +from .context import RuntimeContext |
| 11 | 12 | from .dod import ( |
| 12 | 13 | DefinitionOfDone, |
| 13 | 14 | DefinitionOfDoneStore, |
@@ -49,23 +50,23 @@ class TurnFinalizer: |
| 49 | 50 | |
| 50 | 51 | def __init__( |
| 51 | 52 | self, |
| 52 | | - agent, |
| 53 | + context: RuntimeContext, |
| 53 | 54 | tracer: RuntimeTracer, |
| 54 | 55 | dod_store: DefinitionOfDoneStore, |
| 55 | 56 | set_workflow_mode: WorkflowSetter, |
| 56 | 57 | ) -> None: |
| 57 | | - self.agent = agent |
| 58 | + self.context = context |
| 58 | 59 | self.tracer = tracer |
| 59 | 60 | self.dod_store = dod_store |
| 60 | 61 | self.set_workflow_mode = set_workflow_mode |
| 61 | 62 | |
| 62 | 63 | @property |
| 63 | 64 | def _prompt_format(self) -> str | None: |
| 64 | | - return getattr(self.agent, "prompt_format", None) |
| 65 | + return self.context.prompt_format |
| 65 | 66 | |
| 66 | 67 | @property |
| 67 | 68 | def _prompt_sections(self) -> list[str]: |
| 68 | | - return list(getattr(self.agent, "prompt_sections", [])) |
| 69 | + return list(self.context.prompt_sections) |
| 69 | 70 | |
| 70 | 71 | async def run_definition_of_done_gate( |
| 71 | 72 | self, |
@@ -93,7 +94,7 @@ class TurnFinalizer: |
| 93 | 94 | pending_text = "\n".join(f"- {item}" for item in tracked_pending_items) |
| 94 | 95 | self.dod_store.save(dod) |
| 95 | 96 | await self.emit_dod_status(emit, dod) |
| 96 | | - self.agent.session.append( |
| 97 | + self.context.session.append( |
| 97 | 98 | Message( |
| 98 | 99 | role=Role.USER, |
| 99 | 100 | content=( |
@@ -111,11 +112,11 @@ class TurnFinalizer: |
| 111 | 112 | dod.last_verification_result = "skipped" |
| 112 | 113 | summary.verification_status = "skipped" |
| 113 | 114 | summary.definition_of_done = dod |
| 114 | | - self.agent.session.append_workflow_timeline_entry( |
| 115 | + self.context.session.append_workflow_timeline_entry( |
| 115 | 116 | WorkflowTimelineEntry( |
| 116 | 117 | timestamp=datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ"), |
| 117 | 118 | kind=WorkflowTimelineEntryKind.VERIFY_SKIP.value, |
| 118 | | - mode=self.agent.workflow_mode, |
| 119 | + mode=self.context.workflow_mode, |
| 119 | 120 | reason_code="verification_not_required", |
| 120 | 121 | summary="verification skipped because the turn made no mutating changes", |
| 121 | 122 | decision_kind=WorkflowDecisionKind.FORCED.value, |
@@ -123,7 +124,7 @@ class TurnFinalizer: |
| 123 | 124 | prompt_sections=self._prompt_sections, |
| 124 | 125 | ) |
| 125 | 126 | ) |
| 126 | | - summary.workflow_timeline = list(self.agent.session.workflow_timeline) |
| 127 | + summary.workflow_timeline = list(self.context.session.workflow_timeline) |
| 127 | 128 | self.dod_store.save(dod) |
| 128 | 129 | await self.emit_dod_status(emit, dod) |
| 129 | 130 | return CompletionGateResult( |
@@ -147,7 +148,7 @@ class TurnFinalizer: |
| 147 | 148 | if not dod.verification_commands: |
| 148 | 149 | dod.verification_commands = derive_verification_commands( |
| 149 | 150 | dod, |
| 150 | | - project_root=self.agent.project_root, |
| 151 | + project_root=self.context.project_root, |
| 151 | 152 | task_statement=dod.task_statement, |
| 152 | 153 | ) |
| 153 | 154 | |
@@ -235,7 +236,7 @@ class TurnFinalizer: |
| 235 | 236 | f"{build_verification_summary(dod.evidence)}\n\n" |
| 236 | 237 | "Fix the failures above, then finish the task again." |
| 237 | 238 | ) |
| 238 | | - self.agent.session.append(Message(role=Role.USER, content=failure_prompt)) |
| 239 | + self.context.session.append(Message(role=Role.USER, content=failure_prompt)) |
| 239 | 240 | return CompletionGateResult(should_continue=True, final_response="") |
| 240 | 241 | |
| 241 | 242 | async def verify_definition_of_done( |
@@ -262,7 +263,7 @@ class TurnFinalizer: |
| 262 | 263 | verification_call = ToolCall( |
| 263 | 264 | id=f"verify-{summary.iterations}-{index}", |
| 264 | 265 | name="bash", |
| 265 | | - arguments={"command": command, "cwd": str(self.agent.project_root)}, |
| 266 | + arguments={"command": command, "cwd": str(self.context.project_root)}, |
| 266 | 267 | ) |
| 267 | 268 | await emit( |
| 268 | 269 | AgentEvent( |
@@ -304,7 +305,7 @@ class TurnFinalizer: |
| 304 | 305 | dod.evidence.append(evidence) |
| 305 | 306 | all_passed = all_passed and evidence.passed |
| 306 | 307 | summary.tool_result_messages.append(outcome.message) |
| 307 | | - self.agent.session.append(outcome.message) |
| 308 | + self.context.session.append(outcome.message) |
| 308 | 309 | |
| 309 | 310 | self.dod_store.save(dod) |
| 310 | 311 | summary.verification_status = "passed" if all_passed else "failed" |
@@ -315,20 +316,20 @@ class TurnFinalizer: |
| 315 | 316 | |
| 316 | 317 | summary.usage["tool_calls"] = len(summary.tool_result_messages) |
| 317 | 318 | summary.usage["iterations"] = summary.iterations |
| 318 | | - summary.cumulative_usage = self.agent.session.record_turn_usage( |
| 319 | + summary.cumulative_usage = self.context.session.record_turn_usage( |
| 319 | 320 | summary.usage, |
| 320 | 321 | tool_calls=len(summary.tool_result_messages), |
| 321 | 322 | iterations=summary.iterations, |
| 322 | 323 | ) |
| 323 | | - summary.session_id = self.agent.session.session_id |
| 324 | + summary.session_id = self.context.session.session_id |
| 324 | 325 | summary.last_turn_transition_summary = ( |
| 325 | | - getattr(self.agent.session, "last_turn_transition_summary", None) |
| 326 | + getattr(self.context.session, "last_turn_transition_summary", None) |
| 326 | 327 | ) |
| 327 | 328 | summary.workflow_timeline = list( |
| 328 | | - getattr(self.agent.session, "workflow_timeline", []) |
| 329 | + getattr(self.context.session, "workflow_timeline", []) |
| 329 | 330 | ) |
| 330 | 331 | if summary.definition_of_done and summary.definition_of_done.status == "done": |
| 331 | | - MemoryStore(self.agent.project_root).capture_definition_of_done( |
| 332 | + MemoryStore(self.context.project_root).capture_definition_of_done( |
| 332 | 333 | build_verification_summary(summary.definition_of_done.evidence) |
| 333 | 334 | ) |
| 334 | 335 | summary.trace = list(self.tracer.events) |