mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-07 07:22:21 +02:00
fix(runtime): reject unobserved verification and preserve safe reasoning
This commit is contained in:
@@ -574,6 +574,7 @@ class EvidenceLedger:
|
||||
self.requirements = requirements or CompletionRequirements()
|
||||
self.events: list[EvidenceEvent] = []
|
||||
self._verification_versions: dict[str, str] = {}
|
||||
self._verification_versions_captured = False
|
||||
|
||||
@classmethod
|
||||
def from_tool_events(
|
||||
@@ -716,6 +717,7 @@ class EvidenceLedger:
|
||||
if authoritative:
|
||||
versions = event.get('artifact_versions')
|
||||
self._verification_versions = dict(versions) if isinstance(versions, Mapping) else {}
|
||||
self._verification_versions_captured = isinstance(versions, Mapping)
|
||||
self._append(
|
||||
kind=EvidenceKind.VERIFIER_RESULT,
|
||||
success=success,
|
||||
@@ -791,7 +793,9 @@ class EvidenceLedger:
|
||||
for path in self.requirements.required_artifacts:
|
||||
identity = artifact_identity(path, self.requirements.workspace_root)
|
||||
expected = self._verification_versions.get(identity)
|
||||
if expected in {'unobserved', 'missing-or-unreadable'}:
|
||||
if expected in {'unobserved', 'missing-or-unreadable'} or (
|
||||
expected is None and self._verification_versions_captured
|
||||
):
|
||||
return CompletionDecision(CompletionStatus.BLOCKED, False,
|
||||
'artifact version could not be established for verification',
|
||||
(latest_verifier.event_id,))
|
||||
|
||||
@@ -155,6 +155,10 @@ def with_completion_gate(func):
|
||||
if isinstance(declared, dict):
|
||||
requirements = requirements_from_runtime_context({'completion_requirements': declared})
|
||||
requirements = replace(requirements, workspace_root=trusted_workspace or '')
|
||||
# New obligations affect future receipts only. Never
|
||||
# backfill historical versions with present bytes.
|
||||
journal.observed_artifacts = tuple(dict.fromkeys(
|
||||
(*journal.observed_artifacts, *requirements.required_artifacts)))
|
||||
continue
|
||||
if kind == 'ask_user':
|
||||
awaiting = True
|
||||
@@ -215,6 +219,13 @@ def with_completion_gate(func):
|
||||
yield _event({'type': 'completion_decision', 'data': decision.to_dict()})
|
||||
replaced_answer = bool(reason or unsafe_draft or safe_answer != answer)
|
||||
if replaced_answer:
|
||||
reasoning = [event for event in answer_events if event.get('thinking') is True]
|
||||
_, unsafe_reasoning = completion_answer(
|
||||
''.join(str(event.get('delta') or '') for event in reasoning), ledger,
|
||||
replace(presentation_decision, can_complete=True))
|
||||
if not unsafe_reasoning:
|
||||
for event in reasoning:
|
||||
yield _event(event)
|
||||
yield _event({'type': 'final_response', 'content': safe_answer})
|
||||
else:
|
||||
for event in answer_events:
|
||||
|
||||
Reference in New Issue
Block a user