Skip to content

Ship only each build's own better-sqlite3 prebuild; fix the e2e first-run wizard race in every spec - #54

Merged
iLevyTate merged 3 commits into
mainfrom
claude/gallant-babbage-mlfl4c
Oct 31, 2026
Merged

iLevyTate merged 3 commits into
mainfrom
claude/gallant-babbage-mlfl4c

Conversation

@iLevyTate

@iLevyTate iLevyTate commented Oct 31, 2026 •

Copy link
Copy Markdown
Owner

Summary

Two changes, both prompted by the startup follow-ups:

1. Ship only each build's own better-sqlite3 prebuild (431b4c1).

  • better-sqlite3 13 bundles N-API prebuilds for eight platform/arch combinations (about 16.9 MB). Only Windows excluded other OSes, and it still kept both win32 arches; macOS and Linux shipped all eight.
  • lib/binding.js getPrebuildPath() loads prebuilds/<platform>-<arch>.node, or linuxmusl-<arch>.node on musl Linux. Each platform now keeps only that file through an arch-expanded extglob (app-builder-lib expands ${arch} per packed arch, as Close the startup follow-ups' known limitations: driver-version reset, embedding worker, x64 payload, Linux raster #53 already relies on for the node-llama-cpp prebuilts):
    • win.files: !**/node_modules/better-sqlite3/prebuilds/!(win32-${arch}).node
    • mac.files: !**/node_modules/better-sqlite3/prebuilds/!(darwin-${arch}).node
    • linux.files: !**/node_modules/better-sqlite3/prebuilds/!(linux-${arch}|linuxmusl-${arch}).node
  • Estimated savings: about 15 MB / 7 files per macOS build, about 12 MB / 6 files per Linux build, one more 2 MB file per Windows build. Linux keeps the same-arch musl prebuild because binding.js selects it when glibc is absent (2.4 MB; cannot be tested here, so kept).
  • Without its own prebuild binding.js falls back to build/Release, which is not packaged, so SQLite would fail to load. verify-packaged-artifacts.js now requires each build's prebuild on Windows, macOS and Linux and fails if one for another platform or arch is packaged.
  • docs/RELEASING.md (payload-trim table) and the CHANGELOG [Unreleased] describe the change.

2. Fix the e2e first-run wizard race for every spec (c6d263a, c2ec12e).

  • In a model-less E2E profile the first-run model setup wizard opens about 2 s after ready, after waitForAppReady's single dismissModals() pass; its aria-modal overlay then swallowed the "Relate" click in Search Modal - Cluster Context Menu on this PR's first e2e-smoke (ubuntu-latest) run (1 failed, 2 flaky). 32 of the 40 specs that launch the app (six in the CI smoke list) had the same race; only eight called dismissModelSetupWizard().
  • waitForAppReady() now takes dismissModelWizard (default: the value of dismissModals) and, when set, waits for and skips the wizard last. Callers that keep modals open on purpose (dismissModals: false, e.g. the accessibility audit of the wizard) still get it untouched.
  • dismissModelSetupWizard() remembers windows whose wizard it skipped (skipping latches it closed for that renderer session), so the explicit calls already in eight specs return at once instead of waiting 7 s.
  • c6d263a first added explicit calls to search-modal.spec.js; c2ec12e moves the fix into the helper and returns that spec to plain waitForAppReady(). Net change to the spec: none.
  • Cost: about the 2 s the wizard takes to open per launch, or up to 7 s when no wizard appears.

Scope

  • Area(s): packaging (electron-builder.json), release verification script, E2E helper, docs
  • Risk Level: low to medium (the prebuild rules are only exercised by packaged builds, guarded by verify-packaged-artifacts.js in every release job; the E2E helper change affects every spec's startup)
  • Breaking Changes: none

Type of Change

  • Bug fix
  • Enhancement
  • New feature
  • Refactor
  • Documentation update
  • Breaking change

Test Plan

Automated

  • npm run format:check
  • npm run lint
  • npm test (as part of npm run ci on 431b4c1: 774 suites, 11,231 passed, 26 skipped, coverage thresholds met; audit:production 0 vulnerabilities; build OK)
  • Additional tests added/updated when behavior changed: electron-builder-config.test.js checks all six platform/arch builds with app-builder-lib's own node_modules filter; verifyPackagedArtifacts.test.js covers the prebuild policy, a missing own prebuild, a foreign-arch prebuild and the Linux musl allowance.

Also: app-builder-lib's validateConfiguration accepts all three builder configs; the two unit test files pass with the starting platform faked to darwin and win32 (80/80 each). E2E locally under xvfb-run: with explicit per-spec dismissal the two describes that failed passed 4/4 and the first 28 search-modal tests passed, with the wizard detected and skipped in each; the full CI smoke list is running locally against the helper version.

Manual QA

  • Manual checklist completed (see docs/TESTING.md)
  • Not applicable (explain below)

Manual QA notes:

  • Packaged builds are not produced in CI for PRs; the release workflows' verify-packaged-artifacts.js step now fails if a build lacks its own SQLite prebuild or carries another platform's.

Checklist

  • I scoped this PR to one logical change
  • I self-reviewed code and naming for clarity
  • I updated docs/config references where needed
  • I called out follow-up work or known limitations

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q5Uo5hC58DRSh1qB489Sos

…atform

better-sqlite3 13 bundles N-API prebuilds for eight platform/arch
combinations (about 16.9 MB). Only Windows excluded the other OSes, and
it still kept both win32 arches; macOS and Linux shipped all eight.

lib/binding.js getPrebuildPath() loads prebuilds/<platform>-<arch>.node,
or linuxmusl-<arch>.node on musl Linux, so each platform now keeps only
that file through an arch-expanded extglob (app-builder-lib expands
${arch} per packed arch):
- win.files:   !(win32-${arch}).node
- mac.files:   !(darwin-${arch}).node
- linux.files: !(linux-${arch}|linuxmusl-${arch}).node
Estimated savings: about 15 MB / 7 files per macOS build, about 12 MB /
6 files per Linux build, one more 2 MB file per Windows build.

Without its own prebuild binding.js falls back to build/Release, which
is not packaged, so verify-packaged-artifacts now requires each build's
prebuild and fails if one for another platform or arch is packaged.
electron-builder-config.test.js checks all six platform/arch builds
with app-builder-lib's own node_modules filter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5Uo5hC58DRSh1qB489Sos

Copy link
Copy Markdown
Owner Author

e2e-smoke (ubuntu-latest) failed on 431b4c1: test/e2e/search-modal.spec.js:1093 › Search Modal - Cluster Context Menu › should have cluster visualization in graph view (plus two flaky tests in the same file), 88 passed. Each timed out clicking the "Relate" button because an element inside a role="dialog" overlay intercepted the click; that element is the step list of ModelSetupWizard.jsx ("Set up on-device AI").

This PR does not cause it: it changes only electron-builder.json files patterns, scripts/verify-packaged-artifacts.js, their unit tests and docs. The e2e job runs the app from the source build, where electron-builder's file filters are never applied. e2e-smoke (windows-latest) passed on the same commit, and the push runs on main (#50 to #53) passed e2e.

Cause: the Cluster Context Menu and Quick Actions on Hover describes call only waitForAppReady(), whose single dismissModals() pass can run before the model setup wizard mounts. test/e2e/helpers/electronApp.js documents exactly this race at dismissModelSetupWizard(): a late wizard's aria-modal overlay swallows later clicks. Other specs call that helper after waitForAppReady(); these two describes do not.

Fix (not pushed here, to keep this PR to one change): add await dismissModelSetupWizard(window); after waitForAppReady(window) in those two beforeEach blocks. I will re-run the failed job once when this workflow run finishes.


Generated by Claude Code

…etup

In a model-less E2E profile the first-run model setup wizard opens about
2 s after the app is ready, after waitForAppReady's single
dismissModals() pass. Its aria-modal overlay then swallows clicks: on
PR #54's e2e-smoke (ubuntu-latest) it intercepted the "Relate" tab in
"Search Modal - Cluster Context Menu" (1 failed, 2 flaky).
test/e2e/helpers/electronApp.js documents this race at
dismissModelSetupWizard(), and seven other specs already call it after
waitForAppReady; search-modal.spec.js did not.

Every beforeEach in the file now calls dismissModelSetupWizard(window)
after waitForAppReady (before ensureAdvancedExperienceMode where present).
Locally under xvfb the two failing describes pass 4/4, with the wizard
detected and dismissed in each test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5Uo5hC58DRSh1qB489Sos
@iLevyTate iLevyTate changed the title Ship only each build's own better-sqlite3 prebuild on every platform Ship only each build's own better-sqlite3 prebuild; fix the search-modal e2e wizard race Oct 31, 2026
The previous commit added dismissModelSetupWizard() to every
search-modal setup, but 32 of the 40 specs that launch the app (six of
them in the CI smoke list) share the same race: the first-run model
setup wizard opens ~2 s after ready in a model-less E2E profile, after
waitForAppReady's single dismissModals() pass, and its aria-modal
overlay then swallows later clicks.

Fix it once in the helper instead of at 112 call sites:
- waitForAppReady() takes dismissModelWizard (default: the value of
  dismissModals) and, when set, calls dismissModelSetupWizard() last.
  Callers that keep modals open on purpose (dismissModals: false, e.g.
  the accessibility audit of the wizard) still get it untouched.
- dismissModelSetupWizard() remembers windows whose wizard it skipped:
  skipping latches the wizard closed for that renderer session, so the
  explicit calls already in eight specs return at once instead of
  waiting 7 s for a wizard that cannot reopen.
- search-modal.spec.js goes back to plain waitForAppReady().

Costs about the 2 s the wizard takes to open per launch, or up to 7 s
when no wizard appears.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5Uo5hC58DRSh1qB489Sos
@iLevyTate iLevyTate changed the title Ship only each build's own better-sqlite3 prebuild; fix the search-modal e2e wizard race Ship only each build's own better-sqlite3 prebuild; fix the e2e first-run wizard race in every spec Oct 31, 2026
@iLevyTate
iLevyTate merged commit 6a4e70c into main Oct 31, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants