feat(core,react,components,i18n,types): actions honour the spec's outcomeMessages; core and types floor at @objectstack/spec ^17.6.0; the row-5 booking is struck (objectui#11344) - #11552
Conversation
…i#11438) Regenerated with pnpm 10.31.0 only, by the raise-and-restore route the 17.5.0 bump used: every @objectstack/* specifier raised to ^17.6.0 for one `pnpm install`, every manifest restored byte-for-byte to HEAD, then a second `pnpm install` reconciles the importers to their declared ranges. Resolution census against the base lock: the seven @objectstack/* packages (spec, types, core, client, formula, lint, sdui-parser) move 17.5.0 -> 17.6.0 and nothing else moves. No importer specifier changes. The registry's new `deprecated` field on twelve @yuku-analyzer/binding-* 0.8.7 entries is written into the lock by the same tooling. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…, a component under a name @objectstack/spec 17.6.0 now exports (objectui#11438) @objectstack/spec 17.6.0 exports `EmptyState` from `@objectstack/spec/ui`: the authoring type of a list view's empty-state config (title, message, icon). @object-ui/components publishes `EmptyState` as an alias of the `DataEmptyState` React component. A component is not a config shape, so neither import nor derivation fits; the alias is a published name, so its retirement or rename belongs to its own card. Same disposition objectui#11073 gave the four `Object*Props` collisions 17.5.0 surfaced. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…ing now that @objectstack/spec 17.6.0 carries the arm (objectui#11438) objectui#11206 widened `STRIPPED_LINE`'s key type by `| 'computed'` so it compiled against both a three-arm pin and objectstack `main`, and left a tripwire in `writeWarningToast.test.ts` for the bump that carries the arm. 17.6.0's `DroppedFieldsEventSchema.reason` lists `computed`, so this does what the tripwire says: the key type is the spec union again, the `computed` case is spelled as the literal, the spent tripwire is deleted, and spec-symbol-batch6's `_ReasonIsTheEnum` pins the exact four-member union. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…spec/migrations, where 17.6.0 moved it (objectui#11438) 17.6.0 carries the spec's migrations-entry-split: `MIGRATIONS_BY_MAJOR` is exported from `@objectstack/spec/migrations` and no longer from the root. The test read the root dynamically so it compiled against both the old pin and objectstack `main`, with no fallback, and its docblock asked the bump that moves the pin past the split to replace that with a static import from the subpath. This does that. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…jectstack/spec 17.6.0 refuses by name (objectui#11438) 17.6.0 carries objectstack#20758: `PageHeaderProps.breadcrumb` is a tombstone refused by name. objectui's renderer has not read it since objectui#11166, and its `inputs` entry said it stayed only while the spec accepted the key and would leave with the retirement. It leaves now, so the registry no longer publishes an input the contract refuses (`registry-inputs-spec-parity.test.ts`, "page:header declares no top-level input the spec does not accept"). The slotted-pages guide example drops `breadcrumb: true`, which the contract now refuses (its pin parses the example against the spec row), and the page-header doc and the renderer comment say the key is refused rather than "accepted until retired". Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…7.6.0 made stale (objectui#11438) objectui#11111 decision 3 = B booked `action:button.endpoint` and `action:icon.endpoint` as spec keys held unpublished, owed to objectui#11168. 17.6.0 refuses `endpoint` on both blocks (objectstack b3917d90, the rename to `target`), so neither entry names a key the spec declares, and the dangling-exemption check reds on them. Both are struck and the ledger cap falls from 3 to 1 (`undoable` stays, still owed to objectui#11168). Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
… group, which @objectstack/spec 17.6.0 adds (objectui#11438) 17.6.0's `GetTranslationsResponseSchema.translations` carries a `picklists` group (objectstack addbbf02, the `picklist` metadata kind). The recogniser's group list is written out, and the console's `loadLanguage.test.tsx` walks the spec's list so a group the spec adds turns it red instead of a bundle carrying only that group being returned untransformed and read by nothing. Added; the transform already copies an unlisted group through onto `app`. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…t its key, as @objectstack/spec 17.6.0 raises it (objectui#11438) Through 17.5.0 the spec raised the reserved-name refusal on the `fields` map (`custom @ fields`). objectstack#20997 names the key, and 17.6.0 carries it (`custom @ fields.constructor`). The pin said only this reading moves when that lands; it moves, in the instrument row and in the banner row, which now names `fields.constructor`. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…@objectstack/spec 17.6.0 leaves true, and ledger the four that name a past release (objectui#11438) `check:installed-pin-claims` reads every present-tense claim about the installed `@objectstack/*` version against the resolved artifact. 38 sites named 17.5.0. Each was decided, never find-and-replaced: - RESTAMPED after re-measuring the fact the sentence states against the installed 17.6.0 (each probe was also run against a 17.5.0 tarball as the control, and answered the same on both): `FieldSchema`'s `dependsOn`, `rows` and option `description` readings; `object-calendar.data` and `.calendar`; `record:details.columns`; `record:highlights` `fields[]` and `layout`; `SelectOptionSchema` labels; the `@objectstack/lint` field-rule verdict text; `referenceTo` and its four alias spellings; `CalendarConfigSchema`'s required key, options and refusal hints; `record:alert.visible`; `object-kanban`'s fifteen keys; the screen node's `waitForInput`; `object-calendar`'s ten flat members; `ObjectListViewSchema`'s members; the `view.list.navigation.view` tombstone in the gantt README pin; and the sites whose own tests measure the fact and pass on 17.6.0. - REWORDED where the fact moved: the retired-key type is the branded `[REMOVED]` mark at the pinned 17.6.0 (bare `undefined` through 17.5.0), on `retired-key-type.ts` and the five pins that cite its spellings. - LEDGERED as `historical` (four files, seven sites): lines whose version says WHEN something changed or names a release's record set, where `pinned` is an unrelated verb or the sentence sits under a dated update heading. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…438) Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…ack/spec 17.6.0 moves, and pair the live-e2e backend with it (objectui#11438) Each pin names what moved, measured against a 17.5.0 control: - `ObjectSchema`'s accepted keys are 44, not 43: 17.6.0 adopts `imageField` (gained set exactly that one, lost set empty). Both corpus-guard counts are re-pointed as the 17.3.0 adoption was. - The spec's exports map has 21 entries, not 20: `./migrations` is added (no `browser` arm), nothing removed. Every count and its prose follow. - `check-lockfile-integrity`'s two lockfile samples are rebuilt on the 17.6.0 snapshot keys their own tripwire named. - The objectui#11111 owner total for objectui#11168 follows the cap to 1 (the two `endpoint` entries struck earlier on this branch). - `e2e/live/ci/backend.env` pins `OBJECTSTACK_VERSION=17.6.0`, the version the lockfile resolves, as the pin requires (`@objectstack/cli@17.6.0` resolves to the 17.6.0 tag commit). - The page-header doc drops the version literal it gained on this branch; `doc-version-claims` holds docs to pointers, not version numbers. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…k/spec 17.6.0, so it joins the covered arms (objectui#11438) 17.6.0 types `ComponentPropsMap['object-grid'].grouping` as the grouping config instead of `z.unknown()`. The authored arm's `properties` is that row by reference, so a padded grouping field name is now refused at its entry on all four faces. The census's recorded reason for leaving the bag member uncovered stopped holding; it moves to the declaring table and is pinned like every other arm. The node-level `grouping` stays uncovered: it is the flat spelling's by-name refusal. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…stack/spec 17.6.0's walk descends it (objectui#11438) objectui#11223's block (e) held `page:card`'s `properties.footer` as the one slot the spec's exported walk did not descend, and said to retire itself when that changed. 17.6.0's walk descends `properties.footer[]`, objectui's faces now judge a footer child, and block (d) asked for the position to be added to (a). It is: the footer is a row of (a) on both faces, (e) is deleted, and the CLI doc no longer names the footer as an unjudged slot. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
… @objectstack/spec 17.6.0's root entry shed (objectui#11438) The second payback of objectui#11073's ruled raise, objectstack#20646, reaches objectui with the 17.6.0 bump: the spec root no longer exports its migration chain. Measured with two console builds in one lock hold (`CI=true pnpm exec vite build` after the packages build): `main` at `2d576e46` (17.5.0) weighs 3,636,289 gzipped eager bytes, this branch at `2ba091c` weighs 3,386,193; `vendor-objectstack` alone is -250,108, the other 329 chunks +12. Left alone, the ceiling would sit 3.01x the regression above the payload and the gate's own sensitivity check exits 2 (a blind gauge). So, as objectui#11101 did for the first payback: `MAX_EAGER_CLOSURE_GZIP_BYTES` 3,660,380 -> 3,410,284 and `vendor-objectstack` 1,689,265 -> 1,439,157, each lowered by exactly what it recovered; BASELINE and PER_CHUNK_BASELINE move to the `2ba091c` reading; headroom 0.26x and 0.20x, the bands `main` already had. The test's rendered literal is re-taken (3306.8). The changeset says what the console gains. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
…#11536 under objectui#11438 ruling A′ (objectui#11438) @objectstack/spec 17.6.0 gives `record:line_items` a ComponentPropsMap row (objectstack 24c554da, #21142 / #21244), so registry-inputs-spec-parity judges it from that pin on. objectui#11438 ruling A′ (record 5965062249) applies objectui#11111 decision 3 = B to the bump: the population is re-pinned and every difference is booked to the owner card filed for the group, objectui#11536, with an expiry. Nothing is declared or pinned here. - EXPECTED_COVERED gains `MINOR_17_6_BLOCKS` (`record:line_items`), armed when the installed spec carries it; the census goes 55 -> 56 carried and 39 -> 40 judged. - UNPUBLISHED_EXEMPTIONS books the ten keys `inputs` omit; MEMBER_PIN_EXEMPTIONS books `columns` and `dataSource`, and MEMBER_PIN_EXEMPTION_CEILING goes 0 -> 2 with the booking. - The objectui#11111 ledger gains objectui#11536 as a fourth owner, routed by block. Its entries cite ruling A′ and decision 3 = B and expire 2026-11-02 (thirty days after the ruling, as the 17.5.0 entries' 2026-10-30 is after theirs). Caps: unpublishedKeys 1 -> 11, memberPins 0 -> 2, owner total 12. Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w Co-authored-by: Claude <noreply@anthropic.com>
… beside a pin marker (objectui#11438)
`check:installed-pin-claims` read two of the lines the booking added as
present-tense claims about the installed spec: the `MINOR_17_6_BLOCKS`
guard's docblock ("Does the installed ... carry the 17.6.0 set?") and the
`memberPins` cap comment, where the version sat beside the objectui#11168
slice's "pinned". Both were true at 17.6.0 and would go stale at the next
bump. The guard's docblock now asks about the spec this tree resolves, and
the two cap comments name the ruling that booked the entries instead of the
version. No assertion moves.
Claude-Session: https://claude.ai/code/session_01HRYqpqGcWpJuJkDmbRF75w
Co-authored-by: Claude <noreply@anthropic.com>
…essMessage, then the default; stop reading data.message (objectui#11344)
The runner's success toast follows ActionSchema.outcomeMessages
(@objectstack/spec 17.6.0, ruling A on objectstack-ai/cloud#2315): the entry
named by the handler answer's top-level `outcome`, then `successMessage`, then
the runner's default text. Both author rungs fill in `${result.*}` through the
grammar and scope onSuccess.navigate reads (`substituteScopeTokens` over
`readActionPayload`), inserted as text rather than percent-encoded.
`result.data.message` is no longer read.
ActionDef declares `outcomeMessages` (derived from the spec), and both key
inventories list it, which turns the trunk's actionKeys.pin row green. The two
rows that pinned the retired server-message rung are replaced by rows pinning
the ruled behaviour.
Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37
Co-authored-by: Claude <noreply@anthropic.com>
…orward it from every declared action surface (objectui#11344)
- useObjectLabel gains actionOutcome, the resolver for
`_actions.NAME.outcomeMessages.OUTCOME` (then `globalActions.…`).
- useActionTextLocalizer resolves each declared outcomeMessages entry and
collapses an inline I18nLabel map (on an entry or on successMessage) to the
active language before dispatch; `${result.*}` tokens pass through for the
runner to fill in after the run.
- action:button, action:icon, action:group and action:menu forward
outcomeMessages, which check:action-forward-parity owes once the runner reads
it. The action:button / action:icon registrations do not publish it: their
17.6.0 spec rows do not declare it.
- UIActionSchema declares outcomeMessages, derived from the spec.
- The successMessage input descriptions no longer say a server message takes
precedence, and a useConsoleActionRuntime comment no longer names the
retired data.message read.
Pins: the zh-CN (inline map) and ja-JP (bundle entry) toasts through a real
I18nProvider and ActionProvider, and the toast from each of the four surfaces
plus the action:bar member path.
Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37
Co-authored-by: Claude <noreply@anthropic.com>
…server-message rung (objectui#11344)
- enhanced-actions.mdx's notice bullet describes the three rungs, the
`${result.*}` scope the copy reads, and that a server `message` is shown only
when the copy asks for `${result.message}`.
- Two pending changesets (objectui#10900, objectui#10969) said a server message
reaches the toast verbatim; this change makes that false in the release that
will publish them, so the clause is dropped from each. check:changeset-claims
named both files for a read.
Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37
Co-authored-by: Claude <noreply@anthropic.com>
…cit any (objectui#11344) The localizer's generic already types the action as a string-keyed record, so the cast added one no-explicit-any warning the file did not have before. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
…pins (objectui#11344) `tsc -p tsconfig.test.json` refused the three `execute(localized)` calls: the localizer returns the type it was given, while its work changes the shape at run time (an I18nLabel map in, a string out). One named helper states that hop, as the hosts' own `any` does. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
…Handler mock (objectui#11344) `tsc -p tsconfig.test.json` refused `setToastHandler(toast)` for a bare `ReturnType<typeof vi.fn>`; the sibling 10900 suite's `Mock<ToastHandler>` is the spelling that type-checks. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
…ward key order, useObjectLabel's member count, and the one config-bag predicate (objectui#11344) - action-forward-precedence pins the exact key order of the action:button / action:icon forward; `outcomeMessages` is inserted beside `successMessage`, one added name with no neighbour moved, as the pin's own note on middle insertions reads it. - useObjectLabel-identity-5564 anchors the resolver surface to an absolute; `actionOutcome` takes it from 26 to 27 on the one path both probes share. - configBag.pin allows one "is this a real bag?" spelling in @object-ui/react; the localizer now asks `isConfigBag` instead of spelling it. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
…he published types read ActionSchema.outcomeMessages (objectui#11344) The contract review's ground: @object-ui/core's ActionDef and @object-ui/types' UIActionSchema now index `Action['outcomeMessages']`, a member the spec first declares in 17.6.0, while both packages still admitted ^17.5.0. Measured over the five touched packages' published artifacts, with @objectstack/spec mapped to the 17.5.0 tarball and to the installed 17.6.0 as the control: the only diagnostics in a package's own dist that appear at 17.5.0 alone are the TS2339 on `outcomeMessages` in core's actions/ActionRunner.d.ts and in types' ui-action.d.ts; no dist JS imports a runtime export 17.5.0 lacks. So exactly those two floors move. `pnpm install` moves only the two importers' `specifier:` lines; the resolved version stays 17.6.0. The changeset names the raised floors. Two one-word repairs ride along: enhanced-actions.mdx credits useActionTextLocalizer to @object-ui/react, and objectui#10900's pending changeset says `successMessage` reaches the toast "untranslated" rather than "verbatim". Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
…Messages slice (objectui#11344) Two trunk-only files conflicted because the slice was cut from the trunk at c9121f9 and main carries the trunk's later state of them; both take main's version, which is the trunk's successor: .changeset/11438-objectstack-17-6-bump.md and apps/console/src/__tests__/registry-inputs-spec-parity.test.ts. pnpm-lock.yaml took main's file and was regenerated with pnpm install; it now differs from main only in the packages/core importer's @objectstack/spec specifier (^17.6.0). The packages/types floor was already ^17.6.0 on main. Claude-Session: https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn Co-authored-by: Claude <noreply@anthropic.com>
…der lists the key (objectui#11344)
The 17.6.0 bump booked `ActionSchema.outcomeMessages` as owed to this card in
actionKeys.pin.test.ts (objectui#11438 ruling A″). This slice lists the key in
SPEC_ACTION_KEYS and ACTION_DEF_KEYS, so the booking's own rows go red on
merge, as its ablation LEG 3 measured, and the delta contract review's landing
condition requires the strike in full.
- Removed: the OWED_TO_OBJECTUI_11344 ledger and its docblock, OWED_REASON,
the header's "OWED TO objectui#11344" section, and the whole OWED describe.
- Restored: the spec-inventory cap row to
`expect({ missing, stale }).toEqual({ missing: [], stale: [] })`.
- Removed: .changeset/11344-row5-booking-17-6.md, the booking's empty-frontmatter
changeset, which releases nothing.
The file is now byte-identical to its state before the booking (bebd7ec).
Claude-Session: https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn
Co-authored-by: Claude <noreply@anthropic.com>
…changeset say what the runner does since outcomeMessages (objectui#11344)
The delta contract review's two residual precision notes, carried here because
this slice made both statements inexact:
- packages/i18n/src/locales/en.ts: the comment above `completedSuccessfully`
said the default shows when an action declares no `successMessage` and the
server returned no message. It now says the default shows when no
`outcomeMessages` entry applies and no `successMessage` is declared, and
that the server's message plays no part. It is also now "the one
success-toast text the runner writes itself", since objectui#10969 added the
runner's own error and Undo text.
- objectui#10969's pending changeset: an author's `successMessage` no longer
stays "verbatim", since the runner fills its `${result.*}` tokens; the bullet
is about the runner's translator, so the word is now "untranslated".
Claude-Session: https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn
Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ 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
|
Fixes #11344
Clause-②: yes
What this PR is
The renderers now honour the spec's
ActionSchema.outcomeMessages(@objectstack/spec17.6.0).@object-ui/core(ActionRunner,actionKeys) composes the success toast in this order: an own-propertyoutcomeMessagesentry, thensuccessMessage, then the runner's default. The server's message no longer shows.SPEC_ACTION_KEYSandACTION_DEF_KEYSlist the key.@object-ui/react'suseActionTextLocalizerresolvesoutcomeMessagesalong the spec resolver's address: the object's_actionsentry, thenglobalActions.@object-ui/components' four action renderers forward the key.@object-ui/i18nsuppliesactionOutcome.@object-ui/typesderives the member from the spec.@object-ui/coreand@object-ui/typesraise their@objectstack/specfloor to^17.6.0, because their published types readActionSchema.outcomeMessages, which 17.6.0 first declares.typesalready reads^17.6.0onmain(objectui#11227's floor commit), so only thecoreimporter's specifier differs frommainin the lockfile.The row-5 booking is struck
objectui#11531 landed with row 5 booked to this card (
OWED_TO_OBJECTUI_11344inactionKeys.pin.test.ts). This PR removes it in full, together with.changeset/11344-row5-booking-17-6.md. The pin file's blob is byte-identical to its pre-booking state (3445b86f1), and the spec-inventory row is back tomissing: [],stale: [].Reviews
5968432379(floors), then REWORK5968446861, then the delta contract review PASS5969179064on89b21dafd.5969091930.mainand strikes the booking, as the PASS's landing condition ③.1 requires. It also carries the PASS's two wording notes: objectui#10969's pending changeset, and thecompletedSuccessfullycomment inpackages/i18n/src/locales/en.ts. No contract surface moved beyond the reviewed head.Tests (dev report
5969817428)check:spec-floors --cross-checkis green (21 of 39 packages, 435 pairs);Changeset
.changeset/11344-action-outcome-messages.md: fiveminorentries, nomajor, with the floor sentence.🤖 Generated with Claude Code
https://claude.ai/code/session_016tKoy8NJa35Yih1FdzrVmn