Skip to content

Release: Prerelease 10.6.0-alpha.5 - #35715

Merged
ndelangen merged 330 commits into
next-releasefrom
version-non-patch-from-10.6.0-alpha.4
Aug 10, 2026
Merged

ndelangen merged 330 commits into
next-releasefrom
version-non-patch-from-10.6.0-alpha.4

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 3, 2026 •

Copy link
Copy Markdown
Contributor

This is an automated pull request that bumps the version from `10.6.0-alpha.4` to `10.6.0-alpha.5`.
Once this pull request is merged, it will trigger a new release of version `10.6.0-alpha.5`.
If you're not a core maintainer with permissions to release you can ignore this pull request.

To do

Before merging the PR, there are a few QA steps to go through:

  • Add the "freeze" label to this PR, to ensure it doesn't get automatically forced pushed by new changes.
  • Add the "ci:daily" label to this PR, to trigger the full test suite to run on this PR.

And for each change below:

  1. Ensure the change is appropriate for the version bump. E.g. patch release should only contain patches, not new or de-stabilizing features. If a change is not appropriate, revert the PR.
  2. Ensure the PR is labeled correctly with one of: "BREAKING CHANGE", "feature request", "bug", "maintenance", "dependencies", "documentation", "build", "unknown".
  3. Ensure the PR title is correct, and follows the format "[Area]: [Summary]", e.g. "React: Fix hooks in CSF3 render functions". If it is not correct, change the title in the PR.
    • Areas include: React, Vue, Core, Docs, Controls, etc.
    • First word of summary indicates the type: “Add”, “Fix”, “Upgrade”, etc.
    • The entire title should fit on a line

This is a list of all the PRs merged and commits pushed directly to `next`, that will be part of this release:

  • 🔧 Maintenance: Core: Share the CSF story-shape helpers snippet generators need #35803
  • ✨ Feature Request: Angular-Vite: Run Compodoc on demand #35776
  • ✨ Feature Request: Vue: Add story-docs provider skeleton #35786
  • 🐛 Bug: Tanstack: Wait for router to load before rendering #35784 (will also be patched)
  • ✨ Feature Request: Manifests: Add a warning field to story entries #35794
  • 🐛 Bug: Angular: Stop treating input/output alias collisions as two-way bindings #35777
  • 🔧 Maintenance: React: Share a TypeScript DocumentRegistry across component-meta projects #35468
  • 🐛 Bug: Angular: Derive required inputs from Compodoc's own flag #35758
  • ✨ Feature Request: Angular: Extract docgen on the server via Compodoc #35733
  • 🔧 Maintenance: Angular: Extract Compodoc parsing into its own package #35749
  • 🐛 Bug: Refactor: Update getVersionedPackages method to handle non-Storybook packages correctly #35769 (will also be patched)
  • ✨ Feature Request: Vue: Move vue-component-meta in vue renderer and implement docgen payload builder #35665
  • 🐛 Bug: CLI: Categorize Execa failures for init telemetry #35720
  • 🐛 Bug: TanStack: Keep the layout id when cloning a standalone index file route #35660
  • 🐛 Bug: CLI: Allow esbuild builds for Storybook-owned pnpm dlx #35742
  • ✨ Feature Request: Core: Extract ComponentMetaManager to Core #35657
  • 🏗️ Build: Build: Give AGENTS.md a real comments and JSDoc rule #35818
  • 🏗️ Build: Build: Normalize CRLF in story-shape print assertions #35800
  • 🏗️ Build: Build: Run yarn dedupe after sandbox install #35793
  • 🏗️ Build: Build: Give the addon-mcp component-stories test room to import #35795
  • ❔ Missing Label: Core: Extract React CSF tools into Core #35766
  • 🏗️ Build: Build: Keep the published lockfile and age gate in sandbox CI #35790
  • 🏗️ Build: Build: Fix Windows failure in the Angular docgen worker test #35787
  • 🏗️ Build: Release: Report prereleases to DX also #35773 (will also be patched)
  • 🏗️ Build: Build: Exempt tailwindcss/turbopack from the sandbox age gate #35783 (will also be patched)
  • 🏗️ Build: Build: Keep Yarn's output plain so age-gate rejections stay parseable #35782 (will also be patched)
  • 🏗️ Build: Bench: Gate the docgen perf suite on budgets in CI #35710
  • 🏗️ Build: Build: Narrow only quarantined ranges when generating sandboxes #35775 (will also be patched)
  • 🏗️ Build: Build: Also exempt `vue/language-core` from Vue sandbox age gate #35771 (will also be patched)
  • 🏗️ Build: Build: Preapprove `vue-component-meta` for sandbox age gate #35770 (will also be patched)
  • 🏗️ Build: Build: Update Yarn configuration and set dependencies to latest version #35767 (will also be patched)
  • 🏗️ Build: Build: Update to yarn v4.18.0 #35764 (will also be patched)
  • 🏗️ Build: Build: Migrate sandbox generation to Yarn 4 with 7d npmMinimalAgeGate #34852 (will also be patched)
  • 🏗️ Build: Build: Sanitize publish-time .yarnrc.yml in after-storybook sandboxes #34851
  • 🏗️ Build: Build: Add 7d minimum release age gate to the repository's Yarn config #35763 (will also be patched)
  • 🏗️ Build: Agents: Add Cursor Cloud environment setup notes #35713
  • 🏗️ Build: CI: Remove mcp and addon-mcp from verdaccio proxy #35722

