todo-52.9-atomic-report-bundles-and-audit-parity.md 2.1 KB

Todo 52.9 Atomic Report Bundles and Audit Parity Plan

Status: done

Goal

Replace the fundamentally non-transactional two-path report publication with one atomic bundle publication boundary, and close the remaining report/CLI audit gaps found after Todo 52.8.

Root Cause

Publishing flat JSON and Markdown paths requires two independent filesystem operations. If the second operation conflicts, rolling back the first requires a check-then-unlink sequence that cannot atomically prove pathname ownership. A competing process can replace the first path between the inode check and unlink(), so the writer may delete another process's file or return a mixed pair.

Scope

  • Fully write and fsync report.json and report.md inside one private, uniquely named bundle directory.
  • Publish the complete bundle through one atomic, no-overwrite directory symlink named from the timestamp; a collision chooses the next numeric suffix without deleting or replacing the competitor.
  • Return the two report paths through the published bundle path and leave no flat two-file rollback path.
  • Clean only unpublished private bundle state. Never inspect-then-delete a published competitor-controlled pathname.
  • Treat mutation after successful publication as out of scope: a process with write access to the output directory can replace any published filesystem entry after the command returns.
  • Render runtime errors and semantic failures together in Markdown when both exist, preserving the facts present in JSON.
  • Map summary/error stream failures to exit code 2 without exposing secrets or confusing them with benchmark sample failures.

Files

  • Modify: src/agent_lab/infrastructure/benchmark_reporting.py
  • Modify: src/agent_lab/presentation/benchmark_cli.py
  • Modify: tests/test_benchmark_reporting.py
  • Modify: tests/test_benchmark_cli.py

Verification

  • Reproduce the Todo 52.8 inode-check-to-unlink race before implementation.
  • uv run pytest tests/test_benchmark_reporting.py tests/test_benchmark_cli.py -q
  • concurrent process/thread bundle publication and collision stress tests
  • uv run pytest
  • git diff --check