- Launch screen for the desktop app. Double-clicking the .app used to show nothing for several seconds (bundle unpack + uvicorn boot). The window now appears immediately with the paper-review mark and reports what it is doing (installing skills… → starting local server… → opening library…), then swaps itself over to the gallery. If the server never comes up, the splash turns into a readable error instead of leaving a blank window. Self-contained HTML (no CDN), light/dark aware, and the window background matches the system appearance so dark-mode users get no white flash.
- Cloning anywhere but
~/Projects/paper-review-servicebroke the library.SERVICE_ROOTwas a hardcoded path, so a checkout elsewhere read/wrote papers in a folder that didn't exist. Source installs now resolve to their own checkout; the frozen .app keeps the legacy location andPAPER_REVIEWS_ROOTstill overrides both. install-menubar.shhardcoded the author's clone path — now derived from the script location like the other installers.- The illustration fallback list named images that aren't in the repo (the
IP-character files are gitignored), so a fresh clone could show broken
thumbnails if
/illustrationsever failed. It now lists only shipped art. __version__was still0.1.0while the product shipped 2.x.
?dash=1deep-links straight to the dashboard (also used for the docs screenshots).- README rewritten for newcomers: badges, hero + report/dashboard/review screenshots, a feature table, install paths, architecture diagram, CLI reference, FAQ, roadmap and contributing notes.
- Dashboard split into Intake and Export, both monthly. Tabs at the top of
the dashboard switch between the two views (choice remembered):
- Intake — papers by the month they arrived: Papers / Sections / Avg rating KPIs, review-status funnel, monthly intake chart, rating distribution, top tags.
- Export — papers by the month they were exported: Exported count / export rate / median days intake→export, recent exports list, monthly export chart, and rating/top tags restricted to exported papers. The 52-week activity heatmap is replaced by a 12-month bar chart in both. Dashboard labels are English, matching the rest of the UI.
exported_atin the workbench frontmatter, stamped on every publish — the Export dashboard needs a stable export date (the workbench mtime moves on any later edit). Existing exported papers were backfilled from their vault draft/published file mtime; papers with no vault file are counted as "undated" in the chart subtitle.
- Model picker updated for the Claude 5 generation: Opus 5 (new default),
Opus 4.8, Sonnet 5, Fable 5, Haiku 4.5. Every entry is now a pinned model id
instead of a floating alias — the old list showed "Sonnet 4.6" while the
sonnetalias already served Sonnet 5, so the label lied about what ran. Legacy saved values migrate (opus/sonnet/haiku → the pinned ids, retired Opus 4.7 → default), and installs still sitting on the previous default get a one-time bump to Opus 5; an explicit pick after that is never overridden. (Tag suggestion in ingest keeps thehaikualias on purpose — cheapest, not user-facing.)
- Summary↔Detail no longer jerks the top of the page. Both views repeated the paper title that the topbar already shows, at very different heights — Detail's workbench H1 (~150px) vs the report's sticky nav + hero cover (~615px), a ~400px jump on every toggle. The workbench H1 is now hidden on screen (print/PDF keeps it) and the embedded report hides its nav + hero via injected screen-only CSS, so both views open on TL;DR (4px apart). The standalone report (새 탭) and printed PDFs keep the full cover.
- Sections are now ONE block:
핵심 해설. The old요약+Claude 1차 번역pair made you read the same content twice. Analysis now writes a single self-contained Korean explanation per section — source order preserved but written, not transliterated (~50-70% of a literal translation, load-bearing phrases bolded, numbers/symbols/comparisons kept). Applies to NEW analysis; already-reviewed papers keep 요약+번역 and still render/publish as before. - Wrap-up trimmed to
한 줄 contribution.가장 약한 부분and후속으로 읽을 논문are gone (the report's 05 한계 / 06 후속 연구 cover them), as is 메타's마지막 세션. /finalize now asks one question. Publish still renders those fields for older papers that have them. - Pipeline auto-generation archived. The structured report replaced that need: the generate card, route and prompt are removed. Existing ```pipeline blocks still render, animate and export to GIF for publish.
- Publish exports Detail and Summary separately. The Publish button now
opens a target menu (Detail — full review / Summary — report / Both). The
summary draft comes from a new velog-compatible report.md that report
generation writes alongside report.html (degraded visuals: tables/bullets,
same-origin figure refs materialized into the vault). Both drafts land in
the configured drafts folder — .md and -summary.md — with the
summary tagged
summaryand titled "… (Summary)". Older reports without report.md get a clear 400 asking to regenerate.
- Report button labels are English (Generate Report / Generating… / Regenerate Report / Regenerate · outdated) per the English-UI rule.
- Stale report after Analyze. Running Analyze updated the workbench but the Summary tab kept serving the old report. Now: (1) a successful analyze run automatically rebuilds an existing report in the background (logged in the analyze log); (2) /report returns X-Report-Stale / X-Report-Mtime, the Summary button shows "리포트 재생성 · 변경됨" (amber) when the review changed after the report was built, and the iframe URL is mtime-versioned so a rebuilt report reloads automatically on the next Summary visit.
- Report pane STILL visible at the bottom of Detail (root cause). The
hiddenattribute relies on the UA'sdisplay: none, but our author rule.pane.report { display: flex }overrides UA styles by cascade origin — so everyhiddentoggle on the pane silently never worked (behind all the "창이 여전히 열려 있다" reports). Added[hidden] { display: none !important; }so the attribute always wins; verified with computed styles this time.
- No more report bars/banners. The in-pane "구조화 리포트 —…" bar and the "구조화 리포트 없음 —…" banner are gone. Report generation/regeneration is a single topbar button shown only in Summary; open-in-tab / fullscreen are hover-only overlay buttons on the report pane.
- PDF export follows the screen. In Summary with a report, the PDF button prints the report; in Detail it prints the workbench (as before).
- Per-pane fullscreen. Hover ⛶ on the 원문 pane, the review pane, and the report pane fullscreens just that pane (the topbar F button still fullscreens the whole page).
- Mobile push moved to the gallery. The 📱 button now lives on each list card (slot swapping is a list-level action); removed from the detail topbar.
- Pretty URL is now this-Mac-only. 2.4.3's port-80 listener followed the main --host (0.0.0.0) and advertised the LAN IP over mDNS — widening LAN exposure. macOS only permits unprivileged low-port binds on the wildcard address, so the :80 socket stays wildcard but a middleware now rejects any non-loopback client on port 80 (403), and mDNS advertises 127.0.0.1. The main :7300 keeps its existing policy (LAN access for phones) unchanged.
- Pretty URL: http://paper-review.local/ — serve now also binds port 80
(unprivileged on macOS) and registers the mDNS name via
dns-sd -P, advertising the LAN IP so phones on the same Wi-Fi can use the same address. Menubar menu/open use it when available; falls back to http://127.0.0.1:7300 when port 80 or dns-sd is unavailable.
- Report view sticking to every paper. The Summary/Detail choice was a single global key, so opening the report once made EVERY paper open in the report view (with its top bar). The view is now remembered per paper (default: Detail). The no-report generate banner also shrank to one line.
- Configurable publish path (Settings → 경로). The Obsidian/velog vault
drafts folder is no longer hardcoded: set it in the gallery settings (stored
in ~/.config/paper-review/settings.json; PAPER_REVIEW_DRAFTS_DIR env
overrides; empty = legacy default). Publish routes and
export-draftuse it.
- Report pane leaking into the Detail view. Rapid Summary↔Detail toggling let the async report check resolve late and re-show the pane over Detail; showReportPane now bails unless the current view is summary. The "리포트 생성" banner also moved from the bottom (next to chat) to ABOVE the summary.
- Structured review report (최종 정리) in the Summary view. A "구조화
리포트 생성" button builds a single-file report.html from the finished
review — 00 TL;DR → 01 개념 → 02 배경 → 03 방법론 → 04 실험 → 05 한계 →
06 후속 연구, with hero key numbers, prior-work timeline, result bars /
stat boxes, paper figures (same-origin), scope-discipline callouts,
⚠️ 논문 명시 / 🔍 리뷰 중 발견 limitation split, and WebSearch-backed follow-up papers. The reviewer's 내 정리/Q&A are woven in. Summary tab shows the report once generated (새 탭/재생성 bar); until then it keeps the label-filtered summary with a generate banner. Template adapted from the team review guide (+ dark mode).
- Scope discipline in analysis prompts. Section analysis and the paper-review skill now separate the paper's claims from general-knowledge inference ("논문 밖 일반론", "논문에 명시되지 않음"), require symbol definitions/concrete numbers in method sections, and structure experiment summaries as 실험 목적 → 결과 → 해석.
- Mobile continuation (remote slot). A tiny Vercel app (
remote/, monorepo subfolder) holds ONE paper's workbench + figures. Push from the detail page (📱 button) orpaper-review remote push <slug>; edit on the phone (section-level ✏️ editing, KaTeX/figures rendered, frontmatter via ⚙); pull back from the gallery (📥 button) orpaper-review remote pull(backs up workbench.md.bak first). Manual sync only; optimistic rev check guards concurrent edits. Config in ~/.config/paper-review/remote.json.
- Actionable hint on Claude CLI auth expiry. When an analyze section fails
with an authentication/OAuth error, the log now appends: re-login with
claude auth login, then re-run Analyze (no server restart needed). - Tests for the status PATCH helpers/route (missed in 2.2.16) and the auth hint.
- Status menu labels are now English (Reading / In progress / Reviewed / Exported / Archived) to match the badges and sidebar.
- Manual status change from the gallery. Click a card's status badge to open
a menu and set the status (읽을 예정 / 리뷰 중 / 완료 / 발행 / 보관). New
PATCH /paper/<slug>/statuswrites it to the workbench frontmatter. - Archived status. The default "All" view (and its count) hide archived papers; a new Archived sidebar filter shows them.
- Pipeline player, hero card, mermaid, image-resize, and section anchors gone (2.2.14 regression). The 2.2.14 math-render rewrite accidentally removed the post-render calls (h3/h1/h2 ids, annotateBlocksByLabel, wrapHeroCard, renderPipelinePlayers, injectPipelineGenButton, renderMermaid, setupResizableImages) that run after the workbench HTML is inserted. Restored them; the animated pipeline (and the auto-generate button when absent) render again, and math still pre-renders correctly.
- Detail page hung on some math-heavy papers.
markedtreated$… internals (_,*) as markdown and split each math span across inline elements; KaTeX auto-render (renderMathInElement) then re-paired the looseacross Korean prose into a giant bogus span whose layout froze the page. Math is now shielded from marked (placeholder swap) and each span is pre-rendered withkatex.renderToStringand spliced in — no whole-document delimiter walk. Also renders more math correctly (spans marked previously mangled).
- Stray leading colon in the Wrap-up one-liner. A workbench that wrote
**한 줄 contribution** : value(space before colon) rendered as한 줄 요약: : value._extract_dash_fieldnow drops a leading colon from the extracted value.
- Wrap-up (“## 정리”) dropped from published posts.
_extract_dash_fieldrequired a colon after the label (**한 줄 contribution**:), but a workbench that wrote the label on its own line with the body below (no colon) parsed empty, so the whole Wrap-up section was skipped at publish. The colon is now optional and the value may span the following lines.
- Reverted the math placeholder tokens. 2.2.10 hid
$…$behind◆mathN◆tokens in the editor, which leaked into view and read poorly. Math now shows as its$…$source again; the WYSIWYG backslash/_/*mangling is undone on save inside math spans instead (known ceiling: an escaped\_inside\text{}). - Inserted figures are centered in the editor (
display:block; margin:auto).
- Editing no longer breaks LaTeX math. The WYSIWYG editor mangled
$…$/$$…$$(doubled backslashes, escaped_/*), corrupting KaTeX. Math is now swapped for opaque tokens before loading and restored verbatim on save — lossless, and correct LaTeX is never touched. (A one-off repair fixed 233 already-mangled spans across existing review workbenches.) - Color no longer drops the selection. The color picker popup collapsed the WYSIWYG selection, so you couldn't apply bold to the same text without re-selecting. The selection is now restored after a swatch is picked, allowing color → bold chaining.
- Themes now apply to the review (detail) page. It only honored dark/light;
the brand/original themes (stripe/figma/tesla/sunset/sage) set in the gallery
were ignored. detail.css already had the rules — detail.js just wasn't setting
data-themefor them. - Fullscreen toggle on the review page (topbar button +
Fkey) via the native Fullscreen API, to hide the browser chrome while reviewing.
- Publish moved web figures around / dumped them to the end. Two causes:
(1) the publish renderer dropped each section's
원문 발췌block — where the workbench keeps its figures — then re-inserted every figure by figures.jsonsection_heading, ignoring the editor placement. Now figures the workbench already references are rendered in place (top of their section, with the real caption), and_inline_web_figuresonly rescues figures referenced nowhere. (2) The section parser ended the섹션별 리뷰block at any non-numbered H2, so a stray content heading (e.g.## vLLM에서의 구현) silently dropped every later section and its figures into the trailing## 그림dump. It now stops only at the known structural H2s (Q&A / Wrap-up / 메타 / 그림).
- SVG figures (blog/article) couldn't be resized in the editor. The WYSIWYG
image rule had
max-width: 100%but noheight: auto, so SVG figures (which carry width+height attrs) collapsed to ~2px — leaving nothing to hover or drag. Addedheight: autoto match the read view; figures now render full size and the drag-resize handle attaches.
- Chat now uses the review skill that matches the content type. Previously
the chat always loaded
paper-review; it now selectsblog-review/article-reviewfor web content (bycontent_typein the workbench frontmatter), so blogs and articles get their own rubric.
- Chat "기재" requests didn't write to the workbench. Asking the chat to
record a question/answer/note often produced only a chat-panel reply, never an
edit. The chat system prompt now has an explicit rule: record requests
(기재/기록/메모/저장/추가) MUST Edit
workbench.md(default target## Q&A, or the tied###section), then confirm what was written. The plumbing was already in place (acceptEdits + Edit tool + SSE auto-reload on file change); this closes the instruction gap.
- Garbled strip at the top of the list when scrolling. The scroll container's top padding let cards bleed into a band above the sticky toolbar. Moved that spacing into the toolbar's own padding so its frosted background covers from the very top edge.
- Type badge shown only on web content. Papers had no type badge, so the grid
looked inconsistent. Every card now shows its type (
PAPER/BLOG/ARTICLE).
- Per-card "로그" button on the list. Every gallery card now has a ▤ log button (next to 🏷/🗑) that opens the analyze-log modal in place — the log button moved off the detail topbar onto the list, where it's reachable for any paper without opening it. (The running pulse / "⚠ 분석 실패" chip still open it too.)
- Illustrations dedup by character, not file. A character isn't shown on two
cards until every registered character has been used; variants of the same
character (e.g.
redpanda/redpanda-2) count as one. When a tag group runs out of unused characters, selection widens to the global pool so an unused character appears instead of repeating one.
- Analyze log reachable from the gallery (list page). A running card's
"분석 중" pulse and a "⚠ 분석 실패" chip (shown when a run errored or had failed
sections) now open the full log modal in place — no need to open the detail
page.
/papers/active-jobsalso reports finished error/failed jobs so the list can flag them.
- Applied the make-interfaces-feel-better principles across the gallery,
detail, and source views: scale-on-press (0.96) on buttons, subtle theme-aware
1px image outlines on card illustrations / figures,
text-wrap: balanceon headings +prettyon body, font smoothing on the source pane, and transition-property-specific transitions (nevertransition: all).
- Analyze log window — a "로그" button (topbar + the progress toast) opens a modal with the full run log, status, and failed-section list, reachable any time (even after a clean run or a page reload). Backend keeps more log lines.
- If analysis "completes" but the workbench wasn't filled, it's the pre-2.1.1
--continuefailure — restart the menubar/server so the fix is live, then re-run; the log window now shows exactly what happened.
- Auto-analysis silently aborting on freshly-ingested content. Every claude
call used
--continue, but a just-ingested folder has no prior session, so the first call errored and every section failed. The first call of an analyze run now starts a fresh session (subsequent calls still chain with--continue). - Failures weren't visible. The analyze toast now stays open (with the error log + a ✕ to close) whenever a run errors or any section fails, and re-attaches on page load — instead of auto-dismissing after a few seconds.
Packaged as a standalone macOS app (like data-manager) for one-download accessibility — no Python/uv/clone needed.
- Desktop .app —
packaging/build.shproducesdist/paper-review-<arch>.zip(PyInstaller bundle: FastAPI backend + vendored engine + UI). Double-click opens a native pywebview window over the local server. First launch copies the skills into~/.claude/skillsand installs the subagents. paper-review appruns the same window in dev.
- Vendored scripts now run via a self-re-exec dispatcher (
_run-script) instead ofpython <file>, so the pipeline works inside a frozen bundle. uvicorn is started from the app object (import strings don't resolve when frozen). PATH is augmented at launch so a Finder-launched app still findsclaude.
- Review/chat still require the Claude Code CLI installed and signed in — it can't be bundled. ingest, browsing, and publish work without it.
- The app is ad-hoc signed: first launch needs right-click → Open.
Expands the service from papers-only to papers, engineering/release blogs, and general web articles, and adds a settings surface.
- Web content — ingest any URL (
paper-review init <url>or paste a link in the gallery). Source kind is auto-detected (arXiv · PDF · web) and web content is classifiedblogvsarticle. Web ingest extracts a clean markdown body, section index, and inline figures (incl. SVG) viafetch_web.py. - Per-type review skills —
blog-review,article-reviewalongsidepaper-review, sharing one engine (_paper_reader/references/review-engine.md). - Reading-list save for web — save a URL with metadata only, promote to a full ingest later (▶ Analyze).
- Publish by type —
paper-publishreshapes the workbench using a content-type-aware template (paper / blog / article); web drafts inline their figures by section. - Settings panel (⚙, top-right of the gallery) — switch themes, view/edit installed skills, manage card illustrations (upload / soft-delete to _trash).
- Themes — light/dark plus brand-referenced (Stripe, Figma, Tesla — see
~/Documents/design/themes/) and original (Sunset, Sage) themes, applied across the gallery, detail, and source viewer. - Illustration grouping — cards pick a thumbnail from the group mapped to their tags (vision / language / generative / systems / general), spreading usage so similar-tag papers look consistent without repeating.
- Source viewer — web detail pages render the original article (figures placed inline by section) in place of the PDF pane.
- Tests — a pytest smoke suite (routes, skills, transform, settings).
- Figure-export path-traversal guard; HTML-escaped page titles; UTF-8 for skill/groups file I/O.
- The skills directory is the source of truth, symlinked into
~/.claude/skillsviainstall-skills.sh. Changing server routes requires restarting the menubar app (templates/CSS/JS hot-reload on refresh).
- Initial release: arXiv/PDF paper ingest, section-by-section review with Claude, Velog draft export, FastAPI gallery + macOS menubar.