Skip to content

build: run svelte-check on TypeScript 6 and guard svelte/internal in .ts files - #2225

Merged
chhoumann merged 9 commits into
masterfrom
fix/svelte-check-exit-code
Oct 12, 2026
Merged

chhoumann merged 9 commits into
masterfrom
fix/svelte-check-exit-code

Conversation

@chhoumann

@chhoumann chhoumann commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Summary

#2224 left two gaps in pnpm run lint. When the native TypeScript executable cannot start, svelte-check --tsgo exits 0 with no errors, even for an imported component with a type error. svelte-check 4.7.6, the latest release, ignores the native compiler's exit status. The Oxlint port also applied the svelte/internal import guard only to .svelte.ts files, while ESLint covered every .ts file.

check now runs svelte-check on the TypeScript 6 path, which reports the type error. tsc keeps the native compiler, which exits 1 on a type error and on a missing executable.

Changes

  • check is svelte-check --fail-on-warnings. The tsconfig and Oxlint ignores for .svelte-check are removed because they had no effect. The .gitignore entry stays for overlays that earlier --tsgo runs left behind.
  • The svelte/internal selector is its own Oxlint rule, quickadd/svelte-internal, on every .ts file. quickadd/svelte-runes keeps the store and dispatcher guards on .svelte.ts files. The component checker's rules are unchanged.
  • tests/tooling/svelteCheck.test.ts runs the check command with the native compiler unable to start and requires it to fail on a component type error. The strict-check test moved there too. The Oxlint fixture test now covers svelte/internal in .ts, .svelte.ts, and .test.ts files.
  • Release verification no longer runs pnpm run check a second time after pnpm run lint.

This PR leaves out unimported components. Neither svelte-check path sees them under the **/*.ts include, which predates #2224, and lint:svelte already rejects a malformed one. The policy checker's rule gaps belong to the shared svelte-policy package.

pnpm run check is slower, because the TypeScript 6 checker runs in JavaScript and checks every .ts file again. --tsgo-experimental-api was rejected because it also exits 0 when the native compiler is missing.

Testing / validation

  • One reproduction script, run on master and on this branch. With the native executable removed and an imported type error, check and lint go from exit 0 to exit 1. A svelte/internal import in .ts and .test.ts files takes lint:native from exit 0 to exit 1. Deleting a component after a check passes on both.
  • pnpm install --frozen-lockfile, pnpm run build-with-lint, and pnpm run test pass (7,019 passed, 28 skipped). main.js and styles.css are byte-identical to master.
  • pnpm run check: 2.3 s → 8.9 s, median of 5 alternating runs per side.

Release impact: none. The bundle is unchanged, and build: requests no release.

Checklist

Note

Run svelte-check on TypeScript 6 and split svelte-internal guard into its own rule

  • Removes --tsgo from the check script so svelte-check runs on the TypeScript 6 API package, while tsc keeps using the native compiler
  • Splits the Oxlint plugin: quickadd(svelte-internal) now reports svelte/internal imports, and quickadd(svelte-runes) keeps only the svelte/store and createEventDispatcher checks (tooling/oxlint-plugin.mjs)
  • Enables the new quickadd/svelte-internal rule at error severity for all **/*.ts files, including .svelte-check/ overlay paths
  • Extracts the strict svelte-check test into svelteCheck.test.ts with shared temp-workspace helpers, and adds a test that svelte-check still reports type errors when the native tsc binary cannot start
  • Behavioral Change: quickadd(svelte-runes) no longer flags svelte/internal imports, and the release workflow no longer runs pnpm run check (lint and test remain)

Macroscope summarized 3be3032.

Summary by CodeRabbit

  • Developer Tooling
    • Svelte checks now use the native compiler and continue to fail on warnings. Checks also catch additional Svelte import-policy violations across TypeScript files.
  • Tests
    • Added coverage for Svelte-check diagnostics, including accessibility, unused CSS, and type errors.
  • Documentation
    • Updated guidance for running and interpreting Svelte checks.
  • Chores
    • Release verification no longer runs the separate check command; linting and tests remain in place.

