117 lines
4.2 KiB
Python
117 lines
4.2 KiB
Python
"""Flash's exit-only acceptance check uses the same read-only Checker as Pro."""
|
|
|
|
import asyncio
|
|
|
|
from artemis.agents.checker.checker import run_final_check
|
|
from artemis.context import ArtemisContext
|
|
from artemis.graph.checkpoints import (
|
|
RunOutcome,
|
|
TestSummary,
|
|
final_check_enabled,
|
|
publish_checker_event,
|
|
verdict_payloads,
|
|
write_run_outcome,
|
|
)
|
|
from artemis.runtime.case_result import CaseTestResult, resolve_case_result
|
|
from artemis.utils.logger import get_logger
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
async def settle_flash_outcome(
|
|
ctx: ArtemisContext,
|
|
goal: str,
|
|
execution_report: dict,
|
|
*,
|
|
final_report_received: bool = False,
|
|
) -> dict:
|
|
"""Check once at exit, without operating the device or rerunning the task."""
|
|
stop_capture = getattr(ctx, "on_execution_review", None)
|
|
if stop_capture:
|
|
await stop_capture()
|
|
status = str(execution_report.get("status") or "failed")
|
|
result = None
|
|
if status == "completed" or final_report_received:
|
|
if final_check_enabled(ctx):
|
|
timeout = float(getattr(ctx.execution_setup, "checkpoint_timeout", 180.0))
|
|
publish_checker_event(
|
|
ctx,
|
|
{
|
|
"event": "attempt_started",
|
|
"phase": "final",
|
|
"attempt_id": "final#1",
|
|
"checkpoint_id": "final",
|
|
"check_items": [],
|
|
"status": "running",
|
|
},
|
|
)
|
|
try:
|
|
report = await asyncio.wait_for(
|
|
run_final_check(
|
|
ctx,
|
|
goal=goal,
|
|
plan_text="",
|
|
ledger=[],
|
|
check_items=[],
|
|
attempt_id="final#1",
|
|
execution_report=execution_report,
|
|
),
|
|
timeout=timeout,
|
|
)
|
|
result = report.test_result
|
|
publish_checker_event(
|
|
ctx,
|
|
{
|
|
"event": "attempt_finished",
|
|
"phase": "final",
|
|
"attempt_id": "final#1",
|
|
"checkpoint_id": "final",
|
|
"status": "done",
|
|
"verdicts": verdict_payloads(report.verdicts),
|
|
"test_result": result.model_dump() if result else None,
|
|
"route": "end",
|
|
},
|
|
)
|
|
except Exception as exc:
|
|
detail = (
|
|
f"超过 {timeout:g} 秒"
|
|
if isinstance(exc, TimeoutError)
|
|
else f"{type(exc).__name__}: {exc}"
|
|
)
|
|
logger.warning(f"Flash 测试验收未完成:{detail}")
|
|
result = CaseTestResult(
|
|
status="inconclusive", reason=f"操作已结束,但测试验收未完成:{detail}。"
|
|
)
|
|
publish_checker_event(
|
|
ctx,
|
|
{
|
|
"event": "attempt_finished",
|
|
"phase": "final",
|
|
"attempt_id": "final#1",
|
|
"checkpoint_id": "final",
|
|
"status": "error",
|
|
"error": result.reason,
|
|
"route": "end",
|
|
},
|
|
)
|
|
else:
|
|
result = CaseTestResult(
|
|
status="inconclusive", reason="已关闭最终检查,未进行测试结果验收。"
|
|
)
|
|
|
|
outcome = RunOutcome(
|
|
task_status="completed" if status == "completed" else "blocked", tests=TestSummary()
|
|
)
|
|
payload = outcome.model_dump()
|
|
if result:
|
|
payload["test_result"] = result.model_dump()
|
|
resolved = resolve_case_result(payload, status, str(execution_report.get("explanation") or ""))
|
|
payload["test_result"] = resolved.model_dump() if resolved else None
|
|
if ctx.data_engine:
|
|
write_run_outcome(
|
|
ctx.data_engine.base_dir, outcome, {"test_result": payload["test_result"]}
|
|
)
|
|
publish_checker_event(ctx, {"event": "run_outcome", "phase": "outcome", **payload})
|
|
ctx.run_outcome = payload
|
|
return payload
|