feat(dates): pre-cutover audit utility for the filename date class (#117) #123

Merged
cameron merged 2 commits from feature/filename-audit into master 2026-09-26 14:32:13 +00:00
Owner

Closes #117.

Summary

Pre-cutover audit utility for the filename date class: a one-shot,
operator-run, strictly read-only binary that lists every filename-class
file across the libraries — its current stored date + source and the
date / source / offset-source (plus the numeric offset) the re-based
resolver would assign it. This is the human spot-check that gates the
production backfill drain (#118): the operator reviews the report,
fixes any misclassified file, and only then starts the drain.

Changes

  • src/filename_audit.rs (new): StoredDate / AuditRow /
    SkippedLibrary; per-library walk (PathExcluder with the depth-0
    guard from file_scan) → match_filename_date → one
    resolve_dates_batch pass with empty priors, exactly mirroring
    what the drain will call; run_audit honors the kill switch and the
    watcher's online probe (disabled → skipped, probe-stale → skipped,
    never partially processed); output stable-sorted by (library, path);
    format_report is deterministic with * marking rows whose stored
    legacy date would change.
  • src/bin/filename_audit.rs (new): operator entry point (dotenv,
    DATABASE_URL, EXCLUDED_DIRS, libraries::load_all, report).
    Zero writes.
  • src/memories.rs: match_filename_date canonical matcher returning
    FilenameMatch { pattern, date } so the audit can report which
    pattern matched; extract_date_from_filename is now a thin,
    byte-for-byte behavior-preserving wrapper (verified in review).
  • src/lib.rs: module registration.

Evidence

  • New tests: match_filename_date pattern names + out-of-class None
    (2); audit module — inversion fixture (stored exif/2021 vs
    proposed filename/2014 wall with assumed_server offset -240m and
    changed flag), unix-timestamp utc_direct with camera_offset
    None, exclusion respect, unindexed handling, disabled + offline
    library skip, stable sort across out-of-order libraries, report
    determinism incl. no debug quotes and rendered offset values (4).
  • cargo test: 645 lib + 718 integration, 0 failures.
    cargo fmt --check + cargo clippy --all-targets: clean.
  • Two-axis review (parallel subagents): spec axis — all 6 acceptance
    criteria PASS + all 5 spec-mirroring invariants PASS (empty-priors
    drain mirroring, subprocess-free in-class path, effective-excludes
    union, had_data probe input, binary never writes); standards axis —
    ship-with-fixes, all 6 findings applied (report format spec, depth-0
    guard, dead check, unused derive, column width, doc comment).

Merge Danger

Two-way door. Pure addition: one new module, one new binary, one
behavior-preserving refactor of extract_date_from_filename (same
Option<FilenameDate> values for every input — the 12+ existing call
sites are untouched). No schema change, no migration, no write to any
table, no change to the server's runtime paths. Reverting restores the
prior state exactly. The only behavior surface is a new
cargo run --bin filename_audit that only SELECTs.

Closes #117. ## Summary Pre-cutover audit utility for the filename date class: a one-shot, operator-run, strictly read-only binary that lists every filename-class file across the libraries — its current stored date + source and the date / source / offset-source (plus the numeric offset) the re-based resolver would assign it. This is the human spot-check that gates the production backfill drain (#118): the operator reviews the report, fixes any misclassified file, and only then starts the drain. ## Changes - `src/filename_audit.rs` (new): `StoredDate` / `AuditRow` / `SkippedLibrary`; per-library walk (PathExcluder with the depth-0 guard from `file_scan`) → `match_filename_date` → one `resolve_dates_batch` pass with **empty priors**, exactly mirroring what the drain will call; `run_audit` honors the kill switch and the watcher's online probe (disabled → skipped, probe-stale → skipped, never partially processed); output stable-sorted by (library, path); `format_report` is deterministic with `*` marking rows whose stored legacy date would change. - `src/bin/filename_audit.rs` (new): operator entry point (dotenv, `DATABASE_URL`, `EXCLUDED_DIRS`, `libraries::load_all`, report). Zero writes. - `src/memories.rs`: `match_filename_date` canonical matcher returning `FilenameMatch { pattern, date }` so the audit can report *which* pattern matched; `extract_date_from_filename` is now a thin, byte-for-byte behavior-preserving wrapper (verified in review). - `src/lib.rs`: module registration. ## Evidence - New tests: `match_filename_date` pattern names + out-of-class None (2); audit module — inversion fixture (stored `exif`/2021 vs proposed `filename`/2014 wall with `assumed_server` offset -240m and `changed` flag), unix-timestamp `utc_direct` with `camera_offset` None, exclusion respect, unindexed handling, disabled + offline library skip, stable sort across out-of-order libraries, report determinism incl. no debug quotes and rendered offset values (4). - `cargo test`: 645 lib + 718 integration, 0 failures. `cargo fmt --check` + `cargo clippy --all-targets`: clean. - Two-axis review (parallel subagents): spec axis — all 6 acceptance criteria PASS + all 5 spec-mirroring invariants PASS (empty-priors drain mirroring, subprocess-free in-class path, effective-excludes union, had_data probe input, binary never writes); standards axis — ship-with-fixes, all 6 findings applied (report format spec, depth-0 guard, dead check, unused derive, column width, doc comment). ## Merge Danger **Two-way door.** Pure addition: one new module, one new binary, one behavior-preserving refactor of `extract_date_from_filename` (same `Option<FilenameDate>` values for every input — the 12+ existing call sites are untouched). No schema change, no migration, no write to any table, no change to the server's runtime paths. Reverting restores the prior state exactly. The only behavior surface is a new `cargo run --bin filename_audit` that only SELECTs.
cameron added 2 commits 2026-09-25 22:14:46 +00:00
One-shot, operator-run, strictly read-only utility that lists every
filename-class file with its stored date/source and the date/source/
offset-source the re-based resolver would assign it — the human
spot-check that gates the production backfill drain (#118).

- src/filename_audit.rs: StoredDate/AuditRow/SkippedLibrary; walk +
  PathExcluder (depth-0 guarded) + match_filename_date -> one
  resolve_dates_batch pass with EMPTY priors (mirrors the drain
  exactly); disabled and probe-stale libraries reported as skipped,
  never partially processed; output stable-sorted by (library, path).
- src/bin/filename_audit.rs: operator binary (dotenv, DATABASE_URL,
  EXCLUDED_DIRS, libraries::load_all, format_report).
- src/memories.rs: match_filename_date canonical matcher returning
  FilenameMatch { pattern, date }; extract_date_from_filename is now
  a thin wrapper (byte-for-byte behavior-preserving, verified by
  review).

4 audit tests (inversion + utc_direct + exclusions, offline/disabled
skip, stable sort, report determinism incl. no debug quotes) + 2
matcher tests. 645 lib + 718 integration pass; clippy/fmt clean.
Standards review applied: {:?}->{}, depth-0 walk guard, dead
per-file exclude check removed, unused Default derive removed,
pattern column widened, doc comment reworded.
The spec-mirroring review noted the report showed the offset SOURCE
but not the offset value — the value is what the operator spot-checks.
Each proposed line now ends with offset={+N}m (or - for utc_direct
rows). Tests pin the rendered values.
cameron merged commit ab16bc7da6 into master 2026-09-26 14:32:13 +00:00
cameron deleted branch feature/filename-audit 2026-09-26 14:32:14 +00:00
Sign in to join this conversation.