Skip to content

fix(kb): confirm retrievability with a filtered query, classify TEXT_INDEXED - #908

Open
DerrickF wants to merge 2 commits into
developfrom
fix/kb-filtered-retrievability-probe
Open

fix(kb): confirm retrievability with a filtered query, classify TEXT_INDEXED#908
DerrickF wants to merge 2 commits into
developfrom
fix/kb-filtered-retrievability-probe

Conversation

@DerrickF

@DerrickF DerrickF commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Two findings from running yesterday's fix (#901), plus handoff entries for both and for #901 itself.

The probe could not find its own document

wait_until_retrievable searched for the document id as the query text and checked whether that document came back in the top 5. A document id carries no meaning to an embedding model, so the search returned whatever the reranker preferred. Measured in dev with two documents present:

query=DOC-40e985680a63  ->  5 chunks, ALL from DOC-db44eaf8f072   FOUND ITSELF: False

A perfectly retrievable document, reported as not retrievable.

It scales the wrong way. The more documents a knowledge base holds, the less likely the target lands in an unfiltered top-5 — so every upload to a mature knowledge base would burn its full poll budget and dead-letter. That is worse than the bug #901 fixed. It only ever worked while the knowledge base held exactly one document, where anything returned was necessarily the right thing.

Now an equals filter on document_id: a non-empty result is proof, an empty one is a true negative. equals is already in ISOLATION_SAFE_FILTER_OPERATORS — a prefix operator would let DOC-1 confirm DOC-10. Verified against dev: each document returns 5 of its own chunks, a fabricated id returns none.

TEXT_INDEXED is not in the SDK's enum

The live service returned TEXT_INDEXED for a document with image extraction enabled — text searchable, media still processing — and the packaged model's DocumentStatus enum does not list it. So status handling must not be derived from that enum.

Treated as in-flight, not done: completing there would tell a user an image-only page is ready while the vision model is still running, which is the exact report this module exists to prevent. Unrecognised statuses now default to "keep waiting" as well, so the next value AWS adds does not dead-letter documents.

Also

Arriving to find a document already in flight used to raise immediately, relying on redelivery that Lambda caps at 2 attempts. Both entry paths — just submitted, and found mid-flight — now share one bounded wait.

Test-suite fix: an autouse fixture shortens the poll budgets. With the real 600 s budget this file took 20 minutes; it is now under 6 seconds. That is precisely why those constants are resolved at call time rather than bound as default arguments.

_FakeBackend now models a knowledge base holding other documents, and honours the filter. Without that, a probe that ignores its filter still passes — which is how the query-by-id probe survived until a second document existed.

Mutations

mutation result
probe searches unfiltered caught (12 tests, incl. all three named probe tests)
filter switched to startsWith caught
TEXT_INDEXED dropped from in-flight initially SURVIVED

The third is worth reading. Removing TEXT_INDEXED is behaviour-equivalent — the unknown-status fallback also waits, so the document is handled identically and every behavioural assertion still passed. The honest resolution was to assert the only thing that genuinely differs: that the status is classified, rather than falling through the unknown branch and logging a warning for a state we have already seen in production. Not every surviving mutant means a missing test; some mean the mutation changes nothing.

Handoff

Findings 37–39 recorded, plus two things worth carrying forward:

  • §5.30's wrong constant (0.75–1.03 s) had a second home nobody grepped for. When a wrong constant is found, look for its other copies.
  • A correction: yesterday's claim that a measured 0.9 s gap "confirmed" the 0.75–1.03 s figure was false. With the fabricated indexedAt it was measuring ingest-return → retrievable, not INDEXED → retrievable. A number agreeing with your expectation is not confirmation.

454 passed across lambdas/supply_chain/architecture; ruff clean.

…EXT_INDEXED

Two findings from running yesterday's fix, plus the handoff entries for both and
for #901.

The probe could not find its own document
-----------------------------------------
`wait_until_retrievable` searched for the document *id as the query text* and
checked whether that document came back in the top 5. A document id means nothing
to an embedding model, so the search returned whatever the reranker preferred.
Measured in dev with two documents present:

    query=DOC-40e985680a63 -> 5 chunks, ALL from DOC-db44eaf8f072   FOUND: False

A perfectly retrievable document reported as not retrievable. It scales the wrong
way: the more documents a knowledge base holds, the less likely the target lands in
an unfiltered top-5, so every upload to a mature knowledge base would burn its poll
budget and dead-letter — worse than the bug #901 fixed. It only ever worked while
the knowledge base held exactly one document, where anything returned was
necessarily the right thing.

Now an `equals` filter on `document_id`, so a non-empty result IS proof and an empty
one is a true negative. `equals` is already in ISOLATION_SAFE_FILTER_OPERATORS;
a prefix operator would let DOC-1 confirm DOC-10. Verified against dev: each
document returns 5 of its own chunks, a fabricated id returns none.

TEXT_INDEXED is not in the SDK's enum
-------------------------------------
The live service returned `TEXT_INDEXED` for a document with image extraction
enabled — text searchable, media still processing — and the packaged model's
`DocumentStatus` enum does not list it. So status handling must not be derived from
that enum. Treated as in-flight rather than done: completing at that point would
tell a user an image-only page is ready while the vision model is still running,
which is the report this module exists to prevent. Unrecognised statuses now
default to "keep waiting" too, so the next value AWS adds does not dead-letter
documents.

Also simplifies the flow: arriving to find a document already in flight used to
raise immediately, which relied on redelivery that Lambda caps at 2 attempts.
Both entry paths — just submitted, and found mid-flight — now share one bounded
wait.

Test-suite fix: an autouse fixture shortens the poll budgets. With the real 600 s
budget the file took 20 minutes; it is now under 6 seconds. This is exactly why
those constants are resolved at call time rather than bound as default arguments.

`_FakeBackend` now models a knowledge base holding OTHER documents, and honours the
filter. Without that, a probe ignoring its filter still passes — which is precisely
how the query-by-id probe survived until a second document existed.

Mutations verified caught: probe unfiltered, filter switched to a prefix operator,
and TEXT_INDEXED dropped from the in-flight set. The third initially SURVIVED,
because the unknown-status fallback also waits, making the mutation
behaviour-equivalent; resolved by asserting the only thing that genuinely differs —
that the status is classified rather than falling through the unknown branch. Not
every surviving mutant means a missing test.

Handoff: findings 37-39 recorded, including that §5.30's wrong constant had a
second home nobody grepped for, and a correction — yesterday's claim that a
measured 0.9 s gap "confirmed" the 0.75-1.03 s figure was false, since the
fabricated timestamp meant it measured ingest-return to retrievable instead.

454 passed across lambdas/supply_chain/architecture; ruff clean.
I guessed #902 when writing the handoff entries; the PR is actually #908.
#902 is an unrelated, already-merged PR, so those references pointed somewhere
misleading.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant