- Parenthetical blocks (Author year; Author year) now expand into individual
cite spans so each is independently clickable rather than linking only to the
first author
- Detected citation patterns always emit a cite segment regardless of whether
the reference is in citeIndex; empty-refs spans fall back to a fielded ADS
search (first_author:"Surname" year:YEAR) on click
- Matched corpus citations get a rubric-tinted dotted underline; unmatched get
a grey dotted underline; both turn rubric on hover
- Cite elements changed from <span> to <button> for accessibility
- Add .vite to frontend .gitignore; fix FakeCorpus test stub (arxiv_ids/bibcodes)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add litCount (3–10, default 3) to DISPLAY_DEFAULTS and DisplayMenu range slider; slice lit at generate() time (changes annotator cache keys by design) and at MarginNote render time via tweaks prop
- Accept .txt/.md/.markdown files in Upload drop zone; update subline copy and add ap-splash-about block with prose and how-to mono line
- Rename user-visible "astroparse" → "beacon": wordmark (Upload, Pipeline), toolbar mark, <title>, session download suffix (.beacon.json); localStorage keys and CSS ap-* classes intentionally unchanged
- package.json name → beacon-frontend
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix: scrollable popovers; default annotation mode is historical context
Implements Task 20: clickable Fig./Figure N mentions in paragraph text open a
FigurePopover with the figure image, caption, and five-mode streaming annotator,
reusing CitePopover chrome and NoteBody extracted from MarginNote. Adds the 7th
pipeline stage row (vii · Tipping in the plates · pymupdf), extends session
round-trip with figures/litByFig, and generalises generate() to resolve both
paragraph and figure targets.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix: parse CRLF-framed SSE events from sse-starlette
The browser pipeline screen stalled at the first stage: parseSseChunk
split events on '\n\n' but sse-starlette frames with '\r\n\r\n', so
no event ever parsed. Accept CRLF/LF separators per the SSE spec.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Wires toolbar save/load, localStorage autosave, and a DisplayMenu
popover for palette, body size, justify, and notes-side preferences.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix: move generate calls out of setState updaters
Use a commentaryRef (assigned each render) so onSetMode and onSetAllModes
can check commentary presence without calling generate() inside a setState
updater — eliminating the React StrictMode double-invocation anti-pattern.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat: streaming annotation generation and annotator panel
Implements Task 16: wires annotateStream SSE into App.jsx generate()
with inflight deduplication, adds AnnotatorPanel (three provider chips,
localStorage persist), Toast component (2.6s auto-dismiss), streaming
display in MarginNote (text renders as first token arrives), and a
trailing 150ms throttle on Reader's recompute during token streaming.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ports UploadScreen and PipelineScreen from prototype/pipeline.jsx as
React components; replaces App.jsx placeholder with a state machine
(upload → pipeline → reader) connected to startParse/jobEvents/importSession.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>