fix(runtime): scope completion claims to execution obligations

This commit is contained in:
Alexandre Teixeira
2026-10-01 01:36:18 +01:00
parent 9ee9205bfc
commit 4c122de880
5 changed files with 418 additions and 27 deletions
+92 -6
View File
@@ -280,6 +280,40 @@ def _known_input_is_explicit_mutation_target(instruction: str, path: str) -> boo
)
def _unquoted_statements(text: str) -> Iterable[tuple[str, str]]:
"""Yield original statements and their reportable prose, with quotes masked.
Mask before splitting so punctuation inside an example cannot change the
scope of the surrounding sentence. Inline code identifiers stay visible.
"""
def mask(match: re.Match[str]) -> str:
value = match.group()
# Quotation marks around an artifact identify a target, rather than
# quote a report. Keep that target available for exact path matching.
if value[0] in {'"', "'"} and re.fullmatch(_ARTIFACT_PATH, value[1:-1]):
return ' ' + value[1:-1] + ' '
return re.sub(r'[^\n]', ' ', value)
masked = re.sub(
r'```[\s\S]*?```|~~~[\s\S]*?~~~|"[^"\n]*"|(?<!\w)\'[^\'\n]*\'(?!\w)',
mask, text,
)
start = 0
for boundary in re.finditer(r'(?<=[.!?;])(?=\s)|(?<=\n)', masked):
end = boundary.start()
if end > start:
yield text[start:end], masked[start:end].replace('`', '')
start = end
if start < len(text):
yield text[start:], masked[start:].replace('`', '')
def _execution_obligation(requirements: CompletionRequirements) -> bool:
"""A derived view of the existing contract, never a separate declaration."""
return bool(requirements.required_artifacts or requirements.verifier_required
or requirements.executable_verifier_available or requirements.verifier_commands)
def infer_completion_requirements(
instruction: str,
*,
@@ -289,7 +323,15 @@ def infer_completion_requirements(
) -> CompletionRequirements:
"""Infer only explicitly requested output/edit paths from an instruction."""
text = str(instruction or "")
# Explanations can contain imperative examples. Their embedded actions
# are not requests to execute those actions. Keep independent requests in
# other statements, and keep explicitly supplied verifier requirements.
explanatory_request = re.compile(
r'^\s*(?:please\s+|(?:can|could|would)\s+you\s+)?'
r'(?:explain|describe|summari[sz]e|teach|discuss|'
r'show\s+(?:me\s+)?(?:an?\s+)?example|how\b)', re.I)
text = ''.join(scoped for _, scoped in _unquoted_statements(str(instruction or ''))
if not explanatory_request.search(scoped))
paths: list[str] = []
for pattern in (
_ARTIFACT_REQUEST_RE,
@@ -353,18 +395,23 @@ def infer_completion_requirements(
for command in verifier_commands
if str(command or "").strip()
))
explicit_test_request = re.search(
r'(?:^|[.;\n]|\b(?:and|then))\s*'
r'(?:please\s+|(?:can|could|would)\s+you\s+)?'
r'(?:run|execute)\s+(?:(?:the|all|a|full)\s+)*'
r'(?:tests?\b|test\s+suite\b|pytest\b|unittest\b|npm\s+test\b)', text, re.I)
verifier_required = executable_verifier_available or bool(cleaned_verifier_commands) or bool(
re.search(
explicit_test_request or (paths and re.search(
r"\b(?:then|after(?:wards)?|and)\b[^\n]{0,100}\b(?:test|verify|check|validate)\b",
str(instruction or ""),
text,
re.IGNORECASE,
)
))
)
return CompletionRequirements(
required_artifacts=tuple(paths),
verifier_required=verifier_required,
executable_verifier_available=(
executable_verifier_available or bool(cleaned_verifier_commands)
executable_verifier_available or bool(cleaned_verifier_commands) or bool(explicit_test_request)
),
verifier_commands=cleaned_verifier_commands,
)
@@ -575,6 +622,9 @@ class EvidenceLedger:
self.events: list[EvidenceEvent] = []
self._verification_versions: dict[str, str] = {}
self._verification_versions_captured = False
# Retain receipt command identity privately for presentation matching;
# model prose and client dictionaries never populate this evidence.
self._verifier_commands: dict[str, tuple[str, ...]] = {}
@classmethod
def from_tool_events(
@@ -718,13 +768,14 @@ class EvidenceLedger:
versions = event.get('artifact_versions')
self._verification_versions = dict(versions) if isinstance(versions, Mapping) else {}
self._verification_versions_captured = isinstance(versions, Mapping)
self._append(
verifier = self._append(
kind=EvidenceKind.VERIFIER_RESULT,
success=success,
authoritative=authoritative,
source=event,
detail="executable test/verifier command",
)
self._verifier_commands[verifier.event_id] = executable_words(_command_text(command))
elif tool in {"bash", "host_shell"} and is_validation_command(command) and not mutation_paths:
for path in self.requirements.required_artifacts:
if _path_is_mentioned(command, path):
@@ -736,6 +787,41 @@ class EvidenceLedger:
artifact_path=path,
)
def _supports_verifier_claim(self, identities: Sequence[str] = (), paths: Sequence[str] = ()) -> bool:
"""Only the current passing verifier may support its named runner."""
if self.evaluate().status != CompletionStatus.VERIFIED:
return False
latest = next((event for event in reversed(self.events)
if event.kind == EvidenceKind.VERIFIER_RESULT and event.authoritative), None)
if latest is None or not latest.success:
return False
words = self._verifier_commands.get(latest.event_id, ())
names = {Path(words[0]).name} if words else set()
if words and re.fullmatch(r'python(?:\d+(?:\.\d+)*)?', Path(words[0]).name) and '-m' in words:
module_index = words.index('-m') + 1
if module_index < len(words):
names.add(words[module_index])
return (all(identity in names for identity in identities)
and all(any(_artifact_path_matches_required(word, path, self.requirements.workspace_root)
for word in words) for path in paths))
def _supports_artifact_claim(self, kind: EvidenceKind, paths: Sequence[str]) -> bool:
"""Match every claimed artifact by identity, never by basename."""
targets = tuple(paths) or self.requirements.required_artifacts
if not targets or (not paths and len(targets) != 1):
return False
for path in targets:
matching = [event for event in self.events if event.kind == kind and event.authoritative
and _artifact_path_matches_required(event.artifact_path, path, self.requirements.workspace_root)]
successful = [event for event in matching if event.success]
# Match evaluate(): atomic helper failures preserve the previous
# successful artifact; a partial shell/Python failure may not.
destructive_failure = bool(matching and not matching[-1].success
and matching[-1].tool in {'bash', 'python'})
if not successful or destructive_failure:
return False
return True
def record_media_ingress(self, metadata: Mapping[str, Any]) -> None:
for artifact in metadata.get("artifacts") or []:
if not isinstance(artifact, Mapping):