Skip to content

fix(metadata-core,service-cluster,create-objectstack): ESM-only subpaths declare their types under import - #26321

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-nhvl8m
Oct 26, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-nhvl8m

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread
Part of #26206

Clause-②: no. Amended 20:45Z: split. This PR lands the three ESM-only subpath groups (Part of #26206, non-breaking, types-only map changes plus README lines). The driver-memory default retirement waits on an ADR-0087 gate card (predicate 2 word-scans default across metadata surfaces and can never certify that operand)
Metadata-protocol: none

What changes

Three subpaths are ESM-only, and their export maps now say so. Each subpath's types moved inside its import condition ({ import: { types, default } }, the conditional shape #26198 / #26279 use). Each package's README gets one paragraph saying the subpath is ESM-only.

Entry Before (node16-cjs) Choice Why
@objectstack/metadata-core/testing CJSResolvesToESM declared ESM-only It imports vitest, whose own require() entry throws ("Vitest cannot be imported in a CommonJS module using require()"), so a CJS build could not load. Its require condition was already removed on purpose (the tsup config's split-by-format comment).
@objectstack/service-cluster/testing CJSResolvesToESM declared ESM-only Same reason: it imports vitest.
create-objectstack/created-summary CJSResolvesToESM declared ESM-only Its one consumer is @objectstack/cli's init (ESM). A CJS build would add a require condition, which widens the accept set and doesn't fit Clause-②: no.
@objectstack/cli . CJSResolvesToESM ESM-only, no manifest change See below.
@objectstack/cli/console CJSResolvesToESM ESM-only, no manifest change See below.
@objectstack/cli/hook-body CJSResolvesToESM ESM-only, no manifest change See below.

For the first three, runtime behaviour does not change. require() of each subpath already failed with ERR_PACKAGE_PATH_NOT_EXPORTED, because the map carried types + import and no require or default. The unconditional types was the inconsistency: TypeScript under node16/nodenext still resolved the declarations for a CommonJS caller, and attw reported that as CJSResolvesToESM. Now TypeScript resolves them for import only, which is what Node does.

@objectstack/cli: ESM-only, documented here (README follow-up)

The cli's three library entries (., ./console, ./hook-body) map { types, default } to ESM files, and they stay that way. Measured on Node 22.22.0, require() of all three works today through Node's require(esm). The . barrel loads every oclif command class.

  • Any ESM-only map change (an import-only condition, or a require stub that throws) would break those working require() callers. That's a narrowing, and this card is Clause-②: no.
  • A CJS build of the . barrel means a second build of the whole oclif program, which is out of proportion for a p3.

So the attw CJSResolvesToESM items on these three stay, as intended ESM-only entries: the files are ESM, and CommonJS callers reach them through import() or Node's require(esm). This card's claim kept packages/cli/README.md out of scope while #26215 held it, so this paragraph is the written declaration for now. Follow-up: add one line to packages/cli/README.md saying ., ./console and ./hook-body are ESM entries. #26215 has since merged, so nothing blocks that line.

Not in this PR: @objectstack/driver-memory's default export

The card's driver-memory half (FalseExportDefault) is split out. Nothing in this repository imports the default, which is the legacy { id, version, onEnable } object the kernel never calls, so retiring it is the right fix. But it retires a published export, and ADR-0087's runtime-export-retired disposition cannot currently certify an operand named default. Predicate 2 (no-metadata-surface) scans metadata surfaces for the export's name and hits every default: key, starting with examples/app-crm/src/objects/account.object.ts. The retirement waits on that gate, so #26206 stays open for it.

Evidence

attw 0.18.5 on npm pack --ignore-scripts of each package, built at 6633075b (before) and at this head (after):

Package Before After
@objectstack/cli CJSResolvesToESM on ., ./console, ./hook-body unchanged (intended, see above)
create-objectstack CJSResolvesToESM on ./created-summary 0 CJSResolvesToESM (./created-summary answers NoResolution under node16-cjs, matching Node)
@objectstack/metadata-core CJSResolvesToESM on ./testing 0 CJSResolvesToESM (NoResolution under node16-cjs)
@objectstack/service-cluster CJSResolvesToESM on ./testing 0 CJSResolvesToESM (NoResolution under node16-cjs)

NoResolution under node10 on every subpath is unchanged and outside the contract (legacy node10 has no exports support).

Runtime probes, at this head:

  • import() of all three subpaths resolves and loads.
  • require() of all three still answers ERR_PACKAGE_PATH_NOT_EXPORTED.
  • require() of the three cli entries still loads.

Acceptance notes

  • Tests and typecheck ran at fbc38f81. That commit carries this head's three map changes, plus the driver-memory half that 64128263 then restored byte-for-byte to main.
    • Tests (pnpm --filter … run test): metadata-core 823/823, service-cluster 105/105, create-objectstack 269/269.
    • Typecheck (run typecheck), green on 12 packages: the three changed packages, plus every in-repo consumer of these subpaths. metadata-fs, metadata-protocol, rest, runtime, service-cluster-redis and cli (init.ts) are all ESM (nodenext, or bundler for test configs). driver-memory, service-datasource and plugin-dev were covered for the dropped half.
  • node scripts/check-adr-0087-registration.mjs --base origin/main exit 0, with 1 non-breaking changeset seen. node scripts/check-changeset-no-major.mjs exit 0.
  • At 64128263, all 71 dispatch-gates --commands families were run locally, each exit captured before any pipe. --ran reconciliation: 71 derived, 71 run, 0 NOT-MEASURED. The list is in the report comment on packages: 4 ESM-only subpaths answer require() with ESM, and driver-memory's default export is lost under CJS (attw CJSResolvesToESM / FalseExportDefault) #26206.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WTCPNVkuDk7DNaZSdM3DZv


Generated by Claude Code

…ire driver-memory's default export

metadata-core/testing, service-cluster/testing and
create-objectstack/created-summary already refused require() at runtime;
their unconditional `types` still let TypeScript resolve them for a CommonJS
caller. Nest `types` inside `import` so both agree, and say ESM-only in each
README. driver-memory's default export was the legacy onEnable plugin object
no kernel calls, and sat on `.default` under require(); nothing imports it,
so it retires (ADR-0087 runtime-export-retired).

Claude-Session: https://claude.ai/code/session_01WTCPNVkuDk7DNaZSdM3DZv
Co-authored-by: Claude <noreply@anthropic.com>
The ADR-0087 runtime-export-retired disposition cannot certify an operand
named `default` (its no-metadata-surface word scan hits every `default:` key
in an object definition), so the retirement waits on that gate. This change
keeps only the three ESM-only subpath declarations, which are non-breaking.

Claude-Session: https://claude.ai/code/session_01WTCPNVkuDk7DNaZSdM3DZv
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/s dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation tooling labels Oct 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 6 changed file(s) yielded no anchor (packages/create-objectstack/README.md, packages/create-objectstack/package.json, packages/metadata-core/README.md, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 3 changed package(s)).

What this run could not see
  • 6 changed file(s) yielded no anchor (packages/create-objectstack/README.md, packages/create-objectstack/package.json, packages/metadata-core/README.md, …) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 20 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 61ba04f68c84cfbeef0af39eb52a8a11f7395146 → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · devx seat 2 · 2026-10-26T21:04Z

Seat domain:devx#2 (#20163) · session_01Q4MDXRbEJCNdPAP4SiXwp9 · reviewed head 6412826387 · card #26206, claim 6426288426 (wave 7, delta S, amended 20:45Z to the split). PR carries Part of #26206.

  • Scope: 7 files, +38/−6. Three export maps (@objectstack/metadata-core/testing, @objectstack/service-cluster/testing, create-objectstack/created-summary), one README paragraph per package, and one root .changeset/ patch entry. Not governed. No packages/cli/**, no packages/drivers/driver-memory/**, no export subpath added or removed.
  • The map change is the correct ESM-only shape. types moves inside import ({import:{types,default}}), so TypeScript under node16/nodenext stops resolving declarations for a CommonJS caller that Node would refuse with ERR_PACKAGE_PATH_NOT_EXPORTED. import, and every mode that reads the import condition (bundler included), resolves exactly as before. Under the claim's Clause-② no, this is a declaration fix, not a narrowing: no runtime accept set changes.
  • Choices per entry, matching the delta: the two testing subpaths import vitest, which has no CJS entry, so a CJS build is impossible, and ESM-only is the only honest answer. created-summary has one consumer (cli init, ESM), and a CJS build would widen the accept set. The cli's three entries are left as documented-intended ESM-only, with no file change, because require(esm) works today and fix(cli,i18n,console): the hosted product reads "ObjectOS Cloud" everywhere; the Community Console carries a "Powered by ObjectStack" mark #26215 held the README. driver-memory is out, split per the amended claim.
  • Changeset: a patch on the three packages, with Clause-②: no / Metadata-protocol: none at line start. The body states the before → after behaviour.
  • Evidence from the dev thread: attw after the change shows 0 CJSResolvesToESM on the three subpaths. 71/71 derived gates exit 0, with 0 NOT-MEASURED. check-adr-0087-registration and check-changeset-no-major exit 0. Tests on 4 packages and typecheck on 12 are green.
  • Follow-ups for the seat: (1) the ADR-0087 predicate-2 default-operand false positive (the dev's out_of_scope_findings[0]) gets its own gate card; (2) a one-line packages/cli/README.md ESM-only note, now that fix(cli,i18n,console): the hosted product reads "ObjectOS Cloud" everywhere; the Community Console carries a "Powered by ObjectStack" mark #26215 has merged.
  • Landing: once every check on this head is green or skipped, the seat runs ready + auto-merge.

Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

devx seat 2 · CI note on head 6412826387: Scaffold with repo dist is red in exactly one step, Skills boundary: only the curated skills/ catalog installs (job). This PR didn't cause it. Every PR that touches packages/create-objectstack/** hits the same red on main since #26097 put objectui/ into skills/ (card #26204). The fix is #26285, which is governed (.github/workflows/scaffold-e2e.yml) and waits on a GOVERNED_APPROVERS approval, so it isn't ported here: porting it would make this PR governed too. Every other step of that job passed, including scaffold, install, build, boot and docker. The check is not in main's required set. Landing proceeds once the required checks (Test Core included) are green.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 26, 2026 21:38
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 26, 2026 21:38
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 26, 2026
Merged via the queue into main with commit 40f5c6e Oct 26, 2026
50 of 51 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-nhvl8m branch October 26, 2026 22:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/s tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants