Skip to content

Action confirm and parameter dialogs: a declared dismiss label (ActionSchema.cancelText), so "Cancel Invitation" no longer sits beside "Cancel" #28519

Closed

Description

@objectstack-fleet

domain:ui#1 · os-tesla · session_01L9qibw2uhdSeHYfnZdAf4V

Filing gate: ② the spec half of a measured suggestion row: #27521 row 9, admin half, the last open row of that card (ledger /mnt/project-files/ui-seat-1/r2026-10-31b/out/27521-ledger.md, measured on main efb1620c). ⛔ Not a claim. Triage sets the lane and grade.
Reach: every action whose verb is itself "Cancel …" or "Close …" and that asks for confirmation. On Setup → Invitations, the row menu's Cancel Invitation opens a confirm whose two buttons read Cancel and Cancel Invitation, so an admin cannot tell which button keeps the invitation.
Reader who acts: domain:spec (the key), then domain:ui (the dialog reads it) and the sys_invitation action declares it.
Duplicate search: "cancelText action confirm", "dismiss label action" → none open. #27944 added ActionSchema.submitText for the dialog's submit verb; no dismiss counterpart exists.

Observed (at main efb1620c, code read)

Wanted

  1. ActionSchema.cancelText (an I18nLabelSchema, optional): the label of the dismiss button on the action's confirm and parameter dialogs, beside submitText, with the same translation path (objects.OBJECT._actions.ACTION.cancelText).
  2. The console's ActionConfirmDialog and ActionParamDialog draw it when declared; absent, today's "Cancel" stands.
  3. sys_invitation's cancel action declares cancelText: 'Keep invitation' (with its translations), the row that started this.

Tests

  • Spec: the key parses, translates through the bundle path, and is listed wherever submitText is (the ui SPEC_ACTION_KEYS pin, /meta/types, FLS-style tables that enumerate action keys).
  • Console: a declared cancelText is the dismiss label on both dialogs; control: absent keeps "Cancel".

Acceptance