If you've made any changes doing the above QA (change PR titles, revert PRs), manually trigger a re-generation of this PR with this workflow and wait for it to finish. It will wipe your progress in this to do, which is expected.

Feel free to manually commit any changes necessary to this branch after you've done the last re-generation, following the Make Manual Changes section in the docs, especially if you're making changes to the changelog.

When everything above is done:


Generated changelog

10.6.0-alpha.5

  • Angular-Vite: Run Compodoc on demand - #35776, thanks valentinpalkovic!
  • Angular: Derive required inputs from Compodoc's own flag - #35758, thanks valentinpalkovic!
  • Angular: Extract Compodoc parsing into its own package - #35749, thanks valentinpalkovic!
  • Angular: Extract docgen on the server via Compodoc - #35733, thanks valentinpalkovic!
  • Angular: Stop treating input/output alias collisions as two-way bindings - #35777, thanks valentinpalkovic!
  • CLI: Allow esbuild builds for Storybook-owned pnpm dlx - #35742, thanks ndelangen!
  • CLI: Categorize Execa failures for init telemetry - #35720, thanks ndelangen!
  • Core: Extract ComponentMetaManager to Core - #35657, thanks huang-julien!
  • Core: Share the CSF story-shape helpers snippet generators need - #35803, thanks valentinpalkovic!
  • Manifests: Add a warning field to story entries - #35794, thanks valentinpalkovic!
  • React: Share a TypeScript DocumentRegistry across component-meta projects - #35468, thanks connorshea!
  • Refactor: Update getVersionedPackages method to handle non-Storybook packages correctly - #35769, thanks valentinpalkovic!
  • TanStack: Keep the layout id when cloning a standalone index file route - #35660, thanks Insik-Han!
  • Tanstack: Wait for router to load before rendering - #35784, thanks huang-julien!
  • Vue: Add story-docs provider skeleton - #35786, thanks huang-julien!
  • Vue: Move vue-component-meta in vue renderer and implement docgen payload builder - #35665, thanks huang-julien!

@github-actions github-actions Bot added the release For PRs that trigger new releases. Automated label Aug 3, 2026
@storybook-bot
storybook-bot force-pushed the version-non-patch-from-10.6.0-alpha.4 branch 2 times, most recently from 30e9bcd to 0ef7257 Compare August 4, 2026 08:07
huang-julien and others added 27 commits August 4, 2026 10:24
The docgen work needs one place that says what gets measured, how, and what a
number is allowed to mean. Without it every later change re-argues the same
questions inline.

The note fixes the metric set, the determinism method, the budget shape and
the CI tiers. Two decisions carry the rest: measurements compare ratios taken
in one job on one machine, because absolute wall-clock on shared CI executors
is too noisy to gate; and a pair whose two sides documented different amounts
of work is marked not like-for-like and must not become a budget.

The rules are written per engine rather than per framework, so adding a
framework does not mean adding a section.
Two docgen harnesses need the same pieces: parse and validate flags, take a
memory sample, run a series of simulated saves, summarize it, truncate a
child's output for an error message. This adds them once, under
scripts/bench/docgen-shared/, so the memory harness and the perf harness that
follows do not each keep their own copy.

