Repository navigation
fix: unique ULID filename for staged records (silent-overwrite bug) - #114
Conversation
ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Free Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe pending decision extraction now uses ULID-based unique filenames to prevent overwrites when ChangesPending Decision Filename Uniqueness
🎯 2 (Simple) | ⏱️ ~12 minutes
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
… timestamp collision) stage_pending_decisions named files pending_<call-timestamp>_<index>.md, where the index reset to 000 every call. Two stage calls that shared a timestamp — two calls in the same instant, or re-staging a batch that already carried a fixed timestamp — reused 000/001/... and silently overwrote each other's files. No error; records just vanished. Found in demo prep: copying 12 records that shared an extraction timestamp left only ~9 on disk. Fix: filename is now pending_<timestamp>_<ULID>.md — the ULID is globally unique per record (across calls and instants) while the timestamp prefix keeps files chronologically sortable. ULID is already a dependency (util/ulid.py). Regression test pins datetime.now so both stage calls share one timestamp (the exact trigger) and asserts all 4 records from two batches survive. Verified RED (assert 2 == 4) before the fix, GREEN after. Full suite 379 passed, ruff + pyright clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
a5bcec9 to
0dd16cb
Compare
The bug (found in real demo prep)
stage_pending_decisionsnamed filespending_<call-timestamp>_<index>.md, where the index resets to000every call. The timestamp alone isn't unique, so two stage calls sharing a timestamp silently overwrote each other:No error — records just disappeared. Concretely: copying 12 records that shared one extraction timestamp left only ~9 on disk.
Fix
Filename is now
pending_<timestamp>_<ULID>.md:util/ulid.py).Example:
pending_2026-05-30T12-15-13.182084p00-00_01K9XT9TXEH2GVJW73WT8XR4FW.mdTDD
Regression test pins
datetime.nowso both stage calls get the identical timestamp — the exact collision trigger — then asserts all 4 records from two batches survive on disk.assert 2 == 4— batch B clobbered batch A.(The first version of this test passed without the fix — because sequential
datetime.now()calls get different microseconds — so I rewrote it to pin the timestamp and actually reproduce the bug. Anti-pattern avoided.)Verified: full suite 379 passed, ruff clean, pyright 0 errors.
🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests