Repository navigation
feat(core): show a holeless confirmText / successMessage as written (objectui#13476) - #13482
Conversation
…objectui#13476)
Drop the transitional `${…}` reading objectui#13367 kept for a sentence with
no `{{ }}` hole: `confirmMessage` no longer evaluates it and
`composeSuccessMessage` no longer runs `substituteScopeTokens` over it. A
`${…}` token in either text is now plain text. `outcomeMessages` keeps its
`${result.*}` reading; `errorMessage` is unchanged.
Claude-Session: https://claude.ai/code/session_01P5j5dvWsBeNZNp2qLwwRqH
Co-authored-by: Claude <noreply@anthropic.com>
…ctui#13476)
The app-shell, plugin-grid and react tests that drove `confirmText` /
`successMessage` through the runner with a `${…}` token now author the
`{{ }}` hole the runner reads. The `hasTemplateHoles` docblock and the
enhanced-actions guide stop describing the retired reading.
Claude-Session: https://claude.ai/code/session_01P5j5dvWsBeNZNp2qLwwRqH
Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
席位核对 — ACCEPT (TIER_DEFAULT part) · PR #13482 @
|
Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Requested by Elon · project thread
Fixes #13476
Clause-②: no
Metadata-protocol: narrowed
Summary
objectui#13367 kept one transitional reading in
ActionRunner: aconfirmTextorsuccessMessagesentence with no{{ }}hole still had its${…}tokens filled. This PR removes both branches, so a holeless sentence is shown exactly as written, the same as any other copy with no hole. It is the objectui half of objectstack-ai/objectstack#25702; objectstack-ai/objectstack#25709 (warning to error, deleteACTION_COPY_DOLLAR_TRANSITION_ROOTS) waits for objectstack's.objectui-shato carry this merge.Changes
confirmMessage: the!hasTemplateHoles(text)branch returnstextinstead oftemplates.evaluate(text). The method no longer takes the evaluator; the param dialog'sinterpolate(still the${…}evaluator, out of scope) now builds it right where it is used.composeSuccessMessage: a holelesssuccessMessagereturnssuccessCopyinstead of runningsubstituteScopeTokens.ActionDef.confirmText,ActionDef.successMessage, theRUNNER_TEXTnote,composeSuccessMessage,confirmMessage,templateEvaluatorFor,interpolateTarget's note andsubstituteScopeTokens(the grammar's one toast caller is nowoutcomeMessages), plushasTemplateHolesinactionCopyTemplate.ts.content/docs/core/enhanced-actions.mdx"Post-success behaviour" now saysoutcomeMessagesreads${result.*}andsuccessMessagereads{{ result.* }}/{{ record.* }}; the complex-action example'sconfirmTextuses a{{ record.customer_name }}hole..changeset/13476-holeless-action-copy.md:@object-ui/coreminor (a narrowing; objectui marks breaking changesminor).Untouched, per the card:
outcomeMessageskeeps its${result.*}reading throughsubstituteScopeTokens;errorMessageis still shown as written.The claim's file surface was amended by the seat (card comment 6391456644) for
actionCopyTemplate.ts, the docs page, and the app-shell test. Two more test files outside it also drove the old reading end to end and are converted here:packages/plugin-grid/src/__tests__/rowActionRecordHole-12967.test.tsxandpackages/app-shell/src/views/ObjectView.toolbarScriptSelection-12331.test.tsx, pluspackages/react/src/hooks/__tests__/useActionTextLocalizer.outcomeMessages-11344.test.tsx.Tests
Every fixture that fed the runner a holeless
${…}confirmText/successMessagenow authors the{{ }}hole the runner reads, and three rows pin the new behaviour:ActionRunner.copyTemplate-13367: "a${…}token in a sentence with no hole is text, not an expression" (header door and row door), and "a${result.*}token in a sentence with no hole is text, not filled".ActionRunner.outcomeMessages-11344: "rung 2 — a${result.*}token in a successMessage with no hole is text". The "reads theresultscope only" row moves to anoutcomeMessagesentry, the one toast rung that still uses the${…}grammar.ActionRunner.rowRecordTemplates-12967: the row-less control now readsPause ?(an unbound{{ record.* }}root prints empty) where the evaluator left${record.display_name}raw.Runs, at head
55dfcfd, from the repo root:pnpm exec vitest run packages/core/src/actions/: 41 files, 625 tests passed.onSuccess.navigatehosts, param-dialog record holes,consoleServerAction, componentsrenderers/action/, element-button i18n copy, plugin-grid row-action record hole, console registry parity, reacthooks/, app-shellhooks/__tests__/, record-alert, ListView). The first sweep (44 files, 968 tests) failed 3 rows inrowActionRecordHole-12967andtoolbarScriptSelection-12331, which still authored${…}; after converting them, those 2 files pass (11 tests). The second sweep: 120 files, 1233 tests passed.pnpm --filter @object-ui/core type-check: exit 0, after building the core dependency closure.Ablation (commit first, then mutate, trap-restored): with
ActionRunner.tsreverted toorigin/main, the three new rows fail (Tests 3 failed | 45 passed (48)); restored,git diff HEADis empty and the blob hash matches HEAD.Gates (local subset)
check:new-line-citations,check:control-bytes,check:doc-fences,check:doc-types,check:changeset-claims,check:pending-changeset-literals,check:action-forward-parity: exit 0.node scripts/check-changeset-presence.mjs: passes, 1 changeset declared.check:doc-snippetsandcheck:doc-examples(exit 2, precondition: the doc-snippet build closure is not built here). CI runs both; the docs edit changes one string literal inside a typed snippet.pnpm testandpnpm lintare CI's.Acceptance notes
No in-tree producer authors the holeless
${…}shape: no non-testconfirmText/successMessagein this repo carries${, and objectstack's measurement (card) found none in examples,platform-objects,plugin-approvalsor HotCRM.Fixtures left as
${…}on purpose:element-button-i18nCopy-12757andaction-outcomeMessages-forward-11344(components) only pin that copy reaches the runner unchanged, or never reach rung 2; the react localizer'soutcomeMessagesfixtures are rung 1, which keeps${result.*}.ActionParamDialog.tsx'sinterpolatedocblock still says it fills${...}"in the template scope the runner readsconfirmTextin". The record binding is still shared; the dialect differs now. Carrier: none, noted only.Adds no product-specific widget, dialog, hook or string (see AGENTS.md › Product-neutral renderer)
Generated by Claude Code