Skip to content

Consolidate root scripts into one check runner and unify dependency pins (CL-7442) - #642

Merged
TheGreatAxios merged 6 commits into
mainfrom
cl-7442-scripts-deps
Sep 5, 2026
Merged

TheGreatAxios merged 6 commits into
mainfrom
cl-7442-scripts-deps

Conversation

@TheGreatAxios

@TheGreatAxios TheGreatAxios commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Fixes CL-7442

What changed

One check runner. check:structural was a hand-maintained chain of 18
bun run check:X invocations plus 23 separate root package.json scripts.
scripts/checks/run.ts now discovers every scripts/checks/*.ts file with
an import.meta.main entry point (the same signal each check already used
to run standalone) and runs it, plus generate-tsconfig-references.ts --check (named explicitly — it lives outside scripts/checks/ because it
doubles as the reference generator). check:packages (packed-consumption
audit) stays discoverable and independently runnable but is excluded from
the full run — it spawns a subprocess per workspace package and takes
minutes; it was never part of the full check:structural chain before this
change either (it lived under the now-removed check:all), so this
preserves prior behavior rather than regressing CI wall-clock.

Run one check on its own: bun run check:structural report-error. Forward
flags: bun run check:structural report-error -- --write-baseline.

CI's structural job already invoked exactly bun run check:structural
(see scripts/ci-jobs.test.ts's "same list" assertion) — no CI or docs
drift possible now, since there's only one script to invoke.

Root script list, before → after (36 → 14):

Before (36): check, check:all, typecheck, lint, format, hooks:install,
prepare, build, test, test:e2e, dev, setup, setup:memory, reset,
check:structural, check:deletion, check:report-error, check:error-envelope,
check:killdates, check:packages, check:licenses, check:db-gate,
check:no-product-tenancy, check:browser-safe-subpaths, check:web-utilities,
check:tailwind-source, check:ui-vocabulary, check:react-ui-drift,
check:react-ui-pin, check:tool-package-pins, check:tool-package-freshness,
check:hub-git-safety, check:routine-target-inference,
check:tsconfig-references, build:sidecar-image, eval

After (14): check, typecheck, lint, format, hooks:install, prepare, build,
test, test:e2e, dev, setup, setup:memory, reset, check:structural,
build:sidecar-image, eval

check:all is gone too — nothing referenced it, and folding
check:packages into the runner (as an individually-invocable, opt-out-of
full-run check) makes it redundant.

check:routine-target-inference: kept. apps/web and
packages/chat-ui still exist and the guarded pattern
(agents[0]?.definitionId) still appears live in
packages/chat-ui/src/composer.tsx — routines are not deleted, so the
subject this check guards is still live.

check:tool-package-pins / check:tool-package-freshness: kept as-is.
CL-7402 has not landed (no matching commit on origin/main), and
workflows/* — the subject both checks scan — still exists.

Catalog. Added a check:catalog-pins check (discovered by the same
runner) that fails when a dependency declared in the root catalog is
pinned as a literal elsewhere instead of catalog:. Fixed every drift it
found:

  • drizzle-orm — apps/hub pinned 0.45.2 literally; catalog said
    ^0.45.1. Catalog bumped to ^0.45.2; apps/hub now uses catalog:.
  • hono — 23 workspaces pinned ^4.11.9 literally instead of catalog:
    (root overrides still forces the resolved version to 4.13.3, unaffected).
  • postgres — apps/hub pinned ^3.4.8 literally; now catalog:.
  • @types/react-dom — never catalogued; 9 workspaces split between
    ^19.2.1 and ^19.2.2. Added to the catalog at ^19.2.2; all 9 now use
    catalog:.
  • better-auth — not called out in the ticket's scan, but the same
    drift class: apps/hub pinned ^1.4.18 literally against a catalog
    entry of ^1.4.18. Now catalog: too (found by running the new check
    against the real tree).

The 21 single-workspace dependencies — ruling

Recomputed on origin/main including the root package.json as a
workspace for this purpose (root tooling deps are single-consumer by
construction): 22 external (non-@corbits/@intx/@workbench)
dependencies used by exactly one package.json.

dependency consumer ruling
@eslint/js root keep — root lint tooling, single-consumer by design
eslint root keep — same
jiti root keep — same
prettier root keep — same
puppeteer-core root keep — drives scripts/e2e/browser/walkthrough.ts
typescript-eslint root keep — root lint tooling
@logtape/logtape packages/error-sink keep — the package's own logging backend
@phosphor-icons/react packages/icons keep — the package's reason to exist
@radix-ui/react-dialog apps/web keep — UI primitive, not a domain rule; belongs at the app's composition layer
@radix-ui/react-slot apps/web keep — same
@tailwindcss/vite apps/web keep — build tooling
@vitejs/plugin-react apps/web keep — build tooling
vite apps/web keep — build tooling
tailwindcss apps/web keep — styling engine
sonner apps/web keep — verified live: apps/web/src/app.css styles its [data-sonner-*] DOM directly, and apps/web/test/react-ui-toast-mock.ts mocks it; not unused
better-auth apps/hub keep, now catalog: — auth library, plausible second consumer later
chat (npm package literally named chat) packages/slack-tag keep — verified live: import type { StateAdapter } from "chat" in dispatch.ts and thread-state.ts
corbits-tag packages/slack-tag keep — this package's own Slack integration, single-consumer by design
cronstrue packages/workflows keep — cron humanization, single use is expected
e2b packages/e2b-sandbox-sidecar keep — the package's reason to exist
tar packages/tool-registry-publish keep, already catalog:
y-protocols packages/presence keep — Yjs companion package, single use is expected

No removals: every single-workspace dependency checked out as either
build/lint tooling that is inherently root-only, or a package's own reason
to exist. None were unused.

Fixed while touching this

scripts/checks/run.ts initially discovered itself (run.ts has an
import.meta.main entry point) as a check, spawning an unbounded
self-recursion the first time the full runner executed. Fixed by excluding
the runner by its resolved real path (realpathSync), not its filename, so
a rename or a symlink pointing at run.ts is still recognized as the
runner rather than slipping in as a discovered check — with regression
tests covering both cases (scripts/checks/test/run.test.ts).

web-tailwind-utilities.ts ran its main() eagerly on import instead of
gating it behind if (import.meta.main), so the runner never discovered it
as a standalone check. Gave it the same entry-point guard as every other
check.

Added scripts/checks/test/run.test.ts's explicit EXPECTED_CHECK_NAMES
roster: the discovered-checks set is asserted equal to it, so a check
gaining or losing its import.meta.main entry point fails this test loudly
instead of silently changing what CI runs.

catalog-pins now also reads workspaces.catalog/workspaces.catalogs
(bun accepts both root-level and workspaces-nested catalog fields),
accepts catalog:<name> for a named catalog, parses each package.json
through an arktype schema instead of an as PackageJson cast, and excludes
vendor/intx/*/package.json from workspace discovery — vendored manifests
are governed by VENDORED.md, not this repo's catalog.

Cleared several stale bun run check:<name> references left over from the
pre-consolidation script list (packages/inbox/README.md,
packages/inbox/src/client.ts, IMPLEMENTATION.md,
docs/revendor-inventory.md, docs/workflow-model.md,
scripts/generate-tsconfig-references.ts, VENDORED.md's
check:killdates cells) and aligned scripts/checks/report-error.ts and
its baseline header with AGENTS.md's bun run check:structural <name>
phrasing. AGENTS.md now states explicitly that check:<name> in prose
means bun run check:structural <name>.

Verified

  • bun run check:structural — all checks pass (ran to completion locally,
    including catalog-pins with the vendor/intx exclusion note).
  • bun run typecheck — passes.
  • bun run lint — passes (8 pre-existing unrelated warnings, 0 errors).
  • bun test scripts/run-all.test.ts scripts/ci-jobs.test.ts — passes.
  • bun install from the touched lockfile — resolves cleanly, bun.lock
    diff is limited to the catalog/pin changes above.

Test plan

  • bun run check:structural
  • bun run typecheck
  • bun run lint
  • bun test scripts/checks/test scripts/run-all.test.ts scripts/ci-jobs.test.ts
  • bun install with no unintended lockfile drift

@linear-code

linear-code Bot commented Sep 4, 2026

Copy link
Copy Markdown

CL-7442

Cover the runner excluding itself by resolved real path (a rename, a
symlink) rather than by filename, and a discovered-checks roster kept
in sync with an explicit expected list. Cover catalog-pins reading
named catalogs (catalog:<name>), workspaces.catalog/workspaces.catalogs,
and excluding vendor/intx manifests from workspace discovery.
…ype parse (CL-7442)

The runner now excludes itself by resolved real path instead of by
filename, so a rename or a symlink is still recognized as the runner.
web-tailwind-utilities gains the same import.meta.main guard as every
other check, so the runner discovers it instead of it running eagerly
on import.

catalog-pins now reads workspaces.catalog/workspaces.catalogs
alongside the top-level catalog/catalogs fields, accepts
catalog:<name> for named catalogs, parses package.json through an
arktype schema instead of an `as` cast, and excludes
vendor/intx/*/package.json from workspace discovery — those manifests
are governed by VENDORED.md, not this repo's catalog.
@TheGreatAxios
TheGreatAxios merged commit ff18102 into main Sep 5, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant