feat(runtime): consume governed Activity Core closes

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a06ba0-10aa-7ea0-b20a-4f3fac39efe9
This commit is contained in:
tegwick 2026-09-04 19:54:07 +02:00
parent 0e6d795aa4
commit d00ffcb402
22 changed files with 1218 additions and 148 deletions

View file

@ -1,8 +1,7 @@
"""Durable, idempotent close-evidence outbox core.
"""Durable, idempotent Activity Core close-evidence outbox.
The outbox is intentionally not wired into the live claim loop yet. It stores
bounded Activity Core completion/failure intents outside target checkouts so a
future reconciler can retry close delivery without re-running repository work.
It stores bounded completion/failure intents outside target checkouts so the
claim worker can retry close delivery without re-running repository work.
"""
from __future__ import annotations
@ -32,6 +31,7 @@ _RECORD_KEYS = frozenset(
"entry_id",
"run_id",
"transaction_id",
"worker_id",
"action",
"result",
"error",
@ -61,12 +61,17 @@ class OutboxCorruptError(CloseOutboxError):
"""A durable record cannot be safely decoded or validated."""
class PermanentCloseDeliveryError(CloseOutboxError):
"""Activity Core conclusively refused a close intent; do not retry it."""
@dataclass(frozen=True)
class CloseRequest:
"""One bounded Activity Core completion or failure intent."""
run_id: str
transaction_id: str
worker_id: str
action: str
result: dict[str, Any]
error: str = ""
@ -80,6 +85,7 @@ class CloseRequest:
)
_validate_identifier(self.run_id, "run_id")
_validate_identifier(self.transaction_id, "transaction_id")
_validate_identifier(self.worker_id, "worker_id")
if self.action not in {"complete", "fail"}:
raise InvalidCloseRequestError("action must be 'complete' or 'fail'")
if not isinstance(self.result, dict):
@ -118,6 +124,7 @@ class CloseRequest:
"entry_id": self.entry_id,
"run_id": self.run_id,
"transaction_id": self.transaction_id,
"worker_id": self.worker_id,
"action": self.action,
"result": self.result,
"error": self.error,
@ -128,6 +135,7 @@ class CloseRequest:
return CloseRequest(
run_id=self.run_id,
transaction_id=self.transaction_id,
worker_id=self.worker_id,
action=self.action,
result=json.loads(json.dumps(self.result)),
error=self.error,
@ -203,6 +211,7 @@ class _Record:
request = CloseRequest(
run_id=value["run_id"],
transaction_id=value["transaction_id"],
worker_id=value["worker_id"],
action=value["action"],
result=value["result"],
error=value["error"],
@ -328,6 +337,10 @@ class CloseOutbox:
_atomic_write_json(path, trying.payload())
try:
deliver(record.request.detached_copy())
except PermanentCloseDeliveryError as exc:
self._quarantine(path, str(exc))
quarantined += 1
continue
except Exception as exc:
retained = _Record(
request=record.request,
@ -370,6 +383,32 @@ class CloseOutbox:
with self._locked():
return len(tuple(self.pending_dir.glob("*.json")))
def status(self) -> dict[str, int]:
"""Return bounded operator counts without decoding record contents."""
with self._locked():
quarantined = tuple(
path
for path in self.quarantine_dir.glob("*.json")
if not path.name.endswith(".error.json")
)
return {
"pending": len(tuple(self.pending_dir.glob("*.json"))),
"delivered": len(tuple(self.delivered_dir.glob("*.json"))),
"quarantined": len(quarantined),
}
def entry_state(self, entry_id: str) -> str | None:
"""Return the durable state for one already-validated entry id."""
_validate_identifier(entry_id, "entry_id")
with self._locked():
if (self.delivered_dir / f"{entry_id}.json").exists():
return "delivered"
if (self.pending_dir / f"{entry_id}.json").exists():
return "pending"
if tuple(self.quarantine_dir.glob(f"{entry_id}.*.json")):
return "quarantined"
return None
def _load(self, path: Path) -> _Record:
try:
if path.stat().st_size > _MAX_PAYLOAD_BYTES + 8192: