Repository navigation
spec(AST-017): no file path or subpath makes an API experimental - #8357
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
PR Analysis ReportView Storybook for this PR · View Sandbox for this PR
Generated by PR Enrichment workflow | View current CI run |
|
/approve-spec 4f8ef5a |
There was a problem hiding this comment.
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, alignspec:AST-084FR0, and say whetherrenderneeds 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]
| 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. |
There was a problem hiding this comment.
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.
| 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; |
There was a problem hiding this comment.
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.
| 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 |
There was a problem hiding this comment.
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.
| | 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 | |
There was a problem hiding this comment.
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.
4f8ef5a to
bc17c39
Compare
|
/approve-spec bc17c39 |
There was a problem hiding this comment.
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 alignspec:AST-084FR0. - 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]
bc17c39 to
be2018f
Compare
5cf7cf1 to
3f5f816
Compare
…1 clarification, DEC-27)
3f5f816 to
3fa616d
Compare
There was a problem hiding this comment.
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,useHotkeysanduseEntryAnimation, which the currentmodule:DropdownMenu/useMenuPressrecord 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-084FR0) and the pendingrender, 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
/experimentalsubpath placement that DEC-27 replaces; add a pointer to DEC-27.
[Automated review]
| 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, |
There was a problem hiding this comment.
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.
| 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 |
There was a problem hiding this comment.
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.
| decision (FR59). | ||
| decision (FR59); | ||
| - no file path or subpath marks a surface experimental and Core's behavior and | ||
| utility modules stay unexported (FR21). |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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
|
/approve-spec e11121c |
There was a problem hiding this comment.
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
@experimentalicon-set exports (spec:AST-084FR0); give all three the same scope. - FR21's new own-decision sentence also reaches the CLI's pending
renderexport, which no record decides; scope it like the name rule or namerenderin 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]
| | 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 | |
There was a problem hiding this comment.
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.
| 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, |
There was a problem hiding this comment.
"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.
| establish this boundary. Any public experimental API also carries its own | ||
| specification decision. |
There was a problem hiding this comment.
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.
…n row share FR21's Core scope
|
/approve-spec 4f6fb06 |
There was a problem hiding this comment.
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]
Exact decision needed
Whether a public module can be experimental by its file path alone (a module-level
/experimentalsubpath), and how modules without a stable contract are shared.Existing authority searched
spec:AST-017FR21 owns the experimental boundary: an existing component'sexperimentalprop object and its own/experimentalsubpath, both marked in declarations and docs. It does not say whether a module (not a component) may publish an/experimentalsubpath. This PR clarifies FR21 and records DEC-27.spec:AST-094OQ4 asks the same question; DEC-27 answers it.motion/experimentalandgesture/experimental; feat(core): one interactive-transition driver, with BottomSheet on it #8341 (interactive-transition driver on the experimental motion subpath) and test(core): one internal definition pins core's touch style keys #8331 (exporting touch keys) depend on that and need to bundle the internal source instead.Decision
spec:AST-017FR21 and DEC-27 (Cindy, 2026-10-24; marking form 2026-10-25):experimental_prefix, visible at every import and call site, plus@experimental. Component experimental props stay in theexperimentalprop object./experimentalsubpath; theexperimentalprop object stands. FR23's promotion wording follows.Rejected alternatives
/experimentalsubpaths that mark status by path, for modules or components.Claim scope and non-goals
The experimental boundary for modules only. Component
experimentalprops and component/experimentalsubpaths (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
Scope
Validation
pnpm check:knowledge(CI lint)git diff --check