From 663fbc543f364d997d8ac028d27b79a1db13c60b Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 25 Aug 2026 17:15:44 +0000 Subject: [PATCH] feat(spec): make BaseValidationRuleShape and FilterCondition nameable from the root entry The minimal one-file consumer program (un-annotated export default defineStack(...) with no /data subpath import) still failed declaration emit with exactly two TS2883 diagnostics naming these two types through hash-named internal dist chunks. Same invariant and fix shape as the prior root-entry nameability fix: re-export both types from their declaring /data modules. Regenerates api-surface/root.json and export-origins/root.json (+2 each); extends the pin harness's program-scoping note to record the ruling. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01NDGG54XF5gbTLdQzCtnaVV --- .../root-entry-nameability-data-delta.md | 19 ++++++++++++++ packages/spec/api-surface/root.json | 2 ++ packages/spec/export-origins/root.json | 2 ++ .../root-entry-type-nameability.pin.test.ts | 26 ++++++++++++------- packages/spec/src/index.ts | 8 ++++++ 5 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 .changeset/root-entry-nameability-data-delta.md diff --git a/.changeset/root-entry-nameability-data-delta.md b/.changeset/root-entry-nameability-data-delta.md new file mode 100644 index 0000000000..3817921d7d --- /dev/null +++ b/.changeset/root-entry-nameability-data-delta.md @@ -0,0 +1,19 @@ +--- +"@objectstack/spec": minor +--- + +feat(spec): make `BaseValidationRuleShape` and `FilterCondition` nameable from the root entry (#11709) + +Additive follow-up to the #11350 root-entry nameability fix, same invariant +(a type that appears structurally in an entry's public declarations must be +nameable from that same entry): a minimal consumer program with an +un-annotated `export default defineStack(...)` and **no** `@objectstack/spec/data` +import anywhere in its program still failed declaration emit with exactly two +TS2883 diagnostics — `BaseValidationRuleShape` and `FilterCondition`, both +mentioned structurally by `defineStack`'s return type but reachable only +through hash-named internal dist chunks. The root entry now re-exports both +types from their declaring `/data` modules (`data/validation.zod`, +`data/filter.zod`), exactly as #11350 did for `FormFieldInput` / +`NavigationItemInput` / `StateNodeConfig`. No runtime change; existing +consumers that already imported these names from `@objectstack/spec/data` are +unaffected. diff --git a/packages/spec/api-surface/root.json b/packages/spec/api-surface/root.json index 12dadaca03..4f326806fb 100644 --- a/packages/spec/api-surface/root.json +++ b/packages/spec/api-surface/root.json @@ -21,6 +21,7 @@ "BUILTIN_IDENTITY_PLATFORM_ADMIN (const)", "BUILTIN_MEMBERSHIP_ROLES (const)", "BUILTIN_MEMBERSHIP_ROLE_OPTIONS (const)", + "BaseValidationRuleShape (interface)", "BuiltinIdentityName (type)", "BuiltinMembershipRole (type)", "CONVERSIONS_BY_MAJOR (const)", @@ -58,6 +59,7 @@ "ExpressionSchema (const)", "F (const)", "FIELD_KEY_GUIDANCE (const)", + "FilterCondition (type)", "FormFieldInput (type)", "GUEST_POSITION (const)", "LintableAuthoringCollection (interface)", diff --git a/packages/spec/export-origins/root.json b/packages/spec/export-origins/root.json index eb54b81728..8b44187438 100644 --- a/packages/spec/export-origins/root.json +++ b/packages/spec/export-origins/root.json @@ -21,6 +21,7 @@ "BUILTIN_IDENTITY_PLATFORM_ADMIN": "src/identity/eval-user.zod.ts#BUILTIN_IDENTITY_PLATFORM_ADMIN (const)", "BUILTIN_MEMBERSHIP_ROLES": "src/identity/membership-role.ts#BUILTIN_MEMBERSHIP_ROLES (const)", "BUILTIN_MEMBERSHIP_ROLE_OPTIONS": "src/identity/membership-role.ts#BUILTIN_MEMBERSHIP_ROLE_OPTIONS (const)", + "BaseValidationRuleShape": "src/data/validation.zod.ts#BaseValidationRuleShape (interface)", "BuiltinIdentityName": "src/identity/eval-user.zod.ts#BuiltinIdentityName (type)", "BuiltinMembershipRole": "src/identity/membership-role.ts#BuiltinMembershipRole (type)", "CONVERSIONS_BY_MAJOR": "src/conversions/registry.ts#CONVERSIONS_BY_MAJOR (const)", @@ -58,6 +59,7 @@ "ExpressionSchema": "src/shared/expression.zod.ts#ExpressionSchema (const)", "F": "src/shared/expression.zod.ts#F (const)", "FIELD_KEY_GUIDANCE": "src/data/authoring-key-lint.ts#FIELD_KEY_GUIDANCE (const)", + "FilterCondition": "src/data/filter.zod.ts#FilterCondition (type)", "FormFieldInput": "src/ui/view.zod.ts#FormFieldInput (type)", "GUEST_POSITION": "src/identity/position.zod.ts#GUEST_POSITION (const)", "LintableAuthoringCollection": "src/kernel/metadata-authoring-lint.ts#LintableAuthoringCollection (interface)", diff --git a/packages/spec/scripts/root-entry-type-nameability.pin.test.ts b/packages/spec/scripts/root-entry-type-nameability.pin.test.ts index ec3139f1cf..54fda77e40 100644 --- a/packages/spec/scripts/root-entry-type-nameability.pin.test.ts +++ b/packages/spec/scripts/root-entry-type-nameability.pin.test.ts @@ -36,15 +36,23 @@ * measured that a program file importing a subpath entry makes that entry's * names NAMEABLE program-wide. `context.ts` reproduces that, which is what * scopes this pin to the ruled three (ui/automation names, reachable only - * via the root re-exports under pin). Measured against this same dist: the - * MINIMAL one-file program leaks two MORE names through `/data` - * (`BaseValidationRuleShape`, `FilterCondition`) that the fixed root entry - * still cannot name — deliberately NOT pinned here; that is #11350's - * recorded premise delta, filed as #11709 for its own ruling. For the same - * reason the program contains no `@objectstack/spec/ui` or `/automation` - * import and no direct `import type { FormFieldInput, … }` — any of those - * would mask the very symptom under pin. Direct existence of the three root - * exports is owned by `api-surface/root.json` + `check:api-surface` instead. + * via the root re-exports under pin). Measured against the #11350 dist: the + * MINIMAL one-file program leaked two MORE names through `/data` + * (`BaseValidationRuleShape`, `FilterCondition`) that the #11350 root entry + * still could not name — #11350's recorded premise delta, filed as #11709 + * and ruled the same way (maintainer decision 2026-08-25: A′): the root + * entry now re-exports both from their declaring `/data` modules. Re-run of + * #11709's measurement: pre-fix, this same program minus `context.ts` + * produced exactly 2 × TS2883 (`BaseValidationRuleShape` via the + * `object.zod-*` dist chunk, `FilterCondition` via `filter.zod-*`); + * post-fix it is clean, so `context.ts` no longer masks any known leak — + * it stays because the pin's charter is the REAL consumers' program shape, + * and a follow-up gate for entry-complete nameability (all entries, no + * fixture scoping) is #11986's remit, not this pin's. The program still + * contains no `@objectstack/spec/ui` or `/automation` import and no direct + * `import type { FormFieldInput, … }` — any of those would mask the very + * symptom under pin. Direct existence of the five root re-exports is owned + * by `api-surface/root.json` + `check:api-surface` instead. * * - **canary** — the anti-phantom probe. TS2883 is a DECLARATION-EMIT * diagnostic: drop `declaration: true` from the harness profile and the diff --git a/packages/spec/src/index.ts b/packages/spec/src/index.ts index 8a3408a4b4..a2a790b19e 100644 --- a/packages/spec/src/index.ts +++ b/packages/spec/src/index.ts @@ -145,6 +145,14 @@ export { defineSkill } from './ai/skill.zod'; export type { FormFieldInput } from './ui/view.zod'; export type { NavigationItemInput } from './ui/app.zod'; export type { StateNodeConfig } from './automation/state-machine.zod'; +// [#11709] #11350's recorded premise delta, ruled the same way (maintainer +// decision 2026-08-25, recorded on #11709): the MINIMAL one-file consumer — +// no `/data` subpath import anywhere in its program — leaks two more +// structural mentions of `defineStack`'s return type that the three lines +// above do not cover. Same invariant, same fix shape: re-export from the +// declaring module (both already public on `/data`). +export type { BaseValidationRuleShape } from './data/validation.zod'; +export type { FilterCondition } from './data/filter.zod'; // DX factories for the remaining authoring domains (issue #2035) — one type-safe // entry per writable domain, mirroring the 19 factories above. `defineX` is a