From 534de7929216b50999e8cc64f55fe7e8cb1e0c44 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 00:01:24 +0000 Subject: [PATCH 1/2] fix(gate): state the real reason packages/spec ships its zod sources `check-published-files` allowed `src/**/*.zod.ts` in the spec package's `files[]` on the ground that "downstream code imports them directly, so these sources are product rather than build input". Measured against a real packed tarball, the mechanism in that sentence is false: the exports map declares no `./src/*` subpath and no wildcard, so Node (ESM and CJS), esbuild and tsc all refuse the deep specifier, and a literal path into node_modules cannot load a `.ts` file there either. 191 of the 203 shipped modules also import one of 44 src/ modules the glob does not ship, so a route that reached them would not load them. The conclusion of that sentence is nevertheless true, for a different mechanism: the published skills catalog points agents at these files by path, to READ in a consumer's node_modules, and each skill's reference index is generated from this very set -- 170 pointers across 9 published index files, all inside the glob. Correct the reason to name the read route, and record why neither opening the exports map nor dropping the entry is the repair the false reason invites. Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx Co-authored-by: Claude --- scripts/check-published-files.mjs | 44 ++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/scripts/check-published-files.mjs b/scripts/check-published-files.mjs index e7f5419cca7..df7ae1d2d0d 100644 --- a/scripts/check-published-files.mjs +++ b/scripts/check-published-files.mjs @@ -242,8 +242,50 @@ const EXTRA_ENTRIES = { liveness: 'Per-metadata-type liveness ledgers, read by the ADR-0049 enforce-or-remove tooling.', prompts: 'Authoring prompts shipped for agents consuming the protocol.', 'llms.txt': 'Protocol summary for LLM consumers.', + // src/**/*.zod.ts -- a READ route, and never an import route (#19009) + // ------------------------------------------------------------------ + // + // This entry used to justify itself with "downstream code imports them + // directly". That sentence named a route that has never been open, and + // both of its halves were measured false against a real packed tarball + // before this correction landed: + // + // - the exports map declares no ./src/* subpath and no wildcard, so + // every spelling of the deep specifier is refused at RESOLUTION -- + // Node answers ERR_PACKAGE_PATH_NOT_EXPORTED under both ESM and CJS, + // esbuild answers "not exported by package", and tsc answers TS2307 + // under both bundler and nodenext resolution. A literal file path + // into node_modules does not rescue it either: Node refuses type + // stripping under node_modules by design, so the file cannot load + // even when resolution is bypassed entirely. + // - measured when this landed, 191 of the 203 shipped modules carry a + // relative import onto one of 44 src/ modules this glob does NOT + // ship (src/shared/lazy-schema.ts alone is named by 182), so a route + // that reached them still would not load them. + // + // What they are actually for is a READ route. The published skills + // catalog tells an agent to open these paths inside a consumer's + // node_modules and read the schema as the truth, and each skill's + // reference index is GENERATED from this very set by the spec package's + // own build-skill-references generator. That generator filters its + // closure to the *.zod.ts shape for exactly this reason, in its own + // words: a pointer to any other src file 404s in a consumer's + // node_modules. Which is also why the unshipped-dependency count above + // is a property of the glob and not a defect in it -- a reader never + // resolves those imports. Measured with the tarball in hand: 170 + // pointers across 9 published index files, 0 of them outside this glob. + // + // So what #19009 corrects is the REASON, not the entry, and the two + // repairs the false reason invites are both wrong: + // - do NOT open the exports map to make the old sentence true. It + // would advertise a route that is broken for 191 of 203 files, which + // is a machine-readable surface that lies (Route & surface ownership + // rule 4; Prime Directive #10). + // - do NOT drop the entry as unreachable payload. It is reachable + // product -- by read rather than by resolve -- and dropping it makes + // every generated pointer in the shipped catalog 404 at once. 'src/**/*.zod.ts': - 'The Zod schemas are themselves the contract (Prime Directive #1); downstream code imports them directly, so these sources are product rather than build input. Narrowed to *.zod.ts so no test or helper rides along.', + 'The Zod schemas are themselves the contract (Prime Directive #1), and the published skills catalog points agents at these files by PATH, to read inside a consumer node_modules -- never by specifier to import, a route the exports map does not offer. Product rather than build input, read rather than resolved. Narrowed to *.zod.ts so no test or helper rides along, and because the reference generator emits pointers to exactly that set.', 'api-surface': 'Export snapshot used by downstream compatibility checks — one file per published entry point since #5837.', 'spec-changes.json': 'Machine-readable spec change log driving the upgrade guide.', From c35fcb8728367a0ff2d82b0e4a1616d6df949d86 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 00:18:24 +0000 Subject: [PATCH 2/2] fix(gate): correct two counts in the zod-glob reason The first measurement resolved relative specifiers without mapping the NodeNext `.js` spelling back to `.ts`, so five `.js` specifiers were counted as unshipped targets when the files are shipped (`tenant.zod.ts` and `date-macros.zod.ts` among them). Re-measured with that mapping and zero unresolved specifiers left: 190 of 203, over 42 modules, not 191 over 44. `src/shared/lazy-schema.ts` at 182 importers is unchanged. Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx Co-authored-by: Claude --- scripts/check-published-files.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/check-published-files.mjs b/scripts/check-published-files.mjs index df7ae1d2d0d..28a8944e7ff 100644 --- a/scripts/check-published-files.mjs +++ b/scripts/check-published-files.mjs @@ -258,8 +258,8 @@ const EXTRA_ENTRIES = { // into node_modules does not rescue it either: Node refuses type // stripping under node_modules by design, so the file cannot load // even when resolution is bypassed entirely. - // - measured when this landed, 191 of the 203 shipped modules carry a - // relative import onto one of 44 src/ modules this glob does NOT + // - measured when this landed, 190 of the 203 shipped modules carry a + // relative import onto one of 42 src/ modules this glob does NOT // ship (src/shared/lazy-schema.ts alone is named by 182), so a route // that reached them still would not load them. // @@ -278,7 +278,7 @@ const EXTRA_ENTRIES = { // So what #19009 corrects is the REASON, not the entry, and the two // repairs the false reason invites are both wrong: // - do NOT open the exports map to make the old sentence true. It - // would advertise a route that is broken for 191 of 203 files, which + // would advertise a route that is broken for 190 of 203 files, which // is a machine-readable surface that lies (Route & surface ownership // rule 4; Prime Directive #10). // - do NOT drop the entry as unreachable payload. It is reachable