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
41 changes: 41 additions & 0 deletions .changeset/7212-published-tsconfig-tooling-exclude-ratchet.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
---
---

Repo tooling and build config only — no published package changes, so no version bump.

Published build tsconfigs must now exclude tooling DIRECTORIES, not just tooling FILE NAMES,
and a new per-PR gate enforces it: `pnpm check:published-tsconfig-exclude`
(`scripts/check-published-tsconfig-tooling-exclude.mjs`, wired into `ci.yml`'s Type Check job).

The same defect had been repaired three times and gated never — objectui#4006 (73 `*.test.d.ts`
published from two packages), objectui#4836 (9 more, one of them an emitted module whose first
statement imports `vitest`) and objectui#6943 (the same package as the first, because that fix
wrote the name form and the directory form was never generalised). objectui#7212 measured the
standing exposure instead of another instance: 29 published packages carried the name form with
ZERO offending files, green because nobody had yet added a shared helper to a `__tests__/`
directory, not because the config would stop one. The maintainer ruled for the ratchet on
2026-09-02.

The gate reads `exclude` arrays and nothing else — no build, no artifact, no emit model. That
narrowness is the point: objectui#4846 measured the cheap static gate "no build tsconfig program
may contain a tooling file" and rejected it, because deciding whether a tooling file in a program
is a defect means reimplementing three third-party emit semantics. Asking only DOES THE CONFIG
NAME THE DIRECTORY needs none of that. The artifact-level `pnpm check:published-dist` is
untouched and stays the second line of defence — it is the only criterion that cannot be wrong
about what actually ships.

28 build tsconfigs were converted in the same commit so `main` is green on merge. The conversion
is emit-neutral, and that was measured rather than assumed: each package's build program file
list was resolved with TypeScript's own config resolver before and after, and all 33 enforced
packages came back byte-identical (0 files added, 0 removed). Identical program input means
identical emit, so no published artifact and no bundle moves.

Six published packages are named carve-outs rather than converted, because their emitter never
builds its program from this file list, and each re-proves its own reason on every run instead of
being trusted: `@object-ui/cli`, `@object-ui/create-plugin` and `@object-ui/data-objectstack` emit
from a `tsup` entry graph; `@object-ui/plugin-charts` keeps its tooling exclude in the `dts()`
options and carries no `exclude` key in its tsconfig; `@object-ui/console` and `@object-ui/runner`
are Vite applications with `noEmit: true` and no `dts()` plugin, so they write no declarations at
all. Two of those six — `create-plugin` and `runner` — were found at authoring time and were
inside the ruling's initial red set; requiring a shape in a config their emitter never consults
would have been a check that is green about nothing.
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -263,6 +263,33 @@ jobs:
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:self-import

# A build tsconfig that excludes tooling by FILE NAME (`*.test.ts`) stops
# the files that happen to be named that way and nothing else. The first
# shared helper added to a `__tests__/` directory is then a program input,
# and an emitting program writes it into the published `dist`. That has
# happened three times — objectui#4006 (73 `*.test.d.ts` across two
# packages), objectui#4836 (9 more, one of them an emitted module whose
# first statement imports `vitest`) and objectui#6943 (the same package as
# the first, because that fix wrote the name form) — and every one was
# found by a human, never by a gate. objectui#7212 measured the standing
# exposure: 29 published packages carried the name form with ZERO offending
# files, green because nobody had added such a helper yet. This gate reads
# `exclude` ARRAYS only: no build, no artifact, no emit model, which is what
# keeps it clear of the modelling objectui#4846 declined for the
# artifact-level gate. That gate stays as the second line of defence — it
# is the only criterion that cannot be wrong about what actually ships, and
# it lives in `published-dist-gate.yml` because it needs a full-repo build.
# Its runnable alias is deliberately NOT named anywhere in this file:
# `check-published-dist-tooling.test.ts` asserts by substring that no
# per-PR workflow mentions it, which is how the ruling that kept a
# full-repo build off the PR path is held — prose naming it would read the
# same to that scan as a step running it. Config
# reads plus the sibling gate's `typescript`-importing scanner, so it needs
# the install and nothing built, same as the two steps above.
- name: Verify published build tsconfigs exclude tooling DIRECTORIES, not just names
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:published-tsconfig-exclude

# `sideEffects` is a PUBLISHED CONTRACT, and an ARRAY form of it fails in
# the one direction nothing can witness: an INCOMPLETE array drops a
# registration inside a CONSUMER's bundle, with no error, no warning and
Expand Down
9 changes: 8 additions & 1 deletion content/docs/guide/ci-cd-pipeline.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,6 +50,7 @@
"census:body-dialect": "node scripts/body-dialect-census.mjs",
"check:control-bytes": "node scripts/check-control-bytes.mjs",
"check:published-dist": "node scripts/check-published-dist-tooling.mjs",
"check:published-tsconfig-exclude": "node scripts/check-published-tsconfig-tooling-exclude.mjs",
"check:spec-floors": "node scripts/check-spec-range-floors.mjs",
"check:i18n-keys": "node scripts/check-i18n-call-site-keys.mjs",
"check:i18n-drift": "node scripts/check-i18n-en-drift.mjs",
Expand Down
17 changes: 16 additions & 1 deletion packages/app-shell/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,22 @@
"moduleResolution": "nodenext"
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
],
"references": [
{ "path": "../types" },
{ "path": "../core" },
Expand Down
17 changes: 16 additions & 1 deletion packages/auth/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/collaboration/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/components/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,18 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["src/__tests__", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/i18n/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,20 @@
"lib": ["ES2020", "DOM"]
},
"include": ["src"],
"exclude": ["src/**/*.test.ts", "src/**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"src/**/*.test.ts",
"src/**/*.test.tsx"
],
// `utils/number-display.ts` re-exports `@object-ui/core` (objectui#4576).
// The root tsconfig's `paths` map that specifier at the SOURCE tree
// (`packages/core/src`), which would make those files program inputs under
Expand Down
17 changes: 16 additions & 1 deletion packages/layout/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,5 +13,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/mobile/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/permissions/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-ai/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-calendar/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-chatbot/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-dashboard/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,5 +15,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-detail/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
10 changes: 9 additions & 1 deletion packages/plugin-editor/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,5 +22,13 @@
// Their type coverage did not go away with them: it moved to the
// `tsconfig.test.json` chained off this package's `type-check` script, which
// is what scripts/check-type-check-coverage.mjs verifies.
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
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
41 changes: 41 additions & 0 deletions .changeset/7212-published-tsconfig-tooling-exclude-ratchet.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
---
---

Repo tooling and build config only — no published package changes, so no version bump.

Published build tsconfigs must now exclude tooling DIRECTORIES, not just tooling FILE NAMES,
and a new per-PR gate enforces it: `pnpm check:published-tsconfig-exclude`
(`scripts/check-published-tsconfig-tooling-exclude.mjs`, wired into `ci.yml`'s Type Check job).

The same defect had been repaired three times and gated never — objectui#4006 (73 `*.test.d.ts`
published from two packages), objectui#4836 (9 more, one of them an emitted module whose first
statement imports `vitest`) and objectui#6943 (the same package as the first, because that fix
wrote the name form and the directory form was never generalised). objectui#7212 measured the
standing exposure instead of another instance: 29 published packages carried the name form with
ZERO offending files, green because nobody had yet added a shared helper to a `__tests__/`
directory, not because the config would stop one. The maintainer ruled for the ratchet on
2026-09-02.

The gate reads `exclude` arrays and nothing else — no build, no artifact, no emit model. That
narrowness is the point: objectui#4846 measured the cheap static gate "no build tsconfig program
may contain a tooling file" and rejected it, because deciding whether a tooling file in a program
is a defect means reimplementing three third-party emit semantics. Asking only DOES THE CONFIG
NAME THE DIRECTORY needs none of that. The artifact-level `pnpm check:published-dist` is
untouched and stays the second line of defence — it is the only criterion that cannot be wrong
about what actually ships.

28 build tsconfigs were converted in the same commit so `main` is green on merge. The conversion
is emit-neutral, and that was measured rather than assumed: each package's build program file
list was resolved with TypeScript's own config resolver before and after, and all 33 enforced
packages came back byte-identical (0 files added, 0 removed). Identical program input means
identical emit, so no published artifact and no bundle moves.

Six published packages are named carve-outs rather than converted, because their emitter never
builds its program from this file list, and each re-proves its own reason on every run instead of
being trusted: `@object-ui/cli`, `@object-ui/create-plugin` and `@object-ui/data-objectstack` emit
from a `tsup` entry graph; `@object-ui/plugin-charts` keeps its tooling exclude in the `dts()`
options and carries no `exclude` key in its tsconfig; `@object-ui/console` and `@object-ui/runner`
are Vite applications with `noEmit: true` and no `dts()` plugin, so they write no declarations at
all. Two of those six — `create-plugin` and `runner` — were found at authoring time and were
inside the ruling's initial red set; requiring a shape in a config their emitter never consults
would have been a check that is green about nothing.
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -263,6 +263,33 @@ jobs:
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:self-import

# A build tsconfig that excludes tooling by FILE NAME (`*.test.ts`) stops
# the files that happen to be named that way and nothing else. The first
# shared helper added to a `__tests__/` directory is then a program input,
# and an emitting program writes it into the published `dist`. That has
# happened three times — objectui#4006 (73 `*.test.d.ts` across two
# packages), objectui#4836 (9 more, one of them an emitted module whose
# first statement imports `vitest`) and objectui#6943 (the same package as
# the first, because that fix wrote the name form) — and every one was
# found by a human, never by a gate. objectui#7212 measured the standing
# exposure: 29 published packages carried the name form with ZERO offending
# files, green because nobody had added such a helper yet. This gate reads
# `exclude` ARRAYS only: no build, no artifact, no emit model, which is what
# keeps it clear of the modelling objectui#4846 declined for the
# artifact-level gate. That gate stays as the second line of defence — it
# is the only criterion that cannot be wrong about what actually ships, and
# it lives in `published-dist-gate.yml` because it needs a full-repo build.
# Its runnable alias is deliberately NOT named anywhere in this file:
# `check-published-dist-tooling.test.ts` asserts by substring that no
# per-PR workflow mentions it, which is how the ruling that kept a
# full-repo build off the PR path is held — prose naming it would read the
# same to that scan as a step running it. Config
# reads plus the sibling gate's `typescript`-importing scanner, so it needs
# the install and nothing built, same as the two steps above.
- name: Verify published build tsconfigs exclude tooling DIRECTORIES, not just names
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:published-tsconfig-exclude

# `sideEffects` is a PUBLISHED CONTRACT, and an ARRAY form of it fails in
# the one direction nothing can witness: an INCOMPLETE array drops a
# registration inside a CONSUMER's bundle, with no error, no warning and
Expand Down
9 changes: 8 additions & 1 deletion content/docs/guide/ci-cd-pipeline.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,6 +50,7 @@
"census:body-dialect": "node scripts/body-dialect-census.mjs",
"check:control-bytes": "node scripts/check-control-bytes.mjs",
"check:published-dist": "node scripts/check-published-dist-tooling.mjs",
"check:published-tsconfig-exclude": "node scripts/check-published-tsconfig-tooling-exclude.mjs",
"check:spec-floors": "node scripts/check-spec-range-floors.mjs",
"check:i18n-keys": "node scripts/check-i18n-call-site-keys.mjs",
"check:i18n-drift": "node scripts/check-i18n-en-drift.mjs",
Expand Down
17 changes: 16 additions & 1 deletion packages/app-shell/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,22 @@
"moduleResolution": "nodenext"
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
],
"references": [
{ "path": "../types" },
{ "path": "../core" },
Expand Down
17 changes: 16 additions & 1 deletion packages/auth/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/collaboration/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/components/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,18 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["src/__tests__", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/i18n/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,20 @@
"lib": ["ES2020", "DOM"]
},
"include": ["src"],
"exclude": ["src/**/*.test.ts", "src/**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"src/**/*.test.ts",
"src/**/*.test.tsx"
],
// `utils/number-display.ts` re-exports `@object-ui/core` (objectui#4576).
// The root tsconfig's `paths` map that specifier at the SOURCE tree
// (`packages/core/src`), which would make those files program inputs under
Expand Down
17 changes: 16 additions & 1 deletion packages/layout/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,5 +13,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/mobile/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/permissions/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-ai/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-calendar/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-chatbot/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-dashboard/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,5 +15,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-detail/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
10 changes: 9 additions & 1 deletion packages/plugin-editor/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,5 +22,13 @@
// Their type coverage did not go away with them: it moved to the
// `tsconfig.test.json` chained off this package's `type-check` script, which
// is what scripts/check-type-check-coverage.mjs verifies.
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
41 changes: 41 additions & 0 deletions .changeset/7212-published-tsconfig-tooling-exclude-ratchet.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
---
---

Repo tooling and build config only — no published package changes, so no version bump.

Published build tsconfigs must now exclude tooling DIRECTORIES, not just tooling FILE NAMES,
and a new per-PR gate enforces it: `pnpm check:published-tsconfig-exclude`
(`scripts/check-published-tsconfig-tooling-exclude.mjs`, wired into `ci.yml`'s Type Check job).

The same defect had been repaired three times and gated never — objectui#4006 (73 `*.test.d.ts`
published from two packages), objectui#4836 (9 more, one of them an emitted module whose first
statement imports `vitest`) and objectui#6943 (the same package as the first, because that fix
wrote the name form and the directory form was never generalised). objectui#7212 measured the
standing exposure instead of another instance: 29 published packages carried the name form with
ZERO offending files, green because nobody had yet added a shared helper to a `__tests__/`
directory, not because the config would stop one. The maintainer ruled for the ratchet on
2026-09-02.

The gate reads `exclude` arrays and nothing else — no build, no artifact, no emit model. That
narrowness is the point: objectui#4846 measured the cheap static gate "no build tsconfig program
may contain a tooling file" and rejected it, because deciding whether a tooling file in a program
is a defect means reimplementing three third-party emit semantics. Asking only DOES THE CONFIG
NAME THE DIRECTORY needs none of that. The artifact-level `pnpm check:published-dist` is
untouched and stays the second line of defence — it is the only criterion that cannot be wrong
about what actually ships.

28 build tsconfigs were converted in the same commit so `main` is green on merge. The conversion
is emit-neutral, and that was measured rather than assumed: each package's build program file
list was resolved with TypeScript's own config resolver before and after, and all 33 enforced
packages came back byte-identical (0 files added, 0 removed). Identical program input means
identical emit, so no published artifact and no bundle moves.

Six published packages are named carve-outs rather than converted, because their emitter never
builds its program from this file list, and each re-proves its own reason on every run instead of
being trusted: `@object-ui/cli`, `@object-ui/create-plugin` and `@object-ui/data-objectstack` emit
from a `tsup` entry graph; `@object-ui/plugin-charts` keeps its tooling exclude in the `dts()`
options and carries no `exclude` key in its tsconfig; `@object-ui/console` and `@object-ui/runner`
are Vite applications with `noEmit: true` and no `dts()` plugin, so they write no declarations at
all. Two of those six — `create-plugin` and `runner` — were found at authoring time and were
inside the ruling's initial red set; requiring a shape in a config their emitter never consults
would have been a check that is green about nothing.
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -263,6 +263,33 @@ jobs:
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:self-import

# A build tsconfig that excludes tooling by FILE NAME (`*.test.ts`) stops
# the files that happen to be named that way and nothing else. The first
# shared helper added to a `__tests__/` directory is then a program input,
# and an emitting program writes it into the published `dist`. That has
# happened three times — objectui#4006 (73 `*.test.d.ts` across two
# packages), objectui#4836 (9 more, one of them an emitted module whose
# first statement imports `vitest`) and objectui#6943 (the same package as
# the first, because that fix wrote the name form) — and every one was
# found by a human, never by a gate. objectui#7212 measured the standing
# exposure: 29 published packages carried the name form with ZERO offending
# files, green because nobody had added such a helper yet. This gate reads
# `exclude` ARRAYS only: no build, no artifact, no emit model, which is what
# keeps it clear of the modelling objectui#4846 declined for the
# artifact-level gate. That gate stays as the second line of defence — it
# is the only criterion that cannot be wrong about what actually ships, and
# it lives in `published-dist-gate.yml` because it needs a full-repo build.
# Its runnable alias is deliberately NOT named anywhere in this file:
# `check-published-dist-tooling.test.ts` asserts by substring that no
# per-PR workflow mentions it, which is how the ruling that kept a
# full-repo build off the PR path is held — prose naming it would read the
# same to that scan as a step running it. Config
# reads plus the sibling gate's `typescript`-importing scanner, so it needs
# the install and nothing built, same as the two steps above.
- name: Verify published build tsconfigs exclude tooling DIRECTORIES, not just names
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:published-tsconfig-exclude

# `sideEffects` is a PUBLISHED CONTRACT, and an ARRAY form of it fails in
# the one direction nothing can witness: an INCOMPLETE array drops a
# registration inside a CONSUMER's bundle, with no error, no warning and
Expand Down
9 changes: 8 additions & 1 deletion content/docs/guide/ci-cd-pipeline.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,6 +50,7 @@
"census:body-dialect": "node scripts/body-dialect-census.mjs",
"check:control-bytes": "node scripts/check-control-bytes.mjs",
"check:published-dist": "node scripts/check-published-dist-tooling.mjs",
"check:published-tsconfig-exclude": "node scripts/check-published-tsconfig-tooling-exclude.mjs",
"check:spec-floors": "node scripts/check-spec-range-floors.mjs",
"check:i18n-keys": "node scripts/check-i18n-call-site-keys.mjs",
"check:i18n-drift": "node scripts/check-i18n-en-drift.mjs",
Expand Down
17 changes: 16 additions & 1 deletion packages/app-shell/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,22 @@
"moduleResolution": "nodenext"
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
],
"references": [
{ "path": "../types" },
{ "path": "../core" },
Expand Down
17 changes: 16 additions & 1 deletion packages/auth/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/collaboration/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/components/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,18 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["src/__tests__", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/i18n/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,20 @@
"lib": ["ES2020", "DOM"]
},
"include": ["src"],
"exclude": ["src/**/*.test.ts", "src/**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"src/**/*.test.ts",
"src/**/*.test.tsx"
],
// `utils/number-display.ts` re-exports `@object-ui/core` (objectui#4576).
// The root tsconfig's `paths` map that specifier at the SOURCE tree
// (`packages/core/src`), which would make those files program inputs under
Expand Down
17 changes: 16 additions & 1 deletion packages/layout/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,5 +13,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/mobile/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/permissions/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-ai/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-calendar/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-chatbot/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-dashboard/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,5 +15,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-detail/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
10 changes: 9 additions & 1 deletion packages/plugin-editor/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,5 +22,13 @@
// Their type coverage did not go away with them: it moved to the
// `tsconfig.test.json` chained off this package's `type-check` script, which
// is what scripts/check-type-check-coverage.mjs verifies.
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
41 changes: 41 additions & 0 deletions .changeset/7212-published-tsconfig-tooling-exclude-ratchet.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
---
---

Repo tooling and build config only — no published package changes, so no version bump.

Published build tsconfigs must now exclude tooling DIRECTORIES, not just tooling FILE NAMES,
and a new per-PR gate enforces it: `pnpm check:published-tsconfig-exclude`
(`scripts/check-published-tsconfig-tooling-exclude.mjs`, wired into `ci.yml`'s Type Check job).

The same defect had been repaired three times and gated never — objectui#4006 (73 `*.test.d.ts`
published from two packages), objectui#4836 (9 more, one of them an emitted module whose first
statement imports `vitest`) and objectui#6943 (the same package as the first, because that fix
wrote the name form and the directory form was never generalised). objectui#7212 measured the
standing exposure instead of another instance: 29 published packages carried the name form with
ZERO offending files, green because nobody had yet added a shared helper to a `__tests__/`
directory, not because the config would stop one. The maintainer ruled for the ratchet on
2026-09-02.

