Files
photoanalyzer/README.md

139 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Photo Analyzer
Integrated, restart-safe photo analysis, duplicate review, metadata, upload, and
archive workflow. Planning lives in `INTEGRATED_PIPELINE_CONCEPT.md` and
`delivery_backlog/`.
## Application (`photo_pipeline`)
The target application lives in `photo_pipeline/` (FastAPI + SQLAlchemy + Alembic).
Run it with:
```bash
python -m photo_pipeline migrate # apply database migrations
python -m photo_pipeline serve # start the API + static review UI (127.0.0.1:8000)
```
Configuration comes from `PHOTO_PIPELINE_*` environment variables (see
`photo_pipeline/config.py`); secrets are referenced, never logged.
## Testing
One offline command runs the whole suite (unit, integration, and browser
end-to-end); it needs no network and uses only deterministic synthetic fixtures:
```bash
work_item/scripts/python -m pytest tests -q
```
Browser end-to-end tests require a one-time Playwright browser install:
```bash
python -m playwright install chromium
```
### Phase A acceptance gate
Phase A (Epic E01: shared identity, inventory, duplicates, thumbnails, review UI) is
gated by a reproducible end-to-end suite:
```bash
work_item/scripts/python -m pytest tests/e2e tests/integration -q
```
- `tests/e2e/test_phase_a_pipeline.py` launches the real API process against a fresh
database and a deterministic fixture library, then drives scan, `_IGNORE/`
exclusion, move reconciliation, exact/fuzzy duplicate review, thumbnail
orientation, canonical selection, browser reload, and a full process restart —
asserting durable API and database state after the restart.
- `tests/story_traceability.json` maps every delivered story to its tests;
`tests/e2e/test_traceability.py` fails if a Phase A story loses coverage or a test
file is left unexercised.
### Phase B acceptance gate
Phase B (Epic E02: durable jobs, workflow shell, safety/analysis views) is proven
through the real process and browser boundaries. One command runs the Phase B API,
worker-recovery, and browser (Playwright) suites:
```bash
work_item/scripts/python -m pytest tests/e2e -m phase_b -q
```
- `tests/e2e/test_phase_b_pipeline.py` launches the real server and durable worker as
child processes and drives them only over HTTP/SSE: analysis start/progress,
resumable SSE reconnect, the polling fallback, cancellation, per-asset error
inspection, one-mutating-job rejection during read-only browsing, the NSFW→vision
privacy gate, and durability across a full restart.
- `tests/e2e/test_worker_kill.py` kills a worker mid-item and proves a fresh worker
resumes the fenced job (the "resume" journey).
- `tests/e2e/test_analysis_browser.py` starts a job from the Analyze view and watches
live progress arrive over the browser's real SSE adapter.
The full Phase B regression, including the unchanged Phase A gate, is the whole
end-to-end suite:
```bash
work_item/scripts/python -m pytest tests/e2e -q
```
### Phase C acceptance gate
Phase C (Epic E03: album evidence, naming policy, versioned proposals, Albums view)
is proven through the real process and browser boundaries. One command runs the
Phase C API and browser (Playwright) suites with the deterministic naming provider:
```bash
work_item/scripts/python -m pytest tests/e2e -m phase_c -q
```
- `tests/e2e/test_phase_c_pipeline.py` drives a real server over HTTP: evidence
aggregation, generation through the deterministic naming fake (asserting the exact
provider inputs and that no file path or asset ID ever reaches it), provider
failure and retry, invalid names, path-separator sanitization, editing with
optimistic versions, stale-evidence approval refusal, valid approval, and
durability across a full restart.
- `tests/e2e/test_albums_ui.py` covers the browser journeys: evidence display,
editing, prompt validation, collision guidance, approval, stale conflict, and
keyboard operation.
- Both suites assert that **no fixture path changes** — Phase C proposes names and
never renames.
The deterministic naming provider is enabled only by test configuration
(`PHOTO_PIPELINE_FAKE_NAMING_LOG`); without it the application falls back to the
offline naming-policy name. Phase A and B suites remain green in the full run above.
### Phase D acceptance gate
Phase D (Epic E04: guarded renaming) is the first phase that changes the library on
disk, so its gate is the strictest. One command runs the rename API journeys, the
filesystem fault injection, and the browser suite:
```bash
work_item/scripts/python -m pytest tests/e2e -m phase_d -q
```
- `tests/e2e/test_phase_d_pipeline.py` drives a real server over HTTP: plan and
export, confirmation with the plan version and checksum (a stale token is refused
without touching disk), a valid apply, the case-only rename procedure, a collision
whose occupant survives, a source that changed after planning, and durability
across a full restart.
- **Fault injection is real.** `PHOTO_PIPELINE_FAULT_AFTER=<journal state>` kills the
server process the instant that state is persisted. The suite crashes it at every
journal transition in turn (`moving`, `moved`, `database_updated`, `verified`),
starts a fresh process against the same database and library, and requires recovery
to converge from journal and disk evidence alone — with the asset set, the stable
IDs, and every content hash unchanged. Ambiguous evidence is never guessed: it stays
classified `manual` and keeps blocking. An unresolved rename is the cancellation
boundary — there is no cancel once a run starts, and unrelated mutations (album
proposal generation and approval) are refused with 409 `rename_recovery_required`
until it is resolved, while reads stay available.
- `tests/e2e/test_renames_ui.py` covers the browser journeys: preview of every
affected path, confirmation carrying the server-issued token, apply with progress
and terminal verification, stale confirmation, collision, interruption, recovery,
rollback, keyboard confirmation, and the view still matching the journal after a
server restart.
The fault barrier is test-only configuration; without `PHOTO_PIPELINE_FAULT_AFTER`
the apply path has no crash points. Phases AC remain green in the full run above.