Skip to content

app-showcase: record-action success messages name no record ("Task marked done.") — fails the write-feedback naming rule (ruling C on #25849); the runner fills {{ }} holes, so the copy can name the record #26459

Closed

Description

@objectstack-fleet

Filing gate: ① a clause fail with a live reproduction (QA run, rule 2 checks done), product-defect disposition. The capability works, but the showcase's declared copy violates the ruled convention.
Business reason: a user who marks several tasks done in a row sees "Task marked done." each time and cannot tell which record changed. Maintainer ruling C on #25849 (comment 6417978207) says a record-level write names the record (its title) or the count. #26172 brought the console's create/update toasts in line; an action's authored successMessage is the showcase's own copy, and the console renders it verbatim.
Reader: the app-showcase fixture owner, examples/app-showcase/src/ui/actions/index.ts.
Dedupe (open AND closed): searched for "Task marked done", "showcase Mark Done success toast". The hits are different defects:

Reproduction

Reproduced twice on fresh loads, with ref-targeted clicks.

  1. Boot the stock showcase and sign in as admin.
  2. Open /_console/apps/com.example.showcase/showcase_task/record/ID for a task with done: false (e.g. "PII access review").
  3. Click "Mark Done" in the page header actions. POST /api/v1/actions/showcase_task/showcase_mark_done with {"recordId":"ID","params":{}} → 200; the row reads done: true.
  4. The success toast reads "Task marked done."

Expected (ux-conventions.write-feedback acceptance[1], record-level class): the toast names the record (e.g. Task "PII access review" marked done.) or a count.

Mechanism

  • examples/app-showcase/src/ui/actions/index.ts:69 declares successMessage: 'Task marked done.'.
  • The action runner fills {{ }} holes in an authored successMessage (ui/packages/core/src/actions/ActionRunner.ts, the RUNNER_TEXT docblock around lines 627–630), so the declaration can name the record.
  • The same file's other record-level messages name only the object as well: line 186 "Estimate recalculated.", line 482 "Task archived (demo — no data changed).", and line 332 "Invoice submitted for finance + legal sign-off.". They are worth fixing in the same pass. Line 242 (the selection-wide recalculation) could name its count.

Not confirmed: which hole syntax resolves the record title for a perRecord action ({{record.title}} vs another binding). Read ActionRunner.ts before choosing.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · priority:p3 · domain:ui · area:records · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-27T04:55Z

    ⛔ Not a claim, ⛔ not a dispatch.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 11 · 2026-10-27T07:28Z
    Session: session_01SMps7wq7rBTk53e8KTSEup
    Account: os-steve
    Branch: claude/issue-26459-showcase-action-toasts
    Worktree: objectstack-issue-26459
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: examples/app-showcase/src/ui/actions/index.ts (the authored successMessage strings only), a pin beside the showcase's existing action tests, root .changeset/ if the showcase package takes one. ⛔ ui/packages/core/src/actions/ActionRunner.ts (read only; the runner already fills holes), locale packs, ui/.github/**, root ci.yml.
    Container & model: S, mode:subagent, model: default tier, effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: a user who marks several tasks done in a row and cannot tell which one changed | ActionRunner successMessage holes | the showcase record header actions
    Thread-read: none
    Premise: holds 2026-10-27T07:28Z at origin/main f486e9c1ba: examples/app-showcase/src/ui/actions/index.ts still declares successMessage: 'Task marked done.' on the perRecord Mark Done action; no open PR touches the file.
    Serial constraints cleared: none needed (no other open card or PR on the file).
    Writes: PR only via the relay op pr_create; comments only via the relay write tools; ⛔ no GitHub MCP writes.

    • Seat's route: read ActionRunner.ts for the hole binding that resolves the record's title on a perRecord action, then make the record-level messages named in the card (Mark Done, the estimate recalculation, archive, invoice submit) name the record, and the selection-wide one its count, falling back to today's wording where the binding resolves nothing. Pin the resolved toast text. Ruling C on qa(checklist): ux-conventions — 5 ledger edits from the 18.2.0 release sweep (#25807) #25849 governs. Fixes #26459.
  3. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 26459,
      "status": "done",
      "branch": "claude/issue-26459-showcase-action-toasts",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26604",
      "session": "session_01SMps7wq7rBTk53e8KTSEup",
      "premise_still_valid": true,
      "summary": "The five record-level successMessage strings in examples/app-showcase/src/ui/actions/index.ts (Mark Done, Recalculate Estimate, Recalculate Selection, Archive, Submit for Sign-off) now name the record through a template hole over the runner's record root: the record.title hole for tasks, the record.name hole (Invoice Number) for invoices. ActionRunner.composeSuccessMessage fills holes over exactly two roots, result and record (the dispatch's _rowRecord, else the page record), and an unbound path prints empty, so each hole pipes through the engine's default formatter and falls back to the object wording the toast used before (e.g. 'Task marked done.'). The selection count is not reachable from successMessage (no selection root); the selection bar's aggregate dispatch runs with the success toast off and the bulk dialog reports its own count, so Recalculate Selection's toast only shows at its single-record record_more placement and names that record, falling back to 'the whole selection'. A new pin examples/app-showcase/test/record-action-success-names-record.test.ts resolves each sentence through @objectstack/formula's templateEngine with the runner's roots; a root patch changeset covers the (private, not ignored) showcase package.",
      "tests": "Red first at f9e79460 (pin only): vitest run test/record-action-success-names-record.test.ts -> Tests 6 failed | 4 passed (10) (the 4 passing are the fallback cases, equal to today's wording by design); e.g. Expected 'PII access review marked done.' Received 'Task marked done.'. Green at 6399091d (after merging origin/main, closure rebuilt under os-verify-lock, VERDICT command-exit 0): pin 10/10 passed; pnpm --filter @objectstack/example-showcase test -> Test Files 40 passed (40), Tests 494 passed (494); typecheck (tsc --noEmit) exit 0; validate (objectstack validate) -> Validation passed. No ablation: the change is authored copy, not a tested runtime behaviour.",
      "gates": "At 6399091d: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack -> 50 derived; 49 exit 0; pnpm check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (needs every package dist; only the showcase closure was built) = NOT MEASURED, left to CI. --ran with exit codes: 50 accounted, 49 run, 1 NOT-MEASURED (derived from recorded exit 3). node scripts/check-sdui-manifest.mjs exit 0. Derivation warned the tree was 2 commits behind origin/main at run time (main moving); not re-merged. CI check-runs: not yet read (in_progress at report time).",
      "dogfood_battery": "n/a — no ! in the PR title and Clause-②: no without a (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "2 relay strokes — (1) fleet-write dispatch pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/26604/assignees; (2) post-stamped: POST /repos/objectstack-ai/objectstack/issues/26459/comments (this report). git push is not a REST write.",
      "open_questions": [
        {
          "question": "The zh-CN pack (examples/app-showcase/src/system/translations/index.ts, objects.showcase_task._actions.*.successMessage and the invoice entry) still carries record-less wording, so a zh-CN viewer sees no record name. Locale packs were outside the claimed file surface.",
          "options": [
            "A: a follow-up card rewrites those zh-CN entries with the same holes and default fallbacks",
            "B: leave the zh-CN copy record-less"
          ],
          "recommendation": "A, because the ruling is locale-independent and the fix is the same five mechanical strings"
        },
        {
          "question": "GenerateInvoicePdfAction ('The PDF is attached to the invoice.') is record-level copy the card does not name; left unchanged.",
          "options": [
            "A: fold it into the zh-CN follow-up card",
            "B: leave it"
          ],
          "recommendation": "A, same class and same file"
        }
      ],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — docs/qa/platform-checklist/areas/ux-conventions.json variant text quotes the old Mark Done string ('Task marked done.'); QA ledger evidence prose, for the QA seat",
        "carrier: none · noted, not filed — zh-CN pack copy for these actions stays record-less (see open_questions)"
      ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · seat 2 · 2026-10-27T10:58Z

    probe reading
    PR #26604 MERGED 2026-10-27T10:42Z, merge commit ce9bc104, head bb657a00 (+163/−9, seat record on #26604)
    origin/main contains it (git merge-base --is-ancestor exit 0)
    queue branch gh-readonly-queue/main/pr-26604-*: none left (consumed)
    card closed (completed) by Fixes #26459 on #26604

    Status: the showcase's record-level action toasts name the record in English and in the showcase's own zh-CN bundle (e.g. PII access review marked done.), falling back to the old object wording when no title is bound. Not carried: GenerateInvoicePdfAction's copy and the QA checklist variant text quoting "Task marked done.". pm:dispatched removed.

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

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:uipriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions