Skip to content

spec(AST-017): no file path or subpath makes an API experimental - #8357

Merged
cixzhang merged 3 commits into
mainfrom
spec/no-path-only-experimental
Oct 25, 2026
Merged

cixzhang merged 3 commits into
mainfrom
spec/no-path-only-experimental

Conversation

@cixzhang

@cixzhang cixzhang commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Exact decision needed

Whether a public module can be experimental by its file path alone (a module-level /experimental subpath), and how modules without a stable contract are shared.

Existing authority searched

Decision

spec:AST-017 FR21 and DEC-27 (Cindy, 2026-10-24; marking form 2026-10-25):

  • No file path or subpath marks anything experimental, for components or modules. Behavior and utility modules (motion, gesture, keyboard handling) are internal and never exported, as experimental or otherwise. Where a public API other than a component prop is deliberately experimental, its name carries the experimental_ prefix, visible at every import and call site, plus @experimental. Component experimental props stay in the experimental prop object.
  • Any public experimental API carries its own spec decision.
  • Behavior and utility modules (motion, gesture, keyboard handling) stay internal and unexported.
  • The CLI's compatibility contract, including its experimental exports, comes from its own record under FR54; this PR does not change it.
  • DEC-27 replaces DEC-9's placement of experimental hooks, functions, and types on a component's /experimental subpath; the experimental prop object stands. FR23's promotion wording follows.

Rejected alternatives

  • /experimental subpaths that mark status by path, for modules or components.

Claim scope and non-goals

The experimental boundary for modules only. Component experimental props and component /experimental subpaths (already marked in their APIs) are unchanged.

Evidence and implementation relationship

Spec-only. The affected pull requests adjust as Current-state impact says.

Writing rubric results

  • R1 narration: none.
  • R2 research in the record: none.
  • R3 evidence naming a change: none.
  • R4 rejected alternatives over one line or outside a decision: one, inside DEC-27.
  • R5 pull request or issue references remaining: none.
  • R6 ruled open questions still listing options: none.

Scope

  • This PR contains specification records only.
  • It records observable behavior and preserves equivalent internal implementations.
  • Any named internal mechanism is intentionally public, names its dependent caller/system, and explains why an equivalent implementation would not satisfy the contract.
  • Verification states the evidence layer and failure signal without prescribing CI job/workflow topology.
  • It records one intentional durable decision, not a rescue for a separable tagalong.
  • The canonical knowledge owner, affected current claims, and overlapping open work are named; any ownership collision is resolved or called out for human decision.
  • Adjacent API, visual, accessibility, composition, and implementation facts remain outside scope unless this exact decision depends on them.
  • Public text and artifacts contain no internal Meta context.

Validation

  • pnpm check:knowledge (CI lint)
  • Prettier
  • git diff --check

@vercel

vercel Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Oct 25, 2026 4:27pm UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Oct 25, 2026, 4:56 PM UTC

@github-actions github-actions Bot added the needs:spec-owner-review Current knowledge records await owner approval label Oct 25, 2026
@cixzhang cixzhang changed the title spec(AST-017): a file path never makes a public module experimental spec(AST-017): no file path or subpath makes an API experimental Oct 25, 2026
@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

View Storybook for this PR · View Sandbox for this PR

Current run: The current change has no visual or preview-producing scope. Visual checks are not applicable; preview links are not shown.


Generated by PR Enrichment workflow | View current CI run

@cixzhang

Copy link
Copy Markdown
Contributor Author

/approve-spec 4f8ef5a

@github-actions github-actions Bot added spec-auto-merge Auto-merge was enabled by the spec owner gate and removed needs:spec-owner-review Current knowledge records await owner approval labels Oct 25, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: the direction is owner-approved at this head, but the record's transition and impact need to cover what already ships.

  • FR21's transition sentence and the Current-state impact cover only experimental subpaths, while CLI 0.7.4 already ships experimental exports under ordinary names (icon, iconAdd, iconMap, iconUse, iconNewSet, iconNewDefinition, and the icon-set parsers and types on @astryxdesign/cli/authoring), so say how they move, align spec:AST-084 FR0, and say whether render needs its own decision before it is released.
  • The impact bullet's motion and gesture modules do not exist on main, and the motion and gesture code that does exist is exported, so drop or correct that example.
  • The FR21–FR24 verification row needs a failure for an experimental export whose name lacks the marking, in place of the stable-path wording.

After the next push, an engineering owner records approval again by commenting /approve-spec <full head SHA>, which the author may do as an engineering owner.

[Automated review]

Comment thread docs/specs/AST-017/spec.md Outdated
Comment on lines +381 to +383
contract. An existing experimental subpath keeps working until its exports
carry the marking in their names; that move is an `[experimental]` patch
(FR22) whose release note names each marked replacement.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This transition covers only experimental subpaths. CLI 0.7.4 already ships experimental exports on ordinary entries under unmarked names: icon, iconAdd, iconMap, iconUse, iconNewSet and iconNewDefinition from @astryxdesign/cli/api, and the icon-set parsers and types from @astryxdesign/cli/authoring, marked only by @experimental as spec:AST-084 FR0 states. Extending this sentence to every existing experimental export whose name lacks the marking, wherever it is exported, and saying how those move, would close the gap.

Comment thread docs/specs/AST-017/spec.md Outdated
establish this boundary. Any public experimental API also carries its own
specification decision. A module without a stable public contract stays
internal and is not exported from the package. A workspace package such as
Lab reaches it by bundling the internal source it imports in its own build;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lab's build is a per-file Babel transpile and every Lab import of Core uses a published subpath, so nothing bundles today. Stating the observable rule (Core publishes no internal entry; its exports map is the whole contract) and leaving how Lab carries the source to Lab keeps this within knowledge-contracts INV18. Not blocking on its own.

Comment thread docs/specs/AST-017/spec.md Outdated
contract, and the release process here applies to the result.
contract, and the release process here applies to the result;
- no file path or subpath marks a surface experimental: Core's internal modules,
such as its motion and gesture modules, stay unexported, Lab bundles the

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

main has no Core motion or gesture module yet, and the motion and gesture code it does have is exported (expandMotionScale from @astryxdesign/core/theme; menuPressStep, MENU_PRESS_SETTLE_MS and MenuPressGesture from @astryxdesign/core/hooks). Dropping "such as its motion and gesture modules" keeps this bullet true on main.

Comment thread docs/specs/AST-017/spec.md Outdated
| FR15 | Full manifest-derived command matrix, supported-consumer evidence, and scope-specific contract tests | global invariant, scoped command group, single command, programmatic API | A global control is a no-op for any command, has different meanings, or replaces a narrower owning surface |
| FR16–FR18 | Boundary inventory, hostile side-effect probes, response snapshots, and concurrent API tests | known and new extension, partial result, text/JSON/API parity, independent concurrent calls | A route bypasses the guarantee, omitted work looks complete, or one invocation changes another |
| FR19–FR20 | Proposal evidence with a regression fixture for the detection failure, plus composition and provenance tests | convention covers the case, detection fails, app plus two integrations, refusal, failing contribution, repeated load | A key ships without a reproduced detection failure, a contribution displaces the app or applies twice, a part of the effective value has no inspectable source, or a failure silently weakens protection |
| FR21–FR24 | Published-surface comparison, declaration/doc metadata checks, import-boundary checks, and Changeset classification review | experimental prop object, experimental subpath, patch evolution, promotion, unpublished adjacent field, stable warning behavior, integration theme; a component or module `/experimental` subpath; an internal module bundled into Lab | A prose-only marker excludes a stable API, adjacency falsely publishes a new field, an experimental export leaks through a stable path, a patch changes stable behavior, or a promoted API remains unprotected, a file path or subpath alone marks a surface experimental, an internal module without a stable contract is exported, or Core publishes an internal entry |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No failure here catches an experimental function or type whose exported name lacks the marking, and "an experimental export leaks through a stable path" no longer describes a failure once marked exports may sit on ordinary paths.

@cixzhang
cixzhang force-pushed the spec/no-path-only-experimental branch from 4f8ef5a to bc17c39 Compare October 25, 2026 04:57
@cixzhang

Copy link
Copy Markdown
Contributor Author

/approve-spec bc17c39

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 25, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: the direction is owner-approved at this head, but the record's transition, verification and impact need to cover what already ships.

  • FR21's transition sentence and the Current-state impact cover only experimental subpaths, while CLI 0.7.4 already ships experimental exports under ordinary names (icon, iconAdd, iconMap, iconUse, iconNewSet, iconNewDefinition, and the icon-set parsers and types on @astryxdesign/cli/authoring), so say how they move and align spec:AST-084 FR0.
  • The FR21–FR24 verification row needs a failure for an experimental export whose name lacks the marking, in place of the stable-path wording, and the record should name the form that marking takes.
  • The impact bullet's motion and gesture modules do not exist on main, and the motion and gesture code that does exist is exported, so drop that example.

