Skip to content

Fix golden fixture hashes on Windows and add CI - #104

Merged
WhatsYourWhy merged 3 commits into
mainfrom
chore/ci-and-line-ending-normalization
Aug 14, 2026
Merged

Fix golden fixture hashes on Windows and add CI#104
WhatsYourWhy merged 3 commits into
mainfrom
chore/ci-and-line-ending-normalization

Conversation

@WhatsYourWhy

Copy link
Copy Markdown
Owner

Summary

tests/test_golden_run.py has been failing on Windows checkouts since the fixtures were added. The fixtures were never corrupted. They are stored LF and hash to exactly the pinned values, but core.autocrlf=true with no .gitattributes checked them out as CRLF — 9, 22 and 101 translated line endings — changing their bytes and therefore their SHA-256.

Normalize CRLF→LF and all three are byte-identical to the committed blobs:

fixture committed (LF) Windows checkout (CRLF)
event_spill.json 72e81b37… (pinned) c6e92df5…
normalized_event_spill.json 4c8538e8… (pinned) e44452d1…
incident_evidence_spill.json 723ce988… (pinned) 4857a37c…

Fixed with .gitattributes so the working tree is LF on every platform. The pinned hashes and the fixture contents are both unchanged — the only content change in this PR is .gitattributes, the workflow, a CHANGELOG entry, and a testpaths setting.

This also explains the earlier churn in that file: 4fbab87 made the tests green by repinning to the Windows CRLF hashes (which would then have failed on Linux), and a71d477 correctly reverted it. The revert was right; neither commit found the cause.

CI

The repository had no CI (.github/ contained only FUNDING.yml).

The ubuntu × windows matrix is load-bearing rather than redundancy: a Linux-only matrix cannot catch a CRLF checkout altering hashed bytes, and a Windows-only matrix cannot catch someone pinning Windows-specific hashes. Running both is what keeps .gitattributes honest. There is also an explicit line-ending check before install, so a regression reports as itself rather than as an opaque hash mismatch.

pip-audit runs weekly on a schedule and on manual dispatch, deliberately not as a PR gate — it queries a remote advisory database and a network blip should not block an unrelated review.

Verification

Verified in a fresh clone of this branch configured with core.autocrlf=true (the setting that caused the bug), with its own venv so no editable install could leak source from elsewhere:

  • working tree clean after checkout; all three fixtures hash to the pinned values with zero CRLF
  • 187 passed, 0 failed — the previous baseline of 184 passing plus the 3 golden tests that were red

🤖 Generated with Claude Code

The three assertions in tests/test_golden_run.py have failed on every
Windows checkout since the fixtures were added. The fixtures were never
corrupted: they are stored LF and hash to exactly the pinned values, but
core.autocrlf=true with no .gitattributes checked them out as CRLF,
changing their bytes and therefore their SHA-256. Normalizing CRLF to LF
makes all three byte-identical to the committed blobs.

Fixed by adding .gitattributes, so the working tree is LF on every
platform. The pinned hashes and the fixture contents are both unchanged.
Verified against a fresh clone configured with core.autocrlf=true.

This also explains the earlier churn in that file: 4fbab87 made the tests
green by repinning to the Windows CRLF hashes, which would then have
failed on Linux, and a71d477 correctly reverted it. Neither commit found
the cause.

Adds the repository's first CI. The ubuntu x windows matrix is
load-bearing rather than redundancy: a Linux-only matrix cannot catch a
CRLF checkout altering hashed bytes, and a Windows-only matrix cannot
catch someone pinning Windows-specific hashes. pip-audit runs weekly on a
schedule rather than as a PR gate, since it queries a remote advisory
database and should not block unrelated reviews.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

WhatsYourWhy and others added 2 commits August 14, 2026 00:07
utils/id_generator.py and runners/run_demo.py imported datetime.UTC,
which was added in Python 3.11, so `import hardstop` raised ImportError
on 3.10 while pyproject.toml advertised requires-python = ">=3.10". The
package could not be installed and used on its own declared floor.

Replaced with timezone.utc, which UTC is an alias for, so behavior is
unchanged on every version.

Found by the CI matrix added in the previous commit, on its first run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
test_cmd_incidents_replay_emits_run_record picked the replay record with
sorted(glob("*.json"))[-1]. RunRecords are named
"{started_at}_{run_id}.json", so two records written within the same
clock tick share a timestamp prefix and sort by their random UUID
suffix. On Windows, where clock granularity is coarser, that made the
selection a coin flip: the test passed on the first CI run and failed on
the second with the baseline correlation.window record.

Select by operator_id instead, which is what the assertion actually
means. Only the test was wrong; record filenames remain unique.

Verified with 30 consecutive runs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@WhatsYourWhy
WhatsYourWhy merged commit 6d54b8d into main Aug 14, 2026
5 checks passed
@WhatsYourWhy
WhatsYourWhy deleted the chore/ci-and-line-ending-normalization branch August 14, 2026 04:47
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.

1 participant