phase: 137_pdf_image_context
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:
@@ -41,10 +41,15 @@ do).
|
||||
|
||||
MOCK-ONLY suite: ``E2E_REAL_LLM=1`` is not supported — the fallback's
|
||||
vision surface is the mock's deterministic ``IMAGE_DESCRIPTION_MODE``
|
||||
canned reply (``IMAGE_DESCRIPTION_ANSWER``, the same reply the
|
||||
phase-122 image docs get), which makes the fallback's stored content a
|
||||
PURE FUNCTION of the fixture — the byte-exact content assertions below
|
||||
are exact only against that canned text.
|
||||
canned reply: the BARE ``IMAGE_DESCRIPTION_ANSWER`` for the page
|
||||
screenshots (the fallback's describe calls carry no context —
|
||||
byte-identical to pre-phase-137) and the CONTEXT-AWARE
|
||||
``IMAGE_DESCRIPTION_CONTEXT_ANSWER`` for the fallback PDF's EMBEDDED
|
||||
images (phase 137 task 05 — their describe calls carry the
|
||||
``Extracted from `` provenance block, so the mock's trigger fires),
|
||||
which makes the fallback's stored content a PURE FUNCTION of the
|
||||
fixture — the byte-exact content assertions below are exact only
|
||||
against those canned texts.
|
||||
|
||||
Fixture provenance:
|
||||
* ``hnb/`` — the REAL guide: ``test_sources/hnb_2026_guide.tar.gz``
|
||||
@@ -120,7 +125,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_ANSWER, IMAGE_DESCRIPTION_CONTEXT_ANSWER
|
||||
|
||||
REPO = Path(__file__).resolve().parents[2]
|
||||
|
||||
@@ -643,15 +648,26 @@ def test_garbage_pdf_takes_the_screenshot_path(
|
||||
assert "<illustrator" not in content
|
||||
|
||||
# The fallback's embedded-image leg: both extracted images (one per
|
||||
# page, the 1×1 PNG — ``#page=N#img=0`` paths) indexed with the
|
||||
# canned description (the phase-122 image convention).
|
||||
# page, the 1×1 PNG — ``#page=N#img=0`` paths) indexed — and phase
|
||||
# 137 (task 02, A7) gives each the ORIGIN-LINE-ONLY document
|
||||
# context: the garbage text layer failed the gate, so the "page
|
||||
# text" is dropped (the soup never reaches the embedder), while the
|
||||
# provenance line still names the document and the page.
|
||||
imgs = _image_docs(GARBAGE_SOURCE)
|
||||
assert [i.path for i in imgs] == [
|
||||
f"{GARBAGE_PDF}#page=1#img=0.png",
|
||||
f"{GARBAGE_PDF}#page=2#img=0.png",
|
||||
]
|
||||
for img in imgs:
|
||||
assert img.content == IMAGE_DESCRIPTION_ANSWER
|
||||
page = int(img.path.split("#page=")[1].split("#")[0])
|
||||
origin = f"Extracted from {GARBAGE_SOURCE}/{GARBAGE_PDF} (page {page}):"
|
||||
assert img.image_context == origin
|
||||
# Phase 137 task 05: the origin-line context still names the
|
||||
# document (the mock's ``Extracted from `` trigger fires on the
|
||||
# header alone — the page text was dropped by the gate), so the
|
||||
# canned reply is the CONTEXT-AWARE one, not the bare pre-137
|
||||
# answer.
|
||||
assert img.content == f"{origin}\n\n{IMAGE_DESCRIPTION_CONTEXT_ANSWER}"
|
||||
assert img.summary == img.content # the image convention
|
||||
|
||||
# The sync's ``detail`` is the UNCHANGED shape: the garbage PDF is
|
||||
|
||||
Reference in New Issue
Block a user