Wire instruction report execution

This commit is contained in:
2026-05-19 18:28:23 +02:00
parent 0e7084207e
commit 0dc342eb1b
7 changed files with 513 additions and 16 deletions

View File

@@ -25,6 +25,9 @@ from activity_core.issue_sink import get_issue_sink
from activity_core.orm import ActivityDefinition as ActivityDefinitionRow
from activity_core.orm import ActivityRun, TaskInstance, TaskSpawnLog
from activity_core.rules import evaluate_condition
from activity_core.llm_client import get_llm_client
from activity_core.models import InstructionDef
from activity_core.rules.executor import execute_instruction_with_audit
_session_factory: async_sessionmaker[AsyncSession] | None = None
@@ -267,6 +270,75 @@ async def evaluate_rules(payload: dict) -> list[dict]:
return matched
@activity.defn
async def evaluate_instructions(payload: dict) -> dict:
"""Evaluate instruction blocks and return task specs/reports with audit fields.
Expected keys in payload:
instructions list[dict] — InstructionDef serialised dicts
event dict — EventEnvelope attributes (or empty for cron)
context dict — context snapshot from resolve_context
"""
instructions = payload.get("instructions", [])
event_attrs = payload.get("event", {})
context = payload.get("context", {})
llm_client = get_llm_client()
class _Env:
def __init__(self, attrs: dict) -> None:
self.attributes = _DictObj(attrs)
class _DictObj:
def __init__(self, d: dict) -> None:
self.__dict__.update(d)
event_obj = _Env(event_attrs)
task_specs: list[dict] = []
reports: list[dict] = []
for raw_instruction in instructions:
try:
instruction = InstructionDef.model_validate(raw_instruction)
except Exception as exc:
activity.logger.warning("instruction definition invalid — %s", exc)
continue
result = execute_instruction_with_audit(
instruction,
event_obj,
context,
llm_client,
)
if result.report is not None:
reports.append({
"instruction_id": instruction.id,
"report": result.report,
"condition": result.condition_matched,
"prompt_hash": result.prompt_hash,
"model": result.model,
"output_validated": result.output_validated,
"review_required": result.review_required,
})
for spec in result.tasks:
task_specs.append({
"title": spec.title,
"description": spec.description,
"target_repo": spec.target_repo,
"priority": spec.priority,
"labels": spec.labels,
"due_in_days": spec.due_in_days,
"source_type": "instruction",
"source_id": instruction.id,
"condition": result.condition_matched,
"prompt_hash": result.prompt_hash,
"model": result.model,
"output_validated": result.output_validated,
"review_required": result.review_required,
})
return {"task_specs": task_specs, "reports": reports}
@activity.defn
async def emit_tasks(payload: dict) -> list[str]:
"""Emit TaskSpecs to IssueSink and write task_spawn_log rows.
@@ -316,6 +388,10 @@ async def emit_tasks(payload: dict) -> list[str]:
triggering_event_id=triggering_event_id,
task_ref=ref.external_id,
condition_matched=spec_dict.get("condition"),
prompt_hash=spec_dict.get("prompt_hash"),
model=spec_dict.get("model"),
output_validated=spec_dict.get("output_validated"),
review_required=spec_dict.get("review_required"),
)
session.add(log_row)
except Exception as exc: