diff --git a/src/agent_evidence.py b/src/agent_evidence.py index 4352fc3f5..eaf9b5f19 100644 --- a/src/agent_evidence.py +++ b/src/agent_evidence.py @@ -592,6 +592,29 @@ class EvidenceLedger: artifact_path=path, ) + if tool == "read_file": + try: + read_args = json.loads(command or "{}") + except (TypeError, json.JSONDecodeError): + read_args = None + read_path = ( + _clean_path(str(read_args.get("path") or "")) + if isinstance(read_args, Mapping) + else "" + ) + if read_path and any( + _artifact_path_matches_required(read_path, required) + for required in self.requirements.required_artifacts + ): + self._append( + kind=EvidenceKind.ARTIFACT_VALIDATION, + success=success, + authoritative=authoritative, + source=event, + artifact_path=read_path, + detail="post-write artifact inspection", + ) + if _TEST_COMMAND_RE.search(_command_text(command)) or _matches_declared_verifier( command, self.requirements.verifier_commands, diff --git a/tests/test_agent_evidence.py b/tests/test_agent_evidence.py index 40e37939c..64cc0f386 100644 --- a/tests/test_agent_evidence.py +++ b/tests/test_agent_evidence.py @@ -557,6 +557,41 @@ def test_json_write_file_then_read_records_required_artifact_mutation(): ) +def test_read_file_after_write_satisfies_required_artifact_validation(): + requirements = CompletionRequirements( + required_artifacts=("/workspace/results/paper_digest.md",), + verifier_required=True, + ) + ledger = EvidenceLedger.from_tool_events( + [ + { + "round": 1, + "tool": "write_file", + "command": json.dumps({ + "path": "/workspace/results/paper_digest.md", + "content": "# Verified digest\n", + }), + "output": "wrote /workspace/results/paper_digest.md", + "exit_code": 0, + }, + { + "round": 2, + "tool": "read_file", + "command": json.dumps({ + "path": "/workspace/results/paper_digest.md", + }), + "output": "# Verified digest\n", + "exit_code": 0, + }, + ], + requirements, + ) + + decision = ledger.evaluate() + assert decision.status == CompletionStatus.SATISFIED + assert decision.can_complete is True + + def test_inspect_media_export_satisfies_declared_artifact(): requirements = infer_completion_requirements("Save /workspace/frame.png") ledger = EvidenceLedger.from_tool_events(