* refactor(i18n): migrate app copy to domain namespaces
- Replace the monolithic dialogs catalog with 16 flat product-domain catalogs
- Preserve every translated locale value while moving all 356 messages
- Expose narrow domain composables and retain useI18n as a compatibility aggregate
- Document namespace ownership and admission rules
* fix(i18n): complete migrated locale coverage
- Translate exposed MCP automation, code editor, credential, and media placeholders
- Restore missing German, Spanish, French, Italian, Polish, and Russian diacritics
- Preserve technical product terms and interpolation placeholders
* fix(i18n): polish remaining locale wording
- Correct the mixed-language German code source label
- Preserve stock_photo and Pexels semantics in German and Polish
- Improve Italian MCP and code-editor grammar
- Use the standard Russian term for MCP endpoint
* fix(i18n): migrate diagnostics copy after rebase
- Add a diagnostics domain for newly merged usage and telemetry settings
- Keep settings navigation labels in the settings domain
- Preserve translated diagnostics catalogs from current master
* style(app): format rebased settings components
* refactor(i18n): simplify domain message keys
- Remove redundant domain prefixes from settings, diagnostics, automation, and integration catalogs
- Move feature-specific actions out of the common namespace
- Preserve current-master language picker and diagnostics copy across every locale
- Update consumers to concise semantic keys
* fix(app): preserve font and updater contracts
- Restore browser and abort-aware font loading from current master
- Remove the unused parameter helper from common messages
- Update updater tests for semantic domain keys
* fix(i18n): finish semantic diagnostics access
* refactor(i18n): derive active MCP status message
* fix(i18n): preserve rendering settings after rebase
- Add a rendering domain for tiled canvas preferences
- Preserve the current-master language and rendering settings UI
- Move every translated renderer preference out of the retired dialogs catalog
* fix(i18n): polish reviewed locale semantics
* test(i18n): enforce translation completeness baseline
- Fail on interpolation placeholder drift and suspicious mixed-script values
- Reject new source-identical translations while tracking existing debt explicitly
- Report translated-message coverage for every supported locale
- Require baseline cleanup when existing placeholders are translated
* refactor(i18n): baseline reviewed mixed-script messages
- Replace brittle product-vocabulary exceptions with Unicode script detection
- Track reviewed mixed-script messages by stable locale and message identity
- Reject new entries and stale baseline debt without hardcoded terminology
* fix(fig): resolve relocated stroke test helper
* feat(app): show atomic document loading progress
- Preserve the existing full-canvas pencil loader while adding phase, detail, accessible status, and honest determinate progress
- Keep one generation-safe load owner across FIG decoding, graph preparation, page population, fonts, fallbacks, layout, viewport fitting, and first-render fade
- Prevent nested page setup and viewport cleanup from revealing partially prepared documents
- Cover obsolete sessions, font-resolution ownership, and staged loader UI
* refactor(app): scope editor preparation per tab
- Replace the shared loading boolean with one reactive preparation snapshot and one imperative controller per editor store
- Keep Core page work progress-only and inject canvas suspension from the app boundary
- Route FIG, storage, recovery, DOM import, and page switching through reusable tab-local preparation handles
- Abort only the closing tab's operation and cover generation safety, multi-tab isolation, progress UI, and disposal
* fix(editor): commit prepared pages atomically
- Prepare population, fonts, fallbacks, and layout without changing the visible page
- Reject cancelled and stale prepared pages before committing viewport, selection, and page events
- Keep the preparation overlay until the committed scene version is presented
- Cover call order, cancellation, stale generations, and presentation acknowledgement
* fix(app): stage imported documents before commit
- Prepare imported graphs in an isolated Core editor before replacing the live document
- Share font loading while keeping live selection, graph, renderers, and history untouched during staging
- Preserve the previous graph when staging is cancelled or fails and remove the duplicate pre-font layout pass
* refactor(app): namespace preparation UI
- Move canvas and tab preparation presentations into focused subfolders with concise component names
- Share progress and phase presentation helpers across preparation surfaces
- Show tab-local preparation status without covering the active canvas for background work
* fix(app): cancel preparation work at source
- Publish typed per-store preparation lifecycle events with explicit completion, cancellation, and failure outcomes
- Propagate tab-local AbortSignals through FIG parsing, population workers, and browser font downloads
- Keep cancellable font requests outside shared in-flight caches while retaining globally completed font registrations
- Stop FIG manifest previews from replacing the live graph before atomic document commit
* fix(app): cancel storage and DOM preparation
- Propagate preparation signals through S3 downloads, byte progress, local-cache boundaries, and DOM/CSS conversion checkpoints
- Reuse merged diagnostics and localized toasts for document, storage, and presentation failures
- Replace manual font concurrency and presentation timers with es-toolkit limitAsync and withTimeout
- Guard stalled first presentation and fix the merged recovery dialog title bindings
* fix(app): stage reload and font retry
- Prepare reload graphs in isolation and preserve the current document on read, decode, font, or layout failure
- Restore page and viewport state only after atomic graph commit with cancellable reload reads
- Run font Retry as a tab-local preparation with cache reset, final layout, picture invalidation, and presentation acknowledgement
- Keep completed document pixels visible while Retry reports activity in the tab
* fix(app): enforce exclusive preparation outcomes
- Complete document, storage, recovery, and DOM preparations only after successful commit
- Keep failed and cancelled handles terminal so lifecycle events cannot report contradictory outcomes
- Preserve external AbortError identity across storage timeouts and cancel streamed readers without returning partial bytes
- Cover credential-free pre-abort, mid-stream cancellation, progress cutoff, and terminal outcome exclusivity
* feat(diagnostics): record preparation outcomes
- Persist completed, cancelled, and failed preparation lifecycles through the validated diagnostics recorder
- Store only operation kind, outcome, cancellation or failure category, terminal phase, and coarse duration bucket
- Exclude document subjects, font families, storage identities, URLs, raw durations, messages, and stack traces
* chore(app): keep browser font tests with typography split
- Remove the browser font transport test inherited from a mixed cancellation commit; the source and coverage remain on the typography branch and safety snapshot
* test(vue): assert injected render suspension
- Exercise shouldSuspendRender instead of removed Core loading state\n- Preserve the contract that rendering resumes without a version change
* test(app): complete atomic preparation contracts
- Acknowledge first presentation in headless file-open tests\n- Assert the cancellable font-loading signature at the Tauri fallback boundary
* fix(app): preserve preparation cancellation
- Stage imported graphs before mutating live tabs and propagate aborts through page, DOM, font, and storage work\n- Use the accessible progress primitive and clamp determinate values\n- Cover fallback-font cancellation and yield pending-open test polling to the task queue
* test(text): await fallback font request cancellation
Start the mocked remote font request before aborting so the test proves that the active request receives the preparation signal.
- Keep New tabs provisional so opening or creating a design reuses the active tab
- Separate recent document, storage, menu, worker, and workspace responsibilities
- Add source-aware recents, responsive files UI, loading states, and localized copy
- Preserve native local Open Recent behavior while supporting remote storage history
* Revert "feat(ai): add HarnessAgent sidecar foundation (#560)"
This reverts commit 83a5ea1b42.
* Revert "Revert "feat(ai): add HarnessAgent sidecar foundation (#560)""
This reverts commit 0d8c03515888c62dc47186d4a3b0b7b04e78f8af.
* refactor(ai): ship Harness as optional companion
* fix(ai): support Harness companion on Windows
* test(ai): restore navigator after Harness Windows test
- Open multiple selected design files in separate tabs.\n- Support desktop, File System Access, and fallback pickers.\n- Continue opening later selections when one file fails.
- Serialize recovery cleanup with active snapshot writes
- Preserve version ordering across autosave, restore, and cleanup
- Fall back to memory when IndexedDB operations fail
* fix(tauri): prevent Windows font loading crashes
- Return native font files over binary Tauri IPC instead of JSON byte arrays
- Resolve desktop script fallbacks without parsing large system fonts in JavaScript
* fix(core): restore quality checks
- Use the shared Vector primitive for render-bound offsets
- Remove unsupported SLICE handling from SceneGraph rescaling
- Drop an unused generated-text test binding
* chore: address font fix review
- Place the release note under the Fixed heading
- Name fallback resolution options and use the shared Tauri constant
* fix(mcp): close orphaned servers that no app ever claims
- Add ServerOptions.appAttachTimeoutMs: if no app registers within this
window after startup, the server closes itself and removes its
discovery file, instead of squatting the port indefinitely.
- Wire it through the openpencil-mcp-http CLI as
OPENPENCIL_MCP_APP_TIMEOUT_MS (opt-in, unset/0 disables it — a bare
CLI invocation for manual testing should not self-terminate).
- The desktop app opts in with a 30s timeout when it spawns the server.
Without this, a server that outlives its spawning app (renderer crash,
forced reload) keeps holding its port with a stale discovery file. The
app's liveness check only asks whether something answers /health, not
whether an app has ever registered (see /health's no_app status) — so
every later launch finds the orphan already listening and defers to
it, and MCP tool calls fail with "app is not connected" until someone
manually kills the orphaned process. Closing self-caused orphans at
the source means the next launch finds no discovery file and takes
the normal fresh-spawn path.
Fixes#488
* fix(mcp): clean up servers after app disconnects
- Re-arm the orphan watchdog when the registered app disconnects
- Cancel pending shutdown when the app reconnects within the grace period
- Reject timeout values that overflow the runtime timer range
* test(mcp): make watchdog reconnect coverage deterministic
- Wait for the disconnected health state before reconnecting
- Report distinct safe-integer and timer-range validation errors
---------
Co-authored-by: swe-sanad <sanad.arousi@export119.com>
- Load Prism JSX only after exposing the Prism runtime
- Treat unavailable MCP automation as optional during startup
- Connect the desktop automation bridge only after MCP is ready
- Rename first-party API, RPC, JSON, CORS, SVG, JSX, and related identifiers to preserve acronym casing
- Keep upstream and serialized boundary names unchanged
- Add a lint guardrail and migration notes for exported APIs
- Track remote storage bindings without replacing local file identity
- Route saves and autosaves through the durable local cache before enqueueing uploads
- Clear storage bindings on Save As and cover ordering and identity behavior
Co-authored-by: Rob Coenen <753704+rcoenen@users.noreply.github.com>
- Route npm-installed ACP and MCP launchers through cmd on Windows
- Preserve inherited agent environment and current MCP transport settings
- Cover Windows process resolution and document the user-facing fix
Co-authored-by: Damián Briones <insertnickname1@gmail.com>
- Prefer private Unix sockets with TCP fallback for local MCP clients
- Unify HTTP and WebSocket lifecycle, authentication, and cleanup
- Discover transport details from an owner-only runtime file
- Reject corrupt compressed Kiwi chunks instead of accepting raw garbage\n- Tolerate legacy source metadata without editedFields in renderer fallbacks\n- Align font, derived glyph, shared style, renderer mock, and ownership tests with current contracts\n- Restore clean quick and heavy unit quality gates
- Replace simple no-op test callbacks with explicit undefined returns
- Remove no-empty-function exceptions for autosave, stroke picker, font settings, pen, tauri, AI adapter, and undo helper tests
- Validate check plus affected engine and E2E tests
- Configure oxfmt custom import groups for workspace, app, package, and test aliases
- Keep type imports grouped with their matching source category instead of one global tail group
- Expand the format script to cover formatter config, Vite files, and scripts
- Move top-level engine and e2e prefixed test files under domain folders
- Update fixture path helpers after moving render and pen tests
- Add lint coverage to prevent new top-level prefixed test files
- Refresh testing docs for the new fig and layout paths