Flags go through node:util parseArgs in strict mode and then a Zod schema, so
a typo is rejected instead of falling back to a default. That was a real hole:
--component 5, with the s missing, used to be ignored.

EngineId lists only the engine that exists today. Each later engine adds its
own id when it lands.
- parseHarnessOptions now returns z.infer<Schema> instead of casting onto a
  caller-supplied type parameter. The memory harness's hand-written option
  interface was a duplicate of its schema that nothing checked, so it is gone.
- Drop the harness's own --max-retained-growth self-gate. Nothing passed it, its
  400MB default disagreed with the 60MB budget gate.ts actually asserts, and it
  gave a memory threshold the power to fail an unrelated run.
- Time the cold pass and each save with performance.now(). A warm re-extraction
  of one component takes single-digit milliseconds, and at Date.now()'s 1ms
  granularity a series can median to 0, which every ratio then divides by.
- Report a retained slope only from two or more samples. leastSquaresSlope
  answers 0 for a shorter series, which reads as a measured flat one.
- gate.ts resolves SANDBOX_DIRECTORY through docgen-shared/paths.ts, the same
  module the harness defaults from, rather than a second copy.
- Print "n/a" rather than 0 for an unreported warm member count.
The flag parsed as a nonnegative count and componentSource then clamped it with
Math.max(1, ...), so a run asked for at 0 silently measured something else. The
schema now takes a positive count and the clamp is gone.

Reported by CodeRabbit on #35631.
Named imports from node:path and node:fs, which is what the rest of scripts
uses - the namespace form appears nowhere else in the workspace.

Join the renderer module path instead of concatenating it into a URL. The
concatenation only worked while the directory ended in a separator and the
caller's argument did not begin with one.

Also record what actually stops paths.ts importing SANDBOX_DIRECTORY from
scripts/utils/constants.ts, since 'cannot import it' invites the question.
This is the base of the per-engine perf suite: the metric types, the fixed
measurement profiles, the aggregation that turns repetitions into medians, the
child-process spawn helper, and the BenchEngine base class every engine
implements.

It comes with the first engine, compodoc, which measures Angular. Compodoc
runs as a fresh CLI process, so cold extraction and whole-project scan are the
same measurement and peak memory is sampled from outside the child.

The engine also reads the documentation.json compodoc writes, and reports two
counts: how many members it documented, and how many of those carry a type it
never resolved. The second count matters because compodoc never expands a
named type. Chain a type through twenty files and it documents every member at
the same speed, having looked through none of them, so a member count alone
would read as identical to an engine that expanded all of them.

@compodoc/compodoc is pinned at exactly 2.0.0, the version the Angular docgen
baselines capture against. Its cost moves between versions.

The profile and the engine id list carry Angular only. React and Vue arrive
with their engines in the next PR.

There is no CLI entry point yet. registry.ts, cli.ts and run.ts land in the
PR stacked on top, so this cannot be run end to end; the two test files cover
the aggregation and the documentation.json parsing.
Collapse coldMembers/warmMembers/coldOpaqueTypes into one members() hook
returning MemberCounts, and give BenchEngine an assemble() that turns a
scenario's repetitions into its ScenarioResult.

Both engines implemented the three count hooks as pass-through one-liners, and
the orchestrator had to call all three plus aggregate() and pick the designated
repetition itself - which meant naming a sample shape it cannot know, so the
generic parameter was erased and re-asserted with a cast. assemble() keeps
Sample bound inside the class, so the cast has nowhere to live, and picking the
designated repetition happens in one place instead of two. Sample is now
constrained to { coldMs: number }, which is what designatedRep has always
required and what the erased generic hid.

Pin N at 6 rather than 5. The two sides of a control pair alternate which runs
first by repetition parity, so an odd N hands one side the first slot once more
than the other, and the cold median then lands on a repetition from the majority
slot - turning the ordering effect the alternation exists to cancel into a
systematic bias on the headline ratio.

Report compodoc's peak RSS as n/a when nothing was sampled. `ps` is POSIX-only
and a run can finish inside one poll interval, and the initial 0 was reported as
a measured peak on either path. oneShotMetrics now requires every repetition to
carry a reading before it reports a mean.

