You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(spec,cli): warn the author when a discarded action alias costs them a handler (#3743) (#3838)
#3742 made `target` beat the deprecated `execute` alias everywhere and had the
`ActionSchema` transform DROP the alias from its output, so "two different
scripts for one button" became unrepresentable. What it left behind: an author
who declares both slots with different values still loses one of the two
handlers they wrote, silently. Per Prime Directive #12 that belongs at
authoring time.
New advisory rule `action-target-execute-conflict`: an action declaring both
slots with different values gets a warning naming both handlers, stating that
`target` wins, and giving the one-line fix. Equal values are harmless
duplication and stay quiet. It never fails the build.
The rule has to run PRE-PARSE, because the parse is what consumes the alias.
#3743 proposed the CLI compile pipeline as its home; that window is real but
nearly always empty, because `defineStack` parses inside the author's own
config module — for a `defineStack` app the alias is gone before `os build`
ever loads the module. So the rule lives in `@objectstack/spec`
(`lintDeprecatedAliases`) and is wired into both layers that perform the
discard: `defineStack` warns before parsing (once per distinct conflict), and
`os build`/`os validate` run a pre-parse pass for stacks that skip strict
`defineStack` (plain object export, `strict: false`, inline function handlers).
Each layer reports only its own discards, so one conflict yields one warning.
Behaviour fix in the same contract: #3742 probed for a CALLABLE `target` first,
which left a string `target` beside a function `execute` still resolving the
alias's way — it bound the alias and overwrote the canonical ref the author
wrote. `target` now wins in every string/function combination, matching the
`ActionSchema` transform.
Also documents the rule in the objectui actions reference, which already stated
the precedence while saying nothing about the author finding out.
Copy file name to clipboardExpand all lines: content/docs/protocol/objectui/actions.mdx
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -53,6 +53,8 @@ The `type` field selects how an action is dispatched. The complete enum is **`sc
53
53
54
54
`target`is the canonical binding for every non-`script` type. The deprecated `execute` field is lowered into `target` during parsing and then **removed from the parsed metadata**, so every consumer — server dispatch and renderer alike — reads exactly one slot. If an action declares both, `target` wins and `execute` is discarded.
55
55
56
+
Declaring both with *different* values means one of the two handlers you wrote never runs, so it raises an advisory `action-target-execute-conflict` warning naming both — from `defineStack` when it parses your config, and from `os build` / `os validate` for stacks that skip strict `defineStack`. It never fails the build; the fix is to delete `execute`. The same value in both slots is harmless duplication and stays quiet.
57
+
56
58
### Script Actions
57
59
58
60
Run logic with no server round trip via `body` (an L1 CEL expression or L2 sandboxed JS). `body` is only meaningful when `type` is `script`, and declaring one on any other type is a parse-time error — those types dispatch on `target`, so the body would never be invoked.
0 commit comments