phase: 125_image_anchor_context
All completion criteria verified. The repository is left functional with all changes in the working tree (no commits made, per the harness protocol). ## Final report — phase 125 `image_anchor_context` (verification pass) All 6 tasks were already complete; this pass verified every criterion and ran the full gates: - **Migration 0023** `documents.image_context` (TEXT nullable, reversible) — applied (`alembic current` = 0023 head); round-trip test (4 passed) exercises real upgrade → downgrade 0022 → upgrade. - **Criterion 1** (referenced image enriched + context line in retrieval): integration `test_markdown_referenced_image_gets_context_and_enriched_chunks` + E2E `test_sync_enriches_the_image_doc_with_markdown_context`, `test_chat_answer_quotes_the_context_line` (wire prompt pinned: `<document>` block leads with the one-line `Referenced in …: "alt"` line) — verified present and passing. - **Criterion 2** (standalone image byte-identical): E2E `test_standalone_*` (NULL `image_context`, block body exactly the bare description, no `Referenced in` anywhere in the prompt) + unit `test_describe_image_without_context_is_byte_identical` — passing. - **Criterion 3** (markdown-first: record stored on markdown doc, image picks up context later): integration `test_markdown_indexed_before_image_stores_record_and_image_picks_it_up` + post-index enrichment pass test (markdown file gone from disk) — passing. - **Gates:** `uv run pytest` → 2938 passed, exit 0 · `uv run pytest --cov=app --cov-report=term-missing` → exit 0, TOTAL **99%** (>90%) · `uv run ruff check .` → All checks passed · `uv run pyright` → 0 errors, 0 warnings. - **Phase E2E in isolation:** `uv run pytest tests/e2e/test_image_anchor_context.py -v --no-cov` → 4 passed. - **Mock-LLM change regression check:** neighboring image E2E suites green in isolation — `test_smoke` (3), `test_image_documents` (16), `test_chat_image_questions` (17), `test_answer_images` (17). - No defects found; no code changes needed. No live-infrastructure changes (local dev DB only). No commit made (harness commits). - Next pending phase: check `.agents/phases/todo/` after the harness moves this phase.
This commit is contained in:
@@ -2790,3 +2790,102 @@ def test_zero_read_text_only_turn_still_chips_nothing(
|
||||
assert done["sources"] == [] # phase-119 read-docs-only rule intact
|
||||
for ref in done["sources"] + done["related"]:
|
||||
assert "image_url" not in ref
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 125, task 05 — retrieval display: the suggested tier's ENRICHED
|
||||
# image doc (non-NULL image_context, the task-03/04 block shape) leads
|
||||
# its <document> block with the one-line context line (the referring
|
||||
# markdown's identity + the reference's alt) before the description;
|
||||
# the non-enriched image doc (NULL image_context) stays byte-identical
|
||||
# to pre-phase (LOCKED A4).
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_grounded_turn_suggested_enriched_image_doc_carries_context_line(
|
||||
client, db, seeded_kb: FakeRagLLM
|
||||
) -> None:
|
||||
"""LOCKED A4 end-to-end: a grounded turn whose suggested tier
|
||||
contains an enriched image doc (the task-03/04 ``Referenced in``
|
||||
block stored on ``image_context``) → the system prompt's
|
||||
``<document>`` block for that doc leads with the short context
|
||||
line, a blank line, then the description — and the ``Context:``
|
||||
paragraphs of the stored block never reach the prompt (the line is
|
||||
the locator + purpose, not a duplicate of the paragraphs)."""
|
||||
doc = _seed_image_doc_with_chunk(db)
|
||||
doc.image_context = (
|
||||
"Referenced in docs/homelab/kubernetes.md:\n"
|
||||
'- Alt text: "Cluster layout"\n'
|
||||
" Context: The diagram shows the three Talos nodes.\n"
|
||||
"It is referenced again from the runbook."
|
||||
)
|
||||
db.commit()
|
||||
scripted = FakeRagLLM() # zero-read grounded turn (the image seed block IS its content)
|
||||
fastapi_app.dependency_overrides[chat_api.get_llm] = lambda: scripted
|
||||
try:
|
||||
_, _, frames = _stream_chat(client, QUESTION)
|
||||
finally:
|
||||
fastapi_app.dependency_overrides.clear()
|
||||
|
||||
assert frames[-1]["deflected"] is False
|
||||
system = scripted.seen_messages[0][0]["content"]
|
||||
# The doc is in the suggested tier (retrieval is unchanged by the
|
||||
# phase — the line rides on a doc the retrieval already picked).
|
||||
block_start = system.index(f'<document source="docs" path="{doc.path}"')
|
||||
block = system[
|
||||
block_start : system.index("</document>", block_start) + len("</document>")
|
||||
]
|
||||
line = 'Referenced in docs/homelab/kubernetes.md: "Cluster layout"'
|
||||
# The exact block shape: identity attrs (phase 106 date), the line,
|
||||
# a blank line, the description (the phase-122 content == summary
|
||||
# == vision description invariant).
|
||||
assert block == (
|
||||
f'<document source="docs" path="pic.png" title="pic" '
|
||||
f'date="{_FIXTURE_CREATED_AT:%Y-%m-%d}">\n'
|
||||
f"{line}\n"
|
||||
"\n"
|
||||
f"{doc.summary}\n"
|
||||
"</document>"
|
||||
)
|
||||
# The line is the FIRST thing in the block body (before the
|
||||
# description), inside <documents>.
|
||||
assert system.index("<documents>") < system.index(line)
|
||||
assert system.index(line) < system.index(doc.summary or "")
|
||||
# The Context: body stays out of the whole prompt.
|
||||
assert "The diagram shows the three Talos nodes." not in system
|
||||
assert "referenced again from the runbook" not in system
|
||||
assert "Context:" not in system
|
||||
|
||||
|
||||
def test_grounded_turn_suggested_plain_image_doc_block_is_byte_identical(
|
||||
client, db, seeded_kb: FakeRagLLM
|
||||
) -> None:
|
||||
"""LOCKED A4 (the byte-identity criterion) end-to-end: the SAME
|
||||
flow with ``image_context`` left NULL (the standalone / pre-phase
|
||||
image doc — the phase's default) → the ``<document>`` block is
|
||||
EXACTLY the pre-phase block (the summary alone, no context line,
|
||||
no stray blank) and the marker string does not appear anywhere in
|
||||
the system prompt."""
|
||||
doc = _seed_image_doc_with_chunk(db)
|
||||
assert doc.image_context is None # the seed leaves it NULL (standalone)
|
||||
scripted = FakeRagLLM()
|
||||
fastapi_app.dependency_overrides[chat_api.get_llm] = lambda: scripted
|
||||
try:
|
||||
_, _, frames = _stream_chat(client, QUESTION)
|
||||
finally:
|
||||
fastapi_app.dependency_overrides.clear()
|
||||
|
||||
assert frames[-1]["deflected"] is False
|
||||
system = scripted.seen_messages[0][0]["content"]
|
||||
block_start = system.index(f'<document source="docs" path="{doc.path}"')
|
||||
block = system[
|
||||
block_start : system.index("</document>", block_start) + len("</document>")
|
||||
]
|
||||
# The pre-phase block: identity attrs + the description, verbatim.
|
||||
assert block == (
|
||||
f'<document source="docs" path="pic.png" title="pic" '
|
||||
f'date="{_FIXTURE_CREATED_AT:%Y-%m-%d}">\n'
|
||||
f"{doc.summary}\n"
|
||||
"</document>"
|
||||
)
|
||||
assert "Referenced in" not in system
|
||||
|
||||
Reference in New Issue
Block a user