Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Current State

The test story is uneven across the monorepo.

The mobile workspace focused E2E suite exercises the touch-first shell contract: mobile mode switching, mounted sidebars, right-edge-aligned sidebar reveal, pointer-driven pan gestures with live drag progress and snap settlement, main-panel tap-to-close behavior, center-panel anchored floating controls, scroll-hidden mobile chrome, left-sidebar search routing, the Vaul-backed more-actions drawer, mobile menu drawer rendering, mobile tab actions drawer, mobile settings dialog/sidebar mounting, and startup error tracking for compatibility status-bar plugins.

What exists today

  • the root package defines shared build, test, lint, and formatting commands
  • the root package now defines pnpm test:smoke, the app smoke gate documented in AGENTS.md; it runs the workspace dev-server boot suite and the Electron desktop boot suite when a change can affect the running app; local runs use the desktop dev renderer while CI keeps the full desktop production build
  • the root package now defines pnpm test:daily-use, which runs the workspace Chromium daily-use journey after app smoke in CI and pnpm docker:ci-check; the journey covers note creation, rename persistence, search indexing, notebook execution, reload, and restored notebook outputs
  • the root package now defines pnpm test:official-plugins, which builds the local official external plugin packages, creates a signed local registry fixture with test-only keys, runs the workspace Playwright official-plugin matrix, installs every plugin from the release tooling’s official definition list through the real registry installer with official provenance required, asserts default enablement, install progress cadence, ESM-only runtime diagnostics, reload persistence, and one runtime smoke assertion each for Canvas, Docs, Graph, Markdown Lint, Notebook, PDF, Slides, and Telemetry; the shared CI verify action, Forgejo browser lanes, and official plugin asset publish workflow bootstrap scripts/ensure-xvfb-run-deps.sh before running this command under xvfb-run; when the local registry builder is asked to --skip-build, it now still materializes missing official plugin dist/ outputs from Turbo cache in the current job before packaging fixtures
  • after any code change, the expected validation path is to run the narrowest relevant pnpm check:all command (package-local or repo-root) on modified packages so formatting, source-resolution guards, script tests, package-local static checks, ESLint, spec markdown lint, Svelte warning regressions, and TypeScript regressions are exercised before finishing the change; also run pnpm --filter <package> test (or turbo run test --filter=…) on each modified package that defines tests; run pnpm test:smoke only when the change can plausibly affect workspace or desktop boot, runtime, UI, plugin loading, or related cross-package integration
  • .forgejo/workflows/checks.yml runs a warmed cache-build job first (pnpm ci:build:checks) and then fans out independent CI lanes for repo-checks (static checks), unit-tests, app-smoke, daily-use-e2e, and official-plugin-e2e with strategy.fail-fast: false so one lane failure does not cancel the others; each browser lane uploads Playwright artifacts with actions/upload-artifact@v3; and Turborepo remote cache runs against https://turbo-cache.app.ju.ma while every lane uses the warmed code.ju.ma/lapis-notes/lapis-ci:latest container image
  • the root package defines check:all, which runs check:source-resolution, plugin-host:check, test:scripts, turbo run check:all, check:format:root, lint:root, and spec:lint as the default post-change validation entrypoint; see Monorepo Scripts
  • the root check:all flow runs check:source-resolution before Turbo package checks so first-party Vite development graphs fail fast when any local @lapis-notes/* import resolves to a package dist/ artifact instead of the dependency’s src/ tree
  • individual packages expose package-local check:all and targeted check:* scripts so work can be checked narrowly without always running the root workflow
  • Turbo orchestrates package check:* tasks in parallel with local caching under .turbo/ and optional hosted remote cache in CI; package-local tools stay quiet on success through scripts/run-quiet-check.mjs
  • the root package defines check:types, which runs package-local check:types scripts across the workspace through Turbo so cross-package TypeScript regressions fail in one place instead of surfacing piecemeal during plugin development
  • the root package defines check:format, which runs turbo run check:format across workspace packages and then check:format:root for repo-root paths outside packages (scripts/, spec/, agent docs, CI workflows, and similar)
  • package check:all runs static checks only through scripts/run-package-check-all.mjs; tests run separately through pnpm test or package-specific test scripts
  • the root package defines pnpm e2e-vault:prepare, which stages and verifies a full copy of the tracked e2e-vault fixture (including root INDEX.md) before atomically swapping it into a generated writable vault copy at e2e-vault-temp by default, or a caller-provided path for future e2e harnesses. pnpm media:site consumes that prepared copy for public-site screenshots, restores the tracked default workspace layout for the landing hero still, and uses Workspace: Focus Leaf before capturing the full workspace shell for view-specific stills. The script renames an existing target aside instead of deleting it in place, so --force replace is reliable when the vault is closed; if the swap fails, the error message points at a retained staging directory for recovery. Generated targets are replaced on every run; unmarked existing custom targets require --force. Success is indicated by .lapis-e2e-vault-copy plus root INDEX.md in the prepared target.
  • the root package defines pnpm test:scripts, which runs Node tests for repo scripts such as scripts/prepare-e2e-vault.mjs, and the root check:all flow includes it before Turbo package checks.
  • newly added packages should define package-local check:all, check:format, and check:types scripts, plus check:svelte when the package owns a Svelte UI surface, and that Svelte check should fail on warnings so accessibility and reactive-state regressions stop the normal package check path instead of relying on a second repo-wide warning pass
  • the root package defines spec:lint and spec:lint:fix for markdownlint-based spec checks; root check:all already runs spec:lint, and the root/spec Makefiles still expose spec-lint, spec-lint-fix, lint, and lint-fix aliases for narrow spec-only passes
  • packages/api has the strongest explicit test surface, including Vitest tests and parity fixtures under test/parity
  • packages/api browser-storage tests now cover portable browser-vault transfer behavior in both directions, including import overwrite semantics and export into a user-picked directory handle
  • packages/api now also has focused workspace-model coverage for grouped sidebar layout compatibility, grouped layout round-trips, traversal through grouped leaves, active-leaf restore, sidebar placement defaults, hidden panel persistence, and leaf/group conversion helpers
  • packages/api workspace-model tests now also cover layout drag/drop event ordering and cancellation plus floating-pane and supported/unsupported popout host capability paths, so drag/drop helper regressions fail without needing a real secondary window
  • packages/api now validates SQLite app-database bind compatibility in tests with a sqlite-wasm-like mock that rejects malformed or unused named parameters, so worker-only query regressions such as invalid bind() names fail in CI instead of only in browser sessions
  • packages/api now also covers plugin-manager boot order, failure rollback, manifest preflight, runtime-aware community plugin preflight, failed plugin restart diagnostics, and vault-scoped workspace-trust gating for trusted desktop runtime entries plus brokered capabilities with targeted integration tests
  • packages/api now also covers frontmatter mutation and metadata-type regressions, including first-block creation, last-property block removal, no-op suppression, concurrent frontmatter write retry, nested property membership cleanup, nested rename collision reporting, and falsey-value-preserving metadata renames
  • packages/api now also covers Bases custom-view registration persistence across plugin startup order so plugin-contributed .base renderers survive enable-order differences
  • packages/plugins/plugin-bases includes a test script and now has a focused regression check around virtualized Bases table search state so empty filtered result sets do not reuse stale virtual rows while scrolling
  • packages/plugins/plugin-bases now also preserves custom view types when .base documents are normalized back from source mode so plugin-registered task-specific Bases views do not collapse to the fallback renderer
  • packages/plugins/plugin-canvas now includes focused Vitest coverage for the JSON Canvas serializer and Svelte Flow bridge, and packages/workspace now carries Playwright canvas smoke coverage that opens .canvas files, verifies the canvas renders without the old top banner, confirms the built-in controls stay anchored in the top-right corner, checks colored nodes and arrow-ended connectors render in the workspace shell, checks the loaded graph is fit into view, ensures dragged nodes stay clipped to the pane body, and seeds text, file, link, and group nodes together so runtime page errors such as Svelte effect loops fail the smoke path
  • packages/plugins/plugin-graph now includes focused Vitest coverage for graph assembly, orphan filtering, and local-graph depth derivation from metadata cache fixtures
  • packages/plugins/plugin-telemetry now includes focused Vitest coverage for the trace-tree helpers that drive the local telemetry waterfall and span-search behavior
  • packages/notebook now includes focused Vitest coverage for notebook parsing, dependency graph construction, DuckDB app-table registration, dedicated worker-client transport behavior, and cross-cell execution/value propagation
  • packages/notebook now also includes focused Vitest coverage that Safe Mode blocks active notebook execution commands before they hand work to the runtime
  • packages/workspace now has a Playwright browser regression suite for markdown rendering, exercising live-preview and source-mode heading gutter alignment, wrapped plain-indent guides, nested list rendering, live-preview blockquote widgets, source-mode markdown table reformatting on Tab and Enter, source-mode cm-table line styling, table widgets, and reading-view embeds against the real workspace shell
  • packages/workspace/e2e/pwa-title-bar.spec.ts now clones the production Window Controls Overlay media rules, injects simulated native-control blocker rectangles, and verifies pane-owned top-titlebar geometry stays in flow while interactive controls avoid those blocked regions on macOS and Windows, alongside sidebar split-inset checks, painted-icon visibility, blocker-based non-overlap for sidebar tab buttons, WCO border coverage (including a :root::before 1px divider probe at --workspace-safe-area-top, an outer top-tab border-bottom guard against active-tab notch leakage, and a [data-sidebar="rail"] extends-into-safe-area-strip assertion), an elementsFromPoint probe asserting the sidebar dock radio is the topmost paint at its own centre under WCO (regression guard against root pseudo-elements masking the icons), and reference screenshots clipped to the macOS top-left/top-right and Windows top-right corners under e2e/__screenshots__/pwa-title-bar.spec.ts/
  • packages/workspace/e2e/markdown-showcase.spec.ts opens the tracked e2e-vault/plugin-markdown/CodeMirror Layout Showcase.md content and checks source mode, live preview, and reading mode against the same fixture for tables, grid tables, quoted lists, indentation, wrapping, embeds, links, tags, math, and code rendering.
  • packages/workspace/e2e/csv-editor.spec.ts covers CSV table preview/source sync, 1-based row numbers, header edits, preview undo, column move menu, selection grips, and source-mode lint diagnostics against tracked e2e-vault/plugin-csv fixtures.
  • packages/plugins/plugin-markdown now also has focused widget regressions that exercise text-widget commit behavior on blur and Enter plus checkbox writes on change, which protects the shared frontmatter editor against focus-handoff and remount data loss
  • packages/workspace now also covers frontmatter editing regressions through the real shell, including live-preview property rename, File Properties checkbox commits against vault-backed note contents, and frontmatter-to-search propagation without a manual rebuild
  • packages/workspace now also includes focused Playwright coverage for open-note file lifecycle behavior, proving an active note retargets on rename and closes cleanly on delete instead of keeping stale leaf state
  • packages/workspace/e2e/markdown-hashtag-lint.spec.ts collapses both workspace sidebars and captures Chromium screenshot baselines for source-mode hashtag pills under synthetic cm-lintRange geometries (full-line wrap, prefix split, trailing lint after the tag name, mid-line tags, path tags, and dual-tag lines) via __LAPIS_SYNTHETIC_LINT__ without depending on markdownlint rule IDs
  • packages/workspace/e2e/markdown-lint-tooltip.spec.ts collapses both workspace sidebars before capturing Chromium screenshot baselines for markdownlint MD041 hover tooltips (lapis-lint-tooltip.svelte inside the Lapis-owned .cm-lapis-tooltip), verifies users can move from the lint range into the tooltip, checks MD041 marks the full source line and keeps both the lint gutter row and visible marker centered against the line-number gutter, verifies lint gutter markers also open that custom tooltip, and covers the inline problem widget opened through View Problem, including clipping and below-line placement regressions
  • packages/workspace now also exercises shared menu regressions through the real markdown workspace surface, including right-click table context-menu submenus plus pane-header dropdown menus, and asserts those paths no longer throw the previous Object.entries requires that input parameter not be null or undefined runtime error in Chromium
  • packages/workspace now runs its app Playwright suite against Chromium, matching the Electron renderer engine, and the workspace shell owns a canonical Chromium visual-regression fixture that seeds the file explorer plus a multi-tab, multi-split layout
  • packages/workspace now also includes focused Playwright coverage for grouped sidebar views, including real grouped panel rendering, group-menu and visible-panel basics, vertical grouped-panel resizing, serialized panel-size state, and expanded panel content filling the available pane body
  • packages/workspace/e2e/tab-drag-drop.spec.ts now includes focused deterministic drag-policy assertions alongside the browser flows, exercising explicit strategy overrides, auto mouse/touch/pen routing, activation thresholds, touch jitter tolerance, flick cancellation, and the held-drag initiation delay alongside the existing Playwright pointer regressions
  • packages/workspace now also includes focused Playwright coverage for Safe Mode recovery, covering a failing community plugin path that enters Safe Mode with community plugins disabled plus the visible targeted disable action, and a broken saved-layout path that proves workspace.loadLayout() rejects malformed layout JSON before the shell restarts with layout restore skipped
  • packages/workspace now also includes notebook Playwright coverage for notebook opt-in commands, starter cell insertion, SQL and table output rendering, chart output rendering, downstream markdown interpolation, loading-progress UI during initial notebook execution and stale reruns after notebook source changes, cursor-scoped notebook execution, notebook runtime package install and uninstall flows through the Packages side view, notebook runtime-status and output-restoration messaging in the notebook-owned status banner, and notebook-relative CSV loading in the legacy browser vault
  • packages/workspace now also includes a Chromium-scoped daily-use journey Playwright path that boots an OPFS vault, creates and renames notes, verifies search indexing, executes a notebook, reloads the shell, and confirms the renamed note plus restored notebook outputs survive restart on the supported browser shell; e2e/daily-use-journey.spec.ts plus pnpm test:e2e:daily-use run that journey through playwright.daily-use.config.ts, and CI plus pnpm docker:ci-check invoke it through root pnpm test:daily-use after the Electron smoke phase unless --skip-daily-use is passed
  • packages/workspace now also includes focused Playwright coverage for the search sidebar query input, proving shell clicks focus the CodeMirror editor with a visible caret and ArrowUp / ArrowDown recall persisted recent searches from the start of the query
  • packages/workspace now also includes Playwright coverage for the bundled Tasks plugin, exercising markdown task-note creation, completion toggling through mapped frontmatter writes, deletion, note-opening actions, custom task-folder plus field-role mappings, inline task conversion from the current line, selection, and note-wide batches for supported prefixed task candidates, reading-mode plus source-mode and live-preview convert buttons for supported prefixed Markdown task candidates, task-note summary widgets in reading mode, source mode, and live preview, compact task-link overlays in reading mode, source mode, and live preview, partial metadata extraction for hashtags plus explicit ISO due-date tokens, opening a generated Task List .base file through the custom task Bases renderer against the real workspace shell, and a Fizzy-board regression that verifies tasks land in the expected Maybe/Open/Done lanes without surfacing the previous Svelte effect-depth page error
  • packages/plugins/plugin-tasks now also carries adapter-backed TaskNotes validation coverage for a claimed core-lite bridge against tasknotes-spec 0.1.0-draft, checking canonical mapped writes plus strict completed-date, due-date, and temporal-order rules, alongside representative meta.*, date.*, field.*, config.*, validation.*, create_compat.create, op.*, and delete.remove operations plus explicit known-deviation metadata
  • packages/plugins/plugin-tasks now also carries focused package tests for inline-task line parsing and conversion, and packages/workspace/e2e/tasks.spec.ts covers the initial Create inline task Markdown-editor command flow alongside the existing Tasks list regressions
  • packages/workspace now also covers browser SQLite coordination with Playwright two-tab regressions that boot an OPFS vault, verify owner and proxy session modes, edit a markdown note from the proxy tab, assert delegated app-database search state updates without invalid named-bind runtime errors, and verify a proxy tab promotes itself after the owner tab closes
  • packages/workspace now includes e2e/app-boot-smoke.spec.ts plus pnpm test:e2e:smoke, which runs turbo run build --filter @lapis-notes/workspace, clears stored vault profiles, boots through the normal dev-server path with a fresh Browser (OPFS) vault, waits for visible shell readiness, asserts .workspace and core app services, and fails on startup page errors plus targeted renderer console diagnostics such as derived_inert warnings and Vite Failed to load source map messages; the smoke Playwright timeout now stays above the helper’s internal boot timeout so CI failures surface the startup checklist/message snapshot instead of a raw runner timeout, cold CI workers get extra first-boot headroom beyond local runs, timeout snapshots now report chooser-loading state/message as well as in-shell startup state, and the chooser submit path falls back to the Create vault button when Enter does not dismiss the dialog; the older dev-server-startup.spec.ts path still covers additional dev-server regressions
  • packages/workspace now includes e2e/app-boot-smoke.spec.ts plus pnpm test:e2e:smoke, which runs turbo run build --filter @lapis-notes/workspace, clears stored vault profiles once per Playwright browser context, boots through the normal dev-server path with a fresh Browser (OPFS) vault, waits for visible shell readiness, asserts .workspace and core app services, and fails on startup page errors plus targeted renderer console diagnostics such as derived_inert warnings and Vite Failed to load source map messages; the smoke Playwright timeout now stays above the helper’s internal boot timeout so CI failures surface the startup checklist/message snapshot instead of a raw runner timeout, cold CI workers get extra first-boot headroom beyond local runs, timeout snapshots now report chooser state plus chooser-loading state/message as well as in-shell startup state, and the chooser submit path falls back to the Create vault button when Enter does not dismiss the dialog; the older dev-server-startup.spec.ts path still covers additional dev-server regressions
  • packages/workspace/e2e/mobile-workspace-stage-gesture.spec.ts now covers stepped mid-screen touch pointer paths that must fully open left/right mounted sidebars (track translateX settles to 0 / -2 * sidebarWidth) and short swipes that snap back to center without opening a sidebar
  • packages/workspace/e2e/mobile-workspace-mode.spec.ts now covers the mobile workspace shell in Chromium, proving the shared renderer switches between auto, forced-desktop, and forced-mobile display modes through the registered workspace commands, and exercising the compact always-visible floating dock, hidden full view header plus visible editable mobile inline title inside the active view content, title scroll-out with the editor page, scroll-hidden top chrome, single-page mobile leaf viewport without the desktop root tab strip, floating left toggle, pointer-driven mounted-sidebar pan gestures with live pre-release transform updates, snap-back, touch-style reveal, and DevTools-style mouse close, body-only sidebar content with bottom name selectors, capped main-tab-only live mobile tab preview tiles, fixed open-tab count and Done controls, the mobile tab actions drawer, mobile app-owned menus rendered through drawers, left-sidebar search entry point without opening the command palette, settings sidebar recovery, and Vaul-backed bottom action drawer without runtime page errors; mobile-workspace-navigation.test.ts, mobile-inline-title.test.ts, mobile-workspace-stage-helpers.test.ts, mobile-sidebar-panel.test.ts, and mobile-scroll-chrome.test.ts also cover the mobile sidebar editor-stage state transitions, inline title fallback, deterministic reveal offsets, swipe input/direction decisions, pan snap-point decisions, sidebar selector labels, and scroll chrome state directly
  • packages/desktop-electron now includes e2e/app-boot-smoke.spec.ts plus pnpm test:e2e:smoke, which compiles main/preload and boots through the Vite dev server locally (or runs the full production build in CI), launches Electron with isolated user data and an Electron-safe environment that strips ELECTRON_RUN_AS_NODE, asserts the vault chooser and workspace mount, and fails on renderer or main-process startup errors plus the same targeted renderer console diagnostics before the broader startup-shell integration suite runs. Focused desktop E2E also covers the shared Plugin registry settings tab so registry UI changes cannot ship browser-only.
  • packages/desktop-electron now includes package-local Playwright Electron coverage that launches the built app with isolated user data, auto-selects ~/Documents/vault-copy, seeds and opens Untitled.md, asserts the visible note header, verifies native file-watching by writing a file outside the renderer, smoke-tests the available plugin-sidecar lifecycle plus initial brokered capabilities, exercises the pane-header Split right action, covers grouped sidebar rendering/menu/resizing behavior against the real packaged shell, verifies vault-backed transformers-js semantic indexing with an explicitly selected embedding model, confirms the packaged desktop app returns vector hits for that indexed vault data, settles the footer semantic-search status item back to its ready/completed state, and exercises native Markdown language-service diagnostics through desktop_ls_capabilities and desktop_ls_diagnostics without main-process sidecar failures
  • packages/workspace now also includes a Playwright History regression that seeds tracked file revisions, opens the History sidebar, launches the fullscreen compare overlay, asserts the vendored two-pane diff surface mounts through the real workspace shell without runtime import failures, verifies syntax-highlight overlay tokens render, exercises saving edits back through the editable current-file pane, and restores a selected revision through the overlay
  • e2e-vault is now the canonical tracked sample vault for broad manual and future automated app coverage. Its plugin-* folders provide documentation-like content for markdown, bases, canvas, csv, graph, search, history, notebook, pdf, slides, telemetry, notifications, markdown-lint, Harper, Tasks, and a vault-local manifest-only plugin-test community plugin. The plugin-csv folder documents CSV table preview, source rainbow highlighting, lint fixtures, and settings verification; see e2e-vault/plugin-csv/CSV Feature Tour.md. The plugin-test fixture also exercises declarative settings widgets (object groups, enums, lists, object grid, typed string formats, deprecation, and unsupported JSON fallback) through Settings → Community plugins → Plugin Test Fixture; see e2e-vault/plugin-test/Declarative Plugin Fixture.md and Configuration and Settings. The tracked source vault should remain clean; use pnpm e2e-vault:prepare before running workflows that mutate vault content.
  • most other packages lean more heavily on build, prepack, and svelte-check than on dedicated automated tests
  • manual desktop release paths run the same verification gates before building or uploading release assets unless explicitly skipped; see Release Management

What this means architecturally

  • the runtime package is the most obvious candidate for regression protection
  • view-layer and workspace-shell behaviors still depend heavily on manual validation outside the covered markdown, shell-visual, notebook, tasks, canvas, history, and startup slices
  • the workspace shell now has a small but concrete browser-level regression surface for markdown view rendering, which is the right place for geometry-sensitive bugs that unit tests miss
  • the desktop host now has a packaged Electron smoke path, so shared-renderer startup regressions can fail in automation instead of relying only on manual local host checks
  • plugin lifecycle now has targeted manager coverage, but layout persistence and workspace-shell plugin flows still need broader integration coverage
  • the spec now has a markdown style check that can be run independently or paired with mdbook build spec through Makefile targets

Documentation gap this spec addresses

Several package READMEs are still template defaults. That makes code inspection the main source of truth for architecture today. This book is intended to reduce that gap and give future tests and ADRs a stable narrative reference.

High-value future coverage

  1. broader workspace-shell integration for community plugin loading, dependency injection, and failed-view fallback beyond the current plugin-manager and Safe Mode slices
  2. metadata-cache to chunk and vector search propagation beyond the current frontmatter-driven search update coverage, including embedding invalidation
  3. multi-leaf and non-markdown rename/delete lifecycle behavior beyond the current active-note coverage
  4. markdown and bases view mode transitions beyond the current markdown rendering regression slice