The gate reads `exclude` arrays and nothing else — no build, no artifact, no emit model. That
narrowness is the point: objectui#4846 measured the cheap static gate "no build tsconfig program
may contain a tooling file" and rejected it, because deciding whether a tooling file in a program
is a defect means reimplementing three third-party emit semantics. Asking only DOES THE CONFIG
NAME THE DIRECTORY needs none of that. The artifact-level `pnpm check:published-dist` is
untouched and stays the second line of defence — it is the only criterion that cannot be wrong
about what actually ships.

28 build tsconfigs were converted in the same commit so `main` is green on merge. The conversion
is emit-neutral, and that was measured rather than assumed: each package's build program file
list was resolved with TypeScript's own config resolver before and after, and all 33 enforced
packages came back byte-identical (0 files added, 0 removed). Identical program input means
identical emit, so no published artifact and no bundle moves.

Six published packages are named carve-outs rather than converted, because their emitter never
builds its program from this file list, and each re-proves its own reason on every run instead of
being trusted: `@object-ui/cli`, `@object-ui/create-plugin` and `@object-ui/data-objectstack` emit
from a `tsup` entry graph; `@object-ui/plugin-charts` keeps its tooling exclude in the `dts()`
options and carries no `exclude` key in its tsconfig; `@object-ui/console` and `@object-ui/runner`
are Vite applications with `noEmit: true` and no `dts()` plugin, so they write no declarations at
all. Two of those six — `create-plugin` and `runner` — were found at authoring time and were
inside the ruling's initial red set; requiring a shape in a config their emitter never consults
would have been a check that is green about nothing.
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -263,6 +263,33 @@ jobs:
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:self-import

# A build tsconfig that excludes tooling by FILE NAME (`*.test.ts`) stops
# the files that happen to be named that way and nothing else. The first
# shared helper added to a `__tests__/` directory is then a program input,
# and an emitting program writes it into the published `dist`. That has
# happened three times — objectui#4006 (73 `*.test.d.ts` across two
# packages), objectui#4836 (9 more, one of them an emitted module whose
# first statement imports `vitest`) and objectui#6943 (the same package as
# the first, because that fix wrote the name form) — and every one was
# found by a human, never by a gate. objectui#7212 measured the standing
# exposure: 29 published packages carried the name form with ZERO offending
# files, green because nobody had added such a helper yet. This gate reads
# `exclude` ARRAYS only: no build, no artifact, no emit model, which is what
# keeps it clear of the modelling objectui#4846 declined for the
# artifact-level gate. That gate stays as the second line of defence — it
# is the only criterion that cannot be wrong about what actually ships, and
# it lives in `published-dist-gate.yml` because it needs a full-repo build.
# Its runnable alias is deliberately NOT named anywhere in this file:
# `check-published-dist-tooling.test.ts` asserts by substring that no
# per-PR workflow mentions it, which is how the ruling that kept a
# full-repo build off the PR path is held — prose naming it would read the
# same to that scan as a step running it. Config
# reads plus the sibling gate's `typescript`-importing scanner, so it needs
# the install and nothing built, same as the two steps above.
- name: Verify published build tsconfigs exclude tooling DIRECTORIES, not just names
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:published-tsconfig-exclude

# `sideEffects` is a PUBLISHED CONTRACT, and an ARRAY form of it fails in
# the one direction nothing can witness: an INCOMPLETE array drops a
# registration inside a CONSUMER's bundle, with no error, no warning and
Expand Down
9 changes: 8 additions & 1 deletion content/docs/guide/ci-cd-pipeline.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,6 +50,7 @@
"census:body-dialect": "node scripts/body-dialect-census.mjs",
"check:control-bytes": "node scripts/check-control-bytes.mjs",
"check:published-dist": "node scripts/check-published-dist-tooling.mjs",
"check:published-tsconfig-exclude": "node scripts/check-published-tsconfig-tooling-exclude.mjs",
"check:spec-floors": "node scripts/check-spec-range-floors.mjs",
"check:i18n-keys": "node scripts/check-i18n-call-site-keys.mjs",
"check:i18n-drift": "node scripts/check-i18n-en-drift.mjs",
Expand Down
17 changes: 16 additions & 1 deletion packages/app-shell/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,22 @@
"moduleResolution": "nodenext"
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
],
"references": [
{ "path": "../types" },
{ "path": "../core" },
Expand Down
17 changes: 16 additions & 1 deletion packages/auth/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/collaboration/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/components/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,18 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["src/__tests__", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/i18n/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,20 @@
"lib": ["ES2020", "DOM"]
},
"include": ["src"],
"exclude": ["src/**/*.test.ts", "src/**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"src/**/*.test.ts",
"src/**/*.test.tsx"
],
// `utils/number-display.ts` re-exports `@object-ui/core` (objectui#4576).
// The root tsconfig's `paths` map that specifier at the SOURCE tree
// (`packages/core/src`), which would make those files program inputs under
Expand Down
17 changes: 16 additions & 1 deletion packages/layout/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,5 +13,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/mobile/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/permissions/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-ai/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-calendar/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-chatbot/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-dashboard/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,5 +15,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-detail/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
10 changes: 9 additions & 1 deletion packages/plugin-editor/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,5 +22,13 @@
// Their type coverage did not go away with them: it moved to the
// `tsconfig.test.json` chained off this package's `type-check` script, which
// is what scripts/check-type-check-coverage.mjs verifies.
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
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
41 changes: 41 additions & 0 deletions .changeset/7212-published-tsconfig-tooling-exclude-ratchet.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
---
---

Repo tooling and build config only — no published package changes, so no version bump.

Published build tsconfigs must now exclude tooling DIRECTORIES, not just tooling FILE NAMES,
and a new per-PR gate enforces it: `pnpm check:published-tsconfig-exclude`
(`scripts/check-published-tsconfig-tooling-exclude.mjs`, wired into `ci.yml`'s Type Check job).

The same defect had been repaired three times and gated never — objectui#4006 (73 `*.test.d.ts`
published from two packages), objectui#4836 (9 more, one of them an emitted module whose first
statement imports `vitest`) and objectui#6943 (the same package as the first, because that fix
wrote the name form and the directory form was never generalised). objectui#7212 measured the
standing exposure instead of another instance: 29 published packages carried the name form with
ZERO offending files, green because nobody had yet added a shared helper to a `__tests__/`
directory, not because the config would stop one. The maintainer ruled for the ratchet on
2026-09-02.

