This file was generated by the /doc-truth-up documentation-reconciliation pass. It treats the
code as read-only ground truth and edits only documentation (README.md, CLAUDE.md,
DOC-RECONCILIATION.md) so they reflect the repo's actual current state. No code was changed and
no builds or tests were run. It exists so the operator can audit every finding in one place.
A prior reconciliation pass ran on 2026-05-30 (HEAD db25f8b). That pass corrected README feature
overclaims and CLAUDE.md stack version numbers. Those fixes are in the tree; this pass picks up
remaining drift at HEAD 0430ce7.
Status: consistent
Evidence: verified-by-reading-code
README.md and CLAUDE.md accurately describe Afterimage: a free iPhone-only iOS app that matches a
user photo to a geolocated historical photograph using a bundled SQLite index, with a draggable
slider as the core UX. Verified against Afterimage/App/AfterimageApp.swift (navigation state
machine), Afterimage/Features/Comparison/SliderOverlayView.swift (drag gesture + overlay),
Afterimage/Data/Database/DatabaseManager.swift (read-only DatabasePool).
One feature was missing from README.md — city browse mode — which is fully implemented in
Afterimage/Features/Gallery/CitySelectorView.swift and wired into the navigation state machine
in Afterimage/App/AppState.swift:84–91. Fixed in claim 2 below.
Status: drifted → fixed
Evidence: verified-by-reading-code
Both occurrences of the "Current phase" label in CLAUDE.md read Phase 1: Core App — Camera →
Match → Slider. Reading the source tree shows Phases 0, 1, and 2 are entirely complete:
| Phase | Status | Evidence |
|---|---|---|
| Phase 0 — Data Pipeline | complete | DataPipeline/ingest_oldnyc.py, ingest_wikimedia.py, ingest_flickr.py (contingency), build_index.py, audit_coverage.py, config.py all present; DataPipeline/output/photos.db and staging CSVs exist |
| Phase 1 — Core App | complete | All named source files present and fully implemented: CameraView, CameraViewModel, CameraCoordinator, LocationService, SpatialQuery, HeadingFilter, ThumbnailFetcher, VisionRanker, MatchingService, SliderOverlayView, ComparisonView; unit tests for all five core components |
| Phase 2 — Gallery + Expanded Cities | complete | GalleryPickerView.swift, LocationPickerView.swift (GPS-less location picker), CitySelectorView.swift (city browse mode), and all 6 city centers hardcoded in AppState.swift:28–35 |
| Phase 3 — Confidence UI + Polish | not started | ConfidenceLabel enum exists in the model (HistoricalPhoto.swift:66–70) and is computed in VisionRanker.swift, but no badge overlay in SliderOverlayView.swift or ComparisonView.swift; no multi-match thumbnail strip; no onboarding modal anywhere in the source tree |
| Phase 4 — Share Sheet | not started | No ShareCompositor.swift or ShareSheetView.swift present; no share button in ComparisonView.swift |
Changes made to CLAUDE.md (two occurrences):
## Build / Test / Runsection:Current phase: **Phase 1: Core App — Camera → Match → Slider**→Current phase: **Phase 3: Confidence UI + Polish** (Phases 0–2 complete)## Current Stateblock (portfolio-context region): same string, same fix.
Change made to README.md:
Added missing bullet to Features list:
- **City browse mode** — explore historical photos for any of 6 covered US cities (NYC, SF, Chicago, DC, New Orleans, Boston) without taking a photo
Status: consistent
Evidence: verified-by-reading-code
Afterimage.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved pins:
- GRDB.swift → 7.10.0 — README says "GRDB.swift 7.x", CLAUDE.md says "GRDB.swift 7.x" ✓
- Kingfisher → 8.8.0 — README says "Kingfisher 8.x", CLAUDE.md says "Kingfisher 8.x" ✓
(These version numbers were corrected by the 2026-05-30 pass and remain accurate.)
Status: consistent
Evidence: verified-by-reading-code
README Quick Start documents git clone … && open Afterimage.xcodeproj. The Xcode project
directory is confirmed present (Afterimage.xcodeproj/project.xcworkspace/…/Package.resolved
exists). No Makefile, CI script, or other build surface exists — Xcode-only is correct for this
project type. Prerequisites (Xcode 16+, iOS 17, physical iPhone) are unverifiable from source
alone but are not contradicted by any file.
Status: consistent (where verifiable)
Evidence: verified-by-reading-code
CLAUDE.md's risk list (read-only photos.db, no off-device data, deferred permission requests,
grayscale Vision pre-processing, no Combine, Phase 0 scope gate) all match code constraints:
- Read-only database:
DatabaseManager.swiftopens aDatabasePoolwithreadonly = true - Deferred permissions: camera/location requests live in
CameraViewandAppState.onPhotoCaptured, not inAfterimageApp.init() - Grayscale requirement: enforced in
VisionRanker.swift
Performance claims ("< 5s matching", "≥ 25% grid coverage") and physical-device behaviour are
unverifiable-because-requires-device-or-data — left unchanged.
Status: drifted → addressed by phase-label fix above
Evidence: verified-by-reading-code
The corrected phase label in claim 2 is the "next move" signal. Concretely absent from the source tree (Phase 3 and 4 work):
Afterimage/Features/Comparison/SideBySideView.swift— not presentAfterimage/Features/Comparison/FadeView.swift— not presentAfterimage/Features/Share/ShareCompositor.swift— not presentAfterimage/Features/Share/ShareSheetView.swift— not present- Confidence badge overlay in
SliderOverlayView/ComparisonView— not present - Multi-match thumbnail strip — not present
- First-launch onboarding modal — not present
These drifts are in files outside the editable set (IMPLEMENTATION-ROADMAP.md,
APPSTORE-METADATA.md). A human should apply the fixes.
| Location | What is wrong | One-line fix |
|---|---|---|
| Line ~234 — GRDB dependency | Shows from: "6.0.0" |
Change to from: "7.0.0" — Package.resolved pins 7.10.0 |
| Line ~238 — Kingfisher dependency | Shows from: "7.0.0" |
Change to from: "8.0.0" — Package.resolved pins 8.8.0 |
| Line ~63 — file structure | Source dir shown as afterimage/ (lowercase) |
Change to Afterimage/ — actual Xcode target directory is PascalCase |
| Lines ~105–109 — file structure | Lists ingest_loc.py and ingest_nypl.py as DataPipeline scripts |
Remove both — neither file exists on disk; both sources were dropped (noted in the API Contracts section of the same document) |
| Line ~242 — pip install command | Says pip install aiohttp requests Pillow tqdm geojson |
Remove Pillow and geojson — DataPipeline/requirements.txt contains only aiohttp, requests, tqdm |
| Lines ~173–180 — Swift type definitions | thumbnailURL: URL and fullResURL: URL? |
Change both to String and String? — Afterimage/Data/Models/HistoricalPhoto.swift:32–33 uses String |
| Lines ~172 — Swift type definitions | HistoricalPhoto struct is missing city: String? |
Add let city: String? between lon and heading — present in HistoricalPhoto.swift:30 and in DataPipeline/config.py:52 staging columns |
| Location | What is wrong | One-line fix |
|---|---|---|
| Lines ~116–120 — App Review Notes | "Tap 'Gallery' and browse the bundled historical photos" / "Tap any photo to see its metadata and navigate to its location" — describes the Gallery button as opening a historical photo browser | Rewrite: Gallery opens the user's camera roll via PHPickerViewController; selecting a GPS-tagged photo triggers matching immediately; selecting a GPS-less photo shows a map pin picker |
| Line ~68 — Support URL | https://github.com/d/Afterimage is a placeholder |
Update to the real repo URL (https://github.com/saagpatel/Afterimage per README.md) |
Generated: 2026-06-02 19:29:42 PDT Branch: docs/truth-up-2026-06-02 HEAD reconciled against: 0430ce753d8ed96029dd527ac961a8ac6a983b5b