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 -7
View File
@@ -59,7 +59,7 @@ from app.db import SessionLocal
from app.models import Document
from e2e.auth_helpers import login
from e2e.conftest import ADMIN_PASSWORD, SESSION_SECRET, USE_REAL_LLM, _wait_http
from e2e.mock_llm import IMAGE_DESCRIPTION_ANSWER
from e2e.mock_llm import IMAGE_DESCRIPTION_CONTEXT_ANSWER
REPO = Path(__file__).resolve().parents[2]
SOURCE_NAME = "e2e-pdf" # the archive stem (archive_source_name)
@@ -360,16 +360,33 @@ def seeded(
)
assert img is not None, "the embedded image must become an image doc"
assert img.is_image is True and img.image_path is not None
# content == summary == the mock's description (LOCKED A3
# fail-soft shape; no markdown reference exists — the bare
# prompt's answer).
assert img.content == IMAGE_DESCRIPTION_ANSWER
assert img.summary == IMAGE_DESCRIPTION_ANSWER
# Phase 137 (task 02): the document context — the
# provenance's origin line + page 2's text (no markdown
# reference exists — no ``Referenced in`` block) — is
# stored on ``image_context`` and enriches content (context
# first, then the mock's description); summary === content
# (the image convention — the viewer's Summary-panel
# suppression still applies). Task 05: the describe call
# carries the ``Extracted from `` context, so the mock's
# vision reply is the CONTEXT-AWARE canned description
# (it names the document + page — the deterministic
# witness the context reached the model), not the bare
# pre-137 one.
assert img.image_context == (
f"Extracted from {SOURCE_NAME}/{DOC_PATH} (page 2):\n{PAGE_TWO}"
)
assert img.content == (
f"{img.image_context}\n\n{IMAGE_DESCRIPTION_CONTEXT_ANSWER}"
)
assert img.summary == img.content
finally:
page.close()
yield {
"image_url": f"/api/documents/{img.id}/image",
"description": IMAGE_DESCRIPTION_ANSWER,
# The doc's stored text (the document context + the mock's
# description) — every render surface (the thumbnail alt, the
# viewer's content slot, the figure's caption) settles to it.
"description": img.content,
}