From 12fa6c19d0515f1471d963eeaaba0c9c8a4d3a82 Mon Sep 17 00:00:00 2001 From: Adam Wright Date: Sat, 24 Oct 2026 04:40:46 +0000 Subject: [PATCH 1/2] Spec 013 T024: CLAUDE.md's rule for new service code Both rules T024 waited for emerged in T023: - New code under tools/ is TypeScript. A plain .mjs would be loaded by the type check unchecked, and tools/load.spec.ts fails on one. - A new entry point is loaded under Node by tools/load.spec.ts: a module in a service directory as it is, a new service directory by joining SERVICES, and a script that does its work when loaded by joining RUN_ON_LOAD, so it is checked without being run. From T023's final review: the no-plain-JavaScript check matches any case and .jsx, and excludes only the one generated bundle rather than any file with its name (each shown failing on a probe); three comments name the .ts specs they point at. Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 7 +++++++ specs/013-server-types/tasks.md | 2 +- tools/content-node/body.ts | 2 +- tools/content-node/exporters-endpoints.ts | 2 +- tools/content-node/java-hashmap.ts | 2 +- tools/load.spec.ts | 6 +++--- 6 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index ac39d32d..0560ec55 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -38,6 +38,13 @@ is how a formatting failure reached CI. - **Lint and dead-code counts** are ratcheted: they may go down, never up. So are the services' loose values (`tools/loose-baseline.json`, at zero), and `tools/tsconfig.json` has `noImplicitAny` on: new service code is typed. +- **New code under `tools/` is TypeScript** (spec 013). A plain `.mjs` there would + be loaded by the type check without being checked, so `tools/load.spec.ts` + fails on one. +- **A new entry point is loaded under Node** by `tools/load.spec.ts`. A module in + a service directory is picked up as it is; a new service directory joins its + `SERVICES` list; and a script that does its work when loaded (writes files, + starts a browser) joins `RUN_ON_LOAD`, so it is checked without being run. ## The node content service (`tools/content-node`) diff --git a/specs/013-server-types/tasks.md b/specs/013-server-types/tasks.md index d309fe9b..14a07ad4 100644 --- a/specs/013-server-types/tasks.md +++ b/specs/013-server-types/tasks.md @@ -75,7 +75,7 @@ Each task: rename to `.ts`, update imports, file names that name it (R3 list), f Measured 23 Oct with `checkJs` on: 1,229 errors in 47 `.mjs` files, 70 of them in the five tools and 1,159 in 42 specs. The tools are converted, typed, held at zero both counts, and still run as before (parity and the library guard directly under Node, the harness through its new `playwright.config.ts`, which also mends the README's command: it had found no tests since the harness stopped being called a spec) — #643. The specs go next, in batches: the ten check specs outside the content service (load, started, workflows, check-move, check-baseline-totals, the HAR, flaky and lint checks, and content-node's hermetic), 60 errors — #644. The content service's ten smallest (exporter, cache-headers, molecule-details-bound, component-of, diseases, participating-entities, interactors, query-ids, map-results, mapping), 139 — #645. The next eight (pathways-low, complexes, overview-export, schema-objects, orthology, query-attribute-endpoint, interactors-static, referrers), 183 — #647. Seven more (contained-events, pathways-of, flag, query-attribute, discover, diagram-search, references-mapping), 235 — #649. icon, facet-query and the Java parity spec, 151 — #650. query-search and species-search, 151 — #651. search and service, the last two, with the library-update spec, 252 — #652. No `.mjs` is left in `tools/`, and `tools/load.spec.ts` fails if one is added, so a new module is TypeScript and checked. T023 is complete. -- [ ] T024 `CLAUDE.md`: the rule for new service code (typed, and a load test entry for a new entry point) if one emerges. +- [x] T024 `CLAUDE.md`: the rule for new service code (typed, and a load test entry for a new entry point) if one emerges. Both emerged: new code under `tools/` is TypeScript, held by `tools/load.spec.ts`; and a new entry point is loaded under Node by the same spec, a new service directory joining `SERVICES` and a script that works when loaded joining `RUN_ON_LOAD`. Also from T023's review: the no-plain-JavaScript check matches any case and `.jsx`, and excludes only the one generated bundle; three comments name the `.ts` specs. — #653 --- diff --git a/tools/content-node/body.ts b/tools/content-node/body.ts index ef67fd3c..a303f82a 100644 --- a/tools/content-node/body.ts +++ b/tools/content-node/body.ts @@ -101,7 +101,7 @@ const JAVA_DECODERS = new Map( /** * How to read a body in a charset named in a Content-Type, lower-cased, or * undefined for one this cannot read -- Spring's 415. Latin-1, ASCII and the - * UTF family are read as the JDK reads them (orthology.spec.mjs holds the + * UTF family are read as the JDK reads them (orthology.spec.ts holds the * JDK's answers); any other charset by TextDecoder when it knows the name, * which for a body of stable ids reads the same. A charset only Java knows * (an EBCDIC code page) is refused here and read by Java. diff --git a/tools/content-node/exporters-endpoints.ts b/tools/content-node/exporters-endpoints.ts index 20525cfc..a4d821b0 100644 --- a/tools/content-node/exporters-endpoints.ts +++ b/tools/content-node/exporters-endpoints.ts @@ -406,7 +406,7 @@ export const exportersEndpoints: Endpoint[] = [ { path: '/ContentService/exporter/voronoi/{id}', // No sample, and none from --ids: Java has no such URL, so the parity - // harness has nothing to compare it with. overview-export.spec.mjs holds it. + // harness has nothing to compare it with. overview-export.spec.ts holds it. samplesOnly: true, /** * A species' overview, the Voronoi map the site shows (Reacfoam), drawn diff --git a/tools/content-node/java-hashmap.ts b/tools/content-node/java-hashmap.ts index 81d22931..e5511fed 100644 --- a/tools/content-node/java-hashmap.ts +++ b/tools/content-node/java-hashmap.ts @@ -8,7 +8,7 @@ * red-black tree ordered by hash then String.compareTo, whose root is moved * to the front and whose later keys are linked in after their parent -- so * eleven ids sharing a hash come out in Java's order, not arrival's. Checked - * against the JDK's own HashMap (orthology.spec.mjs). + * against the JDK's own HashMap (orthology.spec.ts). */ /** * One key in a bucket. A bucket that becomes a tree gives its nodes the tree diff --git a/tools/load.spec.ts b/tools/load.spec.ts index 90da04bc..f2d4f1b1 100644 --- a/tools/load.spec.ts +++ b/tools/load.spec.ts @@ -87,10 +87,10 @@ function loadUnderNode(files: string[]): string[] { */ it('holds no plain JavaScript module in tools/', () => { const plain = readdirSync(path.join(ROOT, 'tools'), { recursive: true, encoding: 'utf8' }) - .filter((file) => /\.(mjs|cjs|js)$/.test(file)) + .filter((file) => /\.(mjs|cjs|jsx?)$/i.test(file)) .filter((file) => !file.split(path.sep).includes('node_modules')) - // Generated by esbuild from harness.ts, and gitignored. - .filter((file) => !file.endsWith('harness.bundle.js')); + // Generated by esbuild from harness.ts, and gitignored: that one file only. + .filter((file) => file !== path.join('svg-export-harness', 'harness.bundle.js')); expect(plain).toEqual([]); }); From 9943c3125a0cc60e7c623306b0f0afac177b7ea4 Mon Sep 17 00:00:00 2001 From: Adam Wright Date: Sat, 24 Oct 2026 04:59:01 +0000 Subject: [PATCH 2/2] T024: CLAUDE.md says what the load test discovers: a service directory's top-level modules (from the review) Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 0560ec55..24b0eb85 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -41,9 +41,10 @@ is how a formatting failure reached CI. - **New code under `tools/` is TypeScript** (spec 013). A plain `.mjs` there would be loaded by the type check without being checked, so `tools/load.spec.ts` fails on one. -- **A new entry point is loaded under Node** by `tools/load.spec.ts`. A module in - a service directory is picked up as it is; a new service directory joins its - `SERVICES` list; and a script that does its work when loaded (writes files, +- **A service's new entry point is loaded under Node** by `tools/load.spec.ts`. + A module at the top of a service directory is picked up as it is (one in a + subdirectory only through whatever imports it); a new service directory joins + its `SERVICES` list; and a script that does its work when loaded (writes files, starts a browser) joins `RUN_ON_LOAD`, so it is checked without being run. ## The node content service (`tools/content-node`)