Description
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Filing gate: ② the follow-up half of #28519 (Wanted 2 and 3). The spec half landed as PR #28859 (merge 76bf6c50d8), which declares ActionSchema.cancelText ahead of its reader. This card is that reader, the way #28158 was for #27944. Surface from the dev report (6567093128, open question 6) and the contract review (6567255334, ④ should-fix rows). ⛔ Not a claim. No grade: triage sets it.
Reader who acts: domain:ui (console), with the packages/cli and packages/platform-objects rows below in the same PR.
Reach: every "Cancel …" / "Close …" action that asks first. On Setup → Invitations, Cancel Invitation opens a confirm dialog whose buttons read Cancel and Cancel Invitation.
Wanted
- Console draws it. In
ui/packages/core/src/actions/ActionRunner.ts,ActionDef.cancelTextis derived from the spec andconfirmOptionshands it to the confirm handler; it also joinsactionKeys.tsACTION_DEF_KEYS.react/hooks/useActionTextLocalizer.tsresolves it on the confirm path.components/renderers/action/action-{button,icon,group,menu}.tsxforward it, and theaction-forward-precedencetest covers it. Inui/packages/app-shell,hooks/useConsoleActionRuntime.tsxandviews/RecordDetailView.tsxparamCollectionHandlerpass it.views/ActionParamDialog.tsxdraws it overactionDialog.cancel.ActionConfirmDialog.tsxalready drawsoptions.cancelText.i18n/useObjectLabel.tsgetsactionCancelText. Absent, "Cancel" stands. - The extractor scaffolds it (blocking item 3, per the contract review):
packages/cli/src/utils/i18n-extract.tsemitscancelTextbeside a declaredconfirmTextor a non-emptyparams, the way it emitssubmitText, with a test. - The first consumer:
packages/platform-objectsidentity/sys-invitation.object.tscancel_invitationdeclarescancelText: 'Keep invitation', with its translations regenerated (zh-CN / ja-JP / es-ES values). - Flip the "declared ahead of its reader" text in the same PR (should-fix from the contract review, so the
plannedrow does not go stale, ADR-0049): the spec liveness row goesplanned→ live, withauthorWarn/authorHintdropped; the reconciliationomitrow is deleted; the key is offered inaction.form.ts; "no renderer shows it yet" is dropped from theaction.zod.tsandtranslation.zod.tsdescribes; the references are regenerated; and both "does not draw it yet" sentences incontent/docs/protocol/objectui/actions.mdxflip. ThesubmitTextsection there still says "The console does not draw it yet", which has been false since feat(console): an action's param dialog names its own submit verb (submitTextdrawn in place of Confirm) #28392; fix it here too. - Optional, triage's call:
InlineActionSchemadoes not pickcancelText(norsubmitText). If the console wires the inline runner through the same confirm handler, an inline page action could carry it too.
Tests
A declared cancelText is the dismiss label on both dialogs. Control: absent keeps "Cancel". The bundle key resolves on both paths (objects.OBJECT._actions.ACTION.cancelText, globalActions.ACTION.cancelText).
Not here
Skills docs: skills/objectstack-ui/rules/actions.md and skills/objectstack-i18n/SKILL.md lack the key (PR #28859 Skills-docs: follow-up owed). They are governed (Tier H), so a separate skills card carries them.
Dedupe: "cancelText dismiss button", "Keep invitation" → only #28519 / PR #28859.
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p3 ·
domain:ui·pm:queue· 2026-11-02T03:01Z⛔ Not a claim.
ActionSchema.cancelText,os i18n extractemits it, andsys_invitationdeclares "Keep invitation". The spec half, PR feat(spec): an action's confirm and param dialogs can name their dismiss button —cancelText#28859, merged with the key ledgeredplannedandauthorWarn, exactly assubmitText(Action param dialog: an action key for the submit button's verb, falling back to Confirm #27944 → Action param dialog: draw the action'ssubmitTexton the submit button, falling back to Confirm #28158) did. p3, in step with Action confirm and parameter dialogs: a declared dismiss label (ActionSchema.cancelText), so "Cancel Invitation" no longer sits beside "Cancel" #28519. It goes topm:queueso the ui lane sees it;findingis dropped (one state). The liveness row flips tolivein the same PR.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim: PM loop round 14 · 2026-11-02T04:07Z
Session:
session_01QsR2jQtTxhjJ5tQUg79qSg(card thread, os-dev); dispatched by seat sessionsession_01QsR2jUJ19MstFvFhjgiYTuAccount:
zhuangjianguoBranch:
claude/project-thread-ewid2r(platform-assigned to the card thread; it can push only this branch)Worktree:
objectstack-issue-28879Domain:
domain:uiSeat:
domain:ui#1File surface: the card's Wanted 1-4 list:
ui/packages/core/src/actions/{ActionRunner,actionKeys}.ts,ui/packages/react/src/hooks/useActionTextLocalizer.ts,ui/packages/components/src/renderers/action/action-{button,icon,group,menu}.tsx,ui/packages/app-shell/src/hooks/useConsoleActionRuntime.tsx,ui/packages/app-shell/src/views/{RecordDetailView,ActionParamDialog}.tsx(RecordDetailViewonly atparamCollectionHandler),ui/packages/i18n/src/useObjectLabel.ts,packages/cli/src/utils/i18n-extract.ts,packages/platform-objects/src/identity/sys-invitation.object.tsand its regenerated translations, thecancelTextliveness and reconciliation rows,action.form.tsand theaction.zod.ts/translation.zod.tsdescribes inpackages/spec,content/docs/protocol/objectui/actions.mdx, their tests, the regen artifacts, and a root.changeset. Wanted 5 (inline actions) andskills/**(Tier H, a separate card) are out (stop on breach; explain in the report)Container & model: M,
mode:thread,model: default tier (dispatch-gates --tier: no path-derived mandate),effort: highClause-②: yes (widening)
Metadata-protocol: none
Responsibility:
n/a — not a defect cardThread-read: 6568007869
Premise: holds (at
origin/main``:ActionSchema.cancelTextis declared in `packages/spec/src/ui/action.zod.ts:974` by PR #28859, ahead of its reader; `ActionConfirmDialog.tsx:69` already draws `options.cancelText`; the param dialog and the action-def derivation do not carry it)Serial constraints cleared: #28859 landed (`76bf6c50d8`). #28909 (seat 1, later) also touches `RecordDetailView.tsx` and merges main after this.
objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim amended · 2026-11-02T04:19Z · after the dev's first commit (
f7554578). This widens the file surface by two mechanical consequences. It adds to claim 6568809663. Branch, session, size and declarations are unchanged.ui/packages/types/src/ui-action.tsgainsUIActionSchema.cancelText?: SpecAction['cancelText']. The four action renderers forwardschema.cancelText, which does not type-check without it, andcheck:action-forward-parityderives its owed set from that type. The same shape assubmitText(feat(console): an action's param dialog names its own submit verb (submitTextdrawn in place of Confirm) #28392).ui/packages/app-shell/src/views/RecordDetailView.tsx, one line outsideparamCollectionHandlerchanges. TheuseObjectLabel()destructure gainsactionCancelText, because the handler cannot call the hook itself.useConsoleActionRuntime.*test mocks that gain anactionCancelTextpassthrough are covered by "their tests".Clause-②: yes (widening)already covers the new optional member on@object-ui/types.Metadata-protocol: noneis unchanged.objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jQtTxhjJ5tQUg79qSg
os-dev-report
Card thread session_01QsR2jQtTxhjJ5tQUg79qSg (dispatched by seat session session_01QsR2jUJ19MstFvFhjgiYTu), report at 2026-11-02T05:47Z. Draft PR #28983, head f566aa2.
{ "issue": 28879, "status": "done", "branch": "claude/project-thread-ewid2r", "pr": "https://github.com/objectstack-ai/objectstack/pull/28983", "session": "session_01QsR2jQtTxhjJ5tQUg79qSg", "premise_still_valid": true, "summary": "Both pre-run action dialogs draw the action's cancelText on the dismiss button, falling back to Cancel. Confirm path: ActionDef.cancelText (derived) + ACTION_DEF_KEYS; useActionTextLocalizer resolves it declared-only (I18nLabel collapsed, then useObjectLabel().actionCancelText, bundle first); ActionRunner#confirmOptions hands the string to the confirm handler as options.cancelText, which ActionConfirmDialog already draws. Param path: both paramCollectionHandlers resolve it like submitText and ActionParamDialog draws it. The four action renderers forward it; UIActionSchema.cancelText added (amendment 6568954960). os i18n extract scaffolds cancelText beside confirmText or a non-empty params. sys_invitation cancel_invitation declares 'Keep invitation' (zh-CN/ja-JP/es-ES hand-translated, bundles regenerated). Spec: liveness row planned -> live with authorWarn/authorHint dropped, reconciliation omit row deleted, action.form.ts row 'Cancel button label' (translated), describes trimmed, references and state-counts regenerated, both 'does not draw it yet' sentences in actions.mdx flipped (cancelText and the stale submitText one). Changeset .changeset/28879-action-dialog-cancel-text.md, all patch.", "tests": "At head f566aa2e (after merging origin/main 00d0668d): the 18 new/touched ui test files + RecordDetailView.childWriteRefreshesParent-12244 (main overlap) -> 19 files, 100 passed; cli i18n-extract-action-cancel-text 7 passed. At e389f7f7: ui core/src/actions, i18n, components/renderers/action, useActionTextLocalizer*, useConsoleActionRuntime*, ActionParamDialog*, ActionConfirmDialog*, RecordDetailView* -> 330 files, 3779 passed, 13 skipped; ui packages/types 386 files, 10456 passed; ui scripts/ 169 passed, 2 skipped, exit 0; spec src/ui + src/system 238 files, 8155 passed; spec scripts/liveness 12 files, 359 passed; cli unit test/i18n-extract 12 files, 96 passed; platform-objects 108 files, 1503 passed (after the echo-decisions catalog pin 698 -> 699). Type-check: ui turbo type-check app-shell/components/core/i18n/react/types 70/70 exit 0; cli, spec, platform-objects typecheck exit 0. Ablations (ablation-replace.mjs, committed first): deleting the cancelText spread in confirmOptions reds ActionRunner.confirmCancelText-28879 (2 failed | 3 passed); replacing state.cancelText || t('actionDialog.cancel') with the bare t() reds ActionParamDialog.cancelText-28879 (2 failed | 2 passed); both restored, blob == HEAD, git diff HEAD empty.", "gates": "dispatch-gates --commands derived 112 families at e389f7f7; 111 exit 0, 1 NOT MEASURED (pnpm check:dual-build-cjs-loads exit 3, needs a whole-workspace build; CI's). check:skill-examples and check:i18n-coverage first exited 3 on unbuilt prerequisites, then exit 0 after building client-react and the coverage closure ('OK (14 config(s), 426 baselined untranslated string(s), none new)'). --ran: 112 accounted, 111 run, 1 NOT-MEASURED. At f566aa2e: check-sdui-manifest exit 0, check-i18n-bundles exit 0, spec check:generated all 14 up to date, ui check:new-line-citations 0 new, check-nul-bytes exit 0. PR-body gates on the exact body: check-changeset-no-major exit 0 (yes (widening) / none at patch), check-adr-0087-registration exit 0, check-closing-keyword-parity exit 0, check-partof-closing-keyword exit 0. PR check-runs: in_progress at report time.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "0 GitHub MCP calls (gh api REST reads only for the card, claim and comments)", "api_writes": "3 — git push (4 pushes of the branch, not REST); fleet-write relay pr_create -> POST /repos/objectstack-ai/objectstack/pulls (#28983, body read back 11581/11581 bytes identical, no assignees, no labels); post-stamped comment on #28879 (this report)", "deviations": "The session context asks to assign the PR to zhuangjianguo and request their review after creation; os-dev forbids assignees on a dev's pr_create and the seat hands the PR over, so neither was done.", "open_questions": [], "out_of_scope_findings": [ "carrier: none · noted, not filed — ui/packages/app-shell/src/views/metadata-admin/MetadataTypeActions.tsx, a third ActionParamDialog consumer (Setup metadata-type actions), passes neither submitText nor cancelText, so its buttons keep Confirm / Cancel; the card names the two business-action handlers only (in the PR's Acceptance notes)" ] }objectstack-fleet commentedon Nov 2, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Landed · 2026-11-02T06:44Z · PR #28983 merged through the merge queue as
462b4f92at 2026-11-02T06:42Z (GitHub's clock). ACCEPT 6570449124 at headf566aa2e.462b4f92~1)origin/main)cancelTextinapp-shell/src/hooks/useConsoleActionRuntime.tsxcancelTextinplatform-objects/src/identity/sys-invitation.object.tscancelTextinspec/src/ui/action.form.tscancelTextrow inspec/liveness/action.jsonplannedliveFixes #28879closed this card.pm:dispatchedcomes off in the same stroke as this note.