10% and 25% were both in the SLA matrix, but only one applied to an Acme Enterprise Plus Priority 1 outage.
The support agent asked:
What service credit applies to an Enterprise Plus Priority 1 outage?
The assistant answered 10%, cited sla-matrix.html, and linked to the right Confluence export. The number was not fabricated. It was the Priority 1 credit for the public Business plan. The Enterprise Plus row in the same table said 25%.
The retrieval trace was the first useful clue:
filter: {"visibility":{"$in":["public","internal"]}}
result[0] score=0.842 visibility=public text="Priority 1 | Business | 10% service credit | outage under 4h"
result[1] score=0.817 visibility=internal text="Priority 2 | Enterprise Plus | 10% service credit | outage under 8h"
filtered_candidates=37
There was no parsing failure in that trace. The model was simply never shown the answer. Chroma had the correct row, but it carried visibility=internal-enterprise, a label introduced when the Confluence space was split into public, internal, and account-scoped sections. The retriever default still allowed only public and internal, so the exact row was removed before similarity search and before reranking.
That ordering mattered. By the time rerank-english-v3.0 saw candidates, the best it could do was choose among near-misses: a public Priority 1 row with the right outage language, and an Enterprise Plus row for the wrong priority. The final answer combined the strongest visible match with the user’s plan name and sounded authoritative because the citation pointed to the real SLA export.
The fix was not to increase k or change the prompt. The ACL filter had to be treated as part of retrieval correctness. The tenant policy resolver now expands Acme’s profile to ["public", "internal", "internal-enterprise"], and the service logs both pre-filter and post-filter candidate counts. A regression query for Priority 1 Enterprise Plus service credit fails the build unless the 25% row appears in the top five retrieved chunks.