Repository navigation
feat(console): ownership queues in the Console — two-source queue pickers, Claim on a queued record, an In-a-queue list filter, and the authoring guide (ADR-0142) - #27264
Merged
Conversation
…e sharing-rule recipient (ADR-0142 D6/D7) Claude-Session: https://claude.ai/code/session_01WGufzfFCwcM21eGjVuqwRz Co-Authored-By: Claude <noreply@anthropic.com>
…t filter (ADR-0142 D3/D4) Claude-Session: https://claude.ai/code/session_01WGufzfFCwcM21eGjVuqwRz Co-Authored-By: Claude <noreply@anthropic.com>
…n-a-queue filter (ADR-0142) json-schema-to-fields now keeps a whole registry-and-data binding, so a published two-source queue binding reaches the approver picker. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzfFCwcM21eGjVuqwRz
…als, sharing rules and RLS (ADR-0142) Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzfFCwcM21eGjVuqwRz
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzfFCwcM21eGjVuqwRz
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
…s — null or '' Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzfFCwcM21eGjVuqwRz
…er, and the record page's Claim as answered by explain, not an object grant Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzfFCwcM21eGjVuqwRz
Contributor
Author
维护者速读 (席位终稿)
席位意见:接受。四面都没碰(没有 席位核对 · ACCEPT ·
|
os-zhuang
pushed a commit
that referenced
this pull request
Oct 28, 2026
Conflicts: - ui/packages/plugin-detail/src/synth/buildDefaultPageSchema.ts: main retired the `slots.tabs` slot (#27219) while this branch rewrote the `discussion` slot to the timeline stream and deleted `rightRail`; the resolution keeps main's no-tabs-slot doc and branch, this branch's timeline-stream `discussion` doc, and no `rightRail`. - ui/packages/app-shell/src/views/RecordDetailView.tsx: the `@object-ui/plugin-detail` import line takes the union of main's queue claim imports (#27264) and this branch's timeline/arrangement imports. Claude-Session: https://claude.ai/code/session_cdb7a717def74e719988f089fbaa18ff Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Yibo Wang · project thread
Part of #25769
Ruling-ref: ADR-0142 accepted by the maintainer's merge of #25816 (2026-10-26T06:44:50Z); this PR carries its Execution plan items 3 (Console) and 4 (docs). Item 2, the HotCRM STOPGAP delete, remains on its own lane, so #25769 stays open.
Clause-②: no
Metadata-protocol: none
Skills-docs: none here.
skills/**is out of scope (Tier H); the skills-side teaching of queues and assignment rules is owed to #26475.维护者速读
sys_queue;坐在队列里的记录头部出现「认领」,只在服务端 explain 对 transfer 回答queue_claim: admits时显示,点击即发{ owner_id: 自己 };列表工具栏新增「在队列中」筛选(owner_id为空且queue有值)。另加一篇作者指南content/docs/automation/queues-and-assignment-rules.mdx。queue系统列时出现。回滚即还原本 PR。ui/packages/plugin-detail/src/queueClaim.ts、ui/packages/app-shell/src/views/RecordDetailView.tsx(认领)、ui/packages/plugin-list/src/ListView.tsx(筛选)、ui/packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.tsx(审批人选择器)。cd ui && pnpm exec vitest run packages/plugin-detail/src/queueClaim-25769.test.tsx packages/plugin-list/src/__tests__/ListView.queueSittingFilter-25769.test.tsx packages/fields/src/widgets/RecipientPickerField.queue-25769.test.tsx packages/app-shell/src/views/metadata-admin/inspectors/FlowReferenceField.queuePicker-25769.test.tsx,预期 4 个文件 36 条全绿。What changes
@object-ui/fieldsgainsmergeQueueCandidates/queueCandidateLabel(one list by machine name, declared first, ordered by name) and aRECIPIENT_REGISTRY_AND_RECORD_KINDStable.RecipientPickerFieldlists aqueuerecipient from the metadata store'squeueitems andsys_queuerows (find('sys_queue', { $top: 500, $orderby: { name: 'asc' } })) and stores the name; with either reader missing it keeps the text input. The read face (refLabelDirectory) names a stored queue the same way. In@object-ui/app-shell,FlowReferenceFieldreplaces the "until the console's two-source queue picker lands" placeholder withTwoSourcePickCell, driven by the binding the server publishes (registry-and-data, or the bundled spec's when nothing is published);json-schema-to-fieldsnow keeps a wholeregistry-and-databinding instead of dropping it. A server that publishes anything else forqueuekeeps the old text cell.@object-ui/plugin-detailaddsqueueClaim.ts:recordSitsInQueue(owner empty and a queue named),useQueueClaimOffered(asksPOST /api/v1/security/explain { operation: 'transfer' }and offers only on aqueue_claimrule witheffect: 'admits'; fails closed) andclaimQueuedRecord(sends{ owner_id: <self> }throughupdate; a409 CONCURRENT_UPDATEistaken).RecordDetailViewadds asys_claimheader action on that answer, toasts claimed / taken / refused, and invalidates the record.@object-ui/plugin-listListViewoffers a toolbar toggle only when the served object definition carries the injectedqueuecolumn (system: true). Pressed, it AND-s['owner_id','is_empty',true]and['queue','is_not_empty',true](lowered to$empty) into the fetch, the self-querying views and the export. Empty means null or''on both columns, as the explain engine and the assignment seam read it.fields.recipient.selectQueue,detail.claim/claimed/claimTaken/claimFailed,list.sittingInQueue/sittingInQueueHintin all 10 locales;engine.inspector.reference.pickFromQueuesin the studio en/zh namespaces.content/docs/automation/queues-and-assignment-rules.mdx: declaring a queue and an assignment rule, theloadrequirement, what a parked record is and who sees it, how a claim is spelled (and release / move), and that a queue is not a messaging audience. Linked fromautomation/index.mdx,automation/approvals.mdx,permissions/sharing-rules.mdx(the recipient table gains itsqueuerow) andpermissions/rls.mdx(current_user.queues). The generatedreferences/automation/assignment-rule.mdxis not touched;scripts/docs-audit/handwritten-docs.jsonregenerated by its own--write..changeset/25769-console-queue-affordances.md: patch on@object-ui/fields,@object-ui/app-shell,@object-ui/plugin-detail,@object-ui/plugin-list,@object-ui/i18n.Tests
RecipientPickerField.queue-25769.test.tsx(7): the merge helper's order, collisions and shapes; the picker's two requests, both sources listed and a shadowing row hidden, the stored name, one failing source still offering the other, and the text input with no store (nofindcall).FlowReferenceField.queuePicker-25769.test.tsx(9):json-schema-to-fieldskeeps a whole binding and drops a half one;twoSourceForprecedence; with an adapter,metaList('queue')andfind('sys_queue', …), both options listed, the chosen name committed; a stored name neither lists shown flagged(not found); manual entry and back; no adapter reads nothing; another published binding keeps the text cell.queueClaim-25769.test.tsx(12): sits-in-queue for owned / unowned / no queue;queueClaimAdmittedtrue only onqueue_claim+admits(not a visible transfer, notqueue_membership, not a malformed answer); the hook's POST body, no button onneutral, a non-OK or thrown probe, no probe for a non-sitting record or an unknown user; the write is{ owner_id }only, a 409 istaken, a 403 isrefusedwith its error.ListView.queueSittingFilter-25769.test.tsx(8):objectHasOwnershipQueue(map and array forms, a non-systemqueuerefused); the two triples pinned asis_empty/is_not_empty;buildEffectiveFilterwith and without the conditions; the toggle renders on an injected column and its press and release change the fetch$filter; no toggle without the injected column.Acceptance notes
queueis claimable on the server by anyone with a positive sharing basis (D4), but the Console offers Claim only on a record that sits in a queue, as plan item 3 names it.sys_queueat 500 rows by name, as the record pickers do.queueapprover outside the editor) is unchanged and shows the name.Verification
Head
e3e83a00, merge baseae16687a. Every locked run is read from itsVERDICT command-exitline.VERDICT command-exit 0).os-verify-lock:plugin-detail+i18n+ thefieldsrecipient/queue files, 416 files, 4361 passed / 31 skipped; the app-shell scope (FlowReferenceField*,json-schema-to-fields*,flow-node-config*,utils/approverValueSources*,widget-ref-cells,RecordDetailView*), 103 files, 945 passed / 1 skipped;plugin-listwhole, 168 files, 1675 passed. EachVERDICT command-exit 0. A single combined run of all of them hit the session's 30-minute limit and was split, not narrowed.type-check(tsc --noEmit+tsc -p tsconfig.test.json) of@object-ui/fields,plugin-detail,plugin-list,i18n,app-shell: eachVERDICT command-exit 0.node scripts/pm/dispatch-gates.mjs --commands: 78 commands, allexit 0. Four were run twice.check:role-wordfoundrole:in the new guide; the wording was fixed in4dde047e, and it exits 0. Threescripts/tests timed out at 15s while the locked suites shared the box; on a quiet box, the two files exit 0 and the wholescripts/run passes 5019 tests with 2 skipped.check:skill-examplesexited 3 becauseclient-reactwas not built; after that build it exits 0.check:type-check-debtexited 3 because it got no turn on the lock; run under the lock, it exits 0.dispatch-gates --ran: 78 derived, 78 run, 0 NOT-MEASURED, 0 UNRUN.@object-ui/plugin-formwrite census (affordanceGrantMap-12082, red on CI at58d26514) grades the two new write sites:claimQueuedRecordis a write helper, and the record page'shandleClaimisoutOfFamily, because a claim is admitted from the row's own sharing verdict, not an object grant, and is offered only on the explain answer. Run locked: 55/55 pass, and theplugin-formtype-check givesVERDICT command-exit 0.check:doc-authoring,check-adr-links,check-doc-frontmatter, andcheck:docs-audit-scopeexit 0. Every new/docs/…link resolves to a page in the tree.Check Documentation Links(lychee) runs in CI.Generated by Claude Code