Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,14 @@ jobs:
matrix:
# setup-node rewrites devEngines.runtime.version to this,
# so pnpm's managed runtime (onFail: download) actually runs scripts under it.
# 22.13.0 is the declared engines.node floor (the minimum the pinned pnpm@11.9.0
# can run on; Node 22 is maintenance LTS until 2027-04);
# These are the release lines the DEV toolchain supports — NOT the published
# engines.node floor, which the `floor-smoke` job defends on 22.13.0 instead.
# Pinning the floor here would hold every dev dependency to it: jsdom 30
# already requires ^22.22.2, and vite/oxlint sit 0.01 above 22.13.0.
# '22' is the latest 22.x (maintenance LTS until 2027-04);
# 24.16.0 is the current release used for development (devEngines);
# '26' is the latest of the Current line (active LTS from 2026-10) — early warning.
node-version: ['22.13.0', '24.16.0', '26']
node-version: ['22', '24.16.0', '26']
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand All @@ -85,6 +88,45 @@ jobs:
run: pnpm build
- name: Run tests
run: pnpm test
# Every matrix entry supports unflagged type-stripping (>=22.18.0), so this
# is the only place that covers the `.ts` config contract's modern-Node
# branch (scripts/floor-smoke.mjs's fifth check); `floor-smoke` below pins
# to 22.13.0 and only ever takes the old-Node branch. Bare `node` is
# correct here — actions/setup-node puts the matrix version on PATH.
- name: Run the floor smoke on the matrix Node
run: node scripts/floor-smoke.mjs

floor-smoke:
needs: check
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# 22.13.0 is the published packages' engines.node floor. This is the only job
# pinned to it: it runs the built dist under a bare `node`, so no dev
# dependency (jsdom, vitest, ...) is held to the end-user's Node version.
# pnpm itself is not exempt, though: the pinned pnpm@11.17.0 (root
# package.json) still runs `pnpm install`/`pnpm build` on this floor, so a
# future pnpm bump needs to stay runnable on 22.13.0 too.
- name: Setup Node.js and dependencies
uses: ./.github/workflows/setup-node
with:
node-version: '22.13.0'
- name: Restore package builds
id: dist-cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: packages/*/dist
key: dist-${{ hashFiles('packages/*/src/**', 'pnpm-lock.yaml', 'packages/*/tsup.config.ts') }}
# Fallback only: `needs: check` populates this exact cache key, so a miss means
# eviction. Building here would run tsup on the floor Node.
- name: Build packages
if: steps.dist-cache.outputs.cache-hit != 'true'
run: pnpm build
- name: Run the end-user floor smoke
run: node scripts/floor-smoke.mjs

docs:
runs-on: ubuntu-latest
Expand Down
44 changes: 34 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ svelte-vitals is a static code-health checker for SvelteKit — not a runtime We

## Verify commands

| Purpose | Command | Notes |
| -------------- | -------------------- | ------------------------------------- |
| Build | `pnpm build` | `pnpm -r build` |
| Typecheck | `pnpm typecheck` | `pnpm -r typecheck` |
| Test | `pnpm test` | `pnpm -r test` (vitest) |
| Lint | `pnpm lint` | `oxlint .` + `oxfmt --check .` |
| Format | `pnpm format` | `oxfmt --write .` |
| Publish checks | `pnpm check:publish` | publint + attw (`--profile esm-only`) |

CI (`.github/workflows/ci.yml`) runs four jobs: `lint`, `check` (build + typecheck + check:publish), `test`, `docs`. Run the relevant verify commands yourself and confirm they pass **before** claiming a task is complete.
| Purpose | Command | Notes |
| -------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Build | `pnpm build` | `pnpm -r build` |
| Typecheck | `pnpm typecheck` | `pnpm -r typecheck` |
| Test | `pnpm test` | `pnpm -r test` (vitest) |
| Floor smoke | `pnpm smoke` | needs `pnpm build` first — it runs the built `dist` under a bare `node`; locally that is the devEngines Node, not the floor, so the floor claim is what CI's `floor-smoke` job (pinned to 22.13.0) adds |
| Lint | `pnpm lint` | `oxlint .` + `oxfmt --check .` |
| Format | `pnpm format` | `oxfmt --write .` |
| Publish checks | `pnpm check:publish` | publint + attw (`--profile esm-only`) |

CI (`.github/workflows/ci.yml`) runs five jobs: `lint`, `check` (build + typecheck + check:publish), `test`, `floor-smoke`, `docs`. Run the relevant verify commands yourself and confirm they pass **before** claiming a task is complete.

## Package map

Expand All @@ -39,6 +40,29 @@ install`/`ci upgrade` bundle into scaffolded workflows.
## Hard rules

- **Core purity**: `packages/core/src/index.ts` states verbatim: "runtime-agnostic core (design §8). No `node:` imports, no I/O, no runtime-specific globals." All I/O is injected through the `Runtime` interface (`packages/core/src/runtime.ts`). Never add a `node:` import or direct I/O call inside `packages/core`.
- **Two Node floors, both jobs run the smoke**: the published packages promise
`engines.node: >=22.13.0` (end users); the dev toolchain is pinned by
`devEngines.runtime` and is free to require more. CI keeps these apart —
`test` runs the vitest suite on the release lines the toolchain supports
(`22` / `24.16.0` / `26`), then runs the built `dist` under a bare `node` on
that same matrix Node (`scripts/floor-smoke.mjs`); `floor-smoke` runs that same
script the same way, but pinned to 22.13.0. Running it on both floors is
deliberate: its `.ts`-config check branches on the host Node's type-stripping
support, so `floor-smoke` on 22.13.0 takes the old-Node branch (asserting the
CLI's guided error), while every `test` matrix entry supports unflagged
type-stripping and takes the modern-Node branch (asserting the `.ts` config
loads). That modern-Node assertion used to live in
`packages/cli/test/config-file.test.ts`; it was deleted once the smoke on the
`test` matrix covered it, since vitest's module runner transforms in-process
`import()` and could never reach the raw-Node behaviour either branch depends
on. So a dev dependency raising its Node floor is not a problem _for
dependencies the smoke actually executes_: jsdom 30 requires `^22.22.2` and
that is fine because `floor-smoke` never loads jsdom. pnpm itself, and the
build toolchain (tsup et al.), are not exempt — `floor-smoke` still runs
`pnpm install`/`pnpm build` on 22.13.0, so those stay floor-bound. Never pin
the `test` matrix back to 22.13.0, and never add a dev dependency to the
smoke — it must stay Node-builtins-only. Design doc:
`docs/superpowers/specs/2026-07-31-floor-smoke-design.md`.
- **Dependencies via catalog**: root `package.json` devDependencies are all pinned as `catalog:`; actual versions live in `pnpm-workspace.yaml`. Add/bump shared devDependencies there, not as literal versions in a package's `package.json`.
- **Changesets required**: any user-facing change needs `pnpm changeset`. Merging to `main` opens a release PR (Changesets bot). Internal-only / doc-only changes don't need one.
- **en/ja docs stay in sync**: `docs/src/content/docs/` (English) and `docs/src/content/docs/ja/` (Japanese) are updated together by convention — don't ship an English-only doc change if the Japanese equivalent exists.
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pnpm typecheck # tsc --noEmit
pnpm lint # oxlint + oxfmt --check
pnpm format # oxfmt --write
pnpm check:publish # publint + attw (--profile esm-only)
pnpm smoke # built dist under a bare node (engines.node floor) — run pnpm build first
pnpm bench # manual timing benchmark, never run in CI
```

Expand Down
Loading