…, decision-only pin gap, record-edit-undo premise
Seven ledger items, each at revision +1 with one appended history row:
- approvals.viewer-gating-submitter-side, notification-deep-link,
dynamic-approver-routing and inbox-keyboard-flow read the request's
served record page (/apps/APP/sys_approval_request/record/ID) instead of
the side drawer objectui#12484 deleted. The keyboard item drops the
drawer's left/right walk and its drawer-sheet guard, both removed with it.
- approvals.approver-resolution-matrix: the queue leg follows ADR-0142 D6
(PR #26337) — members at node entry; an empty queue warns, adds no slot,
and admin_rescue opens on the administrators with an empty abandoned slate.
- approvals.decision-only-via-service: no pin drives the generic resume
route plus the approvals API on a booted stack; the gap is re-measured and
kept, naming the layer pins found.
- records-forms.record-edit-undo: BLOCKED premise re-checked and kept.
Claude-Session: https://claude.ai/code/session_01QSeKYmtLvHnqZSNJgjpKRv
Co-authored-by: Claude <noreply@anthropic.com>
Part of #25807 (wave-2 accuracy, slice C)
Clause-②: no
Metadata-protocol: none
维护者速读
origin/main重写:4 个仍描述已退役请求抽屉的审批项改为请求记录页;queue 审批人一项改为"展开为队列成员";decision-only 与 record-edit-undo 两项复核后保留缺口/阻塞。docs/qa/platform-checklist/areas/approvals.json中的inbox-keyboard-flow(删除子句)、approver-resolution-matrix(queue 子句改义)、notification-deep-link(未知 id 的落点改义)。node scripts/check-platform-checklist.mjs,预期输出OK — 16 areas, 329 items。What changes
Seven items, each at
revision+1 from main, main'shistorykept as an exact prefix, and exactly one appended row citing its source. Every edit was read against the tree at basef2fdac5d. Leads come from slice B's report (comment 6457925443,out_of_scope_findingsitems 2, 3 and 5).What replaced the drawer. The inbox opens a request by navigating to its served record page,
/apps/APP/sys_approval_request/record/ID. This covers a row click, a mobile card, Enter on the focused row, and the?request=IDdeep link, which replaces itself in history.ui/apps/console/src/pages/system/ApprovalsInboxPage.tsx,requestPagePathandApprovalsInboxPage.sys_approval_request_detail(packages/plugins/plugin-approvals/src/sys-approval-request.page.ts). Its decision panel drawssys_approval_request's declared actions by theirvisiblepredicates overrecord.viewer(sys-approval-request.object.ts).approvals.viewer-gating-submitter-sideapprovals.notification-deep-linkactionUrl) is unchanged.approvals.dynamic-approver-routingdecisionOutputParams.tsis added as a source. No clause changed.approvals.inbox-keyboard-flowapprovals.approver-resolution-matrixlog→api), variants[9], and the queue notes in source[0] and source[1].approvals.decision-only-via-serviceautomatedstays absent. knownGaps[0] now names the layer pins the search found and where a pin could land. No clause changed.records-forms.record-edit-undoblockedis unchanged. requires[0] says the reading is current. knownGaps[1] records the re-check and the twoundoableshapes the spec now accepts. No clause changed.Queue (ADR-0142 D6).
queueapprover expands to the queue's members at node entry, through theownership-queueservice (approval-service.tsresolveApproverSpec,expandQueueUsers).queue:VALUEliteral is never written. So on an empty queue, the admin_rescue request's__resolvedFrom['admin_rescue:abandoned']is[], with the reason 'no approver on the node resolved to a person'.sys_queueandsys_queue_memberrows (bothmanagedBy: 'config', admin-authored).queueis no longerxEnumDeprecated.decision-only-via-service: why there is no pin. The tree has three kinds of layer pin. None of them drives the generic resume route and the approvals API on a booted stack:
resume-authority-gate.test.ts: an engine unit over a stand-in gated node.approval-node.test.ts: the real ApprovalService and AutomationEngine in process, with no route.http-dispatcher.test.tsandautomation-resume-caller-gate.test.ts: the route over a mocked automation service.Every clause's oracle is the api, so under RUNNER rule 6 none of these scores a clause.
record-edit-undo: why it stays BLOCKED.
examples/declares zeroundoablekeys, and no packaged action inpackages/declaresundoable: true.ui/packages/core/src/actions/ActionRunner.tspushes only an action result'sundo.ui-action-undoable-unfulfillable-refused,undoable: trueparses only withoperation: 'update'plus a patch, or withtype: 'api'. Either shape can be the fixture that lifts the block.Tests
No product code changed, so no package test is owed. Two service-layer pins were run as re-measurement evidence for the queue and decision-only rows (built closure:
pnpm --filter '@objectstack/plugin-approvals^...' build, lockVERDICT command-exit 0):pnpm --filter @objectstack/plugin-approvals exec vitest run --maxWorkers=2 src/approval-service.test.ts -t 'queue approver routes':Tests 4 passed | 382 skipped, lockVERDICT command-exit 0.pnpm --filter @objectstack/plugin-approvals exec vitest run --maxWorkers=2 src/approval-node.test.ts -t 'resume|owning service':Tests 5 passed | 13 skipped, lockVERDICT command-exit 0.The edits were made by a span editor. It re-parses each area file and asserts four things: the document equals the base with the declared edits applied, every other item and top-level key is value-equal, each touched item is at base revision + 1, and each touched item has exactly one appended history row with every earlier row equal.
Acceptance notes
f2fdac5d, and its history row says so. Where a clause changed meaning, the row says a prior verdict does not carry.ui/apps/console/src/registerApprovalsComponents.tsxstill says?request=IDreaches the page's "drawer opener". That is a stale code comment, with no behaviour behind it.approver-resolution-matrix, variants[9] and the two source notes changed beside steps[6] and acceptance[5]. Left alone, they would contradict the rewritten clause in the same item.Verification
At head
b2a41393f(after mergingorigin/maina27f889a0; the incoming commits touched no checklist file):checklist gate and selectors
node scripts/check-platform-checklist.mjs: exit 0,check-platform-checklist: OK — 16 areas, 329 items (324 active, 1 planned)node scripts/check-platform-checklist.mjs --self-test: exit 0,265 assertionsnode scripts/checklist-select.mjs area:approvals: exit 0,20 runnable item(s)node scripts/checklist-select.mjs area:records-forms: exit 0,44 runnable item(s) (1 blocked, hidden …). The hidden one isrecords-forms.record-edit-undo.derived gates (dispatch-gates --commands, 16)
Each was run with its exit captured before any pipe, and each exited 0:
check-adr-links(+--self-test),check-closing-keyword-parity(+--self-test),check-comment-mask-corpus,plan-test-core-shards --self-test,check:doc-formula-expressions,check:ci-filter-parity,check:cross-package-test-inputs,check:doc-authoring,check:driver-memory-census,check:gitlink-declared,check:nul-bytes,check:platform-checklist,check:refd-timer-probe,check:watch-hint-literal.dispatch-gates --ran:16 derived famil(ies) accounted for — 16 run, 0 NOT-MEASURED (a DERIVED zero — all 16 recorded an exit code and none of them is 3).This PR was opened by cloud session
session_01QSeKYmtLvHnqZSNJgjpKRv, dispatched under claim 6461679818.🤖 Generated with Claude Code
Generated by Claude Code