After the next push, an engineering owner records approval again by commenting /approve-spec <full head SHA>, which the author may do as an engineering owner.

[Automated review]

@cixzhang
cixzhang force-pushed the spec/no-path-only-experimental branch from bc17c39 to be2018f Compare October 25, 2026 15:05
@github-actions github-actions Bot added needs:spec-owner-review Current knowledge records await owner approval and removed spec-auto-merge Auto-merge was enabled by the spec owner gate labels Oct 25, 2026
@cixzhang
cixzhang force-pushed the spec/no-path-only-experimental branch 2 times, most recently from 5cf7cf1 to 3f5f816 Compare October 25, 2026 15:09

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval waits on an engineering owner's decision on the rewritten FR21, FR23, FR21–FR24 verification row and DEC-27 at this head, recorded by commenting /approve-spec <full head SHA> on this pull request (the author may do so as an engineering owner). Three record fixes are needed either way:

  • FR21's "behavior and utility modules … are never exported" and the new impact bullet contradict Core's exported useMenuPress, menuPressStep, useLongPress, useHotkeys and useEntryAnimation, which the current module:DropdownMenu/useMenuPress record defines as public; scope the sentence to modules without a public contract.
  • Through FR54, the experimental_ name rule reaches the CLI's released icon-set exports (spec:AST-084 FR0) and the pending render, although the description says the CLI is unchanged; name the record that owns the CLI's marking, or add a transition for existing exports and amend AST-084 FR0.
  • DEC-9 still states the /experimental subpath placement that DEC-27 replaces; add a pointer to DEC-27.

[Automated review]

Comment thread docs/specs/AST-017/spec.md Outdated
types use the owning component's `/experimental` import subpath and are not
re-exported from the package root or the component's ordinary subpath. Declarations
the component's stable defaults and behavior. Behavior and utility modules, such as
motion, gesture, and keyboard handling, are internal: they are never exported,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As written this covers hooks Core already exports publicly: useHotkeys and useListFocus (keyboard), useLongPress, useMenuPress and menuPressStep (gesture) and useEntryAnimation (motion), from @astryxdesign/core and @astryxdesign/core/hooks. The current module:DropdownMenu/useMenuPress record defines useMenuPress and menuPressStep as a public hook exported from @astryxdesign/core/hooks. Scoping the sentence to modules without a public contract, as the verification row's "internal module without a stable contract" already reads, would keep those released contracts standing.

Comment thread docs/specs/AST-017/spec.md Outdated
visible at the call site where it is used, carried by the name the caller
writes, not only in docs, declarations, or a file path; a component's
`experimental` prop object meets this, and any other deliberately
experimental public API meets it with an `experimental_` name prefix. No file path or subpath, for a

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FR54 applies FR21–FR27 to every surface's release and architecture:cli-surface has no rule for experimental exports, so this prefix rule reaches the CLI: the icon-set functions and authoring types released in 0.7.4 under unprefixed names (marked by @experimental as spec:AST-084 FR0 requires), and render on @astryxdesign/cli/api/experimental, which also has no decision of its own. Either name the record that owns the CLI's marking here, or add a transition for existing experimental exports and amend AST-084 FR0.

Comment thread docs/specs/AST-017/spec.md Outdated
decision (FR59).
decision (FR59);
- no file path or subpath marks a surface experimental and Core's behavior and
utility modules stay unexported (FR21).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On main, Core exports behavior hooks from its root and ./hooks (useMenuPress, menuPressStep, useLongPress, useHotkeys, useEntryAnimation), so "stay unexported" does not hold today. This bullet should match whatever scope FR21's module sentence ends up with.

and requiring any experimental public API to show its status at the call
site where it is used, in the name the caller writes, with its own decision,
keeps the public surface honest about what is promised. The `experimental`
prop object and the `experimental_` name prefix are how that is met today. This replaces DEC-9's placement of experimental hooks,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DEC-9 itself still reads "Put experimental hooks, functions, and types on the owning component's /experimental subpath" with no pointer here, and it stays in the compatibility trigger list, so reviewers routed to DEC-9 get the replaced rule. DEC-10 and DEC-11 carry a "DEC-18 supersedes …" note for the same situation; one such sentence in DEC-9 would close it.

…contract, Core marking, CLI marking owned by its records; DEC-9 points to DEC-27
@cixzhang

Copy link
Copy Markdown
Contributor Author

/approve-spec e11121c

