Artifex/graph/task_execution.py
2026-08-15 18:14:21 +07:00

81 lines
4 KiB
Python

from __future__ import annotations
from graph.spec import ExecutionGraphSpec, GraphEdgeSpec, GraphNodeSpec
TASK_EXECUTION_GRAPH_NAME = "task_execution"
TASK_EXECUTION_GRAPH_VERSION = 1
def task_execution_graph_v1() -> ExecutionGraphSpec:
nodes = {
"claim_task": GraphNodeSpec("claim_task", "claim_task", {"idempotent": False, "replay_safe": False}),
"prepare_worktree": GraphNodeSpec("prepare_worktree", "prepare_worktree", {"idempotent": True, "replay_safe": True}),
"build_context": GraphNodeSpec("build_context", "build_context", {"idempotent": True, "replay_safe": True}),
"coder": GraphNodeSpec("coder", "coder", {"idempotent": False, "replay_safe": "checkpointed", "contains_internal_tool_loop": True}),
"run_tests": GraphNodeSpec("run_tests", "run_tests", {"idempotent": True, "replay_safe": "checkpointed"}),
"review": GraphNodeSpec("review", "review", {"idempotent": True, "replay_safe": "checkpointed"}),
"judge": GraphNodeSpec("judge", "judge", {"idempotent": True, "replay_safe": "checkpointed"}),
"commit": GraphNodeSpec("commit", "commit", {"idempotent": False, "replay_safe": "guarded", "destructive": True}),
"retry_or_fail": GraphNodeSpec("retry_or_fail", "retry_or_fail", {"idempotent": False, "replay_safe": "checkpointed"}),
"cleanup": GraphNodeSpec("cleanup", "cleanup", {"idempotent": True, "replay_safe": True}),
"complete": GraphNodeSpec("complete", "complete", {"terminal": True}),
"fail": GraphNodeSpec("fail", "fail", {"terminal": True}),
}
edges = [
GraphEdgeSpec("claim_task", "prepare_worktree", "success"),
GraphEdgeSpec("prepare_worktree", "build_context", "success"),
GraphEdgeSpec("build_context", "coder", "success"),
GraphEdgeSpec("coder", "run_tests", "success"),
GraphEdgeSpec("coder", "retry_or_fail", "failure"),
GraphEdgeSpec("run_tests", "review", "complete"),
GraphEdgeSpec("review", "judge", "PASS"),
GraphEdgeSpec("review", "retry_or_fail", "REWORK_REQUIRED"),
GraphEdgeSpec("review", "retry_or_fail", "REJECTED"),
GraphEdgeSpec("judge", "commit", "PASS"),
GraphEdgeSpec("judge", "retry_or_fail", "FAIL"),
GraphEdgeSpec("commit", "cleanup", "success"),
GraphEdgeSpec("cleanup", "complete", "success"),
GraphEdgeSpec("retry_or_fail", "build_context", "retry_available"),
GraphEdgeSpec("retry_or_fail", "cleanup", "retry_exhausted"),
GraphEdgeSpec("cleanup", "fail", "failed"),
]
spec = ExecutionGraphSpec(
name=TASK_EXECUTION_GRAPH_NAME,
version=TASK_EXECUTION_GRAPH_VERSION,
graph_type="TASK_EXECUTION",
entry="claim_task",
nodes=nodes,
edges=edges,
terminal_nodes=["complete", "fail"],
metadata={"description": "Task execution graph v1 mirrors AutonomousTaskLoop semantics."},
)
spec.validate()
return spec
def task_execution_graph_v2_static_analysis() -> ExecutionGraphSpec:
spec = task_execution_graph_v1()
nodes = dict(spec.nodes)
nodes["static_analysis"] = GraphNodeSpec("static_analysis", "static_analysis", {"deterministic": True})
edges = []
for edge in spec.edges:
if edge.source == "run_tests" and edge.target == "review":
edges.append(GraphEdgeSpec("run_tests", "static_analysis", edge.condition, edge.metadata))
elif edge.source == "review" and edge.target == "judge":
edges.append(edge)
else:
edges.append(edge)
edges.append(GraphEdgeSpec("static_analysis", "review", "PASS"))
challenger = ExecutionGraphSpec(
name=TASK_EXECUTION_GRAPH_NAME,
version=2,
graph_type=spec.graph_type,
entry=spec.entry,
nodes=nodes,
edges=edges,
terminal_nodes=spec.terminal_nodes,
metadata={"parent_version": 1, "change_summary": "Insert deterministic static_analysis node before Reviewer."},
)
challenger.validate()
return challenger