Skip to content

Preserve human-benchmark registry events across concurrent writers and crashes #20

Description

@NeoLorenzo

Audit Priority: P2
Audit Type: FIX

Problem / Opportunity

The human-benchmark registry treats per-attempt JSON files as durable state and also appends lifecycle events to outputs/human_benchmark/results.jsonl. Per-attempt JSON publication is atomic, but append_registry_event() writes directly to the shared JSONL file with a normal append and no serialization or recovery mechanism.

This creates a separate durability problem from canonical-map reservation: concurrent writers can interleave registry-event writes, and a process interruption can leave a truncated final JSON line even when the corresponding attempt JSON was published successfully. The summary currently rebuilds from attempt files, so the benchmark can remain usable while its append-only lifecycle history is malformed or incomplete.

Why This Matters

PolyVision describes human benchmark evidence as persistent and auditable. As #12 completes the remaining canonical attempts, the event log should not silently become weaker than the immutable attempt records it is intended to index. A malformed append-only history makes forensic reconstruction and provenance checks less reliable even if summary.json can still be regenerated.

Evidence

  • tools/human_benchmark.py::atomic_write_json() publishes attempt/summary JSON through a temporary file plus os.replace().
  • persist_attempt() first atomically writes the attempt JSON and then calls append_registry_event().
  • append_registry_event() opens results.jsonl in append mode and writes one serialized line directly; there is no lock, fsync/commit protocol, validation, or repair path around the shared append-only file.
  • load_attempts() and rebuild_summary() use the per-attempt JSON files as authoritative state, so a missing or malformed lifecycle event can exist without preventing the benchmark summary from being produced.
  • Open issue Serialize canonical human-benchmark first-attempt registration #19 protects the cross-file invariant that only one canonical first completion exists per map. That issue does not guarantee atomic/durable publication of the append-only event history itself.

Proposed Outcome

Make lifecycle-event publication consistent with the benchmark's durable registry contract. Registry events should be serialized with other benchmark mutations as needed, and interrupted writes should be detectable and recoverable from authoritative attempt records without silently accepting malformed JSONL history.

Definition of Done

  • Concurrent maintained benchmark writers cannot interleave or corrupt results.jsonl records.
  • A process interruption during event publication cannot leave an undetected malformed lifecycle history.
  • The workflow can validate the event log against authoritative attempt records and either repair/rebuild it deterministically or fail with a clear recovery path.
  • Repeated recovery/rebuild does not duplicate logical lifecycle events.
  • Existing immutable completed-attempt semantics and deterministic summary.json rebuilding remain intact.
  • Regression coverage simulates an interrupted/truncated event append and concurrent/interleaved event publication.
  • Documentation identifies which artifact is authoritative and how the append-only lifecycle history is recovered if damaged.

Constraints / Non-Goals

Do not introduce a database or network service solely for this issue. Coordinate with #19's single-writer mechanism rather than building a second incompatible locking scheme. This issue does not change the first-attempt rule, map pool, statistical gate, or human interface.

Validation

Using a temporary benchmark output root, publish several lifecycle transitions, inject a truncated final JSONL record, and verify the maintained validation/recovery path restores a valid deterministic history from authoritative attempt records. Also exercise two interleaved writers and verify every resulting line is complete JSON and maps unambiguously to a persisted attempt state.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions