Repository navigation
Release 2.0.0-beta.3 - #422
Merged
Merged
Conversation
Builds this commit of the CLI, packs it, installs the tarball globally, and runs the portal suite from apimatic/v4-test-automation against it — so the tests exercise the CLI you just changed rather than whatever is on npm. Three stages: artifacts (what `apimatic portal generate` produced vs what the build's src/apimatic.json declared — SDK archives, package identity, generated pages), visual (screenshots against committed baselines), and functional (behaviour; wired up, cases still being added). Runs on pull requests as well as merges into dev, so a change to generation shows up on the PR that caused it rather than after it lands. windows-latest is required rather than preferred: the suite's visual baselines were captured on win32/Chromium, and font rasterisation differs enough across operating systems that a ubuntu runner would fail every snapshot. Follows the conventions already in this repo — SHA-pinned actions, standalone pnpm 11.0.8 because corepack isn't distributed with Node 25+, and persist-credentials: false on checkout. Needs two secrets before it can go green; see the pull request description. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ci: run the portal automation tests against this build
…round (#410) * fix(portal): render auth scheme descriptions as Markdown in the playground Upgrade fumadocs-openapi from 11.4.1 to 12.1.0, which renders a security scheme's description as Markdown in the playground's auth selector (fuma-nama/fumadocs#3607). 12.x removed the v11 hooks the template used, so the example layout, usage tabs and code block move to useOpenAPI, useOperation, useExampleRequests and useCodeUsage. The cURL tab is now a registered generator under an id of its own. 12.1.0 is younger than the 7-day release age, so it is exempted in pnpm-workspace.yaml until 2026-10-06. Closes apimatic/apimatic-io#2249 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(portal): address review of the fumadocs-openapi 12.1.0 upgrade The 12.1.0 upgrade also changes the playground's OAuth handling: the client credentials flow can send the client ID and secret with HTTP Basic (fuma-nama/fumadocs#3609), a relative tokenUrl resolves against the selected server instead of failing the token fetch (fuma-nama/fumadocs#3610), and the client secret is no longer sent to the authorization server in the state parameter. Pin @scalar/json-magic's undici to 7.29.1. json-magic 0.13.5 pins undici 7.24.4, which carries 21 advisories, and Fumadocs loads it at runtime through the bundler's fetchUrls plugin. Drop the fumadocs-openapi release-age exemption: 12.1.0 is locked, and an unversioned entry would exempt every later release too. Build each Parameter from useOperation().parameters, which Fumadocs has already resolved, deduplicated and grouped by location, instead of re-reading the raw operation and path item. A parameter declared on both is no longer listed twice. Remove the e2e case for the image upload error screen, which 12.1.0 no longer shows, and correct two media adapter comments the upgrade made stale. Refs apimatic/apimatic-io#2252 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* docs(plans): propose a tabs key in the root nav.json The root nav.json's `pages` decides two things at once: which top-level folders are tabs, and the order of Home's sidebar. A folder cannot be ordered inside Home without becoming a tab. The amendment gives the root file a `tabs` list for the tab bar and leaves `pages` ordering Home, as it orders every other folder. The apimatic: tokens can go in either list, and stay refused below the root. A beta.1 root file that relies on the old reading is refused until 2.0.0, and a portal whose only tab is Home hides the tab bar. Section 5 of portal-config.md states the rules and section 16 the delivery; portal-navigation.md and generated-pages.md point to them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(plans): tighten the nav.json tabs proposal after a second review The beta.1 refusal no longer counts a folder serving `/`, which beta.1 itself refused, so no beta.1 file can hold one. The navigation context gains the subfolders with a page in them, since `childNames` cannot tell a page from a folder and both new refusals need to. Section 16 now names the doc comments and existing tests that state the old rule, holds every setting the CLI accepts to the template's schema, and says the e2e suite is red between the template and CLI steps. The serve paragraph speaks of sections rather than tabs, and portal-navigation.md counts `tabs` as the third setting now that `root` is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(portal): read the root nav.json's tabs in the template The root nav.json's `pages` carried two decisions: which top-level folders are tabs, and where Home's nodes go. A folder could not be ordered inside Home without becoming a tab. `tabs` now takes the first decision, and `pages` orders Home's sidebar as every other nav.json orders its folder (.ai/plans/portal-config.md, sections 5 and 16). - navigation-schema.ts extends Fumadocs' metaSchema with `tabs`, typed as `pages`, and the docs collection validates nav.json against it, so the key survives. Unknown keys are still stripped. - A folder is a tab when `tabs` lists it. The API reference and each generated section are tabs unless the root `pages` names them, which places them in Home at the address they always had. - The tabs are ordered by `tabs` through `reorder`, with the defaults the root `pages` gave before for what it leaves unnamed. - portalTabs returns no tab when Home is the only one, so the header shows no switcher over a single choice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(portal): validate the root nav.json's tabs in the CLI The CLI holds `tabs` to the rules the template now reads it by (.ai/plans/portal-config.md, sections 5 and 16). - `tabs` is known in the root nav.json and refused below it with a sentence of its own. Its entries are a folder with a page under it, `api` or `apimatic:api`, `apimatic:sdks` and `apimatic:plugin`. A page, `...`, a folder serving `/`, an unknown name, a duplicate and a node `pages` also names are each refused. - The root `pages` may now name a token, `api` or a folder serving `/`, each placed in Home. Below the root a token is still refused, and the sentence names both places it can go. - A root file with no `tabs` whose `pages` names a folder, `api` or a token is refused, since 2.0.0-beta.1 made tabs of those entries and reading it under the new rule would move them into Home's sidebar. The check goes before 2.0.0 ships. - The content tree takes folder tabs from `tabs`, and leaves a section placed in Home out of the tabs and out of the shared-name warning. - The notice naming the folders the file made tabs of goes: `tabs` says so in its own name. makesSameTabsAs becomes makesSameSectionsAs. - The default fixture moves its tabs from `pages` to `tabs`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(portal): build a portal with every section in Home, and document tabs - A third e2e build, from the sections-in-home fixture, whose root nav.json places the API reference, the SDKs and the Context Plugin in Home with `pages` and names no tab. It checks the prerendered sidebar holds Home alone with each section where `pages` names it, that each section keeps its address, and that the header renders no tab bar. - The README's bullet on tabs is rewritten for `tabs` and `pages`, the tokens placeable in either, and the refusal of a 2.0.0-beta.1 file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(portal): trim the duplication and complexity SonarCloud flagged - entryErrors hands each entry to listEntryError, which brings the function under the cognitive-complexity limit. - The e2e builds share portalBuilt, which registers the before and after hooks and reads the output, and tabPositions, which finds each tab's link in the header, instead of repeating both per describe block. - The tab-order defaults in tabs.test.ts are one table-driven loop. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(portal): answer a root nav.json without tabs in words a new user can act on Found reviewing the tabs change before handing it over. - The scaffold writes `"tabs": []` beside `pages`, so a folder named in a scaffolded file is placed in Home rather than refused. - The refusal of a root file with no `tabs` no longer leans on beta.1 history: it says the file does not say whether the entries are tabs or in Home's sidebar, and how to say either. - A misspelt setting at the root is answered with `tabs` among the settings, which the list left out. - The README states the real default for a section named in neither list: after the folders `tabs` names, before a reference not named ahead of them. - Comments trimmed to one line each; a dead guard in isTabFolder and a membership scan in the content walk are gone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(portal): keep unnamed section tabs behind everything tabs names The unnamed sections' tab position reused the sidebar's anchor, which sits after the last named user content. A tabs list naming only the reference and tokens has none, so the anchor fell to the front and the unnamed sections landed ahead of a reference the file deliberately put first: tabs ["apimatic:api"] gave Home, SDKs, Context Plugin, API Reference. In the tab bar every folder is named, so the unnamed band now follows everything `tabs` names, a named reference included, with an unnamed reference still last. The sidebar keeps its own anchor. The README states the rule as one sentence. Found in review (PR #408, first comment). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(portal): refuse api as a tab when a page carries the name With a page at `content/api.md`, naming `api` in `pages` is refused, since the entry positions the mounted reference and the page could never be placed. The same name in `tabs` was accepted before the shared-name test ran, letting through the quietly wrong sidebar the validator exists to refuse. The tab entry now gives the refusal `pages` gives, from one shared sentence. Found in review (PR #408, second comment). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(portal): point a mistyped tab at what tabs accepts The not-found sentence for a tabs entry borrowed the pages hint, which could point at an entry tabs then refuses: a capitalised page name was answered with "Did you mean 'authentication'?", and following it earned "'authentication' is a page" one run later. A near miss of `api` named only the token, although the folder name is accepted too. The tabs path now has a hint of its own: a folder near miss stays a suggestion, a section is offered as its token, `api` is offered in both spellings, and a page's name is answered in one message with where a page can go. Found in review (PR #408, third comment). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore: keep the README's CRLF line endings An edit on this branch rewrote every line ending from CRLF to LF, so the whole file diffed and hid the 24 lines that actually changed, and any other branch touching the README would conflict on every line. The endings are back as dev stores them; the words are untouched. Found in review (PR #408). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(portal): name the tabs in the order the tab bar shows them The tab list behind the shared-name warning emitted the folders, then the generated sections, then the reference, ignoring where `tabs` put the tokens: with `tabs` naming a section before a folder, the warning listed them the other way around, and the doc comment still promised the report's order. The list now walks `tabs` and emits each entry in place, then the unnamed sections and an unnamed reference, mirroring what the template renders. Found in review (PR #408). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(portal): answer a folder near miss with a stray extension, from one helper The tabs hint matched a folder near miss on the lowered name alone, while the page lookup beside it also stripped a stray extension, so 'Guides.md' got no suggestion in `tabs` although the same entry in `pages` did. The lowering, stripping and matching now live in one nearMiss helper that answers what an entry was meant as, and each list phrases its own sentence over it, so the two cannot drift again. Found in review (PR #408). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(portal): make tabs the whole tab bar, a section it does not name a folder in Home A generated section and the API reference were tabs unless the root `pages` placed them in Home, so `{}` and `"tabs": []` gave Home and three tabs while every folder went into Home, and the tab bar was not what `tabs` said. Now a node is a tab exactly when `tabs` names it: a folder by name, the reference by `api` or its token, a section by its token. Everything else is in Home, where `pages` orders it and, unnamed, Fumadocs' own order holds, a section among the folders like any other. `reorder` loses its bands and anchor, and the root is no longer reordered without a `pages` of its own. A file with no `tabs`, or no file, leaves Home alone with no tab bar. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * feat(portal): read a root nav.json with no tabs as an empty list, and scaffold the sections as tabs With `tabs` the whole tab bar, a root file without it has one reading, no tab, so the refusal of a 2.0.0-beta.1 file goes: there is nothing left to ask. The content tree names a tab for each `tabs` entry and for nothing else, so a section the file does not name is compared with no tab's name. The scaffold writes `apimatic:sdks`, `apimatic:plugin` and `apimatic:api` in `tabs`, so a fresh portal keeps the tabs it had; the sample repository's root file does the same. The default fixture names the plugin's token too, and the branded build, which has no `nav.json`, asserts no tab bar. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * docs(portal): state the tabs rule as it now stands The README bullet and the plans said a section named in neither list kept a tab at a default place, and described the beta.1 refusal. Both now say that `tabs` is the whole tab bar after Home, that what it does not name is in Home in Fumadocs' order, and that a file with no `tabs` makes no tab, with a history entry for the review that decided it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * refactor(portal): resolve each nav.json entry once, for both lists, the tab list and the hints `api` and `apimatic:api` being one node was ruled on in five places. Now `target` says once what an entry names -- the rest entry, an `apimatic:` string that positions nothing here, the API reference, a section, a folder, a page, an empty folder or nothing -- and the duplicate check, each list's rules, the tabs the content tree names and the near-miss hint read that answer. `NavigationSettings.tabs` carries the resolved tabs, undefined for a file with no list. The lists are typed `'pages' | 'tabs'` with a constant each, an entry with its list is one named type, and the sentences a page in `tabs` and an empty folder get are written once. A list of the wrong type no longer hides the other list's entries, and a page named `api` is refused under either spelling of the reference, since it could be positioned under neither. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(portal): take the scaffold's tabs from the validator's token list The scaffold rebuilt `TOKENS` from its parts; the one list now serves both. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * test(portal): hold the template's schema to every root setting the CLI accepts The test hard-coded `tabs`, so a setting added to `ROOT_FIELDS` would have been validated by the CLI and stripped by the template with nothing failing. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * feat(portal): say once when a root file with no tabs makes no tab A root file with no `tabs`, or no root file, makes no tab, and a 2.0.0-beta.1 project had the sections as tabs, so the upgrade was silent. The build now says so once, naming the sections in Home and both ways to settle it: the tokens in `tabs` to have them back, or `"tabs": []` to keep the sidebar, which says nothing. Under `portal serve` it is given once, like the other notices, and again when the plugin block changes what is in Home. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * feat(portal): say when a Home title has no tab bar to show in A root `title` names the Home tab, and one tab draws no tab bar, so with nothing in `tabs` the name showed nowhere and the CLI accepted a setting that did nothing. It now says so once. The sections-in-home fixture drops the title it never showed, and its build looks for a Home link instead. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(portal): stop the prompts calling the SDK pages and the context plugin tabs They are tabs only when `tabs` names them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * refactor(portal): draw no tab bar for one tab, whichever it is `portalTabs` builds its list and returns none for a single entry, which says "one choice switches nothing" directly and covers a tab dropped for having no link. `HOME_TAB_ID` goes back to `navigation.ts`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * refactor(portal): claim the tabs as reorder claims an entry `groupIntoTabs` matched each folder to a `tabs` entry and `reorder` then matched the entries back to folders. `nodeNamed` now resolves an entry to its node for both, and the tabs are the nodes `tabs` names, in its order; `isTab`, `isTabFolder` and `lists` go. The section check runs the cheap path test before the storage read. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * chore(portal): cut the comments that narrated the tabs rule The rule lives in the code and in the plan; the doc comments keep only what the code does not say. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * docs(portal): record the third review The two notices, the entry resolver, and the alphabetical place of an unnamed section kept on purpose. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * chore(portal): quiet the two SonarCloud findings on the notice prompt and the schema test The notice built its suggestion inside a nested template literal, and the schema test passed the same field to the assertion twice. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(portal): refuse a page named api under api alone, not under the token Resolving both spellings to the reference had the shared-name refusal fire for `apimatic:api` too, so every scaffolded portal that added `content/api.md` failed to build, though the entry was the token and the page was never meant to be positioned. Only `api` spelled out might have meant the page, so only that spelling is refused, as on dev; `target()` is unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * feat(portal): name the folders pages made tabs in the no-tabs notice Before `tabs` existed a folder the root `pages` named was a tab as well, so a 2.0.0-beta.1 project that followed the notice's suggested line got its sections back and lost those tabs without a word. The notice now names them, and the line leads with them in `pages` order, as beta.1 showed them; a `(group)` folder serving the home page is left out, since `tabs` refuses it. Under `portal serve` a folder newly named gives the notice again, once. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * docs(portal): record the fourth review The third-review entry said the default order is rarely seen; it is seen by every existing portal the moment a release adds a section, since the scaffold writes `nav.json` once, so that release must tell them to name its token. The entry also claimed the `api` page was refused under either spelling, which the fix before this corrects. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(portal): name only what nothing places in the no-tabs notice The line the notice offered was refused when followed: a folder or token the root `pages` named went into `tabs` too, and a node is in one list or the other. A folder in `pages` is in Home because that is what `pages` means, so the folders go, and the line names only the sections and the reference that nothing places; once `pages` places them all, the notice says nothing. The validator answers with what `pages` places, so the `api` spelling stays ruled on in one place, and the text that leaned on beta.1 is in present terms: the CLI's messages describe how `nav.json` works now, not what it did. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: saeedjamshaid <muhammad.saeed@apimatic.io> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…HTTP Basic (#416) Upgrade fumadocs-openapi from 12.1.0 to 12.1.1. The playground's Client Authentication selector now starts on "Send as Basic Auth header", the method RFC 6749 §2.3.1 requires authorization servers to support, instead of sending the client credentials in the body, which the RFC calls NOT RECOMMENDED (fuma-nama/fumadocs#3629). 12.1.1 also offers the selector in the authorization code flow, sends only client_id in the body when there is no client secret, stops requiring client credentials in the password flow, and adds a Download button to the playground's response panel. Only fumadocs-openapi changes in the lockfile; its dependencies are the same as 12.1.0's. 12.1.1 was taken before the 7-day release age with a temporary exact-version exemption, which is not committed. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…er the base path (#413) * fix(deps): take fumadocs 16.15.17, which links "View as Markdown" under the base path From 16.15.13 the page actions popover handed out its "View as Markdown" link as given, while Copy Markdown on the same page prefixed Vite's base. A portal hosted under a path linked readers to the host's root, where the Markdown companion is not (fuma-nama/fumadocs#3620). 16.15.17 runs the link through the same withBasePath, and Copy Markdown now fails on an error response instead of copying the error page. A new test renders the real popover through Vite with base '/docs/' and '/' and reads the link off the markup; it fails on 16.15.15. The loader now decodes both sides of a slug lookup, so a decoded splat finds its page without slugsFromSplat; page-slugs.test.ts says so. Part of apimatic/apimatic-io#2275. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix comment * chore: address review on the fumadocs 16.15.17 bump Drop the fumadocs release-age excludes, since the lockfile already pins the versions taken. Stop the page-actions test's Vite server from watching the checkout and writing a dependency cache, match the link's href in any attribute position, and trim comments the names now carry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(deps): repair the fumadocs-openapi 12.1.1 lockfile entry from the dev merge The merge renamed the 12.1.0 entry to 12.1.1 by hand, so it kept 12.1.0's dependencies and missed @fumadocs/json-schema, and its peers still named fumadocs-core and fumadocs-ui 16.15.15, which the lockfile no longer has. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
#417) fumadocs-openapi 12.1 skips a response example that has no `value` (fuma-nama/fumadocs#3608), so `undefined` no longer reaches the code block and the operation page no longer crashes. The template's own CodeBlock, which only existed to skip that case (#373), is removed and pages render through Fumadocs' default code block. The usage tabs take the code block from useComponents(), and the cURL tab renders nothing itself when no example request is available, which the removed guard used to cover. Refs #370 Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* feat: handle zip service failures * refactor: return unArchive's Result synchronously and import node:crypto Extraction runs synchronously through adm-zip, so unArchive no longer wraps its Result in a promise its callers had to await. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: use srcDir instead of build * fix: update wording for sdk zipping * refactor(zip): keep unArchive asynchronous unArchive returns a Promise again, as archive does, so that adm-zip's synchronous extraction stays out of the service contract and a later switch to an asynchronous extractor leaves its callers unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(zip): list the directory before handing yazl any file The walk added each file to yazl as it went, and the error listener was attached only after the walk. When a directory deeper in the tree could not be listed, the files added before it still had pending stat calls on a ZipFile with no listener, so a dangling symlink among them crashed the process even though archive had already reported the failure. The walk now finishes before the ZipFile exists, and the listener is in place before the first file is added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor: name the staged upload directory by SOURCE_DIRECTORY_NAME ProjectContext.srcDirZip and PluginConfigContext.stageUpload spelled the project's source directory name as a literal; both now take it from the project layout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: report zip and unzip failures as one FileProblem, with their reason The contexts that zip or unzip returned the error's message as a bare string, which no prompt could switch on. TempContext.zip, ProjectContext.srcDirZip, SdkContext.save, SdkContext.loadSdkInTempDirectory, PluginContext.save and SpecContext.install now all return one shape, FileProblem, with a kind (zipFailed or unzipFailed) and the reason. That removes what the bare string forced on the actions: - sdk generate and plugin generate no longer make up a ServiceError.InvalidResponse for a download they could not unzip, and no longer drop the reason. The user sees the same invalid-response message, now followed by the reason. - plugin generate tags its config and service failures, so its whole chain carries one PluginGenerationProblem that a single prompt words by kind. UploadPackagingFailure, the instanceof/typeof switch in the action and the TODO above the dropped reason are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sdk): name the language directory when the SDK cannot be saved sdk generate --zip named the parent output directory when the SDK could not be zipped into place, while the success message names the language directory. SdkContext.save now reports the directory it was saving to, and the message names it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
MuHamza30
approved these changes
Oct 5, 2026
|
🎉 This PR is included in version 2.0.0-beta.3 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Promotes dev to beta: the first release on the new pipeline (#409), expected to publish 2.0.0-beta.3 to the npm beta dist-tag as a GitHub prerelease. The run commits nothing back to beta; the tag goes on this merge commit.
Merge with Create a merge commit.
What releases
The remaining commits since 2.0.0-beta.2 are ci, chore and test changes, plus the commits of #412, and release nothing.
🤖 Generated with Claude Code