@github-actions github-actions Bot added spec-auto-merge Auto-merge was enabled by the spec owner gate and removed needs:spec-owner-review Current knowledge records await owner approval labels Oct 25, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested: the direction is owner-approved at this head, and two record fixes remain.

  • DEC-27 and the FR21–FR24 verification row require an experimental public API's status in the caller-written name for every package, while FR21 limits that rule to Core, so release review would fail the CLI's released @experimental icon-set exports (spec:AST-084 FR0); give all three the same scope.
  • FR21's new own-decision sentence also reaches the CLI's pending render export, which no record decides; scope it like the name rule or name render in the Current-state impact.

After the next push, an engineering owner records approval again by commenting /approve-spec <full head SHA>, which the author may do as an engineering owner.

[Automated review]

Comment thread docs/specs/AST-017/spec.md Outdated
| FR15 | Full manifest-derived command matrix, supported-consumer evidence, and scope-specific contract tests | global invariant, scoped command group, single command, programmatic API | A global control is a no-op for any command, has different meanings, or replaces a narrower owning surface |
| FR16–FR18 | Boundary inventory, hostile side-effect probes, response snapshots, and concurrent API tests | known and new extension, partial result, text/JSON/API parity, independent concurrent calls | A route bypasses the guarantee, omitted work looks complete, or one invocation changes another |
| FR19–FR20 | Proposal evidence with a regression fixture for the detection failure, plus composition and provenance tests | convention covers the case, detection fails, app plus two integrations, refusal, failing contribution, repeated load | A key ships without a reproduced detection failure, a contribution displaces the app or applies twice, a part of the effective value has no inspectable source, or a failure silently weakens protection |
| FR21–FR24 | Published-surface comparison, declaration/doc metadata checks, import-boundary checks, and Changeset classification review | experimental prop object, experimental subpath, patch evolution, promotion, unpublished adjacent field, stable warning behavior, integration theme; a component or module `/experimental` subpath; an `experimental_` export; a behavior module | A prose-only marker excludes a stable API, adjacency falsely publishes a new field, an experimental export leaks through a stable path, a patch changes stable behavior, or a promoted API remains unprotected, a file path or subpath alone marks a surface experimental, a behavior, utility, or internal module without a public contract is exported, or an experimental public API's call site does not show its status in the name the caller writes |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This failure has no scope, while FR21 applies the call-site name rule in Core only and leaves the CLI's marking to its records. The CLI's icon-set functions released in 0.7.4 (iconAdd and five others), which spec:AST-084 FR0 marks with @experimental alone, would fail it. Scoping it as FR21 does ("a Core experimental public API's call site …") keeps the row and FR21 in step.

Comment thread docs/specs/AST-017/spec.md Outdated
Comment on lines +1399 to +1400
and requiring any experimental public API to show its status at the call
site where it is used, in the name the caller writes, with its own decision,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"any experimental public API" states the name rule for every package, but FR21 applies it in Core only and hands the CLI's marking to its own records. DEC-27 is routed by the compatibility trigger, so CLI reviews receive this sentence; giving it FR21's scope keeps the two consistent.

Comment thread docs/specs/AST-017/spec.md Outdated
Comment on lines +386 to +387
establish this boundary. Any public experimental API also carries its own
specification decision.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence has no scope, so it reaches the CLI's render export on @astryxdesign/cli/api/experimental, pending release in .changeset/cli-experimental-render.md, which no record decides. Scoping it like the name rule, or naming render in the Current-state impact as needing its own decision before that Changeset releases, would close the gap.

@cixzhang

Copy link
Copy Markdown
Contributor Author

/approve-spec 4f6fb06

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommended for approval: every proposed spec:AST-017 change carries an engineering owner's approval at this head, and DEC-27, the FR21–FR24 verification row and the own-decision sentence now share FR21's Core scope, so the CLI's released @experimental icon-set exports and the pending render export stay under the CLI's own records. No record change is required; consider updating the description, whose Decision bullets and non-goal (component /experimental subpaths unchanged) no longer match FR21 and DEC-27. For the first experimental Core hook, note that an experimental_useX name fails React's use-prefix hook check unless callers alias it, which hides the marker at each call.

[Automated review]

@cixzhang
cixzhang merged commit 7e855c0 into main Oct 25, 2026
54 checks passed
@github-actions
github-actions Bot deleted the spec/no-path-only-experimental branch October 26, 2026 06:31

This branch was successfully deployed

1 active deployment
Preview — 4f6fb067 Deployed Oct 25, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot. spec-auto-merge Auto-merge was enabled by the spec owner gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant