Skip to content

Commit 7dbb331

Browse files
committed
ci(typecheck): every package type-checks or is ledgered — the tsup hole becomes a ratchet (#4311)
66 of 77 workspace packages build with tsup (esbuild transpile, no type check), vitest never type-checks, and the CI typecheck job covered four targets — so for most packages nothing read src/ or the tests with tsc at all. #4311 measured the hole: 380 code-tier errors across 18 packages, 241 of them driver-sql tests feeding authored-shape literals into the freshly narrowed QueryAST. Re-measured per-package `tsc --noEmit` on main @ e5a4d26; aggregates match the issue exactly (48 clean / 29 failing / 1 no-tsconfig): - The 48 clean packages (42 new scripts + 6 pre-existing) now declare `typecheck`, run by a new `turbo run typecheck` task (dependsOn ^build) wired into lint.yml's typecheck job after the workspace build. The clean set is locked against regression from today. - The 29 failing ones (858 raw errors) are frozen in a DEBT ledger in scripts/check-type-check-coverage.mjs, each entry carrying its measured count and the issue's code/config/noise triage so a config-tier pile (types: 107, core: 91-with-3-real) is never mistaken for real breakage or the reverse (driver-sql: 241, all real). @objectstack/console is EXEMPT: no TypeScript sources. - The coverage gate (self-tested, reconciled in both directions) fails when a package is neither covered nor ledgered, when a ledger entry goes stale, or when the turbo task / root aggregator / CI step is deleted — the ledger can only shrink. Root `pnpm typecheck` aggregates the task locally; AGENTS.md documents the ratchet. Empty changeset: dev scripts and CI only, releases nothing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011m13wbaZziPveBdtQthrXd
1 parent e5a4d26 commit 7dbb331

48 files changed

Lines changed: 675 additions & 44 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
---
3+
4+
ci(dx): every workspace package now either declares a `typecheck` script (`tsc --noEmit`, run by the new `turbo run typecheck` task in the lint workflow) or carries a measured DEBT/EXEMPT entry in `scripts/check-type-check-coverage.mjs`, whose coverage ratchet runs in CI (#4311). 66 of 77 packages build with tsup, which transpiles without type-checking, and `vitest run` does not type-check either — 48 packages were already clean and are locked in; the 29 failing ones are frozen in the ledger with their raw error counts and the issue's code/config/noise triage. Dev scripts and CI only; releases nothing.

.github/workflows/lint.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,18 @@ jobs:
236236
- name: Install dependencies
237237
run: pnpm install --frozen-lockfile
238238

239+
# Coverage meta-gate (#4311): 66 of 77 workspace packages build with tsup
240+
# (esbuild transpile, no type check) and `vitest run` does not type-check
241+
# either, so a package without a `typecheck` script has NO tsc reading its
242+
# src/ or its tests at all — 380 real errors had accumulated that way,
243+
# invisible to every green build. This gate makes the hole itself the
244+
# failure: every package either declares `typecheck` (run by the turbo
245+
# step below) or carries a measured DEBT/EXEMPT entry in the script's
246+
# ledger, reconciled in both directions so the ledger can only shrink.
247+
# Reads package.json files only; no build, sub-second.
248+
- name: Check every package is type-check covered or ledgered
249+
run: pnpm check:type-check-coverage
250+
239251
- name: Type check (@objectstack/spec)
240252
run: pnpm --filter @objectstack/spec exec tsc --noEmit
241253

@@ -351,6 +363,19 @@ jobs:
351363
- name: Build workspace packages
352364
run: pnpm exec turbo run build --filter='./packages/*' --filter='./examples/*^...'
353365

366+
# The per-package `typecheck` scripts the coverage gate above requires
367+
# (#4311). tsc resolves workspace imports through each dependency's built
368+
# dist/*.d.ts, so the task carries `dependsOn: ^build` in turbo.json —
369+
# which also builds the handful of nested packages (packages/plugins/*,
370+
# packages/services/*, …) the build step's direct-children glob misses
371+
# when no example depends on them. Three filters because the bare
372+
# `./packages/*` glob only matches direct children (see the build step's
373+
# comment): the nested group dirs and apps/ (docs) need their own globs.
374+
# Examples and the downstream contract keep their dedicated steps below —
375+
# they are distinct gates, not bulk coverage.
376+
- name: Type check workspace packages
377+
run: pnpm exec turbo run typecheck --filter='./packages/*' --filter='./packages/*/*' --filter='./apps/*'
378+
354379
- name: Type check example apps
355380
run: pnpm --filter './examples/*' run typecheck
356381

AGENTS.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,15 @@ pnpm install # deps
2020
pnpm setup # first-time: install + build spec
2121
pnpm build # turbo build (excludes docs)
2222
pnpm test # turbo test
23+
pnpm typecheck # turbo typecheck — per-package `tsc --noEmit`; tsup/vitest never type-check (#4311)
2324
pnpm docs:dev # docs site
2425
```
2526

27+
Type-check coverage is ratcheted (`pnpm check:type-check-coverage`, CI-gated): every
28+
workspace package declares a `typecheck` script or carries a measured DEBT/EXEMPT entry
29+
in `scripts/check-type-check-coverage.mjs`. New packages must arrive covered; a package
30+
that graduates deletes its ledger entry in the same PR.
31+
2632
### Running the dev server
2733

2834
| Scenario | Command | Notes |
@@ -408,7 +414,7 @@ composition with its real services, or do not claim an answer.
408414

409415
## Post-Task Checklist
410416

411-
1. `pnpm test` — verify nothing broke.
417+
1. `pnpm test` — verify nothing broke. Touched a type-check-covered package? `pnpm typecheck` too.
412418
2. **Land it — don't leave passing work in the working tree.** Once tests pass,
413419
create a feature branch, commit, push, open a PR, and merge it after remote
414420
CI is fully green (see Multi-agent discipline: never straight to `main`,

apps/docs/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"site:start": "next start",
1111
"site:lint": "next lint",
1212
"types:check": "fumadocs-mdx && next typegen && tsc --noEmit",
13-
"postinstall": "fumadocs-mdx"
13+
"postinstall": "fumadocs-mdx",
14+
"typecheck": "tsc --noEmit"
1415
},
1516
"dependencies": {
1617
"fumadocs-core": "16.12.1",

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"spec:rebuild": "turbo run build --filter=...@objectstack/spec",
1313
"test": "turbo run test",
1414
"test:e2e": "turbo run test:e2e",
15+
"typecheck": "turbo run typecheck",
1516
"clean": "turbo run clean && rm -rf dist",
1617
"setup": "pnpm install && pnpm --filter @objectstack/spec build",
1718
"version": "changeset version && node scripts/sync-protocol-version.mjs && node scripts/sync-template-versions.mjs",
@@ -41,7 +42,8 @@
4142
"check:console-sha": "node scripts/check-console-sha.mjs",
4243
"check:release-notes": "node scripts/check-release-notes.mjs",
4344
"check:node-version": "node scripts/check-node-version.mjs",
44-
"check:published-files": "node scripts/check-published-files.mjs --self-test && node scripts/check-published-files.mjs"
45+
"check:published-files": "node scripts/check-published-files.mjs --self-test && node scripts/check-published-files.mjs",
46+
"check:type-check-coverage": "node scripts/check-type-check-coverage.mjs --self-test && node scripts/check-type-check-coverage.mjs"
4547
},
4648
"keywords": [
4749
"objectstack",

packages/apps/account/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
}
1414
},
1515
"scripts": {
16-
"build": "tsup"
16+
"build": "tsup",
17+
"typecheck": "tsc --noEmit"
1718
},
1819
"dependencies": {
1920
"@objectstack/platform-objects": "workspace:*",

packages/apps/setup/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
}
1414
},
1515
"scripts": {
16-
"build": "tsup"
16+
"build": "tsup",
17+
"typecheck": "tsc --noEmit"
1718
},
1819
"dependencies": {
1920
"@objectstack/platform-objects": "workspace:*",

packages/apps/studio/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
}
1414
},
1515
"scripts": {
16-
"build": "tsup"
16+
"build": "tsup",
17+
"typecheck": "tsc --noEmit"
1718
},
1819
"dependencies": {
1920
"@objectstack/platform-objects": "workspace:*",

packages/cli/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"scripts": {
1212
"build": "if [ -n \"$OS_SKIP_DTS\" ]; then tsc -p tsconfig.build.json --noCheck --declaration false --declarationMap false; else tsc -p tsconfig.build.json; fi",
1313
"dev": "tsc -p tsconfig.build.json --watch",
14-
"test": "vitest run"
14+
"test": "vitest run",
15+
"typecheck": "tsc --noEmit"
1516
},
1617
"keywords": [
1718
"objectstack",

packages/client-react/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
}
1414
},
1515
"scripts": {
16-
"build": "tsup src/index.tsx --config ../../tsup.config.ts"
16+
"build": "tsup src/index.tsx --config ../../tsup.config.ts",
17+
"typecheck": "tsc --noEmit"
1718
},
1819
"peerDependencies": {
1920
"react": ">=18.0.0"

0 commit comments

Comments
 (0)