Skip to content

Finish the AI setting: no model loads when AI is off - #190

Merged
K-Arthur merged 16 commits into
masterfrom
cursor/finish-ai-gate
Oct 30, 2026
Merged

K-Arthur merged 16 commits into
masterfrom
cursor/finish-ai-gate

Conversation

@K-Arthur

@K-Arthur K-Arthur commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Completes the AI gate from merged PR #162, plus the independent re-review of head ec885612e.

AI stays on for a fresh install (missing settings key). A corrupt or unreadable settings blob is treated as off and logged. The model-download host allowlist is unchanged. LICENSE, stable.json, and release-manifest.json are not touched.

Head: 7ced74e64. Merged current master (e114771, #189) into this branch. Conflicts were only CHANGELOG.md (both Security entries kept) and packages/editor/src/__tests__/openFileDedupe.test.tsx (master's DocumentCodec.encode(createDocument(name)) plus the extra helper comment). This PR's boot watchdog values and safe-mode-counter loadHome helper are unchanged. No user-visible UI changed in the merge, so the existing Enhance / Remove-background screenshots still apply.

Re-review fixes

  • Playwright screenshots write to testInfo.outputDir or VARVE_AI_SCREENSHOT_DIR. No hard-coded /opt/cursor/artifacts/screenshots.
  • Vitest resets the AI gate cache before every case. Tests that write the setting also notify. SemanticSearchTab mocks subscribeAiFeaturesEnabled. Storage listeners skip when window.addEventListener is missing. Worker preflight jobs pass aiEnabled: true.
  • Enhance with AI off hides Denoise, Restore + Upscale, Deblur, Deblur + Upscale, Photo cleanup+upscale, Photo AI upscale, Denoise only, and Deblur only. The Download model dialog does not open. The hint is Turn on AI features in Settings to use this. CPU methods stay. With AI on, the previous model options stay.

CI follow-up (a5b647c62 shard 12/24)

tests/e2e/crash/safe-mode-counter.spec.ts hit the 20s HTML boot watchdog ("Startup timed out / The application bundle loaded but never rendered") on a warm shard after privacy-network (79 other tests in that shard passed, including the next crash screenshot spec). This is the documented Vite-dev false timeout, not an AI-gate first-paint break.

  • Packaged builds still report at 20s.
  • Vite /src/main.tsx now extends that watchdog to 120s so a contended transform cannot replace the splash before React mounts.
  • The crash-loop spec now uses the suite navigation budget (300s goto, 180s Home, Reload if the boot error is already showing) and drops the extra reload() between gotos.

Visual evidence (real editor)

AI-off Enhance operations (Auto and Upscale only):

AI-off Enhance operations: Auto and Upscale only

AI-off Enhance presets (Recommended, Fast preview, Pixel art) plus the Settings hint:

AI-off Enhance presets without model presets

AI-off Enhance CPU methods (Pixel art, Fast, Balanced, Quality):

AI-off Enhance CPU upscale methods

AI-on Enhance still shows Denoise, Restore + Upscale, Deblur, Deblur + Upscale:

AI-on Enhance operations still include model options

AI-on Enhance still shows Photo cleanup + upscale and Photo AI upscale:

AI-on Enhance presets still include model presets

AI-off control-bar Remove background produces the Quick result:

AI-off control-bar Remove background Quick review

Other AI-off surfaces from the same Playwright run:

Home Assets hint
Design tab without AI Tools
Selection Sources without Select subject
Export dialog Quick only plus hint

Gate contract

  • Missing settings key, or a readable blob with no ai object: on
  • Corrupt JSON, thrown storage access, native store read error, garbage native value, or a worker with no snapshot: off, logged as [ai-gate]
  • Native store "true" only: on. Any other stored value: off
  • ai.enabled === false: off

Tests

  • Full Vitest at 8fec59bc6 (implementation head): 22680 passed, 23 skipped, 0 failed. Master eb1d23afd still had the intended openFileDedupe fixture failure; this branch keeps that fix. After merging Security policy, incident runbook and CI security scans #189, the helper matches master: DocumentCodec.encode(createDocument(name)) (2 passed).
  • Desktop startup unit: revealMainWindow.test.ts 7 passed (watchdog contract).
  • Playwright tests/e2e/settings/ai-enhance-gate.spec.ts: 2 passed.
  • Playwright tests/e2e/settings/ai-disabled-no-model-load.spec.ts: 1 passed.
  • Playwright tests/e2e/crash/safe-mode-counter.spec.ts: 1 passed locally; CI E2E 24/24 green on 42496687a.

Test plan

  • Targeted unit tests for the previously failing 11 files plus Enhance admission
  • Full Vitest vs master eb1d23afd: 0 new failures
  • Playwright Enhance + Remove-background screenshots
  • Merged master e114771 and resolved both conflicts
  • CI green on 7ced74e64

Checklist

  • CHANGELOG Unreleased > Security updated
  • No em dashes or "open source" added in user-facing review-fix copy
  • Commit(s) are signed off (git commit -s) once DCO is active

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

cursoragent and others added 14 commits October 23, 2026 02:09
The master switch now fails closed on a corrupt or unreadable settings
blob and stays on only for a missing key (fresh install). The three
ONNX workers enforce the same snapshot the main thread sends. Lens Blur
is hidden when AI is off. SAM2 Small decoder and both TrOCR parts are
hash-verified even when the digest is stored as sha256.

Co-authored-by: Kevin Arthur <K-Arthur@users.noreply.github.com>
Constructing ModelLoader used to HEAD bundled .onnx files and fetch the
catalog even after downloads were gated. Those probes now no-op when AI
is off so no model file is requested.
DownloadManager's registerModel wants the core catalog type, so the
integration test now only calls startDownload. The hash audit accepts
optional JSON fields from the on-disk manifest.
verify:affected's format:touched lane rejected the worker import order
and the AI-off Playwright spec wrapping. The Worker postMessage
interceptor now matches both browser overloads.
format:touched still failed on engine barrel exports and two test
wrappers. No behavior change.
Components that read the persisted AI gate from @varve/engine crashed
in tests whose engine mock omitted that export. Face-crop and semantic
search now keep the real gate (or a true stub). The open-file fixture
uses an encoded document so the second-tab case can actually decode.
Home visual search, Object Selection, subject proposal, and export/batch
cutout methods stayed clickable after the engine gate. They now hide and
point to Settings so turning AI off is not just a failed download.
Control-bar and shortcut Remove background now use Quick when AI is off
and no longer mention on-device ML. The native store treats only "true"
as on. The engine gate honours the legacy settings key, caches reads,
fails closed on a missing worker flag, and keeps configure/reset private.
Home, Design-tab AI Tools, and Enhance stay honest: non-AI upscale remains
usable, Asset Browser updates when the toggle changes.
The spec now fails if control-bar Remove background is missing, asserts
Home / Design / Selection Sources / export / Quick mask, and records
screenshots. Quick guidance no longer mentions AI Balanced when AI is off.
When AI features are off, Enhance keeps only CPU operations and presets,
blocks the model download dialog, and shows the Settings hint. Auto can
only resolve to a CPU method.

Unit tests now refresh the gate cache after writing the setting, mock
subscribeAiFeaturesEnabled, and skip the storage listener when
window.addEventListener is missing. Playwright screenshots write to
testInfo.outputDir (or VARVE_AI_SCREENSHOT_DIR) instead of a hard-coded
artifacts path.
The AI-on Playwright assertion used a regex that treated the plus in
Restore + Upscale as a quantifier, so a present option looked missing.
Preset options include descriptions, so an exact-label query missed
Photo cleanup + upscale even though the list was open.
Operations use exact labels so Deblur does not also match Deblur +
Upscale. Presets match the accessible name prefix because options
include descriptions.
Packaged builds still report at 20s. Vite serves /src/main.tsx one file at
a time, so a contended transform was replacing the splash with
"Startup timed out" before React could mount. The crash-loop Home spec
now uses the same navigation budget as the rest of the suite.
@K-Arthur
K-Arthur marked this pull request as ready for review October 23, 2026 11:00
cursoragent and others added 2 commits October 23, 2026 14:39
Resolve the two conflicts from #189 (e114771): keep both Security
changelog entries, and keep master's openFileDedupe helper
(DocumentCodec.encode(createDocument(name))) plus this branch's
watchdog and loadHome changes.
@K-Arthur
K-Arthur merged commit 30ec7a3 into master Oct 30, 2026
62 checks passed
@K-Arthur
K-Arthur deleted the cursor/finish-ai-gate branch October 30, 2026 16:12
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