Skip to content

Windows: capture installed_at from FS mtime with us ceiling, not wall clock #732

@memtomem

Description

@memtomem

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):

  1. Read st_mtime_ns (int, lossless) from the FS using the shared installed-file walker.
  2. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions