phase: 137_pdf_image_context
Build and Push Containers / build-and-push-app (push) Successful in 2m51s
Build and Push Containers / build-and-push-db (push) Successful in 13s

All verification complete — everything is 100% green. Final report:

**Phase 137 final verification pass — all tasks already complete, all criteria verified**

- **Full suite:** `uv run pytest --cov=app --cov-report=term-missing` → 3272 passed, exit 0; `app/` coverage **99%** (>90% ✓)
- **Phase E2E in isolation:** `uv run pytest tests/e2e/test_pdf_image_context.py -v --no-cov` → **4 passed** (forward context, display line, standalone parity, both-blocks markdown case)
- **Pre-existing suites in isolation:** `test_pdf_support.py` + `test_image_anchor_context.py` + `test_image_documents.py` → **14 passed**; ripple-edited `test_garbage_pdf.py` → **3 passed**
- **Lint/types:** `uv run ruff check .` → all passed; `uv run pyright` → 0 errors

**Completion criteria:** (1) forward-path context in vision msg + stored `image_context`/summary — ✓ (unit builder/seam + integration fake-LLM + E2E); (2) both blocks document-first + standalone describe byte-identical — ✓ (combiner + standalone pins); (3) backfill with context + zero-vision idempotent re-sync + parent-gone origin-only — ✓ (6 integration tests); (4) suggestion block leads with `From <source>/<pdf> (page N)` — ✓ (renderer units + E2E); (5) all gates green — ✓ above; (6) no behavior change in phases 122/125/126 + sync `detail` shape untouched — ✓ (verified in code: new counter is log-only); (7) ruff+pyright — ✓; (8) commit — left to the harness per pipeline rules (working tree untouched by me).

**Documentation:** README.md audited in full — the new phase-137 bullet verified against code (6 000-char cap, log-only `image_context_backfilled=N`, `<document>`-body locator placement), all env tables/defaults cross-checked vs `app/config.py` and `.env.example` — consistent, no changes needed. AGENTS.md: every rule/command verified — consistent, no changes needed.

**Notable deviations (pre-existing, documented in task-05 report, forced by design):** `test_pdf_support.py`/`test_garbage_pdf.py` got minimal ripple edits (the "UNEDITED" pin was unsatisfiable once describe calls carry context by design); the unit `test_image_anchor_context.py` CONTEXT_PREFIX pin generalized per ASSUMPTION A5; one extra mock line (`_seed_context_line` accepts `From …`).

**Next pending phase:** none — `todo/` holds only this phase.
This commit is contained in:
2026-09-29 02:14:46 -04:00
parent 0035bdf533
commit 5e87622b30
39 changed files with 3565 additions and 167 deletions
+24
View File
@@ -590,6 +590,30 @@ uploaded archives):
with the toggle off the pass is skipped and the PDF text indexes
normally. Embedded images in a format outside `BOR_IMAGE_EXTENSIONS`
are skipped with a warning.
- **Document context (phase 137).** Every embedded image is described
*with* the document it came from: the vision prompt — and the stored
`image_context` + enriched content — carry an
`Extracted from <source>/<pdf> (page N):` origin line (always
present, even for a text-less page) plus the page's own text
(capped at 6 000 chars; dropped when the phase-133 gate flags the
text layer as garbage — origin line only). Markdown `![alt](path)`
references to the image's synthetic path ride along after it
(phase 125, document block first), so the description names the
document and the page the image illustrates. Image docs a
pre-phase-137 sync left without the block (`image_context` NULL or
markdown-only) are **backfilled on the next sync** — re-described
once with the context (the parent's page text is re-read from the
source while the PDF is still there; parent gone → origin line
only), idempotent (the following sync burns zero vision calls for
them), fail-soft (a failure leaves the row untouched and retries
next sync), counted log-only on the import summary line
(`image_context_backfilled=N`). The stored context is also VISIBLE
in the chat suggestion block: an image doc's `<document>` body leads
with a one-line locator — `From <source>/<pdf> (page N)` for a
PDF-embedded image (with `; Referenced in …` appended when markdown
reference blocks are stored too — document block first),
`Referenced in <source>/<path>: "alt"` for a markdown-referenced
image (phase 125) — the page-text body is never rendered.
- **Garbage text layer → page-screenshot fallback (phase 133).** Before
indexing, the extracted text passes a deterministic garbage gate
(empty text layer, or ≥ 30% tag-looking lines, or ≥ 5% non-printable