Skip to content

fix(plugin-grid): fill a bulk confirmText's param holes with the params' display values - #26217

Merged
objectstack-fleet[bot] merged 17 commits into
mainfrom
claude/project-thread-0ml7qr
Oct 26, 2026
Merged

objectstack-fleet[bot] merged 17 commits into
mainfrom
claude/project-thread-0ml7qr

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread
Fixes #25942
Clause-②: no
Metadata-protocol: none

What

Step 2 of ruling B on #24798, the renderer half. Step 1 was #26030, merged as 66769910. A bulk action's confirmText hole that names one of the def's params is now filled with that param's display value, following the rule the spec states on the slot (packages/spec/src/ui/bulk-action.zod.ts, the confirmText describe).

  • ui/packages/plugin-grid/src/components/bulkConfirmText.ts:
    • bulkConfirmParamDisplayValue(param, value, lookupLabels):
      • an option-bearing param shows the chosen option's label, and a multi-value param shows its labels joined with ', ';
      • a lookup / user param shows the picked record's display name from the confirm step's resolved names, and the id until that name resolves;
      • any other param is returned as the entered value itself, not a string, so the engine's whitelisted formatters apply ({{ amount | currency:EUR }}, {{ due | date:iso }});
      • an empty value is undefined, so it prints empty and {{ x | default:'none' }} can name it.
    • bulkConfirmTemplateScope(scope) builds the roots over the spec's closed scope, bulkConfirmTemplateRoots. It writes count last, so count wins over a param of that name, as the spec declares.
    • bulkConfirmText(confirmText, { count, params, values, lookupLabels }) fills the slot through fillTemplateHoles, exactly as in step 1.
  • BulkActionDialog.tsx passes params, values and lookupLabels into the confirm sentence. The lookup names that resolve after the confirm step opens re-render the sentence, because it is computed in render.
  • scripts/sdui-manifest.sources/plugin-grid.json is re-recorded (node scripts/gen-sdui-manifest-node.mjs). Nothing else in the manifest set moved.
  • Changeset: .changeset/25942-bulk-confirm-param-holes.md, @object-ui/plugin-grid patch.

The ruling, verbatim: "Nothing else moves: no CEL inside holes, no change to the default text, no change to where the confirm step sits." The default sentence, the confirm step and the value summary under it (describeValue) are untouched, and the display value is computed apart from describeValue, whose output is a string and would not take a formatter.

Verification (head 4a874ae1)

  • New file bulkConfirmParams-25942.test.tsx, with 10 tests:
    • helper: option label; multi-value labels joined; a value no option declares; a lookup's resolved name, and its id before that; currency, number and date formatters on the raw value; an empty param printing empty and the default formatter naming it; count winning over a param named count; a hole outside the closed scope printing empty.
    • dialog: the option label the params step chose (Move 2 account(s) to Silver?), and a lookup name arriving after the step opened (… to u1?, then … to Ada Lovelace?, with findOne('sys_user', 'u1')).
  • Confirm-sentence files together (bulkConfirmParams-25942, bulkConfirmCount-25942, bulkConfirmTextEnvelope-13183): Test Files 3 passed, Tests 30 passed.
  • Ablations after commit aaf4a4ac, run with scripts/ablation-replace.mjs; each leg was restored to its HEAD blob and git status --porcelain came back empty:
    • dialog scope cut back to { count: rows.length } (anchor 1 → 0, blob 76a683a69c71 → c1b43e1f66ea): Tests 2 failed | 8 passed (both dialog tests).
    • display value returned raw, without labels (anchor 1 → 0, blob 393b2f5ce8bb → 557d7171d747): Tests 5 failed | 5 passed.
    • No build leg was needed, because the tests import the dialog and helper by relative path.
  • Whole package under the lock: cd ui && pnpm exec vitest run --maxWorkers=2 packages/plugin-grid/ gave Test Files 251 passed (251), Tests 2246 passed (2246), VERDICT command-exit 0.
  • pnpm --filter @object-ui/plugin-grid run type-check exited 0, after pnpm --filter '@object-ui/plugin-grid^...' run build, under the same lock run as the re-record. node scripts/check-sdui-manifest.mjs exited 0.
  • Derived gates at 4a874ae1: 47 commands, all exit 0. --ran with exit codes reports 47 derived, 47 run, 0 NOT-MEASURED, 0 UNRUN. CI owns the type-check lanes, Test Core and the repo-wide scans.

Acceptance notes

  • Formatter locale. The engine reads its formatter locale from the same scope the roots are passed in, so the formatters render en-US, and a param named locale would set the locale for the whole sentence. The seat ruled that this is fixed in the engine on its own card, so it is not folded in here.
  • Params with no options. A boolean param shows true / false, and an array value on a param with no options is joined with ', '. Both follow the spec's "the entered value otherwise".
  • Not touched: ObjectGrid.tsx, ui/.github/** and the root ci.yml.

Generated by Claude Code

claude added 15 commits October 26, 2026 08:45
… run's record count

The bulk dialog printed an authored confirmText as written, so a template
slot's {{ count }} reached the person as braces. bulkConfirmText now fills
the slot over the protocol's bulk-confirm count root through core's
fillTemplateHoles (the shared template engine, whitelisted formatters, no
logic), keeping a hole-less sentence, the default sentence and a refused
source as they were. Param roots stay unbound at this step.

Claude-Session: https://claude.ai/code/session_016zsTRTJ3SP3dpjEkyLrzWS
Co-authored-by: Claude <noreply@anthropic.com>
…-0ml7qr

# Conflicts:
#	scripts/sdui-manifest.record.json
…-0ml7qr

# Conflicts:
#	scripts/sdui-manifest.record.json
…-0ml7qr

# Conflicts:
#	scripts/sdui-manifest.record.json
…-0ml7qr

# Conflicts:
#	scripts/sdui-manifest.record.json
…-0ml7qr

# Conflicts:
#	scripts/sdui-manifest.record.json
…ms' display values

bulkConfirmText now fills the protocol's whole bulk-confirm scope
(bulkConfirmTemplateRoots): count, then each param bound to its display
value: option label (multi joined with ', '), a picker's resolved record
name (the id until it resolves), the entered value otherwise so the
engine's formatters apply. count wins over a param of that name.

Claude-Session: https://claude.ai/code/session_016zsTRTJ3SP3dpjEkyLrzWS
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对

ACCEPT · domain:ui seat 2 · session_01SMps7wq7rBTk53e8KTSEup · 2026-10-26T16:27Z · head 4a874ae1

  1. 形态 (shape): a draft PR into main, assigned to os-steve. The body leads with Fixes #25942, because this is step 2 and the card closes with it. The diff against main is step 2 only: 5 files, +252/−12. Those are bulkConfirmText.ts, a one-line change in BulkActionDialog.tsx, the new bulkConfirmParams-25942 test, the root .changeset/, and scripts/sdui-manifest.sources/plugin-grid.json. That is inside the claim's surface.
  2. 前提实测 (premise, measured): the seat read the diff at this head.
    • bulkConfirmTemplateScope fills exactly the protocol's closed root set, bulkConfirmTemplateRoots. count is written last, so it wins over a param of the same name, as declared.
    • bulkConfirmParamDisplayValue follows the confirmText display rule:
      • an option-bearing param shows the option label;
      • a lookup or user param shows the resolved name, or the id until the name arrives (the dialog re-renders when it does);
      • anything else passes the raw value through, so formatters apply;
      • a multi-value param is joined with , ;
      • an empty value is undefined.
    • describeValue is untouched.
    • Evidence: 30/30 confirm tests pass. Both ablation legs went red (2 and 5 failures). The plugin-grid suite passes, 251 files / 2246 tests.
  3. 门禁 check-runs (gates): landing waits until every check is green. One known red on PR CI is main's and not this PR's: the MetadataService ObjectSchema key-count guards, expected 48 to be 47, whose fix is app-shell: MetadataService.retiredObjectEnabled corpus guard expects 47 ObjectSchema keys, main now has 48 after #26005 added sharing, so Test UI is red for every ui PR #26218.
  4. 接受的偏差 (accepted deviation): the branch is the card thread's assigned branch, brought level with main by a merge with no force-push, rather than a fresh branch. Accepted, because the diff against main is step 2 only.
  5. 范围外去向 (out of scope): the formatter-locale finding (ctx.extra.locale shares the template roots) is ruled B and filed as action copy templates: a bulk param named locale sets the formatter locale of the whole confirm sentence, because the template engine reads its locale from the same extra roots #26232. It is not folded in here.
  6. 落地条款 (landing terms):

…-0ml7qr

# Conflicts:
#	scripts/sdui-manifest.sources/plugin-grid.json
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Seat 2 · head update · 2026-10-26T18:46Z

Patch round at head 019fe1a8: merge of origin/main at 9598405e (merge commit f303357c; sources/plugin-grid.json taken from main), then a re-record under the lock that moves sources/plugin-grid.json only. The diff against main is unchanged (5 files, +252/−12) and no product or test logic changed since the ACCEPT (6421338109).

check reading
check-sdui-manifest exit 0
Console build 71/71 tasks
plugin-grid suite 251 files / 2247 tests passed
dispatch gates 47 derived, 47 run, all exit 0
line plugin-grid #26030 ✓ → #26033 ✓ → #26050 ✓ → this
drift no commit on main touches plugin-grid or its sources record since 9598405e; git merge-tree clean
governance NOT governed

Seat's route: ready + auto-merge. #25884 follows on the plugin-grid line.

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

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

2 participants