The gate reads `exclude` arrays and nothing else — no build, no artifact, no emit model. That
narrowness is the point: objectui#4846 measured the cheap static gate "no build tsconfig program
may contain a tooling file" and rejected it, because deciding whether a tooling file in a program
is a defect means reimplementing three third-party emit semantics. Asking only DOES THE CONFIG
NAME THE DIRECTORY needs none of that. The artifact-level `pnpm check:published-dist` is
untouched and stays the second line of defence — it is the only criterion that cannot be wrong
about what actually ships.

28 build tsconfigs were converted in the same commit so `main` is green on merge. The conversion
is emit-neutral, and that was measured rather than assumed: each package's build program file
list was resolved with TypeScript's own config resolver before and after, and all 33 enforced
packages came back byte-identical (0 files added, 0 removed). Identical program input means
identical emit, so no published artifact and no bundle moves.

Six published packages are named carve-outs rather than converted, because their emitter never
builds its program from this file list, and each re-proves its own reason on every run instead of
being trusted: `@object-ui/cli`, `@object-ui/create-plugin` and `@object-ui/data-objectstack` emit
from a `tsup` entry graph; `@object-ui/plugin-charts` keeps its tooling exclude in the `dts()`
options and carries no `exclude` key in its tsconfig; `@object-ui/console` and `@object-ui/runner`
are Vite applications with `noEmit: true` and no `dts()` plugin, so they write no declarations at
all. Two of those six — `create-plugin` and `runner` — were found at authoring time and were
inside the ruling's initial red set; requiring a shape in a config their emitter never consults
would have been a check that is green about nothing.
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -263,6 +263,33 @@ jobs:
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:self-import

# A build tsconfig that excludes tooling by FILE NAME (`*.test.ts`) stops
# the files that happen to be named that way and nothing else. The first
# shared helper added to a `__tests__/` directory is then a program input,
# and an emitting program writes it into the published `dist`. That has
# happened three times — objectui#4006 (73 `*.test.d.ts` across two
# packages), objectui#4836 (9 more, one of them an emitted module whose
# first statement imports `vitest`) and objectui#6943 (the same package as
# the first, because that fix wrote the name form) — and every one was
# found by a human, never by a gate. objectui#7212 measured the standing
# exposure: 29 published packages carried the name form with ZERO offending
# files, green because nobody had added such a helper yet. This gate reads
# `exclude` ARRAYS only: no build, no artifact, no emit model, which is what
# keeps it clear of the modelling objectui#4846 declined for the
# artifact-level gate. That gate stays as the second line of defence — it
# is the only criterion that cannot be wrong about what actually ships, and
# it lives in `published-dist-gate.yml` because it needs a full-repo build.
# Its runnable alias is deliberately NOT named anywhere in this file:
# `check-published-dist-tooling.test.ts` asserts by substring that no
# per-PR workflow mentions it, which is how the ruling that kept a
# full-repo build off the PR path is held — prose naming it would read the
# same to that scan as a step running it. Config
# reads plus the sibling gate's `typescript`-importing scanner, so it needs
# the install and nothing built, same as the two steps above.
- name: Verify published build tsconfigs exclude tooling DIRECTORIES, not just names
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:published-tsconfig-exclude

# `sideEffects` is a PUBLISHED CONTRACT, and an ARRAY form of it fails in
# the one direction nothing can witness: an INCOMPLETE array drops a
# registration inside a CONSUMER's bundle, with no error, no warning and
Expand Down
9 changes: 8 additions & 1 deletion content/docs/guide/ci-cd-pipeline.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,6 +50,7 @@
"census:body-dialect": "node scripts/body-dialect-census.mjs",
"check:control-bytes": "node scripts/check-control-bytes.mjs",
"check:published-dist": "node scripts/check-published-dist-tooling.mjs",
"check:published-tsconfig-exclude": "node scripts/check-published-tsconfig-tooling-exclude.mjs",
"check:spec-floors": "node scripts/check-spec-range-floors.mjs",
"check:i18n-keys": "node scripts/check-i18n-call-site-keys.mjs",
"check:i18n-drift": "node scripts/check-i18n-en-drift.mjs",
Expand Down
17 changes: 16 additions & 1 deletion packages/app-shell/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,22 @@
"moduleResolution": "nodenext"
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
],
"references": [
{ "path": "../types" },
{ "path": "../core" },
Expand Down
17 changes: 16 additions & 1 deletion packages/auth/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/collaboration/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/components/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,18 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["src/__tests__", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/i18n/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,20 @@
"lib": ["ES2020", "DOM"]
},
"include": ["src"],
"exclude": ["src/**/*.test.ts", "src/**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"src/**/*.test.ts",
"src/**/*.test.tsx"
],
// `utils/number-display.ts` re-exports `@object-ui/core` (objectui#4576).
// The root tsconfig's `paths` map that specifier at the SOURCE tree
// (`packages/core/src`), which would make those files program inputs under
Expand Down
17 changes: 16 additions & 1 deletion packages/layout/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,5 +13,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/mobile/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/permissions/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-ai/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-calendar/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-chatbot/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-dashboard/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,5 +15,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-detail/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
10 changes: 9 additions & 1 deletion packages/plugin-editor/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,5 +22,13 @@
// Their type coverage did not go away with them: it moved to the
// `tsconfig.test.json` chained off this package's `type-check` script, which
// is what scripts/check-type-check-coverage.mjs verifies.
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
41 changes: 41 additions & 0 deletions .changeset/7212-published-tsconfig-tooling-exclude-ratchet.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
---
---

Repo tooling and build config only — no published package changes, so no version bump.

Published build tsconfigs must now exclude tooling DIRECTORIES, not just tooling FILE NAMES,
and a new per-PR gate enforces it: `pnpm check:published-tsconfig-exclude`
(`scripts/check-published-tsconfig-tooling-exclude.mjs`, wired into `ci.yml`'s Type Check job).

The same defect had been repaired three times and gated never — objectui#4006 (73 `*.test.d.ts`
published from two packages), objectui#4836 (9 more, one of them an emitted module whose first
statement imports `vitest`) and objectui#6943 (the same package as the first, because that fix
wrote the name form and the directory form was never generalised). objectui#7212 measured the
standing exposure instead of another instance: 29 published packages carried the name form with
ZERO offending files, green because nobody had yet added a shared helper to a `__tests__/`
directory, not because the config would stop one. The maintainer ruled for the ratchet on
2026-09-02.

