Background
Discovered as a follow-up to the umbrella #634 (Windows + macOS CI matrix) and the PR-D C2a / #630 invariant.
A single dirty-detection cluster in test_dirty.py + test_context_status.py fails on Windows-CI matching the 'dirty' == 'clean' / 'ok' / 'behind' / 'stale-pin' shape. The root cause is not content / line-ending / permission related — dirty.py:_iter_files already skips symlinks, and CRLF / file-mode bits never enter the comparison (the rule is strictly mtime). The bug is two stacked clock / precision defects in how installed_at is captured.
Two-layer root cause
1. Capture domain
installed_at = utcnow_iso8601_z() reads Python's wall clock. NTFS records st_mtime from a different timer (FILETIME). Under dirty.py:148's strict mtime > installed_at_epoch check, just-written files can land strictly later than the captured timestamp. The current code was written under the POSIX assumption that both timers share a source — true on POSIX, false on Windows.
2. µs round-trip truncation
Even if capture moves to the FS, st_mtime (float seconds) → ISO-8601Z %H:%M:%S.%fZ (microsecond format) → datetime.fromisoformat().timestamp() truncates the NTFS 100-ns residual. The just-written file's own st_mtime_ns still carries the full nano-tick, so even self-comparison can violate mtime ≤ installed_at_epoch by ≤1µs. This is the actual failure surface — moving capture to FS without addressing precision leaves the same shape of bug.
Fix
installed_at_from_dest(dst):
- Read
st_mtime_ns (int, lossless) from the FS using the shared installed-file walker.
- Ceiling-divide ns → µs before formatting.
The formatted installed_at round-trips to a value >= every walked file's actual st_mtime — byte-identical to today on POSIX (where ordinary writes give st_mtime_ns % 1000 == 0; ceil is a no-op) and with a <= 1µs safety margin on NTFS.
Locked decision #5 in PR-D C2 (strict >) is preserved — we strengthen the underlying capture, not the comparison.
Validation
- Pin tests in
TestInstalledAtFromDest (test_dirty.py) cover empty fallback, single/multi mtime, skip rules, and the load-bearing µs residual.
- Mutation validation: reverting capture or removing the ceiling fails specific pin tests (documented in PR body).
- POSIX is byte-identical for ordinary writes — sanity check, not sign-off.
- Windows-CI is the actual ground truth.
References
🤖 Generated with Claude Code
Background
Discovered as a follow-up to the umbrella #634 (Windows + macOS CI matrix) and the PR-D C2a / #630 invariant.
A single dirty-detection cluster in
test_dirty.py+test_context_status.pyfails on Windows-CI matching the'dirty' == 'clean' / 'ok' / 'behind' / 'stale-pin'shape. The root cause is not content / line-ending / permission related —dirty.py:_iter_filesalready skips symlinks, and CRLF / file-mode bits never enter the comparison (the rule is strictlymtime). The bug is two stacked clock / precision defects in howinstalled_atis captured.Two-layer root cause
1. Capture domain
installed_at = utcnow_iso8601_z()reads Python's wall clock. NTFS recordsst_mtimefrom a different timer (FILETIME). Underdirty.py:148's strictmtime > installed_at_epochcheck, just-written files can land strictly later than the captured timestamp. The current code was written under the POSIX assumption that both timers share a source — true on POSIX, false on Windows.2. µs round-trip truncation
Even if capture moves to the FS,
st_mtime(float seconds) → ISO-8601Z%H:%M:%S.%fZ(microsecond format) →datetime.fromisoformat().timestamp()truncates the NTFS 100-ns residual. The just-written file's ownst_mtime_nsstill carries the full nano-tick, so even self-comparison can violatemtime ≤ installed_at_epochby ≤1µs. This is the actual failure surface — moving capture to FS without addressing precision leaves the same shape of bug.Fix
installed_at_from_dest(dst):st_mtime_ns(int, lossless) from the FS using the shared installed-file walker.The formatted
installed_atround-trips to a value>=every walked file's actualst_mtime— byte-identical to today on POSIX (where ordinary writes givest_mtime_ns % 1000 == 0; ceil is a no-op) and with a<= 1µssafety margin on NTFS.Locked decision #5 in PR-D C2 (
strict >) is preserved — we strengthen the underlying capture, not the comparison.Validation
TestInstalledAtFromDest(test_dirty.py) cover empty fallback, single/multi mtime, skip rules, and the load-bearing µs residual.References
installed_atpost-copy capture)os.sepfor memory_dir prefix), fix(search): normalize separators in source_filter match (#720) #722 (source_filterseparator fold)🤖 Generated with Claude Code