Both tests fail on master. svelte-check --tsgo exits 0 with zero diagnostics when the native TypeScript executable cannot start, and Oxlint applies the svelte/internal guard only to .svelte.ts files.
svelte-check 4.7.6 under --tsgo ignores the native compiler's exit status, so pnpm run check and pnpm run lint passed a component type error when the native executable could not start. The TypeScript 6 path reports it. tsc keeps the native compiler, which fails on a type error and on a missing executable.
Only svelte-check --tsgo and --incremental write .svelte-check, and check uses neither. TypeScript's ** pattern already skips dot-directories, and Oxlint lints only src and tests.
ESLint's svelte/no-svelte-internal covered every linted .ts file. The Oxlint port enabled the selector only through quickadd/svelte-runes on .svelte.ts files. It is now its own rule on **/*.ts, and svelte-runes keeps only the store and dispatcher guards.
…re basenames

The preload uses module.registerHooks, which Node 22.15 added, and package.json allows Node 22.12. Oxlint prints file:// URLs in JetBrains terminals, so the guard assertions compare file basenames.
svelte-check --tsgo and --incremental leave the directory behind, and checkouts that ran check after #2224 already have one.
The strict-check test moves next to the native-compiler test. Both read the check command from package.json in one place, and the preload extends NODE_OPTIONS instead of replacing it.
pnpm run lint already ends with pnpm run check.
Also label the .gitignore entry and restore the README condition that svelte-check must run on the native compiler's API before the TypeScript 6 package can go.
@coderabbitai

coderabbitai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d3657a09-a632-441e-8f3f-9b1b534fa5e0

📥 Commits

Reviewing files that changed from the base of the PR and between e4133fa and 3be3032.


📒 Files selected for processing (9)
  • .github/workflows/release.yml
  • .gitignore
  • .oxlintrc.syntax.json
  • package.json
  • tests/tooling/svelteCheck.test.ts
  • tests/tooling/sveltePolicy.test.ts
  • tooling/README.md
  • tooling/oxlint-plugin.mjs
  • tsconfig.json

💤 Files with no reviewable changes (1)
  • .github/workflows/release.yml

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.



📝 Walkthrough

Walkthrough

The Svelte tooling changes split internal-import and runes lint checks, update the Svelte-check command and its validation tests, and revise related configuration and documentation. The release workflow no longer runs pnpm run check; lint and tests remain.

Changes

Svelte tooling checks

Layer / File(s) Summary
Separate Svelte import policy
tooling/oxlint-plugin.mjs, .oxlintrc.syntax.json, tests/tooling/sveltePolicy.test.ts, tooling/README.md
The Oxlint plugin now registers separate svelte-internal and svelte-runes rules while retaining the combined svelteImportGuards export. The internal-import rule applies to TypeScript files, and policy tests check diagnostics for .ts, .svelte.ts, and .test.ts files.
Svelte-check command and validation
package.json, tsconfig.json, .oxlintrc.syntax.json, .gitignore, tests/tooling/svelteCheck.test.ts, tests/tooling/sveltePolicy.test.ts, .github/workflows/release.yml, tooling/README.md
The check command uses svelte-check without --tsgo and retains --fail-on-warnings. New tests check warning, type-error, legacy-reactivity, and native-compiler-startup failure cases. The Svelte-check overlay directory is no longer excluded by the listed configurations. The release workflow removes pnpm run check, and the documentation describes the updated command and verification.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix


Merge Risk: ⚪ Minimal · up to 3be30

The tooling changes appear ready to merge after normal checks; no specific outstanding failure is established.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 3 files. (5 skipped: 5 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly identifies the two main changes: updating the svelte-check TypeScript 6 path and adding svelte/internal protection for TypeScript files.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 3 files. (5 skipped: 5 unsupported.)


  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

I’m a rabbit with a checklist bright,
I test each warning, type, and bite.
Internal imports meet their rule,
Runes checks keep their scope in view.
I hop through checks and leave them right.

Comment @coderabbitai help to get the list of available commands.

@chhoumann

Copy link
Copy Markdown
Owner Author

Independent verification: PASS+NOTES

  • Head: 3be3032d3d99428ac13317cca9ee225a853b4790
  • Base master: e4133fa3b473ac1025b9ead4345af216cc2d24fc
  • Patch-id (git diff e4133fa3...3be3032d | git patch-id --stable): da2b0a2dd7ea36451c4e34ca7298f2245b5edbec (matches)

I tested two detached worktrees, each with its own pnpm install --frozen-lockfile (Node 24.19.0, pnpm 10.32.1). Every result below comes from the real pnpm scripts. For the native-missing cases I renamed node_modules/.pnpm/@typescript+typescript-linux-x64@7.0.2/.../lib/tsc inside that worktree only. node_modules/.pnpm is a real local directory in both worktrees, and the file was restored with an unchanged sha256.

Claim Command and setup master head
1 pnpm run check, probe Probe.svelte type error imported by entry.ts, native tsc present (control) 1 1
1 pnpm exec tsc --version, native tsc missing 1 (Executable not found) 1 (Executable not found)
1 pnpm run check, same probe, native tsc missing 0 (59 FILES 0 ERRORS) 1 (Probe.svelte 1:25 Type 'string' is not assignable to type 'number')
1 pnpm run lint, same probe, native tsc missing 0 1 (fails in check on Probe.svelte)
1 pnpm run check, no probe, native tsc missing (control) 0 0
2 pnpm run lint:native, svelte/internal in src/qa_probe/internal.ts and tests/qa_probe/internal.test.ts 0 1 (quickadd(svelte-internal) on both files)
2 pnpm run lint:native, probes removed 0 0
3 pnpm run check with Comp.svelte importing ./helper 0 0
3 pnpm run check after deleting both 0 0
3 .svelte-check/ written yes (119 files, stale ++Comp.svelte.ts kept) no (never created in any head run)
4 pnpm run build-with-lint 0 0
4 main.js sha256 d83aa6eeaa77bbcfe0e3574f3ab1e67c57469506074c43f5e67087bf64ae6127 identical
4 styles.css sha256 9467ef3622cd1137ce5a0148e16de23b9f5be87bc8c204fb6050c48f8f29994d identical
4 pnpm-lock.yaml - unchanged
5 pnpm run test - 0 (501 files passed, 6 skipped; 7019 tests passed, 28 skipped)

Extra checks:

  • I copied head's tests/tooling/svelteCheck.test.ts into master as a probe and ran it against master's check script. The native-missing test fails there (expected +0 to be 1), and the warnings test passes. Both tests run and pass on head (Node 24, so module.registerHooks exists and the second test is not skipped). The new regression test catches the bug.
  • I copied master's leftover .svelte-check/ (including stale overlays for a deleted component) into head and ran head's tsc -noEmit -skipLibCheck, pnpm run check and pnpm run lint:native. All three exited 0, and check counted the same 1509 files as a clean run, so dropping the .svelte-check excludes is safe for checkouts that still have the old directory.
  • The diff touches only tooling, config, tests, docs and the release workflow. Nothing in src/ changes, which the identical bundle hashes confirm. pnpm run check leaves release verification safely, because pnpm run lint already runs it, and CI still runs it through build-with-lint.

Notes (not blocking):

  1. pnpm run check is about 4x slower on head: 9.9 to 13.9 s against 2.5 to 3.0 s on master (3 runs each). build-with-lint takes 13.2 s against 6.6 s. The TypeScript 6 path checks 1509 files, where --tsgo checked 58. That is the cost of the fix.
  2. .ts files are now type-checked twice with different compiler versions: TypeScript 7 in tsc -noEmit and TypeScript 6 in svelte-check. Any future difference between TS 6 and TS 7 will show up as a failure in only one of the two. None appeared in this run.

All probes were removed and the renamed native tsc was restored in both worktrees. git status is clean on both sides.

@chhoumann
chhoumann merged commit d57eb15 into master Oct 12, 2026
15 checks passed
@chhoumann
chhoumann deleted the fix/svelte-check-exit-code branch October 14, 2026 06:23
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.

1 participant