fix(build,docs): dependency preflight before the build wipes dist, docs drift for 1.40.0

- scripts/build.mjs resolves exceljs/dist/exceljs.min.js and fflate first,
  before tsc and before rm -rf dist/web/public. A tree whose node_modules
  predate those devDependencies (pulled but never ran npm install) used to
  fail in prepare-spreadsheet-assets.mjs with the live dist assets already
  deleted, so the running server served an index.html whose hashed files
  were gone. It now exits 1 with "run `npm install` first", nothing touched.
  test/spreadsheet-assets.test.ts pins the order, that the list covers every
  require.resolve in the prepare script, and runs a relocated copy of the
  build to prove the exit and message.
- CLAUDE.md: the header visibility rule's stock desktop default now lists
  Tiles (1180px and wider), which ships ON on desktop.
- docs/wiki/Agent-CLIs.md: "Before 1.36.0" becomes "Before 1.40.0" (four
  places); 1.36.0 never ships.
- docs/wiki/Home.md: the "Everything in the manual" index lists Tile Grid
  and Custom Model Endpoints, matching the sidebar. test/wiki-home-index
  fails when a sidebar page is missing from that index.
- docs/wiki/Tile-Grid.md: the Tiles default is off on tablets too since the
  touch-primary default landed, not only on phones.
- docs/browser-testing-guide.md: the fixed port table and new WebServer(PORT)
  snippet give way to the port-0 pattern (new WebServer(0, false, true),
  server.boundPort) that test/test-ports-guard.test.ts enforces; the
  examples that opened localhost:3000, the live instance, use BASE_URL.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-10-09 09:47:22 +02:00
parent ecd577157b
commit 9d38cbf51a
8 changed files with 169 additions and 23 deletions
+27
View File
@@ -4,6 +4,7 @@
* Extracted from the package.json one-liner for readability and debuggability.
*
* Steps:
* 0. Preflight: the build-time packages resolve (nothing is touched before it)
* 1. TypeScript compilation
* 2. Copy static assets (web/public, templates)
* 3. Build vendor xterm bundles
@@ -13,6 +14,7 @@
*/
import { execSync } from 'child_process';
import { createRequire } from 'module';
import { appendFileSync, readFileSync, writeFileSync, renameSync } from 'fs';
import { createHash } from 'crypto';
import { fileURLToPath } from 'url';
@@ -25,6 +27,31 @@ function run(label, cmd) {
execSync(cmd, { stdio: 'inherit', cwd: ROOT, shell: true });
}
// 0. Preflight: resolve the build-time packages the asset stage reads only AFTER it has
// deleted dist/web/public (step 2), before anything is touched. A tree whose node_modules
// predate them (a deploy that pulled but never ran `npm install`) used to fail mid-build
// with dist/web/public already wiped, so the running server kept serving an index.html
// whose hashed assets were gone. Keep the list in step with every require.resolve in
// scripts/prepare-spreadsheet-assets.mjs (test/spreadsheet-assets.test.ts checks it).
// Only specifiers that resolve without an exports map in the way: a subpath of a package
// that has one (@xterm/*) can throw ERR_PACKAGE_PATH_NOT_EXPORTED while installed.
// A hand-run of the asset stage alone (past a blocked tsc) skips this check.
const BUILD_TIME_MODULES = ['exceljs/dist/exceljs.min.js', 'fflate'];
const requireFromBuild = createRequire(import.meta.url);
const missingModules = BUILD_TIME_MODULES.filter((specifier) => {
try {
requireFromBuild.resolve(specifier);
return false;
} catch {
return true;
}
});
if (missingModules.length > 0) {
console.error(`[build] missing build dependency: ${missingModules.join(', ')}`);
console.error('[build] run `npm install` first, then `npm run build` again. Nothing was built or deleted.');
process.exit(1);
}
// 1. TypeScript compilation
run('tsc', 'tsc');
run('chmod dist/index.js', 'chmod +x dist/index.js');