Skip to content

build(deps): move to @antelopejs/tooling-configs 0.5.0 - #190

Merged
Upd4ting merged 2 commits into
mainfrom
build/bump-tooling-configs
Nov 10, 2026
Merged

Upd4ting merged 2 commits into
mainfrom
build/bump-tooling-configs

Conversation

@Upd4ting

@Upd4ting Upd4ting commented Nov 10, 2026 •

Copy link
Copy Markdown
Member

Why

This puts the repo on the latest @antelopejs/tooling-configs release, 0.5.0, and makes every check pass on it, not just carry a new version number (ANT-1759). It also clears the two rules that tooling-configs#282 turns from notes into sync --check failures, so this branch keeps passing after the next tooling release.

It also fixes main's red CI. Since the interface 0.4.1 release, sync --check on main fails on the module README's compatibility table, and the sync here rewrites it.

What changed

  • Version and sync. @antelopejs/tooling-configs is at ^0.5.0 in the root and module manifests, with both lockfiles updated. pnpm run sync rewrote package.json (new prepare hook, the verify layer's devDependencies), .agents/setup, the AGENTS.md rule table and the module README's compatibility table.

  • release runs typecheck. Both packages' release scripts now start with pnpm run typecheck. In the module, typecheck builds the interface first, so the release still builds the interface as it did before.

  • skipLibCheck. No tsconfig sets it, including through extends, so nothing changed there. The two skipLibCheck hits in src are compiler options for the builder engine's in-memory ts-morph projects, which no script's tsc reads.

  • New lint findings from 0.5.0, all fixed, none suppressed:

    • require-tsconfig-include on packages/dms-builder/knip.config.ts. The package tsconfig can't list it (rootDir is src). It is now listed by a new composite tsconfig.config.json beside it, referenced from the package tsconfig, following the pattern in the preset README; tsc -p leaves that config unbuilt. The config's default export is typed KnipConfig, so that config also compiles on its own.
    • require-safety-comment-for-type-assertion in the verify journeys database.mjs and i18n.mjs. Both casts are removed instead of justified.
    • no-runtime-typeof in frontend-source-check.cjs. The catalog is already parsed by isMessageTree, so instanceof Object meant "not a string". It now branches on the existing isString guard.
  • A lint race in checks, on main too. antelopejs-checks runs typecheck beside lint, and the module's typecheck is the build, which starts with rimraf dist. query-templates.test.cjs took its types from dist, so lint reported no-unsafe-* there whenever it ran while dist was gone. The test now loads the built files as unknown and narrows them with guards in tests/helpers/built-exports.js, typed from src, as builder-enabled.test.cjs does.

  • A verify journey that read too early, on main too. editor/the-layers-tab-lists-every-block-and-selecting-opens-its-settings read the Layers tree right after clicking the tab, before it rendered, and failed with [] on main as on this branch. It now waits for the tree's last row first, as the Developer-mode journey in the same file already does.

Proof

Before: main at b44fce7 with only the bump to 0.5.0 and pnpm install, dist prebuilt

pnpm run sync:check


> @antelopejs/dms-builder-workspace@0.0.0 sync:check <repo>
> antelopejs-sync --check

Drift: package.json; run antelopejs-sync
Drift: .agents/setup; run antelopejs-sync
Drift: AGENTS.md; run antelopejs-sync
Drift: packages/dms-builder/README.md; run antelopejs-sync
 ELIFECYCLE  Command failed with exit code 1.
exit 1

pnpm run checks


> @antelopejs/dms-builder-workspace@0.0.0 checks <repo>
> antelopejs-checks

[lint]

> @antelopejs/dms-builder-workspace@0.0.0 lint <repo>
> oxlint && pnpm --dir packages/dms-builder/frontend-vue lint && antelopejs-check-interface-ranges && pnpm --filter @antelopejs/dms-builder check:package-contract && pnpm --filter @antelopejs/dms-builder check:frontend-source

.claude/skills/verify-dms-builder/journeys/i18n.mjs:48:20: error anti-slop(require-safety-comment-for-type-assertion): This type assertion has no `SAFETY:` justification. State the checked invariant immediately before the assertion or its containing statement.
.agents/skills/verify-dms-builder/journeys/i18n.mjs:48:20: error anti-slop(require-safety-comment-for-type-assertion): This type assertion has no `SAFETY:` justification. State the checked invariant immediately before the assertion or its containing statement.
packages/dms-builder/scripts/frontend-source-check.cjs:91:9: error anti-slop(no-runtime-typeof): `instanceof Object` is a `typeof` check in another form. Parse input at its I/O boundary, or move the check into a type guard such as `(value: unknown): value is Function`.
.claude/skills/verify-dms-builder/journeys/database.mjs:21:117: error anti-slop(require-safety-comment-for-type-assertion): This type assertion has no `SAFETY:` justification. State the checked invariant immediately before the assertion or its containing statement.
.agents/skills/verify-dms-builder/journeys/database.mjs:21:117: error anti-slop(require-safety-comment-for-type-assertion): This type assertion has no `SAFETY:` justification. State the checked invariant immediately before the assertion or its containing statement.
packages/dms-builder/knip.config.ts:1:1: error antelopejs(require-tsconfig-include): No tsconfig.json lists this file, so type-aware lint reads it in tsgolint's inferred program, without this repository's compiler options or `types`: Node and test-runner globals are error types, so `typescript/no-unsafe-*` reports here are false and findings that need those types go missing. List the file in a tsconfig.json that names the `types` it uses: one beside it that extends the root tsconfig, or, for a file at the root, a composite tsconfig that the root tsconfig references.
packages/dms-builder/tests/query-templates.test.cjs:10:7: error typescript(no-unsafe-assignment): Unsafe assignment of an any value. help: Assigned value has type `any`, so the target is also inferred as `error`. Use a safely typed value or `unknown`, and narrow it before use.
packages/dms-builder/tests/query-templates.test.cjs:11:7: error typescript(no-unsafe-assignment): Unsafe assignment of an any value. help: Assigned value has type `any`, so the target is also inferred as `any`. Use a safely typed value or `unknown`, and narrow it before use.
packages/dms-builder/tests/query-templates.test.cjs:31:9: error typescript(no-unsafe-assignment): Unsafe assignment of an error typed value. help: Assigned value has type `error`, so the target is also inferred as `error`. Use a safely typed value or `unknown`, and narrow it before use.
packages/dms-builder/tests/query-templates.test.cjs:32:19: error typescript(no-unsafe-return): Unsafe return of a value of type `any`. help: Returned expression has type `any`. Return a safely typed value or narrow the value before returning it.
packages/dms-builder/tests/query-templates.test.cjs:40:9: error typescript(no-unsafe-assignment): Unsafe assignment of an error typed value. help: Assigned value has type `error`, so the target is also inferred as `error`. Use a safely typed value or `unknown`, and narrow it before use.
packages/dms-builder/tests/query-templates.test.cjs:41:19: error typescript(no-unsafe-return): Unsafe return of a value of type `any`. help: Returned expression has type `any`. Return a safely typed value or narrow the value before returning it.
packages/dms-builder/tests/query-templates.test.cjs:47:9: error typescript(no-unsafe-assignment): Unsafe assignment of an error typed value. help: Assigned value has type `error`, so the target is also inferred as `error`. Use a safely typed value or `unknown`, and narrow it before use.
packages/dms-builder/tests/query-templates.test.cjs:57:9: error typescript(no-unsafe-assignment): Unsafe assignment of an error typed value. help: Assigned value has type `error`, so the target is also inferred as `error`. Use a safely typed value or `unknown`, and narrow it before use.
packages/dms-builder/tests/query-templates.test.cjs:65:5: error typescript(no-unsafe-argument): Unsafe argument of type error typed assigned to a parameter of type string.
 ELIFECYCLE  Command failed with exit code 1.

[sync:check]

> @antelopejs/dms-builder-workspace@0.0.0 sync:check <repo>
> antelopejs-sync --check

Drift: package.json; run antelopejs-sync
Drift: .agents/setup; run antelopejs-sync
Drift: AGENTS.md; run antelopejs-sync
Drift: packages/dms-builder/README.md; run antelopejs-sync
 ELIFECYCLE  Command failed with exit code 1.
Checks: 9 passed, 2 failed.
 ELIFECYCLE  Command failed with exit code 1.
exit 1

After: this branch

pnpm run sync:check


> @antelopejs/dms-builder-workspace@0.0.0 sync:check <repo>
> antelopejs-sync --check

Guardrails are in sync.
exit 0

pnpm run checks


> @antelopejs/dms-builder-workspace@0.0.0 checks <repo>
> antelopejs-checks

Checks: 11 passed, 0 failed.
exit 0

pnpm run checks with both dist folders deleted first, so lint runs while the build recreates them


> @antelopejs/dms-builder-workspace@0.0.0 checks <repo>
> antelopejs-checks

Checks: 11 passed, 0 failed.
exit 0

The #282 rules

The shipped checkTypecheckCoverage from 0.5.0's antelopejs-sync, the check #282 turns into a failure, run against each package root:

base   packages/dms-builder             ["package.json: script \"release\" does not run \"typecheck\", so a release can publish a build that skipped the lib check. ..."]
base   packages/interface-dms-builder   ["package.json: script \"release\" does not run \"typecheck\", so a release can publish a build that skipped the lib check. ..."]
head   <repo>                           []
head   packages/dms-builder             []
head   packages/interface-dms-builder   []

Lint of the race-prone test, dist removed

Before, on main and on 0.5.0: typescript(no-unsafe-*) errors in packages/dms-builder/tests/query-templates.test.cjs. After: none, with or without dist. node --test tests/*.test.cjs passes.

Verify layer (verify-dms-builder, every feature, since the diff touches package.json, the lockfiles and a tsconfig)

Verify: PASS+NOTES at head 28ca114. Every one of the skill's features ran and passed. No one-way door: the contract and publish paths flagged by doors are the two package.json files, whose only changes are the release scripts and the tooling devDependency range. No formal check covers the diff.

Run `pnpm run sync` for 0.5.0, make both `release` scripts run
`typecheck` first, and fix the lint findings 0.5.0 adds: list the
module's knip config in a tsconfig, drop two casts from the verify
journeys, branch on `isString` in the frontend source check, and load
the built query exports through guards typed from `src`, so lint no
longer races the build that `checks` runs beside it.
@Upd4ting
Upd4ting merged commit 19aa20b into main Nov 10, 2026
13 checks passed
@Upd4ting
Upd4ting deleted the build/bump-tooling-configs branch November 10, 2026 15:40
Upd4ting added a commit that referenced this pull request Nov 10, 2026
## Summary

Every builder save typechecks the project before it writes. The check
asked TypeScript for the whole program's diagnostics. Those include
every declaration file in `node_modules`, and the builder drops their
errors anyway. On the DMS module template (`declaration: true`, no
`skipLibCheck`) that dropped work was most of each save.

```diff
 relevantDiagnostics(project)            engine/writable.ts
-  project.getPreEmitDiagnostics()       whole program, node_modules .d.ts included
+  for each program file not in node_modules
+    sourceFile.getPreEmitDiagnostics()  that file only
   drop file-less and node_modules diagnostics
```

The loop walks the program's files, not `project.getSourceFiles()`, so a
file that only an import reaches is still checked. Examples are a file
created in an editor while the server runs, or one outside `include`.

## Evidence

Evidence level: benchmark of the engine operations, plus an end-to-end
profile in the dashboard.

Workload: the repository playground (Board page, orders table) copied
into a fixture inside the package. Each operation is called the way the
dashboard calls it, with the draft built the way `structureToDraft`
builds it. Sides run interleaved, 5 runs each of 3 calls, on a shared
and noisy server.

| Operation | main | this PR |
| --- | ---: | ---: |
| `SetPageBlocks` (a dashboard save) | 1419 ms (1329–1931) | 437 ms
(369–499) |
| `ConfigurePage` | 1044 ms (994–1253) | 107 ms (100–119) |
| `AddBlock` | 1566 ms (1430–1663) | 621 ms (581–643) |
| `SetPageBlocks`, 10 pages | 2348 ms (2322–3550) | 824 ms (761–1177) |

The typecheck alone, measured with the template's tsconfig: 4568 ms
(3672–5216) before, 496 ms (390–632) after. The diagnostics are the same
with and without a type error, including an error in a file outside
`include` and one in a file created after the project was parsed. With
`skipLibCheck: true` there is no change: 272 ms before, 248 ms after.

Cumulative impact: about 1 s less waiting on each save in the editor,
every save. The order of diagnostics across files can change. Only the
joined error banner reads that order.

The engine specs (`test:unit`) pass: 523 passing.

## Verification

- `pnpm run checks` passes. Main fails `sync:check` on a stale compat
row in `packages/dms-builder/README.md` (interface-dms-builder 0.4.0,
published 0.4.1), so a separate commit syncs it. It is the same line
#190 carries, byte for byte, so whichever of the two lands second has an
empty or trivial conflict there.
- Verify harness on a stack of the three perf PRs: `smoke`, `blocks`
(3), `pages` (3) and `resources` (4) journeys pass. Dashboard save, Save
click to the server's answer, 15 saves per side: 2325 ms (2010–3792) on
main, 630 ms (440–1102) with the three PRs.
- `formal-page-save`: the same output on main and on this branch. The
only finding is the recorded F2 (#163), which none of these lines touch.
The gate flags the covered code's emit as changed.

## Merge Danger

**Door:** two-way. Nothing is stored. A revert restores the old check.

**Blast Radius:** saves.

A diagnostic located in an own file that TypeScript reports only while
checking a `node_modules` declaration file would no longer refuse a
save. Neither review found a checker path that does this.
Upd4ting added a commit that referenced this pull request Nov 10, 2026
## Summary

Before and after a save rewrites a page, the builder asks which named
imports the page file uses, so it can prune the ones the rewrite
orphaned. It asked once per import with a project-wide
find-all-references. That search reads every other file and builds
display text for each definition, then keeps only the hits in the page
file.

```diff
 isReferenced(sourceFile, specifier)              engine/writable.ts
-  specifier.getNameNode().findReferencesAsNodes()  every file, display parts built
+  languageService.getDocumentHighlights(file, binding, [file])  this file only
   keep a use outside the import declaration
```

The highlights are those of the local binding: the alias, else the name.
That is what a use in the file refers to.

## Evidence

Evidence level: benchmark (micro and engine operations).

`referencedImportNames` on the Board page (24 named imports), after an
edit, 5 runs:

| Pages in the app | find-all-references | document highlights |
| ---: | ---: | ---: |
| 1 | 358 ms (303–958) | 32 ms (23–47) |
| 100 | 3175 ms (2450–5820) | 40 ms (28–212) |

Both give the same names, including an aliased import that is used (`Get
as Fetch`) and one that is not (`Post as Unused`).

A save (`SetPageBlocks`), sides interleaved:

| Workload | main | this PR |
| --- | ---: | ---: |
| 10 pages, 3 pairs | 2584 ms (2549–2665) | 1495 ms (1385–2100) |
| 100 pages, 2 pairs | 4529–6626 ms | 2285–3843 ms |
| 1 page, on top of the typecheck fix, 5 pairs | 676 ms (509–758) | 188
ms (167–209) |

On main with one page the gain hides inside the whole-program typecheck,
which then pays the program rebuild the search used to pay. The
typecheck fix removes that.

Cumulative impact: the search runs twice per save, so the cost grows
with the number of pages in the app. That is about 0.3 s per save at 1
page and seconds at 100 pages.

The engine specs (`test:unit`) pass: 523 passing.

## Verification

- `pnpm run checks` passes. Main fails `sync:check` on a stale compat
row in `packages/dms-builder/README.md` (interface-dms-builder 0.4.0,
published 0.4.1), so a separate commit syncs it. It is the same line
#190 carries, byte for byte, so whichever of the two lands second has an
empty or trivial conflict there.
- Verify harness on a stack of the three perf PRs: `smoke`, `blocks`
(3), `pages` (3) and `resources` (4) journeys pass. Dashboard save, Save
click to the server's answer, 15 saves per side: 2325 ms (2010–3792) on
main, 630 ms (440–1102) with the three PRs.
- `formal-page-save`: the same output on main and on this branch. The
only finding is the recorded F2 (#163), which none of these lines touch.
The gate flags the covered code's emit as changed.

## Merge Danger

**Door:** two-way.

**Blast Radius:** import pruning on save.

Two theoretical forms differ, and the reviews found neither in a page
the builder writes. The first is an aliased import whose export does not
resolve: it is now counted as used. The typecheck refuses that save
either way. The second is the same export bound twice through different
names: the unused one is now kept, as `pruneUnusedImports` intends.
Upd4ting added a commit that referenced this pull request Nov 10, 2026
#192)

## Summary

The page index and the resource index each parsed the whole app into
their own ts-morph project. They did it after every write, and again
after every outside edit. The editor reads both right after each save:
table usage, the page list and the table list. So each save paid two
full parses.

```diff
 getSourceIndex()                  engine/source-index.ts
-  createModulesProject()          own parse
+  indexedProject()                engine/indexed-project.ts, shared
 getResourceIndex()                engine/resource-index.ts
-  createModulesProject()          own parse
+  indexedProject()
```

`indexedProject()` keeps the stamp check the two indexes had: a new
parse once a file it read was written since, or after either index is
invalidated. Each index rescans when the parse it read is replaced.

## Evidence

Evidence level: benchmark of the engine operations, plus an end-to-end
profile in the dashboard.

Workload: the repository playground in a fixture. An outside edit of the
Board page is followed by what the editor reads after a save: table
usage, `ListPages` and `ListResources`. Sides run interleaved, 5 runs
each.

| Workload | main | this PR |
| --- | ---: | ---: |
| Rescan after an outside edit, 1 page | 1063 ms (1042–1084) | 584 ms
(573–629) |
| Rescan after a write, 10 pages, 3 runs | 1702 ms (1559–2025) | 828 ms
(782–1046) |
| Opening the editor, cold engine | 2228 ms (2157–2289) | 1700 ms
(1644–1717) |

In the dashboard, `GET /api/builder/pages` during the editor's open
drops from about 550 ms to 15 ms. `/resources` has already parsed the
shared project by then.

Cumulative impact: one parse less after every save and on every editor
open, about 0.5 s of server CPU each time. The backend's event loop is
blocked during a parse, so other requests wait too.

The engine specs (`test:unit`) pass: 523 passing.

## Verification

- `pnpm run checks` passes. Main fails `sync:check` on a stale compat
row in `packages/dms-builder/README.md` (interface-dms-builder 0.4.0,
published 0.4.1), so a separate commit syncs it. It is the same line
#190 carries, byte for byte, so whichever of the two lands second has an
empty or trivial conflict there.
- Verify harness on a stack of the three perf PRs: `smoke`, `blocks`
(3), `pages` (3) and `resources` (4) journeys pass. Dashboard save, Save
click to the server's answer, 15 saves per side: 2325 ms (2010–3792) on
main, 630 ms (440–1102) with the three PRs.
- `formal-page-save`: the same output on main and on this branch. The
only finding is the recorded F2 (#163), which none of these lines touch.
The gate flags the covered code's emit as changed.

## Merge Danger

**Door:** two-way.

**Blast Radius:** page and resource listings.

Invalidating one index now also rescans the other: `RefreshSourceIndex`
reads resources again too. Neither scanner edits the project, and every
write opens its nodes from the writable project.
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