The gate reads `exclude` arrays and nothing else — no build, no artifact, no emit model. That
narrowness is the point: objectui#4846 measured the cheap static gate "no build tsconfig program
may contain a tooling file" and rejected it, because deciding whether a tooling file in a program
is a defect means reimplementing three third-party emit semantics. Asking only DOES THE CONFIG
NAME THE DIRECTORY needs none of that. The artifact-level `pnpm check:published-dist` is
untouched and stays the second line of defence — it is the only criterion that cannot be wrong
about what actually ships.

28 build tsconfigs were converted in the same commit so `main` is green on merge. The conversion
is emit-neutral, and that was measured rather than assumed: each package's build program file
list was resolved with TypeScript's own config resolver before and after, and all 33 enforced
packages came back byte-identical (0 files added, 0 removed). Identical program input means
identical emit, so no published artifact and no bundle moves.

Six published packages are named carve-outs rather than converted, because their emitter never
builds its program from this file list, and each re-proves its own reason on every run instead of
being trusted: `@object-ui/cli`, `@object-ui/create-plugin` and `@object-ui/data-objectstack` emit
from a `tsup` entry graph; `@object-ui/plugin-charts` keeps its tooling exclude in the `dts()`
options and carries no `exclude` key in its tsconfig; `@object-ui/console` and `@object-ui/runner`
are Vite applications with `noEmit: true` and no `dts()` plugin, so they write no declarations at
all. Two of those six — `create-plugin` and `runner` — were found at authoring time and were
inside the ruling's initial red set; requiring a shape in a config their emitter never consults
would have been a check that is green about nothing.
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -263,6 +263,33 @@ jobs:
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:self-import

# A build tsconfig that excludes tooling by FILE NAME (`*.test.ts`) stops
# the files that happen to be named that way and nothing else. The first
# shared helper added to a `__tests__/` directory is then a program input,
# and an emitting program writes it into the published `dist`. That has
# happened three times — objectui#4006 (73 `*.test.d.ts` across two
# packages), objectui#4836 (9 more, one of them an emitted module whose
# first statement imports `vitest`) and objectui#6943 (the same package as
# the first, because that fix wrote the name form) — and every one was
# found by a human, never by a gate. objectui#7212 measured the standing
# exposure: 29 published packages carried the name form with ZERO offending
# files, green because nobody had added such a helper yet. This gate reads
# `exclude` ARRAYS only: no build, no artifact, no emit model, which is what
# keeps it clear of the modelling objectui#4846 declined for the
# artifact-level gate. That gate stays as the second line of defence — it
# is the only criterion that cannot be wrong about what actually ships, and
# it lives in `published-dist-gate.yml` because it needs a full-repo build.
# Its runnable alias is deliberately NOT named anywhere in this file:
# `check-published-dist-tooling.test.ts` asserts by substring that no
# per-PR workflow mentions it, which is how the ruling that kept a
# full-repo build off the PR path is held — prose naming it would read the
# same to that scan as a step running it. Config
# reads plus the sibling gate's `typescript`-importing scanner, so it needs
# the install and nothing built, same as the two steps above.
- name: Verify published build tsconfigs exclude tooling DIRECTORIES, not just names
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:published-tsconfig-exclude

# `sideEffects` is a PUBLISHED CONTRACT, and an ARRAY form of it fails in
# the one direction nothing can witness: an INCOMPLETE array drops a
# registration inside a CONSUMER's bundle, with no error, no warning and
Expand Down
9 changes: 8 additions & 1 deletion content/docs/guide/ci-cd-pipeline.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,6 +50,7 @@
"census:body-dialect": "node scripts/body-dialect-census.mjs",
"check:control-bytes": "node scripts/check-control-bytes.mjs",
"check:published-dist": "node scripts/check-published-dist-tooling.mjs",
"check:published-tsconfig-exclude": "node scripts/check-published-tsconfig-tooling-exclude.mjs",
"check:spec-floors": "node scripts/check-spec-range-floors.mjs",
"check:i18n-keys": "node scripts/check-i18n-call-site-keys.mjs",
"check:i18n-drift": "node scripts/check-i18n-en-drift.mjs",
Expand Down
17 changes: 16 additions & 1 deletion packages/app-shell/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,22 @@
"moduleResolution": "nodenext"
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
],
"references": [
{ "path": "../types" },
{ "path": "../core" },
Expand Down
17 changes: 16 additions & 1 deletion packages/auth/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/collaboration/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/components/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,18 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["src/__tests__", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/i18n/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,20 @@
"lib": ["ES2020", "DOM"]
},
"include": ["src"],
"exclude": ["src/**/*.test.ts", "src/**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"src/**/*.test.ts",
"src/**/*.test.tsx"
],
// `utils/number-display.ts` re-exports `@object-ui/core` (objectui#4576).
// The root tsconfig's `paths` map that specifier at the SOURCE tree
// (`packages/core/src`), which would make those files program inputs under
Expand Down
17 changes: 16 additions & 1 deletion packages/layout/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,5 +13,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/mobile/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/permissions/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-ai/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-calendar/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-chatbot/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-dashboard/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,5 +15,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-detail/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
10 changes: 9 additions & 1 deletion packages/plugin-editor/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,5 +22,13 @@
// Their type coverage did not go away with them: it moved to the
// `tsconfig.test.json` chained off this package's `type-check` script, which
// is what scripts/check-type-check-coverage.mjs verifies.
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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
41 changes: 41 additions & 0 deletions .changeset/7212-published-tsconfig-tooling-exclude-ratchet.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
---
---

Repo tooling and build config only — no published package changes, so no version bump.

Published build tsconfigs must now exclude tooling DIRECTORIES, not just tooling FILE NAMES,
and a new per-PR gate enforces it: `pnpm check:published-tsconfig-exclude`
(`scripts/check-published-tsconfig-tooling-exclude.mjs`, wired into `ci.yml`'s Type Check job).

The same defect had been repaired three times and gated never — objectui#4006 (73 `*.test.d.ts`
published from two packages), objectui#4836 (9 more, one of them an emitted module whose first
statement imports `vitest`) and objectui#6943 (the same package as the first, because that fix
wrote the name form and the directory form was never generalised). objectui#7212 measured the
standing exposure instead of another instance: 29 published packages carried the name form with
ZERO offending files, green because nobody had yet added a shared helper to a `__tests__/`
directory, not because the config would stop one. The maintainer ruled for the ratchet on
2026-09-02.

