add_citation tool experiment tried and parked; hover popover and rescroll fix kept

nwhitehouse tried replacing the freeform `<CITATIONS>` JSON block with an explicit `add_citation` tool call. The model wrote the inline markers but skipped the tool calls entirely. The UI fixes from the same commit are worth taking; the tool path is not.

searchchat-ui

The first commit (6321e28a) swaps the system prompt to instruct Olava to call add_citation per [N] marker, on the theory that tool calls are more reliable than freeform output for small models. The same commit also ships two UI improvements: a styled hover popover (filename, page, serif quote excerpt) replacing the browser-native title= tooltip, and a same-doc rescroll fix where clicking citation #2 on an already-open doc tab would stay on citation #1's scroll position. The fix drops initialScrollTop from upsertTab when the new mode carries its own scroll target.

8731d95e, 40 minutes later, reverts the system prompt back to <CITATIONS> JSON block format. The model was placing [N] markers in prose but not firing the tool, so no citations rendered. The <CITATIONS> block path works; add_citation doesn't on this LoRA.

The defensive parser improvements from the experiment were kept: page schema simplified to a plain string (the previous oneOf broke some tool-call parsers), and normalizeCitation now coerces string-of-digits markers to integers. The tool definition stays in the codebase and dispatch still fires if the model ever calls it - re-enabling is just a prompt change.

Useful negative result: tool-call routing is not universally more reliable than freeform JSON output. It depends entirely on how the format was trained into the model.

So what Skip the `add_citation` tool path - it's an unproven dead end on Olava's LoRA. The hover popover and same-doc rescroll fix are portable and worth taking. The defensive parser changes (string page, marker coercion) are safe improvements regardless. If you run a different model, tool-call citation routing might be worth retesting from scratch.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

2 commits from nwhitehouse/mike, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
6321e28a [feat-006] add_citation tool + hover popover + same-doc rescroll fix Nick Whitehouse 2026-05-04 ↗ GitHub
commit body
Replaces the freeform <CITATIONS> JSON block with an explicit add_citation
tool the model invokes per [N] marker. Tool calls are far more reliable
on Olava than freeform output formats, mirroring the SLM-friendly pattern
established by feat-005's multi-pass orchestrator. Legacy block parsing
remains as a fallback so any model regression still surfaces citations.

Frontend: replaces the browser-native title= tooltip with a styled hover
popover (filename + page + serif quote). Fixes a same-doc rescroll bug
where clicking citation #2 on an already-open doc tab kept the viewer
on citation #1 - upsertTab now drops the prior initialScrollTop when
the new mode has its own scroll target.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8731d95e [feat-006] Park add_citation tool path; restore <CITATIONS> JSON prompt Nick Whitehouse 2026-05-04 ↗ GitHub
commit body
Empirically the add_citation tool route was unreliable on Olava - model
wrote [N] markers but skipped the tool call, so no citations rendered.
Reverting the system prompt to the original <CITATIONS> JSON block format
restores the proven path. The add_citation tool stays defined and
dispatched (events still emit if called), and collectTurnCitations still
prefers tool-emitted citations when present - so re-engaging this path
later is just a prompt change.

Defensive parser improvements kept: page schema simplified to a string
(was oneOf, which not all tool-call parsers handle cleanly), and
normalizeCitation now coerces string-of-digits markers to integers.
Both make the legacy <CITATIONS> parser more robust to model output
variation as well.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-107.md from inside the repo you want the changes in.

⬇ Download capture-thread-107.md