Dates: filename date class — per-pattern conventions + filename-over-EXIF priority #116

Closed
opened 2026-09-24 22:54:02 +00:00 by cameron · 1 comment
Owner

Parent

ImageApi #113 — SPEC: true-instant date contract (ADR-0001).

What to build

The filename date class becomes first-class: every existing filename pattern is explicitly tagged with its convention, and files whose name carries the original date resolve their date from the filename — outranking EXIF — while files outside the class keep the global EXIF-wins rule unchanged. Wall-clock patterns (screenshot, dash, compact) go through the offset cascade like any other wall clock; Unix-timestamp patterns are true instants directly (source audit utc_direct).

The existing pattern list is the baseline; no patterns are added or removed in this ticket (the audit ticket that follows will surface any gaps). The inversion is documented in the resolver as a deliberate, named exception to EXIF-wins — the filename is the original date of record for this class.

Acceptance criteria

  • Every filename pattern in the extractor carries an explicit convention: wall (goes through the offset cascade) or utc (instant directly); a pattern matching nothing falls through to the normal waterfall.
  • A Screenshot_2014-06-01-20-44-50.png-style file with an EXIF date that disagrees is stored with the filename's date, wall clock converted via the cascade, source recorded as the filename step with the resolved offset-source.
  • A Unix-timestamp-named file (e.g. att_1422489664680106.jpeg) is stored as the instant it names (with the existing millisecond/seconds disambiguation), source utc_direct, no offset applied.
  • A file whose name matches no pattern resolves exactly as before (EXIF-wins, unchanged behavior).
  • A file in the class with no zone evidence still resolves (server-zone assumption, recorded) — the class never fails to date a file it previously dated.
  • Tests at the waterfall seam: each convention class, the priority inversion (filename beats EXIF inside the class, EXIF wins outside), and the audit values emitted.

Blocked by

  • ImageApi #114 (foundation: schema + EXIF branch + display zone)
## Parent ImageApi #113 — SPEC: true-instant date contract (ADR-0001). ## What to build The filename date class becomes first-class: every existing filename pattern is explicitly tagged with its convention, and files whose name carries the original date resolve their date from the filename — outranking EXIF — while files outside the class keep the global EXIF-wins rule unchanged. Wall-clock patterns (screenshot, dash, compact) go through the offset cascade like any other wall clock; Unix-timestamp patterns are true instants directly (source audit `utc_direct`). The existing pattern list is the baseline; no patterns are added or removed in this ticket (the audit ticket that follows will surface any gaps). The inversion is documented in the resolver as a deliberate, named exception to EXIF-wins — the filename is the original date of record for this class. ## Acceptance criteria - [ ] Every filename pattern in the extractor carries an explicit convention: `wall` (goes through the offset cascade) or `utc` (instant directly); a pattern matching nothing falls through to the normal waterfall. - [ ] A `Screenshot_2014-06-01-20-44-50.png`-style file with an EXIF date that disagrees is stored with the filename's date, wall clock converted via the cascade, source recorded as the filename step with the resolved offset-source. - [ ] A Unix-timestamp-named file (e.g. `att_1422489664680106.jpeg`) is stored as the instant it names (with the existing millisecond/seconds disambiguation), source `utc_direct`, no offset applied. - [ ] A file whose name matches no pattern resolves exactly as before (EXIF-wins, unchanged behavior). - [ ] A file in the class with no zone evidence still resolves (server-zone assumption, recorded) — the class never fails to date a file it previously dated. - [ ] Tests at the waterfall seam: each convention class, the priority inversion (filename beats EXIF inside the class, EXIF wins outside), and the audit values emitted. ## Blocked by - ImageApi #114 (foundation: schema + EXIF branch + display zone)
cameron self-assigned this 2026-09-25 20:06:28 +00:00
cameron added a new dependency 2026-09-25 20:11:22 +00:00
Author
Owner

Resolved by PR #122 (feature/filename-date-class, commit a97bf53).

What landed

  • memories::extract_date_from_filename now returns FilenameDate: Wall(NaiveDateTime) for the screenshot/dash/compact patterns, Utc(DateTime) for the unix-timestamp patterns. No patterns added or removed — the baseline list is unchanged; each pattern carries an explicit convention.
  • Both waterfalls (resolve_date_taken, resolve_dates_batch) run a shared filename_class_resolved step FIRST: an in-class name is the original date of record and outranks EXIF / container dates; in-class files skip exiftool entirely. Wall patterns run the offset cascade over the kamadak prior's evidence (empty evidence -> assumed_server, so a class file always resolves); timestamp patterns are true instants (tz_source = utc_direct, no offset).
  • Legacy date_taken stays byte-identical: wall-as-UTC for wall patterns, epoch for timestamp patterns, via FilenameDate::legacy_datetime/legacy_timestamp at the seven consumer call sites.
  • Out-of-class files keep the global EXIF-wins waterfall unchanged.

Acceptance criteria — all covered by tests at the waterfall seam: filename_class_wall_without_evidence_assumes_server_zone, filename_class_wall_outranks_exif_and_uses_its_evidence (the inversion), filename_class_wall_gps_evidence_uses_capture_zone, filename_class_timestamp_is_utc_direct, in_class_video_name_resolves_without_exiftool; out-of-class EXIF-wins pinned by the existing prior-exif tests. 639 lib + 716 integration tests pass; fmt + clippy clean. Two-axis code review (standards + spec): spec clean, standards no violations.

CLAUDE.md's date-pipeline section rewritten to document the inversion as a named, deliberate exception (ADR-0001).

Resolved by PR #122 (feature/filename-date-class, commit a97bf53). **What landed** - memories::extract_date_from_filename now returns FilenameDate: Wall(NaiveDateTime) for the screenshot/dash/compact patterns, Utc(DateTime<Utc>) for the unix-timestamp patterns. No patterns added or removed — the baseline list is unchanged; each pattern carries an explicit convention. - Both waterfalls (resolve_date_taken, resolve_dates_batch) run a shared filename_class_resolved step FIRST: an in-class name is the original date of record and outranks EXIF / container dates; in-class files skip exiftool entirely. Wall patterns run the offset cascade over the kamadak prior's evidence (empty evidence -> assumed_server, so a class file always resolves); timestamp patterns are true instants (tz_source = utc_direct, no offset). - Legacy date_taken stays byte-identical: wall-as-UTC for wall patterns, epoch for timestamp patterns, via FilenameDate::legacy_datetime/legacy_timestamp at the seven consumer call sites. - Out-of-class files keep the global EXIF-wins waterfall unchanged. **Acceptance criteria** — all covered by tests at the waterfall seam: filename_class_wall_without_evidence_assumes_server_zone, filename_class_wall_outranks_exif_and_uses_its_evidence (the inversion), filename_class_wall_gps_evidence_uses_capture_zone, filename_class_timestamp_is_utc_direct, in_class_video_name_resolves_without_exiftool; out-of-class EXIF-wins pinned by the existing prior-exif tests. 639 lib + 716 integration tests pass; fmt + clippy clean. Two-axis code review (standards + spec): spec clean, standards no violations. CLAUDE.md's date-pipeline section rewritten to document the inversion as a named, deliberate exception (ADR-0001).
cameron added the wayfinder:task label 2026-09-30 00:47:16 +00:00
Sign in to join this conversation.