The gate reads `exclude` arrays and nothing else — no build, no artifact, no emit model. That
narrowness is the point: objectui#4846 measured the cheap static gate "no build tsconfig program
may contain a tooling file" and rejected it, because deciding whether a tooling file in a program
is a defect means reimplementing three third-party emit semantics. Asking only DOES THE CONFIG
NAME THE DIRECTORY needs none of that. The artifact-level `pnpm check:published-dist` is
untouched and stays the second line of defence — it is the only criterion that cannot be wrong
about what actually ships.

28 build tsconfigs were converted in the same commit so `main` is green on merge. The conversion
is emit-neutral, and that was measured rather than assumed: each package's build program file
list was resolved with TypeScript's own config resolver before and after, and all 33 enforced
packages came back byte-identical (0 files added, 0 removed). Identical program input means
identical emit, so no published artifact and no bundle moves.

Six published packages are named carve-outs rather than converted, because their emitter never
builds its program from this file list, and each re-proves its own reason on every run instead of
being trusted: `@object-ui/cli`, `@object-ui/create-plugin` and `@object-ui/data-objectstack` emit
from a `tsup` entry graph; `@object-ui/plugin-charts` keeps its tooling exclude in the `dts()`
options and carries no `exclude` key in its tsconfig; `@object-ui/console` and `@object-ui/runner`
are Vite applications with `noEmit: true` and no `dts()` plugin, so they write no declarations at
all. Two of those six — `create-plugin` and `runner` — were found at authoring time and were
inside the ruling's initial red set; requiring a shape in a config their emitter never consults
would have been a check that is green about nothing.
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -263,6 +263,33 @@ jobs:
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:self-import

# A build tsconfig that excludes tooling by FILE NAME (`*.test.ts`) stops
# the files that happen to be named that way and nothing else. The first
# shared helper added to a `__tests__/` directory is then a program input,
# and an emitting program writes it into the published `dist`. That has
# happened three times — objectui#4006 (73 `*.test.d.ts` across two
# packages), objectui#4836 (9 more, one of them an emitted module whose
# first statement imports `vitest`) and objectui#6943 (the same package as
# the first, because that fix wrote the name form) — and every one was
# found by a human, never by a gate. objectui#7212 measured the standing
# exposure: 29 published packages carried the name form with ZERO offending
# files, green because nobody had added such a helper yet. This gate reads
# `exclude` ARRAYS only: no build, no artifact, no emit model, which is what
# keeps it clear of the modelling objectui#4846 declined for the
# artifact-level gate. That gate stays as the second line of defence — it
# is the only criterion that cannot be wrong about what actually ships, and
# it lives in `published-dist-gate.yml` because it needs a full-repo build.
# Its runnable alias is deliberately NOT named anywhere in this file:
# `check-published-dist-tooling.test.ts` asserts by substring that no
# per-PR workflow mentions it, which is how the ruling that kept a
# full-repo build off the PR path is held — prose naming it would read the
# same to that scan as a step running it. Config
# reads plus the sibling gate's `typescript`-importing scanner, so it needs
# the install and nothing built, same as the two steps above.
- name: Verify published build tsconfigs exclude tooling DIRECTORIES, not just names
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:published-tsconfig-exclude

# `sideEffects` is a PUBLISHED CONTRACT, and an ARRAY form of it fails in
# the one direction nothing can witness: an INCOMPLETE array drops a
# registration inside a CONSUMER's bundle, with no error, no warning and
Expand Down
9 changes: 8 additions & 1 deletion content/docs/guide/ci-cd-pipeline.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,6 +50,7 @@
"census:body-dialect": "node scripts/body-dialect-census.mjs",
"check:control-bytes": "node scripts/check-control-bytes.mjs",
"check:published-dist": "node scripts/check-published-dist-tooling.mjs",
"check:published-tsconfig-exclude": "node scripts/check-published-tsconfig-tooling-exclude.mjs",
"check:spec-floors": "node scripts/check-spec-range-floors.mjs",
"check:i18n-keys": "node scripts/check-i18n-call-site-keys.mjs",
"check:i18n-drift": "node scripts/check-i18n-en-drift.mjs",
Expand Down
17 changes: 16 additions & 1 deletion packages/app-shell/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,22 @@
"moduleResolution": "nodenext"
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
],
"references": [
{ "path": "../types" },
{ "path": "../core" },
Expand Down
17 changes: 16 additions & 1 deletion packages/auth/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/collaboration/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/components/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,18 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["src/__tests__", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/i18n/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,20 @@
"lib": ["ES2020", "DOM"]
},
"include": ["src"],
"exclude": ["src/**/*.test.ts", "src/**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"src/**/*.test.ts",
"src/**/*.test.tsx"
],
// `utils/number-display.ts` re-exports `@object-ui/core` (objectui#4576).
// The root tsconfig's `paths` map that specifier at the SOURCE tree
// (`packages/core/src`), which would make those files program inputs under
Expand Down
17 changes: 16 additions & 1 deletion packages/layout/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,5 +13,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/mobile/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/permissions/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-ai/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-calendar/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-chatbot/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-dashboard/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,5 +15,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-detail/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
10 changes: 9 additions & 1 deletion packages/plugin-editor/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,5 +22,13 @@
// Their type coverage did not go away with them: it moved to the
// `tsconfig.test.json` chained off this package's `type-check` script, which
// is what scripts/check-type-check-coverage.mjs verifies.
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
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
41 changes: 41 additions & 0 deletions .changeset/7212-published-tsconfig-tooling-exclude-ratchet.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
---
---

Repo tooling and build config only — no published package changes, so no version bump.

Published build tsconfigs must now exclude tooling DIRECTORIES, not just tooling FILE NAMES,
and a new per-PR gate enforces it: `pnpm check:published-tsconfig-exclude`
(`scripts/check-published-tsconfig-tooling-exclude.mjs`, wired into `ci.yml`'s Type Check job).

The same defect had been repaired three times and gated never — objectui#4006 (73 `*.test.d.ts`
published from two packages), objectui#4836 (9 more, one of them an emitted module whose first
statement imports `vitest`) and objectui#6943 (the same package as the first, because that fix
wrote the name form and the directory form was never generalised). objectui#7212 measured the
standing exposure instead of another instance: 29 published packages carried the name form with
ZERO offending files, green because nobody had yet added a shared helper to a `__tests__/`
directory, not because the config would stop one. The maintainer ruled for the ratchet on
2026-09-02.

