Port master's v4.5.0 monospace font embedding feature (JetBrains Mono +
Fira Code TTF assets, embedded into PDF/DOCX/EPUB/HTML exports) and
rename branch identity to Markdown Converter React so dev build coexists
with the installed markdown-converter deb without appId/productName
collisions.
Amit Haridas
- batch.showConverter: open BatchMediaConverterDialog for image/audio/video
types (uses existing universal-convert-batch handler with ImageMagick/FFmpeg)
- tools.documentCompare: line-by-line diff of two open tabs with confirmation
dialog, shows diff count in toast and full diff in console
- No more 'coming soon' toasts for any menu item
simple-git returns objects with Map/Set fields that cannot be cloned
over Electron IPC. Flatten all git operation results into plain
JSON-serializable objects to fix 'An object could not be cloned' error.
- App.tsx: call electronAPI.file.rendererReady() on mount so main process
opens pendingFile (files passed via CLI or file associations)
- FindReplaceBar: move updateMatchCount declaration before executeCommand
to fix 'Cannot access d before initialization' crash in minified build
(executeCommand referenced updateMatchCount via closure before its
const declaration in the same scope)
The main process list-directory handler returns {path, entries} but
the file store was calling .map() directly on result.data. Since
arrays have a .entries iterator method, the nullish coalescing
fallback didn't work. Now properly extracts the entries array with
Array.isArray check.
Two related bugs surfaced during end-to-end verification:
1. The 'isAlreadyV5' short-circuit in both the main-side and renderer-side
v4-to-v5 transforms returned the persisted object as-is when a
migration.version=5 marker was present. A previously-shipped v4 build
had written theme: 'ayu-light' (and similar) under the v5 marker;
the transform trusted the marker and passed the invalid theme through,
which then failed the renderer's zod schema on every launch and
reset user settings to defaults.
Fix: in both transforms, when isAlreadyV5 matches, normalize theme
against the v5 enum (light/dark/system) and validate the full result
with the v5 schema before returning. Out-of-range values are replaced
with the v5 default ('system').
2. The renderer's settings-store onRehydrateStorage callback called
useSettingsStore.setState() to reset the store on validation failure.
At that moment the store is still being constructed, and setState
could hit a TDZ ReferenceError (the one we already wrapped in a
try/catch in v5.0.0, which only hid the symptom).
Fix: return the normalized state object from onRehydrateStorage
instead. Zustand's persist middleware applies the returned value
*after* construction completes, so there is no TDZ.
Tests: 334 vitest + 208 jest = 542 passing.
E2E: 12/12 verify-features.mjs steps green; no console errors.
Amit Haridas
1. ThemeSettings: change 'auto' radio value to 'system' to match
the v5 settingsSchema enum. Storing 'auto' silently wipes all
settings on next launch.
2. UpdateBanner: render an 'available' branch so users see a CTA
when a new version is detected (the store already had this state,
but the banner was silent). Added a test.
3. feed-config: remove the unused resolveFeedUrl / FEEDS exports.
feedConfigFor is the actual implementation used by the IPC
handler. Updated tests to match.
4. main/index.js: tighten app:open-external regex to https:// only.
- verify-features.mjs: dismiss FirstRunWizard if visible before clicking
toolbar (wizard overlay blocked previous toolbar clicks); write a
firstRun=true settings.json to test wizard visibility; emit
'updater:status' from main via Playwright IPC.
- package.json: dev:electron now passes --no-sandbox to match the
.claude/skills/run-desktop driver scripts.
Brainstormed with the user (ULTRATHINK context). Sub-project 1 of 4 in the
v5+ roadmap (production polish → cloud/licensing → plugins → perf+a11y).
Spec covers:
- Two-channel distribution: GitHub Releases (default) + ConcreteInfo self-hosted
- Light, skippable first-run wizard (theme + update channel + starter template)
- Auto-migrate v4.4.1 settings with v4 backup and toast on success/failure
- Local crash dump capture (no third-party) with a CrashReportModal
- Non-blocking update banner with user-confirmed restart-to-install
- IPC allowlist additions for updater:* and crash:*
- GitHub Actions CI extension (latest.yml generation, PR test suite)
Defers to v5.1: code signing, Sentry, delta updates, beta tracks.
After user review and approval, write the implementation plan via the
writing-plans skill.