Soften the tone of the docs and comments written today

This commit is contained in:
2026-08-11 10:12:25 +07:00
parent 97cb6d16f4
commit 6b8f7584ed
18 changed files with 921 additions and 64 deletions
+75
View File
@@ -0,0 +1,75 @@
# Claude ownership claim — 2026-08-11
Read `CLAUDE_HANDOFF_2026-08-10.md` first. Two items in it have since moved
on (checked against the code and against live production on 2026-08-11):
1. The structured-claims refactor it describes as in progress is finished and
shipped (`dfdbf52`, then `9c3acd0`). `pytest -q --ignore=tests/test_api.py
--ignore=tests/test_live_datastores.py` = 219 passed at the start of this
session.
2. Entailment majority vote (2-of-3) is no longer in the code. `df55af4`
introduced it; `9c3acd0` replaced it with a single pass
(`_ENTAILMENT_MAX_ATTEMPTS = 1`), with the reasoning in
`_verify_entailment`'s docstring: repeating an identical temperature-0
prompt is a correlated retry rather than an independent vote.
## What this session is changing, and why
All five items come from driving production (`https://realvuxbaro.me`) by
hand plus direct `/api/chat` probes — measured, not inferred from docs.
- **`rag/answer.py`** — availability failures during the entailment pass are
currently recorded and shown as `unsupported_claim`, so a timing or outage
problem reaches the user as a content failure. The failure taxonomy in
`docs/current-rag-pipeline-audit.md` §4 keeps these separate. Reusing
the reason codes that already exist and are already mapped in
`apps/web/app/api/chat/route.ts` (`request_budget_exhausted`,
`provider_unavailable`, `malformed_output`) — **no new reason code**, so
the frontend mapping needs no change. Fail-closed behaviour is unchanged;
only the label changes.
- **`rag/answer.py`** — `_verify_entailment`'s `for _ in
range(_ENTAILMENT_MAX_ATTEMPTS)` loop always returns on its first
iteration, so raising that constant silently does nothing, and the
unreachable `return False` after it returns a `bool` where every caller
reads `.supported`. Making the single-pass intent explicit.
- **`rag/agent.py`** — the pediatric dosing gate asks "Bé bao nhiêu tuổi và
cân nặng bao nhiêu kg?" even when the user just gave one of the two.
Reproduced 5/5 live ("18 ký", "18 cân", explicit "18 kg", "Trẻ 5 tuổi").
**The gate itself is NOT being loosened** — both fields stay required,
which is clinically right here (the correct answer uses both an age band
and a mg/kg rule). Only the question text becomes specific to what is
actually missing.
- **`apps/web/app/_components/ChatPanel.tsx`** — a hard 25s client abort
against a backend whose own budget is 40s (`config.py:60`). Measured
n=8 sequential: 2/8 exceeded 25s, and one of those was a **correct**
`answerable`/grounded/2-citation reply at 25.1s that the user never saw.
Caddy (`reverse_proxy web:3000`, no timeout) and the BFF (`signal:
request.signal`, no own timeout) do not cap this, so the client constant
is the only binding limit.
- **`packages/ui/src/ChatBubble.tsx`** — chips dedupe by `chunkId` but the
label is only drug+section+page, so several distinct chunks render as
identical-looking chips. **Not** collapsing them by label: the click
handler maps to a specific citation index, so collapsing would make real
evidence blocks unreachable from the prose, and provenance is a hard
guardrail.
## Files claimed
`apps/ai-service/rag/answer.py`, `apps/ai-service/rag/agent.py`,
`apps/ai-service/tests/test_grounded_generation.py`,
`apps/ai-service/tests/test_agent.py`,
`apps/web/app/_components/ChatPanel.tsx`,
`packages/ui/src/ChatBubble.tsx`, and this file.
Not touching `ingestion/`, retrieval adapters, `rag/service.py`,
`rag/understanding.py`, or anything sparse/BM25 related — task #4 (real
BM25 via Qdrant native sparse vectors) is still **not started**.
## Test-coverage context for review
These areas start with little automated cover: no tests currently touch
`missing_pediatric_age_or_weight` / `missing_population`, and the repo has no
frontend test setup (no `test` script in `apps/web/package.json`, no
ChatPanel/ChatBubble tests). A passing `pytest` run therefore is not on its
own sufficient evidence here. Backend tests are being added alongside the
changes, and the two frontend changes are verified by driving the real site.
+17
View File
@@ -1,5 +1,22 @@
# Claude handoff — 2026-08-10, in case of context/token cutoff
> **Update 2026-08-11 — two items below have moved on since this was
> written.** Checked against the code and against live production.
>
> 1. The structured-claims refactor described below as in progress shipped
> the same day (`dfdbf52`, then `9c3acd0`); the conversion is complete and
> the suite is at 230 passing.
> 2. Entailment majority vote (2-of-3) is no longer in the code. `df55af4`
> introduced it and `9c3acd0` replaced it with a single pass
> (`_ENTAILMENT_MAX_ATTEMPTS = 1`); `_verify_entailment`'s docstring gives
> the reasoning — repeating an identical temperature-0 prompt is a
> correlated retry rather than an independent vote.
>
> Task #4 (real BM25 via Qdrant native sparse vectors) further down is still
> accurate and still not started. For current state see
> `coordination/CLAUDE_CLAIM_2026-08-11.md` and the 2026-08-11 entry in
> `docs/progress-log.md`.
Read this before touching `apps/ai-service/rag/answer.py`, `rag/prompt.py`,
`adapters/bedrock_claude.py`, or any test file under `apps/ai-service/tests/`
that references the answer-generation schema. A structured-claims refactor
+21
View File
@@ -105,7 +105,28 @@ self-hosted embedding/vLLM plan (assumption GĐ-3 in
## Active ownership
- Claude: **2026-08-11** — see `CLAUDE_CLAIM_2026-08-11.md` for the full
claim and reasoning. Five production bugs found by driving
`https://realvuxbaro.me` (not by reading docs), fixed, deployed and
re-verified over 37 live cases: the 25s client abort that was discarding
correct grounded answers, availability failures mislabelled as
`unsupported_claim`/`incomplete_answer`, the pediatric clarify question
re-asking for fields the user had just given, a no-op entailment retry
loop, and identical-looking citation chips. Touched
`rag/answer.py`, `rag/agent.py`, their tests, `ChatPanel.tsx`,
`ChatBubble.tsx`. **Deliberately NOT changed**: the pediatric gate still
requires both age and weight, chips are not collapsed, the completeness
judge was not relaxed. 230 passed (was 219). Commits `93aa322`, `4e78363`.
- **Note on reading status text here, 2026-08-11**: ownership entries in this
file and in `CLAUDE_HANDOFF_2026-08-10.md` are written at a point in time
and can fall behind — five commits landed on 2026-08-10 between 17:09 and
17:27 after the entries below were written. `git log` is the reliable
source for current state; these entries are useful for intent and
reasoning.
- Codex parallel session: **STOPPED, 2026-08-10** — owner ended the session.
(Commits `9c3acd0``4438c5f` landed after this line was written.)
Left `rag/expansion.py` and `rag/context.py` finished and tested but not
wired into any live retrieval path; `rag/fusion.py`/`tests/test_fusion.py`
(a third, separate ChatGPT session's work, per Codex's own note above)