Also: read the compodoc RSS poll interval from its constant rather than back out
of the params bag, and say in the "retained metrics missing" error that a series
shorter than two saves reaches it too.
The orchestrator settles on the child's close event, so a compodoc that hangs -
which it can, on some inputs - stalled the whole suite with no way out. The run
is now killed after ten minutes and reported as a timeout, so the engine fails
on its own rather than taking the suite with it.

Reported by CodeRabbit on #35636.
The generator was a sequence of writes, so the only way to see what compodoc is
pointed at was to run it and look at a directory. angularProjectFiles returns the
project as path -> contents instead, and generateAngularProject writes that map.
The bookkeeping of which paths are components stops being tracked separately from
the writes that create them.

The new test snapshots that map: the tree, the fake @angular/core that keeps it
hermetic, the tsconfig include that decides the measured set, and a component at
zero and four extra props. Generated output is byte-identical.
run.ts is the entry point behind the new yarn bench:docgen-perf. registry.ts is
the table of which engine measures what, with which flags; adding an engine
means adding one row, and the orchestrator has no per-engine branches. ratios.ts
divides each framework's legacy median by its new-engine median, both taken in
the same run. report.ts prints the table.

Only the Compodoc engine is registered here, so a run measures Angular. The
React and Vue engines land next, and the control pairs they belong to are
already listed: a pair whose two engines are not both registered yields no
ratio.

The suite prints documented-member counts next to every ratio and marks a pair
not like-for-like when the two sides disagree. A ratio between engines that did
different amounts of work measures resolution depth, not speed, and must not
become a budget.

No CI job runs this. Only bench:docgen-memory is wired into CI, and only on the
daily tier, so manual runs are how anyone finds out whether the suite still
works.
engineOrderForRep reverses the engine list on even repetitions instead of
swapping each control pair in place. Pairs can share an engine, and swapping
such a chain pairwise moves the shared engine twice, which leaves the first pair
in its original relative order - so a pair could alternate on paper and never in
the run. A reversal flips every pair at once, needs no knowledge of the pair
table, and cannot be defeated by adding a pair. The test now asserts that
property rather than one expected permutation, driven off CONTROL_PAIRS so it
keeps covering new pairs as they are added.

medianRatio returns undefined for a non-finite ratio. A warm re-extraction can
finish below the clock's resolution, and dividing by that median yielded
Infinity, which rendered as a ratio and serialized into the results file as null.

run.ts hands each scenario's repetitions to engine.assemble(), so it no longer
names a sample shape it cannot know: the unknown[] store, the cast onto it, and
the second designated-repetition pick are gone.

renderResults formats the retained slope through formatCell like every other
cell, instead of hand-rolling the one column formatCell could not express.
report.test.ts checked the renderer with toContain on individual lines, which
could not see the thing the module exists to produce: an aligned table, and the
notes that travel beside a ratio. The cases are now inline snapshots of the
joined output, so a diff shows the report as a reader would see it.

The fixtures grew to match: a series engine and a one-shot engine side by side,
plus a skip and a failure, because the column widths are computed across the
whole table and a status line replaces a row rather than joining one. Adds the
two comparability verdicts nothing rendered before, next-documents-less and
next-resolves-less.

Writing the output down also showed that every row carried trailing spaces,
since the last column is padded like the rest. Rows are trimmed now.
process.exit truncates a piped stderr, which is the one case where the
per-engine failure reasons are actually being read. Match the pattern the
top-level catch handler already uses.

Also stop the intro promising a CI tier that gates, since the same document
says a few sections later that the gate does not exist yet.
Windows unit tests failed when recast.print emitted CRLF while the
assertion expected LF. The expected/received strings looked identical in
the log. Normalize printed code to LF in the shared test helpers.

Co-authored-by: Cursor <cursoragent@cursor.com>
@storybook-bot
storybook-bot force-pushed the version-non-patch-from-10.6.0-alpha.4 branch from 5f24b83 to 4f3b7fc Compare August 7, 2026 13:07
Tanstack: Wait for router to load before rendering
@storybook-bot
storybook-bot force-pushed the version-non-patch-from-10.6.0-alpha.4 branch from 4f3b7fc to 82d4a8d Compare August 7, 2026 13:39
…rovider-skeleton

Vue: Add story-docs provider skeleton
@storybook-bot
storybook-bot force-pushed the version-non-patch-from-10.6.0-alpha.4 branch from 82d4a8d to f724d93 Compare August 7, 2026 13:48
…s-crlf

Build: Normalize CRLF in story-shape print assertions
@storybook-bot
storybook-bot force-pushed the version-non-patch-from-10.6.0-alpha.4 branch from f724d93 to 259d0fc Compare August 7, 2026 14:00
…nning-compodoc-on-demand

Angular-Vite: Run Compodoc on demand
@storybook-bot
storybook-bot force-pushed the version-non-patch-from-10.6.0-alpha.4 branch from 259d0fc to 11c4621 Compare August 7, 2026 14:17
valentinpalkovic and others added 2 commits August 7, 2026 18:44
React's snippet generator grew several helpers that are not React-specific:
resolving a `render` identifier to the function it names, telling an absent
`render` apart from an unreadable one, and reading CSF2's `Story.args = {}`
assignment form. The Angular and Vue providers need the same answers.

They move into `csf-tools/story-shape` and React imports them back, so its
snapshots are what proves the move is behaviour-preserving. `propertyValue`
and `returnedObjectExpression` join them for the providers stacked on top.
…hape-helpers

Core: Share the CSF story-shape helpers snippet generators need
@storybook-bot
storybook-bot force-pushed the version-non-patch-from-10.6.0-alpha.4 branch from 11c4621 to 89e832b Compare August 8, 2026 18:33
valentinpalkovic and others added 8 commits August 9, 2026 09:50
The single bullet under Code Authoring Principles said comments should
explain why rather than narrate an investigation, which left most of the
decisions open. It did not say when a comment is warranted at all, it said
nothing about JSDoc, and agents kept producing `@param`/`@returns` that
restate the TypeScript signature, ASCII section banners, and change
narration that git history already carries.

Replaces the bullet with a section stating the two cases that justify a
comment, the shape of public-API JSDoc, and an explicit list of what never
to write.
AGENTS.md is read in full on every session, so a 40-line rule that only
matters when you are about to write a comment belongs one hop away. The
section keeps the two-sentence summary and links out; the detail moves to
`.agents/guidelines/comments-and-jsdoc.md`, next to the skills already
living under `.agents/`.
Measured against the Angular docgen stack after a cleanup pass that applied
the previous wording: one comment per seven lines of source, 224 JSDoc
blocks, six of them on private members, and eighteen where the docblock was
longer than the code it described (worst: eleven lines of prose on a
one-line body).

Every rule in the previous version was a judgement the author makes about
their own writing, and "internal, non-exported helpers get no JSDoc" does not
read as covering a private method on an exported class. Replaces them with
four rules that can be applied without deciding whether the sentence is any
good: JSDoc only for what a consumer can import, a comment never longer than
its code, nothing on private members, and no JSDoc in tests. Reframes the
"why" escape hatch as a deletion test whose output is one sentence.
The blanket ban went too far. A private method implementing a subtle
algorithm, or holding a non-obvious invariant, is worth a docblock, and
banning those outright trades one failure mode for another.

Keeps the pressure without the ban: the deletion test still applies, and so
does the rule that a comment may not outgrow its code. What changes is that
"rename or split it instead" becomes the usual better answer rather than the
only permitted one.
Co-authored-by: Valentin Palkovic <dev@valentinpalkovic.dev>
…-guidance

Build: Give AGENTS.md a real comments and JSDoc rule
@storybook-bot
storybook-bot force-pushed the version-non-patch-from-10.6.0-alpha.4 branch from 89e832b to 3049590 Compare August 10, 2026 07:34
@ndelangen ndelangen added ci:daily Run the CI jobs that normally run in the daily job. freeze Freeze the Release PR with this label labels Aug 10, 2026
@ndelangen
ndelangen merged commit d5512cc into next-release Aug 10, 2026
290 of 297 checks passed
@ndelangen
ndelangen deleted the version-non-patch-from-10.6.0-alpha.4 branch August 10, 2026 09:00
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Core Team Projects Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:daily Run the CI jobs that normally run in the daily job. freeze Freeze the Release PR with this label release For PRs that trigger new releases. Automated

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

7 participants