286 lines · 10.7 KB · TOML
RawDownload
# Task orchestration for the repository gate.## `pnpm check` used to run seven stages in series (~6 min) and re-ran every one# of them even when a change could not possibly affect them. The stages here are# the same commands, still defined once in package.json, but mise runs them in# parallel and skips any whose declared `sources` have not changed since the# last successful run.## Rust stays on rustup: the Tauri targets, and the toolchain the release# workflow signs with, are managed there, and a second toolchain manager owning# the same `cargo` would only be a way to drift. [tools]# The same major as CI (.github/actions/setup-pnpm/action.yml, release.yml):# a test that passes on a newer local Node can still fail there.node = "22"pnpm = "10.13.1" # Vitest, tsc, and cargo each saturate several cores on their own, so the four# heavy stages are already enough to fill a laptop. Raising this mostly makes# every stage slower.[settings]jobs = 4 [tasks.i18n-check]description = "Extract catalogs, fail on drift, compile, and run the coverage guard"run = "pnpm i18n:check"# The catalogs are both an input and an output of this stage. Compiled `.js`# catalogs are generated, so they must not feed the freshness check.sources = [  "src/**/*.{ts,tsx}",  "!src/locales/**/*.js",  "lingui.config.ts",  "src/locales/**/*.po",  "scripts/check-i18n-coverage.mjs",  "scripts/i18n-unlocalized-baseline.txt",  ".oxlintrc.json",] # knip rides along: it reads the same trees plus scripts/, and keeps unused# files, dependencies and exports from creeping back in. So does# perf:evidence, which recomputes the benchmark tables in docs/performance*.md from# their retained runs (scripts/check-perf-evidence.mjs).[tasks.lint]description = "Oxlint over src and tools (the warning cap is a debt ratchet — lower it, never raise it), knip, and the benchmark-table evidence check"run = ["pnpm lint", "pnpm knip", "pnpm perf:evidence"]sources = [  "src/**",  "docs/performance.md",  "docs/performance-history.md",  "docs/performance-data/**",  "!src/locales/**/*.js",  "tools/**",  "scripts/**",  "knip.json",  ".oxlintrc.json",  "tsconfig.json",  "package.json",  "pnpm-lock.yaml",] [tasks.test]description = "Vitest suite"run = "pnpm test"sources = [  "src/**",  "!src/locales/**/*.js",  # Vitest also discovers script-level tests, whose imported implementation  # modules must invalidate this stage just like src/ does.  "scripts/**",  # scripts/agent-quality-eval.test.ts grades the committed agent transcripts.  "evals/**",  # Compatibility tests execute the shipping script and check its HTML order.  "public/polyfills.js",  "index.html",  # Invariant tests read the Rust sources and embedded skills, the Tauri  # config and capabilities, the tutorial templates and fixtures, and the  # shipped notices (tauri-security-config, window-layout, native-locale,  # open-slide-skill, board-store, third-party-notices, ...).  "src-tauri/src/**",  "src-tauri/tauri.conf.json",  "src-tauri/capabilities/**",  "src-tauri/templates/**",  "src-tauri/tests/fixtures/**",  "THIRD_PARTY_NOTICES.md",  "vitest.config.ts",  "tsconfig.json",  "package.json",  "pnpm-lock.yaml",] [tasks.build]description = "Typecheck and produce the production web bundle"run = "pnpm build"sources = [  "src/**",  "!src/locales/**/*.js",  "index.html",  # `tools/` is not a build input, but tsc typechecks it (tsconfig.json  # `include`), and this stage runs tsc before vite.  "tools/**",  "vite.config.ts",  # The Timeless font plugin vite.config.ts imports (the fonts themselves live  # outside the checkout, so a new copy of them does not invalidate this stage).  "scripts/private-fonts.ts",  # The React Compiler suppression list vite.config.ts imports.  "scripts/react-compiler-suppressions.ts",  "tsconfig.json",  "tsconfig.node.json",  "package.json",  "pnpm-lock.yaml",  "public/**",  "scripts/app-size-report.mjs",  "scripts/app-size-report-selftest.mjs",  "scripts/check-webkit-compat.mjs",  # Copied out of pdfjs-dist by vite.config.ts on every build; an input that the  # build itself rewrites can never be fresh.  "!public/pdfjs/**",]outputs = ["dist"] # The public literature Worker is a separate pnpm project with its own# lockfile, so the root install never sees it and none of the stages above# cover it. Its typecheck and test are not root package.json scripts, so they# are spelled out here rather than wrapped.## The tests run on @cloudflare/vitest-pool-workers, which starts a local workerd# and simulates the bindings declared in wrangler.jsonc. No Cloudflare account# or `wrangler login` is needed; only a deploy talks to Cloudflare.[tasks.literature-worker]description = "Typecheck and test the literature Worker (its own pnpm project)"run = [  # Its own lockfile, so a fresh worktree has none of its packages yet.  "pnpm --dir literature-worker install --frozen-lockfile",  "pnpm --dir literature-worker typecheck",  "pnpm --dir literature-worker test",]sources = [  "literature-worker/src/**",  "literature-worker/test/**",  "literature-worker/tsconfig.json",  "literature-worker/vitest.config.ts",  "literature-worker/wrangler.jsonc",  "literature-worker/package.json",  "literature-worker/pnpm-lock.yaml",] [tasks.cargo-fmt]description = "rustfmt check (CI enforces this; it used to be missing from the local gate)"run = "cargo fmt --manifest-path src-tauri/Cargo.toml --all -- --check"sources = ["src-tauri/**/*.rs", "!src-tauri/target/**"] [tasks.cargo-test]description = "Rust unit and integration tests"run = "cargo test --manifest-path src-tauri/Cargo.toml"sources = [  "src-tauri/**/*.rs",  "src-tauri/src/**/*.c",  "src-tauri/src/**/*.sh",  "!src-tauri/target/**",  "src-tauri/Cargo.toml",  "src-tauri/Cargo.lock",  "src-tauri/tauri.conf.json",  "src-tauri/capabilities/**",  # Compiled in through include_str!/include_bytes!: the templates, the test  # fixtures, and the frontend files macos_window.rs pins the title bar to.  "src-tauri/templates/**",  "src-tauri/tests/fixtures/**",  "src/app/use-native-window.ts",  "src/App.css",  "src/styles/app-shell.css",  "src/styles/foundations.css",] [tasks.clippy]description = "Clippy with warnings denied"run = "cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets --all-features -- -D warnings"sources = [  "src-tauri/**/*.rs",  "src-tauri/src/**/*.c",  "src-tauri/src/**/*.sh",  "!src-tauri/target/**",  "src-tauri/Cargo.toml",  "src-tauri/Cargo.lock",  "src-tauri/tauri.conf.json",  "src-tauri/capabilities/**",  # Compiled in through include_str!/include_bytes!: the templates, the test  # fixtures, and the frontend files macos_window.rs pins the title bar to.  "src-tauri/templates/**",  "src-tauri/tests/fixtures/**",  "src/app/use-native-window.ts",  "src/App.css",  "src/styles/app-shell.css",  "src/styles/foundations.css",] # Aggregated third-party notices. ~2 s, which is why it belongs here rather than# in the "run it by hand and hope" category: THIRD_PARTY_NOTICES.md is a legal# artifact, and the way it rots is that someone adds a dependency and nobody# regenerates.## `--allow-unresolved` is deliberate. The generator exits 2 when a package# declares a license but ships no text and none was found in its repository# either (`pnpm notices --fetch-upstream` recovers the rest into# licenses/upstream/). That is a standing condition recorded in the file itself,# not drift, and a gate that is red on every run is a gate people learn to# ignore. This stage checks only that# the generated section matches the installed trees; run `pnpm notices` to see# the gaps, which it still prints in full.## The sidecar closure is skipped unless `src-tauri/synara-runtime/` happens to be# staged from the current pin, since `pnpm check` normally runs against the# placeholder stub. When it is absent or stale the previously generated section# is carried over untouched and only the npm and crates closures are verified —# the generator says so on stderr.## CI runs the same check in its `lint-and-build` job.[tasks.notices]description = "Check THIRD_PARTY_NOTICES.md against the installed npm and crates trees"run = "pnpm notices:check"# The closures are read from node_modules and the cargo registry, so the# lockfiles are the freshness signal; the generated output and the vendored# license texts are inputs too, because editing either is drift.sources = [  "package.json",  "pnpm-lock.yaml",  "src-tauri/Cargo.toml",  "src-tauri/Cargo.lock",  "scripts/generate-notices.mjs",  "scripts/lib/util.mjs",  "scripts/lib/package-notices.mjs",  "scripts/lib/license-classification.mjs",  "scripts/lib/license-grouping.mjs",  "scripts/lib/dependency-closures.mjs",  "scripts/lib/upstream-licenses.mjs",  "public/licenses/**",  "licenses/**",  "THIRD_PARTY_NOTICES.md",] # The interaction benchmark CI gates on (docs/performance.md). Not part of# `check`: it drives a local Chrome, then Playwright's WebKit# (`pnpm exec playwright-core install webkit` once), for a few minutes each,# and its counts are meant to be read on an otherwise idle machine.[tasks.perf-bench]description = "Interaction benchmark: fail when a gated count exceeds its ceiling in scripts/perf-bench/budgets.json (Chromium) or budgets-webkit.json (WebKit), or a layout check fails in either engine"run = ["pnpm perf:bench --check --layout", "pnpm perf:bench --check --layout --engine webkit"] # The Open Slide presentation server is another nested pnpm project, staged# into the app by scripts/prepare-presentation-runtime.mjs. Its tests run on# node:test against server.mjs; the install is frozen and fast, so it runs# here rather than being a separate setup step to forget. Staging prunes the# installed tree and then serves the editor from it, so it proves the pruned# runtime still has everything the editor, decks, and exports load.[tasks.open-slide-runtime]description = "Test the Open Slide presentation server (its own pnpm project) and stage its pruned runtime"run = [  "pnpm --dir tools/open-slide-runtime install --frozen-lockfile",  "pnpm --dir tools/open-slide-runtime test",  "node scripts/prepare-presentation-runtime.mjs",]sources = [  "tools/open-slide-runtime/*.mjs",  "tools/open-slide-runtime/package.json",  "tools/open-slide-runtime/pnpm-lock.yaml",  "tools/open-slide-runtime/patches/**",  "src-tauri/src/presentation.rs",  "scripts/prepare-presentation-runtime.mjs",  "scripts/check-presentation-runtime.mjs",  "src-tauri/templates/tutorial/**",] [tasks.check]description = "THE gate: everything CI runs, in parallel, skipping unchanged stages"depends = [  "i18n-check",  "lint",  "test",  "build",  "literature-worker",  "open-slide-runtime",  "cargo-fmt",  "cargo-test",  "clippy",  "notices",]