Uh oh!
There was an error while loading. Please reload this page.
Render the Ask answer as Markdown - #31
Conversation
THE PAGE WAS INERT ON ARRIVAL, and that is the defect underneath the rest. The selection was seeded by a `useState` initialiser, which runs on the FIRST render - and on that render `library` is `[]`, because App.tsx fetches it after mount. So `source` was fixed at "" for the life of the page while the `<select>` displayed Turalio: a select whose React value matches no option falls back to displaying option zero, and reading `.value` off the DOM returns that option's value. Every readout agreed and the state underneath was empty. `send` and `summarise` both open with `if (... || source === "") return`, so every suggestion chip, the summary button and Ask did nothing at all - no request, no error, no pending turn - until the dropdown was changed by hand. It is derived from the library now, so a pick that names no real document falls back on its own rather than sticking at "". THE DOCUMENT IS THE SUBJECT, SO IT GETS A ROW. The picker was a `.field` inside `.pagehead .actions`, which with `margin-left: auto` meant it took whatever width the title did not - a 565px native select floating below the lede, aligned to nothing, in the slot a page uses for its actions. It is not an action: every question, answer and citation below it is about ONE document, and changing it clears the thread. The summary moves onto that row for the same reason - it acts on the document, not on the conversation. ONE COMPOSER, ONE ACTION. The box held six full-sentence suggestions wrapped to three rows, a primary-styled summary button, and the send button - which `button.primary:disabled` draws as a transparent hairline, the state it is in every time the box is empty. The loudest control in the composer was Summarise and the quietest was the one the box exists for. Suggestions are a way in before there is a thread, so they sit above it and leave when spent. MARKDOWN NEEDED BOTH HALVES. A summary measured off this deployment is 5,953 characters containing ZERO newlines, with "Animal findings (rats):" and "Human clinical findings:" as run-on labels inside one paragraph - nothing had ever asked the model for structure, so there was nothing to render and a `<p>` was not wrong. ask.ts asks for it now; markdown.tsx renders it. Neither alone changes the screen. Inline emphasis is fenced off on purpose: ask-eval scores `statedFact` with patterns like `30[06]\s*mg/kg`, and `**300** mg/kg` puts asterisks where that `\s*` expects whitespace, scoring a correct answer as a miss. Structure is free; a marker between a number and its unit is not. The renderer builds React elements and never touches innerHTML, so HTML in a model's answer is text on the page. Links are not a construct: an answer is drawn from a PDF page and has nowhere legitimate to point, and provenance is the citation rows the server resolves. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> (cherry picked from commit b84728c)
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
A `<p>` COLLAPSES NEWLINES, which is why the reported screenshot looks the way it
does: the model's markdown was well-formed - `### Reported Studies`, `- **General
Toxicology:**` - and the old `<p>{answer}` rendered it as one run-on line with the
markers still in it. markdown.tsx fixes that case and this commit does not change it.
WHAT IT DOES FIX is the case underneath. `answer` is one JSON string, and a model
writing six thousand characters into a string field does sometimes emit the MARKERS
without the newlines. Fed to `parse` that is a single line beginning with `###`, so
the whole answer became ONE heading - not a wall of text any more but a wall of
heading, which is worse than what was reported. A test carrying the reported answer
verbatim, with its newlines removed, now asserts two headings and three list items.
CONFINED TO THE DEGENERATE CASE, and the test is the whole string rather than a
per-line judgement. An answer that broke ANY of its lines was formatted by a model
that knew how, and reconstructing over the top of that would be this file inventing
structure where real structure already exists. Only an answer with no newline at all
is repaired, so nothing that works today takes a different path.
EVERY RULE IS ANCHORED TO SOMETHING UNAMBIGUOUS. A mid-line `###` is not prose. A
mid-line bullet is recognised only by the `**` label the ask prompt asks for, because
a bare ` - ` is a dash in a reviewer's prose and splitting on it would cut a sentence
of transcribed evidence in half with nothing on screen to show it happened. `1.` stays
part of a number. A heading that ran into its paragraph is cut at a sentence opener,
never mid-title: `### Studies In Rats` keeps "In" because "Rats" is capitalised.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>Darkest-Teddy
commented
Aug 17, 2026
Superseded by #32, which merges main into this branch and carries this work plus the run-on renderer fix. |
The Ask page was showing the model's answer as one raw blob - literal
###and**on screen, no paragraphs, no bullets (see the reported screenshot).This is a cherry-pick of b84728c from
main, which fixed it there but never reachedfeat/product-in-the-atmosphere. The two branches had diverged;pages.tsx,services/api/ask.tsandtest/pages.test.tsxwere byte-identical to the commit's parent, and onlyapp.cssneeded an auto-merge.Both halves ship together, because neither works alone:
services/api/ask.tsasks the model for structure. A measured summary off the deployment was 5,953 characters with zero newlines - there was nothing to render, so the old<p>was not wrong.apps/deliberation/src/markdown.tsxrenders it: headings, bullets, ordered lists,**bold**,`code`.The renderer builds React elements and never touches
innerHTML, so HTML in a model's answer stays text on the page. Links are not a construct - an answer is drawn from a PDF page and has nowhere legitimate to point; provenance stays the citation rows the server resolves.The prompt also forbids a marker between a number and its unit, so
300 mg/kgstays intact for ask-eval's30[06]\s*mg/kgpatterns.The commit also carries the Ask-page fixes it was authored with: the source
useStateinitialiser that leftsourcepinned at""(making every chip and the Ask button inert), and the picker/composer layout.Verification
npx vitest run), including 19 new markdown testsnpm run build --workspace @arbiter/deliberationclean.md-h/.md-liststyles survived theapp.cssauto-merge🤖 Generated with Claude Code