Measured while implementing #4162 (making action:menu consume autoTrigger). Filed separately: it is a property of the FLAG's relationship to the visibility gate, not of the overflow split #4162 fixes, and it predates that card in action:button.
Fact
action:button declares its auto-trigger effect before its visible early return:
useAutoTriggerOnce(hasAutoTrigger(schema), handleClick); // effect
...
if (hasDeclaredVisibilityGate(schema.visible) && !isVisible) return null;
React commits effects for a component that returns null, so an action carrying both autoTrigger: true and a declared-false visible renders nothing and executes anyway. Measured on origin/main at e16fd9597, real action:button plus the real runner:
PROBE-VISIBLE-FALSE: rendered="" execute=1
Empty DOM, one execution. #4162 extends the same semantics to action:menu deliberately — its whole point is that inline and overflow must not disagree about a flag, and disagreeing here would have re-created the divergence one predicate over. So the two renderers now agree, and this card is about whether what they agree ON is right. The parity itself is pinned in packages/components/src/renderers/action/__tests__/action-overflow-autotrigger.test.tsx ("the ACTION's own declared visible gate does not suppress it"), which points here.
Note the neighbouring rule is different and is not in question: a container that renders nothing mounts no children, so a hidden action:bar or action:menu auto-triggers nothing. That one is pinned too.
Why it may matter
autoTrigger is never persisted metadata — hosts compose it client-side onto an action they already hold, so today's producers set it on an action they have just decided to run. Reaching this needs a host that composes the flag onto an action whose metadata ALSO declares a false visible, which no host in this repo does; that is why this is filed as observation-class rather than as a defect with a user behind it.
The reason it is worth a decision rather than a shrug is that the two gates answer different questions and only one of them is about the user's intent:
visible is the metadata author's verdict on whether this action may be OFFERED here (fails closed on a throwing predicate, per ActionEngine.getActionsForLocation);
autoTrigger is the host's statement that the user has already asked for it.
Reading the second as outranking the first means a deep link can invoke an action the author declared unofferable in this context — the runner's own confirm / param / entitlement gates still apply, so this is not an authorization hole, but it is a gate being bypassed by a transport flag. Reading it the other way costs the host a silent no-op, which is the failure mode #4123 and #4162 were both about, so "just gate it" is not obviously right either — a third answer (refuse loudly when both are declared) may fit the repo's contract-first instinct better.
Not fixed here: changing it means changing action:button's behaviour for every existing consumer of #844's flag, which is a design call, not a patch.
Related
Generated by Claude Code
Measured while implementing #4162 (making
action:menuconsumeautoTrigger). Filed separately: it is a property of the FLAG's relationship to the visibility gate, not of the overflow split #4162 fixes, and it predates that card inaction:button.Fact
action:buttondeclares its auto-trigger effect before itsvisibleearly return:React commits effects for a component that returns
null, so an action carrying bothautoTrigger: trueand a declared-falsevisiblerenders nothing and executes anyway. Measured onorigin/mainate16fd9597, realaction:buttonplus the real runner:Empty DOM, one execution. #4162 extends the same semantics to
action:menudeliberately — its whole point is that inline and overflow must not disagree about a flag, and disagreeing here would have re-created the divergence one predicate over. So the two renderers now agree, and this card is about whether what they agree ON is right. The parity itself is pinned inpackages/components/src/renderers/action/__tests__/action-overflow-autotrigger.test.tsx("the ACTION's own declared visible gate does not suppress it"), which points here.Note the neighbouring rule is different and is not in question: a container that renders nothing mounts no children, so a hidden
action:baroraction:menuauto-triggers nothing. That one is pinned too.Why it may matter
autoTriggeris never persisted metadata — hosts compose it client-side onto an action they already hold, so today's producers set it on an action they have just decided to run. Reaching this needs a host that composes the flag onto an action whose metadata ALSO declares a falsevisible, which no host in this repo does; that is why this is filed as observation-class rather than as a defect with a user behind it.The reason it is worth a decision rather than a shrug is that the two gates answer different questions and only one of them is about the user's intent:
visibleis the metadata author's verdict on whether this action may be OFFERED here (fails closed on a throwing predicate, perActionEngine.getActionsForLocation);autoTriggeris the host's statement that the user has already asked for it.Reading the second as outranking the first means a deep link can invoke an action the author declared unofferable in this context — the runner's own confirm / param / entitlement gates still apply, so this is not an authorization hole, but it is a gate being bypassed by a transport flag. Reading it the other way costs the host a silent no-op, which is the failure mode #4123 and #4162 were both about, so "just gate it" is not obviously right either — a third answer (refuse loudly when both are declared) may fit the repo's contract-first instinct better.
Not fixed here: changing it means changing
action:button's behaviour for every existing consumer of #844's flag, which is a design call, not a patch.Related
packages/components/src/renderers/action/action-button.tsx,action-menu.tsx, and the shared guardauto-trigger.tsautoTriggeraction that spills past action:bar's maxVisible lands in action:menu, which never runs it — deep link consumed, nothing triggered #4162autoTrigger/ visible gate /action:menu) — no duplicate. Unassigned.Generated by Claude Code