Uh oh!
There was an error while loading. Please reload this page.
fix(spec,core): give pluralToSingular a schema-free home on /meta-spelling - #12006
Conversation
…lling (#11503) Restores the #10096 standing invariant for core's store-key fold: the defineStack manifest-collection vocabulary moves to a leaf module on the /meta-spelling entry graph, /shared re-exports it, and core imports the fold from /meta-spelling instead of /shared. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K93P8PbH7kVjsAXkqzH1zY
…gins (#11503) gen:export-origins — the four manifest-collection symbols land on the meta-spelling shard and shared's origins repoint to the moved declaration. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K93P8PbH7kVjsAXkqzH1zY
📓 Docs Drift CheckThis PR changes 2 package(s): 29 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 4 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 132 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 51930e80e7dd07e329c38524a4d357b4ab283e51 && git checkout 51930e80e7dd07e329c38524a4d357b4ab283e51
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 1e79aa4f812708d5d097ca33d9b7040e02b958c6 59cfccf50862cca92c6fb7300890207ca4db1325 && git checkout -B drift-repro 1e79aa4f812708d5d097ca33d9b7040e02b958c6 && git merge --no-ff 59cfccf50862cca92c6fb7300890207ca4db1325
node scripts/docs-audit/affected-docs.mjs --json 1e79aa4f812708d5d097ca33d9b7040e02b958c6
|
#11503) gen:api-surface — touched: meta-spelling.json; check:api-surface and check:generated green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K93P8PbH7kVjsAXkqzH1zY
Uh oh!
There was an error while loading. Please reload this page.
…os-regen deferral) os-regen-merge.sh sequence: merge committed first, then the full gen chain on the merged source. check:generated --fix regenerated the 4 provably stale artifacts; the audit-door entries (this PR) and the #12001/#12006 sibling entries coexist in the regenerated set. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K93P8PbH7kVjsAXkqzH1zY
Fixes#11503
What
Restores the #10096 standing invariant for
@objectstack/core's plural→singular store-key fold. The maintainer ruling on #10096 (2026-08-20), quoted verbatim and untranslated:@objectstack/core— on every browser consumer's eager graph through@objectstack/client— carried the one value import that violated it:Disposition 2 was measured first (triage's claim constraint), and the answer is no
Does core need the map at module scope at all, or can the read move behind the call?
pluralToSingularis called insidecanonicalMetadataServiceType, a synchronous exported fold consumed on the store-key path of all three shippedIMetadataServiceimplementations (createMemoryMetadatain core,MetadataManager,MetadataFacade) plus the spec-side contract double.import(), which would force the whole register/read contract async: a contract-shape change, and a consumer-side workaround of exactly the kind rule 5 forbids.MetadataFacadeanswers threeregister→getround-trip cases differently from every other shippedIMetadataService#7378 row-2 ruling (the map has ONE owner; a copy is per-implementation folk normalization).So the module-scope value import is genuinely needed, and the fix is disposition 1: give the symbol a schema-free home.
Disposition 1 — widen
./meta-spelling(the sanctioned #10096 shape)Per the claim's clause-② declaration: this PR does widen a spec export surface, and the widened entry is the sanctioned shape under #10096 —
./meta-spellingis already the ruling's reference pattern and is already declared (withexternals: []) inbrowser-reachable-entries.json, so no ledger promotion was needed; the existing gate now proves the widened surface too.packages/spec/src/meta-spelling/manifest-collection-spelling.ts(new): the declaration ofPLURAL_TO_SINGULAR/SINGULAR_TO_PLURAL/pluralToSingular/singularToPlural, moved verbatim, importing nothing.packages/spec/src/shared/metadata-collection.zod.ts: re-exports the four symbols —/sharedkeeps its published surface, every existing consumer (kernel authoring lint, conversions, rest, runtime, objectql, …) is untouched.packages/spec/src/meta-spelling/index.ts: exports the four symbols; module doc now documents the entry as two deliberately distinct spelling contracts. Per #7894 lands five new public exports in@objectstack/spec/shared— should the three predicate helpers stay internal? #8424 there is no merge:PLURAL_TO_SINGULAR(manifest-collection keys; nofields/seeds/external_catalogs/translations) andMETA_URL_TO_SINGULAR(URL path segments) stay distinct symbols, and the new pin test asserts both the re-export identity and the distinctness.packages/core/src/metadata-service-contract.ts: the import flips to@objectstack/spec/meta-spelling; comment block rewritten to carry the reason.packages/spec/scripts/build-meta-url-spelling.ts: the generator readsPLURAL_TO_SINGULARfrom its new home (same one owner, same derivation).scripts/check-stack-collection-maps.mjs: thePLURAL_TO_SINGULARsite pin follows the declaration to its new file (--self-testgreen).@objectstack/spec/cloud, so any runtime test that loads a compiled artifact dies with ENOTDIR #9457 every aliasing config resolves@objectstack/spec/<ns>through one anchored regex, andmeta-spellingmatches it.⛔ The spec root barrel was not touched (seat-ledger hazard: root-entry export changes can flip downstream d.ts synthesized specifiers). Verified below via the full-workspace typecheck.
Disposition 3 (mechanizing the principle as a gate) already landed as
check:browser-reachable-entries(#10199) and is out of this card's scope; this PR only rides the existing gate.Acceptance evidence (node-side, per the card)
@objectstack/coredist/carries no value import of@objectstack/spec/shared; positive control:@objectstack/spec/meta-spellingpresent. (Readings in the os-dev-report on the issue.)dist/meta-spelling/index.mjs(4.8 KB):pluralToSingularpresent, zod-machinery probe 0 hits; positive control: same probe ondist/shared/index.mjshits.check:browser-reachable-entries— "2 declared browser-reachable entries link no zod; 44 bundle(s) scanned, 40 zod link(s) seen elsewhere (instrument calibrated)".check:meta-url-spelling— "meta-url-spelling data is current (34 spellings, 27 registry-declared types; manifest/derived agreement holds)."check:stack-collection-maps— "7 enumerations reconciled against 31 declared collections (16 waiver rows, each with a reason)."Test and typecheck readings (head
43986ca)@objectstack/specfull suite (vitest, maxWorkers=2): first lap at4f94bf0— "Test Files 1 failed | 423 passed | 1 skipped (425) / Tests 1 failed | 11275 passed | 1 skipped (11277)"; the one red wasscripts/export-origins.test.tsdemanding the widened surface be recorded.gen:export-originsregenerated the two shards (that commit is43986ca, JSON-only), and the failing file re-ran green on that tree: "Test Files 1 passed (1) / Tests 22 passed (22)". The shard JSONs feed no other test.@objectstack/corefull suite at43986ca: "Test Files 38 passed (38) / Tests 939 passed (939)".43986ca: turbo "Tasks: 70 successful, 70 total".43986ca(the specifier-drift check): turbo "Tasks: 129 successful, 129 total" — no downstream d.ts specifier blow-up; core's own emitted d.ts references@objectstack/spec/meta-spellingand contains zerospec/sharedoccurrences./sharedmutated to a forkedpluralToSingular(mutation confirmed on disk, marker grep = 1) → pin RED on exactly the identity assertion → restored (marker grep = 0) → green.check:type-check-debt(re-measure on the built workspace),check:test-source-alias,check:cross-package-test-inputs,check:nul-bytes, changeset gates and the rest of the dispatch-gates derivation: readings in the os-dev-report comment on@objectstack/coreimportspluralToSingularfrom@objectstack/spec/shared, putting the schema-bearing entry on every browser consumer eager graph #11503.Refs
#10096 (standing ruling), #8424 (the two maps are deliberately distinct), #7378 (row 2: one owner), objectui#5359 / objectui#5324 (consumer measurements).
Generated by Claude Code