Delegate task execution to native graph runtime

This commit is contained in:
Daniel Maddern 2026-08-15 17:06:56 +07:00
parent fde298a1b5
commit 8109d01992
6 changed files with 73 additions and 0 deletions

View file

@ -0,0 +1,19 @@
from __future__ import annotations
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("graph", "0002_graphnoderun_visit_index"),
("projects", "0002_commitrecord_coder_commitrecord_judge_and_more"),
]
operations = [
migrations.AddField(
model_name="commitrecord",
name="graph_run",
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="commits", to="graph.graphrun"),
),
]

View file

@ -173,6 +173,9 @@ class CommitRecord(TimestampedModel):
verification = models.ForeignKey(
"verification.Verification", on_delete=models.SET_NULL, null=True, blank=True, related_name="commits"
)
graph_run = models.ForeignKey(
"graph.GraphRun", on_delete=models.SET_NULL, null=True, blank=True, related_name="commits"
)
sha = models.CharField(max_length=64)
branch_name = models.CharField(max_length=255)
message = models.TextField()

29
graph/bootstrap.py Normal file
View file

@ -0,0 +1,29 @@
from __future__ import annotations
from django.utils import timezone
from graph.models import ExecutionGraphDefinition, ExecutionGraphVersion, ExecutionGraphVersionStatus
from graph.task_execution import task_execution_graph_v1
def champion_task_execution_graph_v1() -> ExecutionGraphVersion:
spec = task_execution_graph_v1()
definition, _ = ExecutionGraphDefinition.objects.get_or_create(
name=spec.name,
defaults={"graph_type": spec.graph_type, "description": str(spec.metadata.get("description", ""))},
)
version, created = ExecutionGraphVersion.objects.get_or_create(
graph=definition,
version=spec.version,
defaults={
"status": ExecutionGraphVersionStatus.CHAMPION,
"graph_spec": spec.to_dict(),
"metadata": {"immutable_after_use": True},
"promoted_at": timezone.now(),
},
)
if not created and version.status != ExecutionGraphVersionStatus.CHAMPION:
version.status = ExecutionGraphVersionStatus.CHAMPION
version.promoted_at = timezone.now()
version.save(update_fields=["status", "promoted_at"])
return version

View file

@ -130,6 +130,8 @@ class BuildContextNode(TaskNode):
attempt.save(update_fields=["context_snapshot", "updated_at"])
metadata["current_attempt_id"] = str(attempt.id)
self.save_metadata(context, metadata)
context.graph_run.task_attempt = attempt
context.graph_run.save(update_fields=["task_attempt", "updated_at"])
return NodeResult("COMPLETE", "success", {"attempt_id": str(attempt.id), "attempt_number": attempt.attempt_number})
@ -306,6 +308,7 @@ class CommitNode(TaskNode):
test_run=test_run,
review_id=metadata.get("review_id"),
verification_id=metadata.get("verification_id"),
graph_run=context.graph_run,
sha=sha,
branch_name=worktree.branch_name,
message=f"Artifex task: {task.goal[:80]}",

View file

@ -10,7 +10,11 @@ from control_plane.events.bus import EventBus
from control_plane.events.models import EventType
from control_plane.projects.models import CommitRecord, Task, TaskAttempt, TaskStatus, Worktree
from control_plane.verification.models import VerificationResult
from graph.bootstrap import champion_task_execution_graph_v1
from graph.models import GraphRun
from graph.native_runtime import NativeGraphRuntime
from graph.scheduler import TaskScheduler
from graph.task_nodes import TaskExecutionServices, task_execution_registry
from knowledge.context_builder import WorkerContextBuilder
from model_router.router import ModelRouter
from tools.capabilities import Capability
@ -45,6 +49,19 @@ class AutonomousTaskLoop:
return task
def _execute_task(self, task: Task, test_command: list[str]) -> None:
graph_version = champion_task_execution_graph_v1()
graph_run = GraphRun.objects.create(
execution_graph_version=graph_version,
project=task.project,
milestone=task.milestone,
feature=task.feature,
task=task,
current_node=graph_version.graph_spec["entry"],
)
services = TaskExecutionServices(self.router, bus=self.bus, test_command=test_command)
NativeGraphRuntime(task_execution_registry(services), bus=self.bus).run_until_terminal_or_paused(graph_run)
return
coder_version = self._champion(AgentRole.CODER)
reviewer_version = self._champion(AgentRole.REVIEWER)
judge_version = self._champion(AgentRole.PROJECT_JUDGE)

View file

@ -85,6 +85,8 @@ def assert_accepted_trace(task: Task) -> CommitRecord:
assert review.status == "PASS"
assert verification.result == VerificationResult.PASS
assert commit.sha
assert commit.graph_run_id is not None
assert commit.graph_run.execution_graph_version.graph.name == "task_execution"
assert commit.coder.agent.role == "CODER"
assert commit.reviewer.agent.role == "REVIEWER"
assert commit.judge.agent.role == "PROJECT_JUDGE"