Skip to content

Action confirm and param dialogs: draw the action's cancelText on the dismiss button, falling back to Cancel; sys_invitation declares "Keep invitation" #28879

Closed

Description

@objectstack-fleet

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

  1. Console draws it. In ui/packages/core/src/actions/ActionRunner.ts, ActionDef.cancelText is derived from the spec and confirmOptions hands it to the confirm handler; it also joins actionKeys.ts ACTION_DEF_KEYS. react/hooks/useActionTextLocalizer.ts resolves it on the confirm path. components/renderers/action/action-{button,icon,group,menu}.tsx forward it, and the action-forward-precedence test covers it. In ui/packages/app-shell, hooks/useConsoleActionRuntime.tsx and views/RecordDetailView.tsx paramCollectionHandler pass it. views/ActionParamDialog.tsx draws it over actionDialog.cancel. ActionConfirmDialog.tsx already draws options.cancelText. i18n/useObjectLabel.ts gets actionCancelText. Absent, "Cancel" stands.
  2. The extractor scaffolds it (blocking item 3, per the contract review): packages/cli/src/utils/i18n-extract.ts emits cancelText beside a declared confirmText or a non-empty params, the way it emits submitText, with a test.
  3. The first consumer: packages/platform-objects identity/sys-invitation.object.ts cancel_invitation declares cancelText: 'Keep invitation', with its translations regenerated (zh-CN / ja-JP / es-ES values).
  4. Flip the "declared ahead of its reader" text in the same PR (should-fix from the contract review, so the planned row does not go stale, ADR-0049): the spec liveness row goes planned → live, with authorWarn / authorHint dropped; the reconciliation omit row is deleted; the key is offered in action.form.ts; "no renderer shows it yet" is dropped from the action.zod.ts and translation.zod.ts describes; the references are regenerated; and both "does not draw it yet" sentences in content/docs/protocol/objectui/actions.mdx flip. The submitText section 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 (submitText drawn in place of Confirm) #28392; fix it here too.
  5. Optional, triage's call: InlineActionSchema does not pick cancelText (nor submitText). 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

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p3 · domain:ui · pm:queue · 2026-11-02T03:01Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    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 session session_01QsR2jUJ19MstFvFhjgiYTu
    Account: zhuangjianguo
    Branch: claude/project-thread-ewid2r (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-28879
    Domain: domain:ui
    Seat: domain:ui#1
    File 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 (RecordDetailView only at paramCollectionHandler), ui/packages/i18n/src/useObjectLabel.ts, packages/cli/src/utils/i18n-extract.ts, packages/platform-objects/src/identity/sys-invitation.object.ts and its regenerated translations, the cancelText liveness and reconciliation rows, action.form.ts and the action.zod.ts / translation.zod.ts describes in packages/spec, content/docs/protocol/objectui/actions.mdx, their tests, the regen artifacts, and a root .changeset. Wanted 5 (inline actions) and skills/** (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: high
    Clause-②: yes (widening)
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6568007869
    Premise: holds (at origin/main ``: ActionSchema.cancelText is 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.

  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    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.

    • File surface (added): ui/packages/types/src/ui-action.ts gains UIActionSchema.cancelText?: SpecAction['cancelText']. The four action renderers forward schema.cancelText, which does not type-check without it, and check:action-forward-parity derives its owed set from that type. The same shape as submitText (feat(console): an action's param dialog names its own submit verb (submitText drawn in place of Confirm) #28392).
    • File surface (widened): in ui/packages/app-shell/src/views/RecordDetailView.tsx, one line outside paramCollectionHandler changes. The useObjectLabel() destructure gains actionCancelText, because the handler cannot call the hook itself.
    • Tests: the seven sibling useConsoleActionRuntime.* test mocks that gain an actionCancelText passthrough are covered by "their tests".
    • Declaration: Clause-②: yes (widening) already covers the new optional member on @object-ui/types. Metadata-protocol: none is unchanged.
  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    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)"
      ]
    }
  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

    Landed · 2026-11-02T06:44Z · PR #28983 merged through the merge queue as 462b4f92 at 2026-11-02T06:42Z (GitHub's clock). ACCEPT 6570449124 at head f566aa2e.

    probe before (462b4f92~1) now (origin/main)
    cancelText in app-shell/src/hooks/useConsoleActionRuntime.tsx 0 3
    cancelText in platform-objects/src/identity/sys-invitation.object.ts 0 1
    cancelText in spec/src/ui/action.form.ts 0 2
    cancelText row in spec/liveness/action.json planned live

    Fixes #28879 closed this card. pm:dispatched comes off in the same stroke as this note.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions