Skip to content

list bulk action confirmText: fill the template slot's declared holes — {{count}} first, the action's params second (the renderer half of objectstack#24798 ruling B) #25942

Closed

Description

@objectstack-fleet

Filing gate ③ — the objectui half of ruling B on #24798 (the maintainer's 「同意」 in the director's chat, 2026-10-20), filed by the director seat (summon objectstack-ai/objectui#45 continuation 1, session_01Lg6GQ4xjqmvEzYv78d6H7i) under ruling D on #24591: a card that straddles repositories is split by repository. ⛔ Not a claim.

Reader who acts: the objectui domain:ui seat, once the @objectstack/spec release that types confirmText as a template slot is installable here (the framework pin moves past that release). Until then this card is pm:blocked.

Blocked-by: objectstack-ai/objectui#13407

What the ruling binds for this repository

  • Today packages/plugin-grid/src/components/BulkActionDialog.tsx:412 renders def.confirmText verbatim (objectui origin/main 91b658a75d64), and only the default t('grid.bulk.confirmDefault', { count }) fills a count. After the spec release, an authored confirmText is a template-dialect slot (ADR-0032 Decision 2 and 3): the dialog fills its {{ }} holes through the same template engine the flow notifications render with, over the bulk-confirm scope the spec declares.
  • Step 1, this card's first PR: {{count}} = the affected-record count (rows.length), plus the whitelist formatters the engine already carries.
  • Step 2, a second PR only after the spec PR states the display-value rule: {{<param name>}} = that param's display value (option label for picklists, record name for lookups, formatted dates and numbers via the whitelist).
  • Nothing else moves: no CEL inside holes (an ADR-0032 non-goal), no change to the default text, no change to where the confirm step sits. A hole the spec does not declare never reaches the dialog — objectstack validate, compile and the publish gate refuse it by name on the objectstack side.

Dedupe

objectstack-ai/objectui#13154 (closed: moved to objectstack as the decision card). Open domain:ui cards scanned by title and body for confirmText / bulk confirm / template slot: 0 hits.

Related

#24798 (the ruling, letter B) · objectstack-ai/hotcrm#2188 (the maintainer's browser pass that found {{count}} on screen) · the sibling spec card on objectstack that types the remaining person-facing text slots.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Unblocked · domain:ui seat 1 (seat post objectstack-ai/objectui#5560, project run by the Sales account) · session_01WJozybDmRH8z2c5SD7vJkj · 2026-10-23T20:46Z

    The blocker objectui#13407 has landed: .objectstack-sha now names objectstack 915e9404, which carries objectstack#24947 (git merge-base --is-ancestor 925fd0772c 915e9404 exits 0). Step 2, filling the template slot's holes with {{count}} first, can start. The card goes from pm:blocked back to pm:queue.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Pause lifted · domain:ui seat 4 (vacant; written by its signed-off session session_01XWGTsmqrtrt1Zqh1ioWqsT) · 2026-10-25T14:10Z

    The os-sales tenure held this card back for the planned objectui → objectstack repo move. The maintainer lifted that pause in this project on 2026-10-25T14:08Z: 「你放回队列就写」. The card already carries pm:queue and is dispatchable under the normal rules. Nothing dispatches it now, because the domain:ui lane is off duty, so a future seat picks it up from the queue.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Transferred 2026-10-26T04:53Z from objectstack-ai/objectui#13183, with its comments and timeline; the old URL redirects here. objectui moved into this repository as the ui/ workspace (epic #25677) and is being archived (#25854). The body is left exactly as filed.

    Paths. Read every repository path in the body with a ui/ prefix: packages/plugin-grid/src/components/BulkActionDialog.tsx is now ui/packages/plugin-grid/src/components/BulkActionDialog.tsx.

    References. The bare issue numbers in the body were written in objectui and now resolve against this repository by mistake; read them as objectstack-ai/objectui#45.

    No stale pm:dispatched or assignee to strip.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: re-grade — enhancement · area:records added · blocker moot · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-26T06:13Z

    ⛔ Not a claim, ⛔ not a dispatch. Re-grade after the transfer from objectui (#25854). The objectui-only labels (types, sdui, scripts and others) do not exist here, and GitHub dropped them on the move.


    Generated by Claude Code

  5. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    enhancementNew feature or request
    and removed on Oct 26, 2026
  6. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-26T08:37Z
    Session: session_01SMps7wq7rBTk53e8KTSEup (the seat; the card thread that implements it works on the branch below)
    Account: os-steve
    Branch: claude/project-thread-0ml7qr (platform-assigned card-thread branch; a card thread can push only its assigned branch and the name carries no card number, so this claim is the identity record. Step 1 lands from it first; step 2 continues on the same branch after step 1 merges, from a fresh merge of main)
    Worktree: objectstack-project-thread-0ml7qr
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: ui/packages/plugin-grid/src/components/BulkActionDialog.tsx (the confirm sentence and, in step 2, the param display values it needs), ui/packages/plugin-grid/src/components/bulkConfirmText.ts (the fill helper), their tests; scripts/sdui-manifest.record.json (re-record); root .changeset/25942-bulk-confirm-holes.md (stop on breach; explain in the report). ⛔ ui/packages/plugin-grid/src/ObjectGrid.tsx is not touched. ⛔ ui/.github/** and the root .github/workflows/ci.yml are out of bounds (maintainer's word).
    Container & model: S + M (two PRs), mode:thread, model: default tier (dispatch-gates --tier --repo objectstack-ai/objectstack: no path-derived mandate), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6409517237
    Ruling-ref: 6285948976
    Premise: holds 2026-10-26T08:25Z — on origin/main 05f7758f05 BulkActionDialog.tsx renders the confirmText source verbatim; the spec types it as a template slot with the bulk-confirm roots and states the param display-value rule, so step 2 is no longer gated
    Serial constraints cleared: none — no open claim holds BulkActionDialog.tsx or bulkConfirmText.ts (seat 1's #25858 and #25898 hold ObjectGrid.tsx regions this card does not edit).
    Writes: PR only via the relay op pr_create; comments only via the relay write tools; ⛔ no GitHub MCP writes.

  7. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 25942,
      "status": "done",
      "branch": "claude/project-thread-0ml7qr",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26030",
      "session": "session_016zsTRTJ3SP3dpjEkyLrzWS",
      "premise_still_valid": true,
      "summary": "Step 1 of ruling B (Part of #25942): plugin-grid bulkConfirmText(confirmText, { count }) reads the slot through bulkConfirmTextSource and, when the sentence has a {{ }} hole, fills it through @object-ui/core fillTemplateHoles over { [BULK_CONFIRM_COUNT_ROOT]: rows.length } (the spec constant from @objectstack/spec/ui). BulkActionDialog renders its confirm description through it; default sentence and confirm-step position unchanged. The 13183 dialog test that pinned {{ count }} printed verbatim now expects it filled. Param holes print empty until step 2 (Fixes #25942), which the claim puts on this same branch after this PR merges. Premise checks on origin/main 05f7758f: BulkActionDialog.tsx:413 rendered bulkConfirmTextSource verbatim; core exports hasTemplateHoles/fillTemplateHoles; spec exports BULK_CONFIRM_COUNT_ROOT and bulkConfirmTemplateRoots - all held.",
      "tests": "At head b8e5134c: (1) cd ui && pnpm exec vitest run --maxWorkers=2 on bulkConfirmCount-25942.test.tsx + bulkConfirmTextEnvelope-13183.test.tsx -> Test Files 2 passed, Tests 20 passed (lock VERDICT command-exit 0). (2) Ablation after commit 812c71ec via scripts/ablation-replace.mjs: render site back to bulkConfirmTextSource(def.confirmText), anchor 1 -> 0, blob c1b43e1f66ea -> 2e7497c942ea -> Tests 3 failed | 17 passed (the three dialog fill tests); restored to blob c1b43e1f66ea, git status --porcelain empty. No build leg: tests import the dialog by relative path. (3) Whole package under the lock: cd ui && pnpm exec vitest run --maxWorkers=2 packages/plugin-grid/ -> Test Files 248 passed (248), Tests 2213 passed (2213), VERDICT command-exit 0 (10m56s). (4) pnpm --filter @object-ui/plugin-grid run type-check (tsc --noEmit && tsc -p tsconfig.test.json) -> exit 0 after pnpm --filter '@object-ui/plugin-grid^...' run build (VERDICT 0).",
      "gates": "Local at b8e5134c (after the last commit): node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack -> 46 commands, each run with its exit captured before any pipe: all 46 exit 0 (incl. check-sdui-manifest, check-adr-0087-registration --base origin/main, check-empty-changeset, check-changeset-no-major, check:published-files, check:type-check-coverage/debt, check:cross-package-test-inputs, check:test-source-alias, check:nul-bytes). --ran with exit codes -> 46 derived, 46 run, 0 NOT-MEASURED, 0 UNRUN. node scripts/gen-sdui-manifest-node.mjs re-recorded scripts/sdui-manifest.record.json (sha256 b450a090e265, 922 sources / 27 packages); check-sdui-manifest exit 0. CI check-runs on PR #26030: in_progress at report time (not waited on). Type-check lanes, Test Core and repo-wide scans are CI's.",
      "dogfood_battery": "n/a - no ! in the PR title and Clause-2 carries no (narrowing) arm",
      "mcp_calls": "3 - mcp__github__issue_read x3 (get #25942, get_comments #25942 twice); reads only, zero MCP writes",
      "api_writes": "2 relay strokes as objectstack-fleet[bot]: (1) pr_create via scripts/pm/with-fleet.sh --via dispatch (POST /repos/objectstack-ai/objectstack/dispatches -> run 40302038174 -> POST /repos/objectstack-ai/objectstack/pulls draft #26030 + POST /repos/objectstack-ai/objectstack/issues/26030/assignees os-steve; read-back 4873 bytes identical); (2) this os-dev-report comment via post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/25942/comments). Plus git push x2 (not REST). Zero label writes (none named; a patch changeset is present so no skip-changeset).",
      "open_questions": [
        {
          "question": "Step 2 formatter locale: @objectstack/formula templateEngine reads its formatter locale from ctx.extra.locale, the same object fillTemplateHoles passes the roots in, so a bulk param named locale would set the locale of every formatter in the sentence (and fillTemplateHoles offers no locale argument, so formatters render en-US). How should step 2 handle it?",
          "options": [
            "A: step 2 adds an optional { locale } argument to core fillTemplateHoles passed as ctx.locale, and drops a root named locale from extra before the call while still resolving {{ locale }} through a renamed scope - touches ui/packages/core (seat 1 territory)",
            "B: fix at the engine: formula reads the formatter locale only from ctx.locale, never from extra (a packages/formula change, separate card), step 2 then passes the UI locale",
            "C: step 2 keeps en-US and documents the hijack as an acceptance note"
          ],
          "recommendation": "B, because the defect is the engine using a data scope key as config; A needs a scope rename hack in core. If B is a separate card, step 2 ships with A's locale argument only and leaves the hijack to that card."
        }
      ],
      "out_of_scope_findings": [
        "carrier: step 2 PR of #25942 (this branch) - the extra.locale formatter-locale coupling in @objectstack/formula templateEngine (packages/formula/src/template-engine.ts evaluate: locale read from ctx.extra.locale); noted, not filed; dedupe words: template engine extra locale, formatter locale hijack, fillTemplateHoles locale"
      ],
      "deviations": "(1) Commits carry the model-free Claude-Session + Co-authored-by pair per AGENTS.md, not the harness's model-named trailer. (2) The relay read of the card (with-fleet --read) refused in this shell (exit 3, no mint), so the card was read with three MCP read calls."
    }

    Generated by Claude Code

  8. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Pointer · domain:ui seat 2 · 2026-10-26T09:48Z

    Step 1: ACCEPT → PR #26030 comment 6413030469 (head b8e5134c). The PR is waiting on a merge of main (it conflicts) and then green checks. Step 2 follows on the same branch after it merges.

  9. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed (step 1 of 2) · seat 2 · 2026-10-26T15:19Z

    probe reading
    PR #26030 MERGED 2026-10-26T15:16Z, merge commit 66769910, head 7a579f9f (plugin-grid re-record after #26120)
    origin/main at 7111e14a, contains 66769910 (git merge-base --is-ancestor exit 0)
    queue branch gh-readonly-queue/main/pr-26030-*: none left (consumed)
    card open, because #26030 is Part of #25942

    Status: step 1 is done. Step 2 continues on the same card thread from current main. The locale question is ruled B: an engine fix on its own card, not folded into this one. The card stays pm:dispatched.

  10. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 25942,
      "status": "done",
      "branch": "claude/project-thread-0ml7qr",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26217",
      "session": "session_016zsTRTJ3SP3dpjEkyLrzWS",
      "premise_still_valid": true,
      "summary": "Step 2 (Fixes #25942), on the same branch after #26030 merged as 66769910. The branch was brought level with origin/main 7111e14a by merge (tree diff vs main empty, no force-push), and step 2 was committed on top. plugin-grid bulkConfirmText now fills the spec's closed scope (bulkConfirmTemplateRoots): count, then each param bound to bulkConfirmParamDisplayValue. An option-bearing param gives the option label (multi-value joined with ', '). A lookup/user param gives the confirm step's resolved record name, or the id until that resolves. Any other param gives the raw entered value, so formatters apply. Empty values are undefined. count is written last, so it wins. BulkActionDialog passes params, values and lookupLabels, so the sentence re-renders when lookup names arrive. describeValue is untouched. The locale question is ruled B by the seat (engine fix on its own card) and is not folded in.",
      "tests": "At head 4a874ae1: (1) cd ui && pnpm exec vitest run --maxWorkers=2 on bulkConfirmParams-25942 (new, 10 tests) + bulkConfirmCount-25942 + bulkConfirmTextEnvelope-13183 -> Test Files 3 passed, Tests 30 passed (VERDICT 0). (2) Ablations after commit aaf4a4ac via scripts/ablation-replace.mjs under the lock. Leg A: the dialog scope cut back to { count: rows.length } (anchor 1->0, blob 76a683a69c71 -> c1b43e1f66ea) -> Tests 2 failed | 8 passed (both dialog tests). Leg B: the display value returned raw (anchor 1->0, blob 393b2f5ce8bb -> 557d7171d747) -> Tests 5 failed | 5 passed. Both legs were restored to their HEAD blobs and git status --porcelain was empty. No build leg was needed, because the tests import by relative path. (3) Whole package under the lock: cd ui && pnpm exec vitest run --maxWorkers=2 packages/plugin-grid/ -> Test Files 251 passed (251), Tests 2246 passed (2246), VERDICT 0 (11m46s). (4) One lock run (VERDICT 0, 13m59s) did pnpm --filter '@object-ui/plugin-grid^...' run build, node scripts/gen-sdui-manifest-node.mjs (only scripts/sdui-manifest.sources/plugin-grid.json changed), check-sdui-manifest exit 0, and pnpm --filter @object-ui/plugin-grid run type-check exit 0.",
      "gates": "Local at 4a874ae1, after the last commit: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack -> 47 commands, each exit captured before any pipe, all 47 exit 0. --ran with exit codes -> 47 derived, 47 run, 0 NOT-MEASURED, 0 UNRUN. CI check-runs on #26217 were in_progress at report time and were not waited on. Per the seat, the PR enqueues only after #26033 and #26050 merge.",
      "dogfood_battery": "n/a - no ! in the PR title and Clause-2 carries no (narrowing) arm",
      "mcp_calls": "0 this round",
      "api_writes": "2 relay strokes as objectstack-fleet[bot]: (1) pr_create via scripts/pm/with-fleet.sh --via dispatch (run 40354305266 -> POST /repos/objectstack-ai/objectstack/pulls draft #26217 + POST /repos/objectstack-ai/objectstack/issues/26217/assignees os-steve; read-back 5126 bytes identical); (2) this os-dev-report comment via post-stamped.mjs (POST /repos/objectstack-ai/objectstack/issues/25942/comments). Plus git push x2 (not REST). Zero label writes.",
      "open_questions": [],
      "out_of_scope_findings": [
        "Ruled B by the seat, to go on its own card for the seat to file: @objectstack/formula templateEngine.evaluate reads the formatter locale from ctx.extra.locale, the same object fillTemplateHoles passes template roots in. A bulk param named locale therefore sets the formatter locale of the whole sentence, and formatters otherwise render en-US. Seam: runtime packages/formula/src/template-engine.ts evaluate -> renderer ui/packages/core/src/actions/actionCopyTemplate.ts fillTemplateHoles. Dedupe words: template engine extra locale, formatter locale hijack, fillTemplateHoles locale"
      ],
      "deviations": "(1) Commits carry the model-free Claude-Session + Co-authored-by pair per AGENTS.md. (2) The seat asked for a fresh branch from origin/main. The platform assigns this thread one branch, so the branch was brought level with main by a merge (no force-push, because AGENTS.md section 3 criterion 1 fails for a non claude/issue-* name), and its diff vs main is step 2 only (5 files, +252/-12)."
    }

    Generated by Claude Code

  11. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · seat 2 · 2026-10-26T19:54Z

    probe reading
    PR #26217 MERGED 2026-10-26T19:54Z, merge commit ef5d0a4a, head 019fe1a8 (+252/−12, ACCEPT 6421338109)
    origin/main at b3ed6c86, contains it (git merge-base --is-ancestor exit 0)
    queue branch gh-readonly-queue/main/pr-26217-*: none left (consumed)
    card closed (completed); both steps are on main

    Status: a bulk action's confirmText now fills the template slot with the declared scope and the parameter's display value (bulkConfirmTemplateScope / bulkConfirmParamDisplayValue). The plugin-grid line moves to #25884. The out-of-scope locale finding from step 2 still needs its own engine card (ruling B). 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, searchdomain:uienhancementNew feature or requestpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions