Repository navigation
fix(core): the console runs a stored action that leaves type to its default as a script action - #26964
Merged
Conversation
…he spec's default script route `ActionSchema.type` defaults to `script`, but the console runs a stored row unparsed, so a typeless action resolved its route to its own name, matched no executor and was refused as "not executable". The runner now reads a missing `type` as the spec's default at the one place it picks the dispatch route. An unknown `type`, an empty schema, a handler registered under the action's name and the runner's own legacy keys keep their behaviour. Claude-Session: https://claude.ai/code/session_01QsR2jUfE6TDKDHQvod289V Co-authored-by: Claude <noreply@anthropic.com>
Contributor
Author
席位核对ACCEPT · seat
Landing: no contract review is owed (no published schema, no governed text, no exported type, |
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.
Requested by Steedos · project thread
Fixes #26879
Clause-②: no
Metadata-protocol: none
维护者速读
@object-ui/core的ActionRunner)在选派发路由的唯一一处,把「没写type」的已存动作读成 spec 的默认值script,于是它走已注册的script派发,打平台动作路由POST /api/v1/actions/{object}/{action}。ActionSchema.type默认是script,但控制台跑的是存储里的原样行、不是解析后的行。Studio「新建」骨架和旧版 Studio 存下的无type动作,路由被解析成动作自己的名字,匹配不到执行器,被报「not executable」,点了没反应。type、无actionType、有名字、名下没注册处理器、也没写运行器自有键(navigate/api/endpoint/onClick/redirect/显式 reload、close)」的动作:原来必然被拒,现在走 script。未知type、空动作仍拒绝;按名注册的处理器仍优先。回滚即还原resolveDispatchType一个函数。ui/packages/core/src/actions/ActionRunner.ts的resolveDispatchType与declaresRunnerBehavior(新增)以及execute里改用它的那一行;ActionRunner.specDefaultType-26879.test.ts(8 个用例)。pnpm --dir ui exec vitest run packages/core/src/actions/__tests__/ActionRunner.specDefaultType-26879.test.ts,预期 8 个测试全绿。What changes
executeused to resolve the dispatch key astype || actionType || name. It now callsresolveDispatchType, which keeps the first three legs (an authoredtype, theaction:*block'sactionType, thenamewhen a handler is registered under it or the action carries a runner-own key) and, for a named action that has none of those, answersActionSchema.type's default,script. Nothing unnamed takes the default, so{}still lands inexecuteActionSchemaand is refused.refusalBeforeInput(the dispatch's early refusal, so a typeless script action meets the script dispatch's row guard) and bydispatchCollected.declaresRunnerBehaviornames the runner-own keys once;executeActionSchema's guard now reads it instead of its own copy (same keys:navigatenever reaches that guard becausedispatchCollectedruns it first).scriptat route selection, or the serve path returning the parsed row. The runner is in this lane's file surface and covers every unparsed source at once (stored rows from any Studio build or by hand), with no server change. No writer addstype, and no stored row is rewritten.@object-ui/core's exports are unchanged: both helpers and the constant are module-private.@object-ui/corepatch.Tests
New
ui/packages/core/src/actions/__tests__/ActionRunner.specDefaultType-26879.test.ts, 8 cases:{ name, body }and a typeless{ name, operation: 'update', patch }both POST/api/v1/actions/tasks/NAMEthrough the realcreateServerActionHandler.scriptdispatch'srefuseBeforeInput.@objectstack/spec'sActionSchema, and with a spy handler under every runnable type the typeless action reaches exactly the handler named by the parsedtype. If the spec's default ever moves, this case goes red.typeis refused,{}is refused as "not executable", a handler registered under the action's name runs ahead ofscript, and a typeless namedredirectaction still redirects.The typeless update shape already reached the route through the
operationcheck that runs ahead oftype(pinned inActionRunner.updateOperation.test.ts); it is pinned again here at the new resolution.Acceptance notes
typeand an empty schema are still refused (cases above).ObjectActionsPanel.tsxstill leavestypeoff, as its comment intends; with this change that row runs. Its pinned Type control reading "—" until the first write is untouched (outside this claim's file surface).Verification
All at head
e7e7e357, a worktree offorigin/main8074feb6(main has moved 27 commits since, none inui/packages/core/;git merge-treeagainst it is clean).Tests, ablation and type-check
pnpm --dir ui exec vitest run packages/core/src/actions/underscripts/pm/os-verify-lock.sh:Test Files 45 passed (45),Tests 660 passed (660); the new file alone, verbose: 8/8.ActionRunner,ActionProvider,useActionRunneroruseConsoleActionRuntimeoutsidepackages/core/src/actions/(383 files: app-shell, plugin-grid, components, react, plugin-detail, plugin-view, console and others),--maxWorkers=2in four locked batches: 47 + 45 + 145 + 146 files passed, 630 + 452 + 1656 + 1310 tests passed, 0 failed.scripts/ablation-replace.mjson the committed head:return SPEC_DEFAULT_ACTION_TYPE;replaced byreturn name;(anchor 1 -> 0, blobecfc5fa6->9f29d4cd). The new file went3 failed | 5 passed (8): the typeless body action, the early-refusal case and the spec-default case. The typeless update case stays green, as expected:operationis read ahead oftype. Restored: blob back toecfc5fa6= HEAD,git diff HEADempty.pnpm exec turbo run type-check --filter=@object-ui/core --concurrency=2under the lock:VERDICT command-exit 0, 4/4 tasks, core'stype-checka cache miss (it runstsconfig.test.jsontoo, so the new test file is compiled).Derived dispatch gates (34/34)
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 34 commands; every one exited 0, the PR-body gates (check-closing-keyword-parity,check-adr-0087-registration,check-changeset-no-major) against this body.pnpm --dir ui exec vitest run scripts/under the lock:Test Files 178 passed | 2 skipped (180),Tests 5065 passed | 2 skipped (5067).pnpm check:type-check-debtunder the lock:0 raw tsc error(s) total, none above its recorded number.dispatch-gates --ran:34 derived famil(ies) accounted for — 34 run, 0 NOT-MEASURED.pnpm check:new-line-citations(fromui/):0 new citation(s). Control-byte self-scan of the three files: no hit.No dogfood battery: no
!in the title and no(narrowing)arm.Generated by Claude Code