The gate reads `exclude` arrays and nothing else — no build, no artifact, no emit model. That
narrowness is the point: objectui#4846 measured the cheap static gate "no build tsconfig program
may contain a tooling file" and rejected it, because deciding whether a tooling file in a program
is a defect means reimplementing three third-party emit semantics. Asking only DOES THE CONFIG
NAME THE DIRECTORY needs none of that. The artifact-level `pnpm check:published-dist` is
untouched and stays the second line of defence — it is the only criterion that cannot be wrong
about what actually ships.

28 build tsconfigs were converted in the same commit so `main` is green on merge. The conversion
is emit-neutral, and that was measured rather than assumed: each package's build program file
list was resolved with TypeScript's own config resolver before and after, and all 33 enforced
packages came back byte-identical (0 files added, 0 removed). Identical program input means
identical emit, so no published artifact and no bundle moves.

Six published packages are named carve-outs rather than converted, because their emitter never
builds its program from this file list, and each re-proves its own reason on every run instead of
being trusted: `@object-ui/cli`, `@object-ui/create-plugin` and `@object-ui/data-objectstack` emit
from a `tsup` entry graph; `@object-ui/plugin-charts` keeps its tooling exclude in the `dts()`
options and carries no `exclude` key in its tsconfig; `@object-ui/console` and `@object-ui/runner`
are Vite applications with `noEmit: true` and no `dts()` plugin, so they write no declarations at
all. Two of those six — `create-plugin` and `runner` — were found at authoring time and were
inside the ruling's initial red set; requiring a shape in a config their emitter never consults
would have been a check that is green about nothing.
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -263,6 +263,33 @@ jobs:
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:self-import

# A build tsconfig that excludes tooling by FILE NAME (`*.test.ts`) stops
# the files that happen to be named that way and nothing else. The first
# shared helper added to a `__tests__/` directory is then a program input,
# and an emitting program writes it into the published `dist`. That has
# happened three times — objectui#4006 (73 `*.test.d.ts` across two
# packages), objectui#4836 (9 more, one of them an emitted module whose
# first statement imports `vitest`) and objectui#6943 (the same package as
# the first, because that fix wrote the name form) — and every one was
# found by a human, never by a gate. objectui#7212 measured the standing
# exposure: 29 published packages carried the name form with ZERO offending
# files, green because nobody had added such a helper yet. This gate reads
# `exclude` ARRAYS only: no build, no artifact, no emit model, which is what
# keeps it clear of the modelling objectui#4846 declined for the
# artifact-level gate. That gate stays as the second line of defence — it
# is the only criterion that cannot be wrong about what actually ships, and
# it lives in `published-dist-gate.yml` because it needs a full-repo build.
# Its runnable alias is deliberately NOT named anywhere in this file:
# `check-published-dist-tooling.test.ts` asserts by substring that no
# per-PR workflow mentions it, which is how the ruling that kept a
# full-repo build off the PR path is held — prose naming it would read the
# same to that scan as a step running it. Config
# reads plus the sibling gate's `typescript`-importing scanner, so it needs
# the install and nothing built, same as the two steps above.
- name: Verify published build tsconfigs exclude tooling DIRECTORIES, not just names
if: steps.relevant.outputs.should_run == 'true'
run: pnpm check:published-tsconfig-exclude

# `sideEffects` is a PUBLISHED CONTRACT, and an ARRAY form of it fails in
# the one direction nothing can witness: an INCOMPLETE array drops a
# registration inside a CONSUMER's bundle, with no error, no warning and
Expand Down
9 changes: 8 additions & 1 deletion content/docs/guide/ci-cd-pipeline.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -50,6 +50,7 @@
"census:body-dialect": "node scripts/body-dialect-census.mjs",
"check:control-bytes": "node scripts/check-control-bytes.mjs",
"check:published-dist": "node scripts/check-published-dist-tooling.mjs",
"check:published-tsconfig-exclude": "node scripts/check-published-tsconfig-tooling-exclude.mjs",
"check:spec-floors": "node scripts/check-spec-range-floors.mjs",
"check:i18n-keys": "node scripts/check-i18n-call-site-keys.mjs",
"check:i18n-drift": "node scripts/check-i18n-en-drift.mjs",
Expand Down
17 changes: 16 additions & 1 deletion packages/app-shell/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,22 @@
"moduleResolution": "nodenext"
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
],
"references": [
{ "path": "../types" },
{ "path": "../core" },
Expand Down
17 changes: 16 additions & 1 deletion packages/auth/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/collaboration/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/components/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,18 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["src/__tests__", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
15 changes: 14 additions & 1 deletion packages/i18n/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,20 @@
"lib": ["ES2020", "DOM"]
},
"include": ["src"],
"exclude": ["src/**/*.test.ts", "src/**/*.test.tsx"],
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"src/**/*.test.ts",
"src/**/*.test.tsx"
],
// `utils/number-display.ts` re-exports `@object-ui/core` (objectui#4576).
// The root tsconfig's `paths` map that specifier at the SOURCE tree
// (`packages/core/src`), which would make those files program inputs under
Expand Down
17 changes: 16 additions & 1 deletion packages/layout/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,5 +13,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/mobile/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/permissions/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,5 +34,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-ai/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-calendar/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-chatbot/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-dashboard/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,5 +15,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
17 changes: 16 additions & 1 deletion packages/plugin-detail/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,5 +14,20 @@
"skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
// Tooling is excluded by DIRECTORY, not just by file NAME. A helper under
// `__tests__/` that is not itself called `*.test.ts` is otherwise a program
// input, and an EMITTING program writes it into the published `dist`
// (objectui#4006 / #4836 / #6943 -- the same defect three times, each found
// by hand). Enforced repo-wide by `pnpm check:published-tsconfig-exclude`
// (objectui#7212), which derives these directory names from `TOOLING_FILE`
// in scripts/check-phantom-dependencies.mjs.
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
10 changes: 9 additions & 1 deletion packages/plugin-editor/tsconfig.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,5 +22,13 @@
// Their type coverage did not go away with them: it moved to the
// `tsconfig.test.json` chained off this package's `type-check` script, which
// is what scripts/check-type-check-coverage.mjs verifies.
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx"]
"exclude": [
"node_modules",
"dist",
"**/__tests__/**",
"**/__mocks__/**",
"**/__benchmarks__/**",
"**/*.test.ts",
"**/*.test.tsx"
]
}
Loading
Loading