autoPropsDisabled is accepted by Svelte and vanilla stories and does nothing. #459 made the reference pages say so; nothing tells the person who already wrote the prop and is looking at an empty controls panel.
A warning is the right answer. I built one in an earlier revision of #459 and removed it, because a max-effort review found it broken in five separate ways. This issue exists so the second attempt starts from what that cost, rather than rediscovering it.
Build it at the app layer, not per plugin
The first version lived in packages/poveste-plugin-svelte/src/client/MountVariant.svelte. That was the wrong altitude, and it is why most of the defects below exist.
packages/poveste-app/src/app/util/mapping.ts:9 already copies autoPropsDisabled for every framework, and mapFile receives file.supportPluginId — the app switches on it at GenericRenderStory.vue:19, StorySourceCode.vue:21 and util/docs.ts:16. One check there — prop set, plugin is not Vue — covers Svelte, vanilla, and the React and Solid plugins in #371 and #61 without any of them writing a line.
What the leaf-component version got wrong
It never fired for the shape the docs document. MountStory.svelte:20 forwards $$restProps only in the variants.length === 1 && variants[0].id === '_default' branch; the {:else} renders a bare <slot /> and drops story-level props. So <Hst.Story autoPropsDisabled> over explicit <Hst.Variant> children — the shape most conformance stories use — warned nowhere. Verified in a browser against a built preview: console empty.
A config default would have warned on stories nobody wrote the prop on. autoPropsDisabled is not in omitInheritStoryProps, and poveste/src/node/collect/index.ts:138 merges defaultStoryProps onto the story object with ??=. A mixed Vue+Svelte book setting defaultStoryProps: { autoPropsDisabled: true } for its Vue stories would get the warning on every Svelte story, blaming the author for a line in poveste.config.ts that the warning's own advice cannot address. Any implementation has to distinguish an explicitly-written prop from a config-inherited one, or say which it is.
Dedupe is harder than it looks. A plain {} keyed by variant.id is wrong twice: prototype names (constructor, toString, __proto__) read truthy on the first check and suppress the warning forever, and variant.id is only story-scoped, so two stories reusing id="default" — which docs/reference/svelte/variant.md recommends — may collide. RenderStory.svelte:35 and RenderVariant.svelte:32 already solve this with a flag on the variant object (__pvtStateWarned); prefer that idiom over inventing a third.
The realms are not what they look like. mount.ts:75 always sets __pvtTargetVariantId to a store, so the ?? null in MountVariant.svelte never yields null — gating on "the app realm" suppresses the warning entirely. The duplicate line people see is the app realm plus one sandbox, not two sandboxes; in grid layout it is 2N. Whatever emits the warning has to decide deliberately how many realms speak.
It shipped with no test. Deleting the warning left lint, test, test:scripts and the whole Playwright suite green. examples/svelte5/playwright/state-sync.spec.ts:62 already does page.on('console', …) filtered on [poveste] for the sibling initState diagnostic and is the model to copy — note it matches console.error while this one is a console.warn.
The empty controls panel
StoryControls.vue:75 renders "No controls available for this story" for every framework. #459 tried adding "Add a controls slot, or return state from initState" and reverted it: vanilla has neither name — its API is onMountControls and a MountApi.state mutated in onMount — and for Vue the named pair is the documented secondary path while auto-props, the primary one, goes unmentioned. The panel has supportPluginId in scope, so per-framework advice is available; it is a small piece of the same job and belongs with it.
A guard, if one is worth building
#459 also carried scripts/check-auto-props.ts, asserting that the set of files writing _hPropDefs matched what the docs claim. It was removed. Two reasons it did not work, both worth avoiding:
Its regex only recognised the object-literal key form — state._hPropDefs = defs, bracket assignment and shorthand all slipped through, while a plain type declaration { _hPropDefs: PropDefinition[] } was a false positive. It failed open on the exact event it existed to catch.
And its failure message said "add the file to PRODUCERS", with nothing checking the docs half it also demanded. The documented remedy turned the check off.
If drift between the pages and the code is worth guarding, the repo already has a better-shaped mechanism: e2e/stories.ts SHARED_STORIES and e2e/controls.spec.ts drive the same conformance story across all four books. A story whose component has real props, asserting the Svelte book shows the empty controls state, fires on any second implementation regardless of how it is written, and survives renames and rewordings.
Not this issue
Real Svelte controls — Poveste owning the mounting so it owns the props — is #233, which stays open.
Related: #233, #371, #61, #459.
autoPropsDisabledis accepted by Svelte and vanilla stories and does nothing. #459 made the reference pages say so; nothing tells the person who already wrote the prop and is looking at an empty controls panel.A warning is the right answer. I built one in an earlier revision of #459 and removed it, because a max-effort review found it broken in five separate ways. This issue exists so the second attempt starts from what that cost, rather than rediscovering it.
Build it at the app layer, not per plugin
The first version lived in
packages/poveste-plugin-svelte/src/client/MountVariant.svelte. That was the wrong altitude, and it is why most of the defects below exist.packages/poveste-app/src/app/util/mapping.ts:9already copiesautoPropsDisabledfor every framework, andmapFilereceivesfile.supportPluginId— the app switches on it atGenericRenderStory.vue:19,StorySourceCode.vue:21andutil/docs.ts:16. One check there — prop set, plugin is not Vue — covers Svelte, vanilla, and the React and Solid plugins in #371 and #61 without any of them writing a line.What the leaf-component version got wrong
It never fired for the shape the docs document.
MountStory.svelte:20forwards$$restPropsonly in thevariants.length === 1 && variants[0].id === '_default'branch; the{:else}renders a bare<slot />and drops story-level props. So<Hst.Story autoPropsDisabled>over explicit<Hst.Variant>children — the shape most conformance stories use — warned nowhere. Verified in a browser against a built preview: console empty.A config default would have warned on stories nobody wrote the prop on.
autoPropsDisabledis not inomitInheritStoryProps, andpoveste/src/node/collect/index.ts:138mergesdefaultStoryPropsonto the story object with??=. A mixed Vue+Svelte book settingdefaultStoryProps: { autoPropsDisabled: true }for its Vue stories would get the warning on every Svelte story, blaming the author for a line inpoveste.config.tsthat the warning's own advice cannot address. Any implementation has to distinguish an explicitly-written prop from a config-inherited one, or say which it is.Dedupe is harder than it looks. A plain
{}keyed byvariant.idis wrong twice: prototype names (constructor,toString,__proto__) read truthy on the first check and suppress the warning forever, andvariant.idis only story-scoped, so two stories reusingid="default"— whichdocs/reference/svelte/variant.mdrecommends — may collide.RenderStory.svelte:35andRenderVariant.svelte:32already solve this with a flag on the variant object (__pvtStateWarned); prefer that idiom over inventing a third.The realms are not what they look like.
mount.ts:75always sets__pvtTargetVariantIdto a store, so the?? nullinMountVariant.sveltenever yields null — gating on "the app realm" suppresses the warning entirely. The duplicate line people see is the app realm plus one sandbox, not two sandboxes; in grid layout it is 2N. Whatever emits the warning has to decide deliberately how many realms speak.It shipped with no test. Deleting the warning left
lint,test,test:scriptsand the whole Playwright suite green.examples/svelte5/playwright/state-sync.spec.ts:62already doespage.on('console', …)filtered on[poveste]for the siblinginitStatediagnostic and is the model to copy — note it matchesconsole.errorwhile this one is aconsole.warn.The empty controls panel
StoryControls.vue:75renders "No controls available for this story" for every framework. #459 tried adding "Add acontrolsslot, or return state frominitState" and reverted it: vanilla has neither name — its API isonMountControlsand aMountApi.statemutated inonMount— and for Vue the named pair is the documented secondary path while auto-props, the primary one, goes unmentioned. The panel hassupportPluginIdin scope, so per-framework advice is available; it is a small piece of the same job and belongs with it.A guard, if one is worth building
#459 also carried
scripts/check-auto-props.ts, asserting that the set of files writing_hPropDefsmatched what the docs claim. It was removed. Two reasons it did not work, both worth avoiding:Its regex only recognised the object-literal key form —
state._hPropDefs = defs, bracket assignment and shorthand all slipped through, while a plain type declaration{ _hPropDefs: PropDefinition[] }was a false positive. It failed open on the exact event it existed to catch.And its failure message said "add the file to PRODUCERS", with nothing checking the docs half it also demanded. The documented remedy turned the check off.
If drift between the pages and the code is worth guarding, the repo already has a better-shaped mechanism:
e2e/stories.tsSHARED_STORIESande2e/controls.spec.tsdrive the same conformance story across all four books. A story whose component has real props, asserting the Svelte book shows the empty controls state, fires on any second implementation regardless of how it is written, and survives renames and rewordings.Not this issue
Real Svelte controls — Poveste owning the mounting so it owns the props — is #233, which stays open.
Related: #233, #371, #61, #459.