Skip to content

evals: prevent silent overwrites in results writer artifacts#131

Merged
renaudcepre merged 1 commit into
mainfrom
fix-results-writer-collisions
Jun 24, 2026
Merged

evals: prevent silent overwrites in results writer artifacts#131
renaudcepre merged 1 commit into
mainfrom
fix-results-writer-collisions

Conversation

@renaudcepre

Copy link
Copy Markdown
Owner

What

Closes #119. Two silent data-loss gaps in the per-case markdown artifacts (results_writer.py).

1. Case-name collisions

Names were sanitized with re.sub(r"[^\w\-]", "_", name), so a/b and a:b both became a_b.md — the second silently overwriting the first. The writer now tracks the stems used in each run dir and appends a numeric suffix on collision (a_b.md, a_b-2.md), so every case keeps its own file. (Also falls back to case when a name sanitizes to empty.)

2. Same-second / racing run directories

Run dirs are timestamped to the second with mkdir(exist_ok=True), so two runs of the same suite within one second — or two racing processes — merged their case files into one directory. _make_run_dir now creates with exist_ok=False and bumps a numeric suffix until mkdir wins. mkdir is atomic, so this is also safe across concurrent processes.

Tests

New tests/evals/test_results_writer.py (kept separate to avoid growing the already-large test_e2e.py, cf. #98):

  • colliding sanitized names produce two distinct files, each with its own content;
  • empty name falls back to case.md;
  • successive run dirs are distinct and all exist;
  • a pre-existing timestamp dir forces the suffix branch.

Full suite: 1246 passed, ruff clean, mypy --strict clean.


Generated by Claude Code

Two silent data-loss gaps in the per-case markdown artifacts:

- Distinct case names sanitized with re.sub(r'[^\w\-]', '_', name) could
  collide ('a/b' and 'a:b' both -> 'a_b.md'), the second silently
  overwriting the first. Track the stems used in each run dir and append a
  numeric suffix on collision so every case keeps its own file.

- Run directories are timestamped to the second with mkdir(exist_ok=True),
  so two runs of the same suite within one second (or two racing processes)
  merged their case files. Create with exist_ok=False and bump a numeric
  suffix until mkdir wins; mkdir is atomic, so this is safe across processes.

Closes #119
@renaudcepre
renaudcepre merged commit 12a79af into main Jun 24, 2026
11 checks passed
@renaudcepre
renaudcepre deleted the fix-results-writer-collisions branch June 24, 2026 20:08
renaudcepre added a commit that referenced this pull request Jun 25, 2026
Two silent data-loss gaps in the per-case markdown artifacts:

- Distinct case names sanitized with re.sub(r'[^\w\-]', '_', name) could
  collide ('a/b' and 'a:b' both -> 'a_b.md'), the second silently
  overwriting the first. Track the stems used in each run dir and append a
  numeric suffix on collision so every case keeps its own file.

- Run directories are timestamped to the second with mkdir(exist_ok=True),
  so two runs of the same suite within one second (or two racing processes)
  merged their case files. Create with exist_ok=False and bump a numeric
  suffix until mkdir wins; mkdir is atomic, so this is safe across processes.

Closes #119

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

results writer: sanitized case names can collide (silent overwrite) and same-second runs merge directories

2 participants