feat: expose cleanup and reporting outcomes for gateway runs
Some checks failed
ci / validate (push) Has been cancelled

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0726e-5232-73f2-aaca-2c05ceb62efb
This commit is contained in:
tegwick 2026-09-06 11:12:30 +02:00
parent f76cb7d955
commit 356e34992a
6 changed files with 177 additions and 7 deletions

View file

@ -216,11 +216,14 @@ class ExecutionEvidence(ContractModel):
tool_events_count: int = Field(default=0, ge=0)
tool_events_completeness: Literal["complete", "partial", "unavailable"] = "unavailable"
refs: dict[str, Any] = Field(default_factory=dict)
session_cleanup: Literal["unknown", "not_attempted", "succeeded", "failed"] = "unknown"
sandbox_destroy: Literal["unknown", "not_attempted", "succeeded", "failed"] = "unknown"
class GatewayResult(ContractModel):
ok: bool
evidence: ExecutionEvidence
hub_report_status: Literal["unknown", "not_requested", "accepted", "failed"] = "unknown"
# Direct caller output only. gateway.py deliberately excludes these fields
# from State Hub detail because they can contain prompts/model responses.
tool_output: str = ""

View file

@ -110,6 +110,8 @@ def run_execution(
status = None
session = None
session_cleanup = "not_attempted"
sandbox_destroy = "not_attempted"
try:
try:
manager = manager if manager is not None else SandboxManager()
@ -198,7 +200,9 @@ def run_execution(
if session is not None:
try:
selected_rein.cleanup_session(session)
session_cleanup = "succeeded"
except Exception as exc:
session_cleanup = "failed"
if outcome == "succeeded" or not error:
outcome = "failed"
failure_stage = "teardown"
@ -206,7 +210,9 @@ def run_execution(
if status is not None:
try:
manager.destroy(status.sandbox_id)
sandbox_destroy = "succeeded"
except Exception as exc:
sandbox_destroy = "failed"
if outcome == "succeeded" or not error:
outcome = "failed"
failure_stage = "teardown"
@ -226,6 +232,8 @@ def run_execution(
tool_result=tool_result,
summary=summary,
refs=refs,
session_cleanup=session_cleanup,
sandbox_destroy=sandbox_destroy,
)
_report(request, result)
return result
@ -282,6 +290,8 @@ def _build_result(
tool_result: ToolResult | None,
summary: ExecutionSummary | None,
refs: dict,
session_cleanup: str = "not_attempted",
sandbox_destroy: str = "not_attempted",
) -> GatewayResult:
duration = max(0.0, time.monotonic() - started)
resolved_model = (
@ -331,6 +341,8 @@ def _build_result(
tool_result.events_completeness if tool_result else "unavailable"
),
refs=refs,
session_cleanup=session_cleanup,
sandbox_destroy=sandbox_destroy,
)
return GatewayResult(
ok=outcome == "succeeded",
@ -342,9 +354,10 @@ def _build_result(
def _report(request: ExecutionRequest, result: GatewayResult) -> None:
if not request.report_to_hub:
result.hub_report_status = "not_requested"
return
evidence = result.evidence.model_dump(mode="json", exclude_none=True)
hub.post_progress_event(
accepted = hub.post_progress_event(
summary=(
f"gateway run: {request.title} "
f"({'ok' if result.ok else result.evidence.outcome})"
@ -352,3 +365,4 @@ def _report(request: ExecutionRequest, result: GatewayResult) -> None:
event_type="gateway_run",
detail=evidence,
)
result.hub_report_status = "accepted" if accepted else "failed"