Files
stack/packages/mosaic/framework/tools/lease-broker/receipt_observer.py
jason.woltje 07553ead33
All checks were successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
WI-5 #832: Receipt-challenge protocol (compaction-refresh, milestone 188) (#845)
2026-07-19 23:18:56 +00:00

107 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""Trusted latest-assistant-message observer boundary for receipt promotion.
Runtime adapters must implement ``observe_latest_assistant_message`` directly:
Claude selects the exact latest assistant entry and Pi selects ``message_end``.
The broker accepts no observed message through its request protocol.
"""
from __future__ import annotations
import json
import os
import stat
from pathlib import Path
from typing import Protocol
class ReceiptObserver(Protocol):
def observe_latest_assistant_message(
self,
session_id: str,
runtime: str,
runtime_generation: int,
binding: dict[str, object],
) -> str | None: ...
class UnavailableReceiptObserver:
"""Production-safe default until a runtime adapter injects an observer."""
def observe_latest_assistant_message(
self,
_session_id: str,
_runtime: str,
_runtime_generation: int,
_binding: dict[str, object],
) -> str | None:
return None
class TestReceiptObserver:
"""Deterministic controlled observer used only by byte-build tests."""
def __init__(self) -> None:
self._messages: dict[tuple[str, int], str] = {}
def record_latest_assistant_message(
self, session_id: str, runtime_generation: int, message: str
) -> None:
self._messages[(session_id, runtime_generation)] = message
def observe_latest_assistant_message(
self,
session_id: str,
_runtime: str,
runtime_generation: int,
_binding: dict[str, object],
) -> str | None:
return self._messages.get((session_id, runtime_generation))
class FileTestReceiptObserver:
"""Private fixture-file observer for isolated out-of-process test drivers."""
def __init__(self, path: Path) -> None:
self.path = path
def observe_latest_assistant_message(
self,
session_id: str,
_runtime: str,
runtime_generation: int,
_binding: dict[str, object],
) -> str | None:
flags = os.O_RDONLY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0)
try:
descriptor = os.open(self.path, flags)
except OSError:
return None
try:
metadata = os.fstat(descriptor)
if (
not stat.S_ISREG(metadata.st_mode)
or stat.S_IMODE(metadata.st_mode) != 0o600
or metadata.st_uid != os.geteuid()
or metadata.st_size > 64 * 1024
):
return None
raw = os.read(descriptor, 64 * 1024 + 1)
finally:
os.close(descriptor)
if len(raw) > 64 * 1024:
return None
try:
value = json.loads(raw)
except (json.JSONDecodeError, UnicodeDecodeError):
return None
if (
not isinstance(value, dict)
or set(value) != {"session_id", "runtime_generation", "latest_assistant_message"}
or value["session_id"] != session_id
or value["runtime_generation"] != runtime_generation
or not isinstance(value["latest_assistant_message"], str)
):
return None
return value["latest_assistant_message"]