All three Wanted items are pinned, or answered "will not do" with the reason. Clause-②: yes (widening).

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: half-state healed · pm:queue · 2026-11-02T00:27Z

    ⛔ Not a claim.

    • When triage graded this card p3, it routed it but set no pm state. That left it invisible to every lane's candidate query (check-half-states H13). The card names a concrete defect at a named location and asks nothing of the maintainer, so it enters pm:queue. Priority stays p3, and the lane takes it in priority order.

    Generated by Claude Code

  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

    Claim: PM loop round 1 · 2026-11-02T00:31Z
    Session: session_01ADHkmPi25XXKx92Xmg4viS (seat); dev = card thread session_01ADHkmNhdF5oapRdMKNBctQ
    Account: os-steve
    Branch: claude/project-thread-ejulkc
    Worktree: the card thread's own checkout of objectstack-ai/objectstack
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: the spec half only (Wanted 1 + its tests), mirroring PR #28188's surface for cancelText: packages/spec/src/ui/action.zod.ts + a new test, packages/spec/src/system/translation.zod.ts, packages/spec/src/system/i18n-resolver.ts, packages/lint/src/validate-translation-references.ts + test, packages/spec/liveness/action.json + state-counts/action.md, packages/spec/authorable-surface/ui.json, the metadata-protocol meta-types test pin, ui/packages/core/src/actions/actionKeys.ts, regenerated content/docs/references/**, content/docs/protocol/objectui/actions.mdx, root .changeset/ (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default — dispatch-gates --tier: "no path-derived mandate … the tier stays the PM's per-card judgment call (floor sonnet · default opus · ceiling fable)"; a widening of packages/spec/src owes one CONTRACT_REVIEW_TIER review before the queue, effort: xhigh
    Clause-②: yes (widening)
    Metadata-protocol: added
    Responsibility: n/a — not a defect card
    Thread-read: 6566175889
    Premise: holds (ActionSchema has submitText at packages/spec/src/ui/action.zod.ts ≈L938 and no dismiss-label key; object-form carries cancelText at component.zod.ts L7091)
    Serial constraints cleared: none (no open PR names cancelText; the seat has no other card in flight)

    PR body first line: Part of #28519. Wanted 2 (console dialogs) and Wanted 3 (sys_invitation declares it) are the follow-up half, split as #27944 → #28158 was; the seat files that follow-up from the dev's report. The new public key name cancelText waits for the maintainer's approval before landing (asked in the project); building under it proceeds meanwhile.

    Amended: the Metadata-protocol: line now reads added. widened is outside the closed set (added | narrowed | semantic | none) that check-changeset-no-major reads; the dev measured it MALFORMED (report 6567093128, PR #28859). The judgement is unchanged: a new optional key.

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmNhdF5oapRdMKNBctQ
    os-dev-report

    {
      "issue": 28519,
      "status": "done",
      "branch": "claude/project-thread-ejulkc",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/28859",
      "head": "6e2b3ddb",
      "session": "session_01ADHkmNhdF5oapRdMKNBctQ",
      "premise_still_valid": true,
      "summary": "Spec half of #28519 (Wanted 1 + its tests), mirroring #28188's surface: ActionSchema.cancelText, an optional I18nLabel for the dismiss button of the dialog an action opens before it runs (the confirm dialog of a param-less action with confirmText, or the param dialog of an action with non-empty params). Blank refused at parse; refused on an action that declares neither confirmText nor non-empty params (the submitText no-dialog rule carried to this button's two hosts, ADR-0078); cancelLabel renames to it; not picked onto InlineActionSchema. Translation slot objects.OBJECT._actions.ACTION.cancelText / globalActions.ACTION.cancelText, overlaid by translateAction only for an action that opens either dialog; lint checkActionCancelText reports a translation under a dialog-less action as translation-target-unknown (error). Liveness row planned + authorWarn, reconciliation omit row, authorable-surface, SPEC_ACTION_KEYS, meta-types count 51 -> 52, docs section, regenerated references, three changesets (spec minor, lint patch, @object-ui/core patch). PR body line 3 is `Part of #28519`. The PR is a non-governed draft; per the claim it owes one CONTRACT_REVIEW_TIER review before the queue.",
      "tests": "At head 6e2b3ddb (origin/main 3e62a22c merged in), each via os-verify-lock (VERDICT command-exit 0): spec test Files 789/789, Tests 23311 passed + 1 todo; lint Files 189/189, Tests 7829/7829; metadata-protocol (rerun after the main merge, main moved its src) Files 297 passed + 4 skipped, Tests 22093 passed + 26 skipped; @object-ui/core Files 228/228, Tests 4226 passed + 27 skipped. typecheck spec/lint/metadata-protocol Done, @object-ui/core type-check exit 0; eslint on the 8 changed packages/ .ts files exit 0, ui eslint on actionKeys.ts exit 0. Ablations through ablation-replace, each restored to the HEAD blob: no-dialog refinement -> action-cancel-text.test.ts 2 failed | 18 passed; lint confirmText guard -> 2 failed | 231 passed; translateAction guard -> 1 failed | 19 passed; SPEC_ACTION_KEYS minus cancelText -> actionKeys.pin.test.ts 1 failed | 18 passed with missing ['cancelText'] (the pin reads the rebuilt spec dist).",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 6e2b3ddb: 109 commands, 21 paths vs merge base 3e62a22c4, 525 changed lines (+513/-12). All 109 exit 0 (check-plugin-teardown-shape --self-test exited 3 first on a shallow clone; after git fetch --depth=1 origin 621a4876 it reports 48 cases pass, exit 0). --ran: '109 derived famil(ies) accounted for — 109 run, 0 NOT-MEASURED (a DERIVED zero)'. check-changeset-no-major --event with this PR body: exit 0, @objectstack/spec minor for yes (widening) + added. Local-only: check:skill-frame-freshness exit 0; check:dev-prereqs exit 1 as a box precondition (34 ui/ workspace dists not built here; packages/** build 78/78). CI check-runs on #28859: in_progress at report time (not waited on).",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "files_changed": [
        ".changeset/28519-action-cancel-text.md",
        ".changeset/28519-action-keys-cancel-text.md",
        ".changeset/28519-lint-cancel-text-translation.md",
        "content/docs/protocol/objectui/actions.mdx",
        "content/docs/references/data/object.mdx",
        "content/docs/references/kernel/metadata-plugin.mdx",
        "content/docs/references/system/translation.mdx",
        "content/docs/references/ui/action.mdx",
        "content/docs/ui/translations.mdx",
        "packages/lint/src/validate-translation-references.test.ts",
        "packages/lint/src/validate-translation-references.ts",
        "packages/metadata-protocol/src/protocol.meta-types-degenerate-derivation.test.ts",
        "packages/spec/authorable-surface/ui.json",
        "packages/spec/liveness/action.json",
        "packages/spec/liveness/state-counts/action.md",
        "packages/spec/src/system/i18n-resolver.ts",
        "packages/spec/src/system/metadata-form-zod-reconciliation.test.ts",
        "packages/spec/src/system/translation.zod.ts",
        "packages/spec/src/ui/action-cancel-text.test.ts",
        "packages/spec/src/ui/action.zod.ts",
        "ui/packages/core/src/actions/actionKeys.ts"
      ],
      "line_budget": "21 files, +513 / -12 (525 changed lines, under the 3000 human-merge threshold); no governed path; the claimed file surface, nothing outside it",
      "deviations": [
        "Metadata-protocol line: the PR body and the spec changeset say `added`, not the claim's `widened`. `widened` is outside the closed set (added|narrowed|semantic|none): check-changeset-no-major --event with `widened` exits 1, 'metadata-protocol line: MALFORMED … LEVEL AXIS: NOT MEASURED'; with `added` it exits 0. The seat may amend the claim line.",
        "PR body layout: lines 1-2 are the session's required attribution block (marker + Requested-by line), so `Part of #28519` is line 3, right after it (os-dev's harness-attribution exception).",
        "The session's harness instruction to set os-steve as the PR's assignee and reviewer was not carried out: os-dev forbids PR assignees and the standard order forbids MCP writes. The seat hands the PR on.",
        "check:dev-prereqs exit 1 is a box precondition (ui/ dists absent in this container), not run to green."
      ],
      "mcp_calls": "0 — no mcp__github__ calls; reads went through gh api (REST GET)",
      "api_writes": "2 — (1) fleet-write relay dispatch pr_create -> #28859 (POST /repos/objectstack-ai/objectstack/dispatches, run 41373886121 success, 13108 bytes sent = stored); (2) this os-dev-report comment on #28519 through post-stamped.mjs (relay). git push is not counted.",
      "open_questions": [
        {
          "question": "New public key name: does the maintainer approve `cancelText` (standard order item 5)?",
          "options": ["A `cancelText` — the protocol's existing word (object-form's cancelText beside submitText)", "B another name — a rename on this branch"],
          "recommendation": "A, because it pairs with ActionSchema.submitText and object-form's submitText/cancelText; the seat already asked Steve."
        },
        {
          "question": "The no-dialog refusal (cancelText on an action with neither confirmText nor non-empty params is refused at parse) is not in Wanted 1's text. Keep it?",
          "options": ["A keep — the submitText precedent's second rule, so a label that can never show fails loudly (ADR-0078)", "B drop it and keep only the blank refusal"],
          "recommendation": "A, because without it the key parses clean on a click-to-run action and is never drawn, the declared-not-enforced shape the precedent refused."
        },
        {
          "question": "Aliases: only `cancelLabel` (measured on the console's form and alert-dialog renderers) renames to cancelText. Add unmeasured spellings such as dismissText / dismissLabel?",
          "options": ["A cancelLabel only", "B add dismissText / dismissLabel"],
          "recommendation": "A, because the precedent took only measured near-miss spellings."
        },
        {
          "question": "Cross-reference with object-form's cancelText?",
          "options": ["A as built: the ActionSchema docblocks name object-form's pair and each other (submitText's docblock now points at actionCancelText); component.zod.ts describes untouched", "B also add a back-reference in object-form's describes"],
          "recommendation": "A, because submitText's precedent added no back-reference there and B would widen this PR into component.zod.ts and its regenerated reference."
        },
        {
          "question": "Migrations: nothing owed? Checked: git grep -c 'cancelLabel|cancelText' over packages/spec/src/migrations + conversions = 0 files (control submitLabel: 4 files, 17 lines); element:form's six retired keys hold no cancel label; translation-component-submit-label-retired concerns the component copy key submitLabel alone.",
          "options": ["A no twin entry — cancelText moves no existing key", "B add an entry"],
          "recommendation": "A, because nothing is retired or renamed."
        },
        {
          "question": "Follow-up card for Wanted 2 + 3 (as #28158 was for #27944), suggested surface:",
          "options": [
            "ui: core/actions/ActionRunner.ts (ActionDef.cancelText derived from the spec; confirmOptions hands it to the confirm handler) + actionKeys.ts ACTION_DEF_KEYS; react/hooks/useActionTextLocalizer.ts resolves it for the confirm path; components/renderers/action/action-{button,icon,group,menu}.tsx forward it (+ action-forward-precedence test); app-shell hooks/useConsoleActionRuntime.tsx + views/RecordDetailView.tsx paramCollectionHandler pass it; views/ActionParamDialog.tsx draws it over actionDialog.cancel (ActionConfirmDialog.tsx already draws options.cancelText); i18n/useObjectLabel.ts actionCancelText",
            "framework: cli/src/utils/i18n-extract.ts emits it (beside confirmText or params) + test; platform-objects identity/sys-invitation.object.ts cancel_invitation declares cancelText 'Keep invitation' + regenerated translations with zh-CN/ja-JP/es-ES values; spec liveness row -> live (drop authorWarn), delete the reconciliation omit row, offer the key in action.form.ts, drop 'no renderer shows it yet' from the two describes, regenerate references; docs actions.mdx flip both 'does not draw it yet' sentences",
            "tests: a declared cancelText is the dismiss label on both dialogs; control: absent keeps Cancel; bundle key resolves on both paths. Skills (Tier H, separate PR): skills/objectstack-ui/rules/actions.md, skills/objectstack-i18n/SKILL.md"
          ],
          "recommendation": "File it as one ui-lane card with the platform-objects + cli rows, Blocked-by #28859, and a separate skills card for the two governed files."
        }
      ],
      "out_of_scope_findings": [
        "carrier: the Wanted 2+3 follow-up card · noted, not filed — content/docs/protocol/objectui/actions.mdx's submitText section still ends 'The console does not draw it yet', false since #28392 (liveness row live); not this card's defect class"
      ]
    }

    Stamped 2026-11-02T01:44Z.


    Generated by Claude Code

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS

    Landed · 2026-11-02T02:31Z

    Probe Reading
    PR #28859 MERGED, merge commit 76bf6c50d8, via the merge queue (Part of #28519)
    Wanted 1 (ActionSchema.cancelText) landed by PR #28859; maintainer approved the key name 「新协议键 cancelText 这个名字 同意」 (triage record 6567306297)
    Wanted 2 + 3 (console dialogs draw it; sys_invitation declares "Keep invitation") carried to #28879, which also takes the cli extractor and the "declared ahead of its reader" flips from the contract review (6567255334)
    #28519 closed completed by the seat, split as #27944 → #28158 was

    pm:dispatched removed. The seat record is ACCEPT 6567121709 and the contract review is PASS 6567255334, both on PR #28859. Skills-docs follow-up (two Tier H files) is named in #28879 "Not here".

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

Metadata

Metadata

Assignees

Labels

domain:specDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions