next: add build-scripts/ pipeline, cut over default build/dev
Introduce a plain-Node build pipeline under packages/next/build-scripts/
that replaces the taskr DSL for the everyday build and dev paths:
build-scripts/
├── release.mjs phase orchestrator (compile → bundle → post-bundle ∥ types ∥ check-errors)
├── compile.mjs 36 SWC variants as a data table
├── bundle.mjs 14 rspack runtime variants
├── precompile.mjs copies src/compiled, polyfills, docs, skills, styled-jsx
├── post-bundle.mjs ncc_react_refresh_utils, ncc_next_font, capsize_metrics
├── watch.mjs watchpack + per-file SWC (no re-globbing)
├── lib/{swc,ncc,rspack,compile-glob,copy}.mjs shared primitives
└── ncc/index.mjs 134 vendor-bundling recipes (108 table-driven, 16 custom, 10 copy)
Script cutover in packages/next/package.json:
dev taskr → node build-scripts/watch.mjs
build taskr release → node build-scripts/release.mjs
ncc-compiled taskr ncc → node build-scripts/ncc/index.mjs
(new) — → build:{precompile,compile,bundle,post-bundle,types,check-errors}
(fallback) — → build:taskr, dev:taskr, ncc-compiled:taskr
Update turbo.json inputs: swap the `taskfile*.js` glob for
`build-scripts/**` now that the new scripts are what the `build` task
actually reads. Taskr files remain in the tree as fallback for
`build:taskr`; a follow-up commit deletes them.
The taskfile*.js files, taskr devDep, and taskr patch are intentionally
kept in this commit as a fallback. A follow-up commit removes them.
Measured on a stable tree:
- Warm rerun via turbo cache: 22s → ~0.4s (only with the preceding
turbo.json input scoping commit).
- Single-file watch rebuild: 860ms → 84ms (per-file SWC instead of
re-globbing the full source dir).
- Cold build wall time: 20.5s → ~16s (types now runs in parallel with
compile+bundle).
- All 8000+ SWC-compiled dist outputs are byte-identical to taskr's.
Incidental fix: api_esm source maps now resolve correctly in
dist/api/ (taskr wrote the ESM-relative path into both dist/api/ and
dist/esm/api/, which was wrong for the CJS copy).
- Bundle output bytes differ from a clean taskr build only because
rspack embeds pnpm-store paths; functional output is equivalent.