Skip to content

Commit e68669a

Browse files
docs(qa): wave-2 accuracy slice C — approvals drawer items, queue leg, decision-only pin gap, record-edit-undo premise (#27112)
Part of #25807 (wave-2 accuracy, slice C) Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:审批与记录表单两个清单区共 7 个测试项按 `origin/main` 重写:4 个仍描述已退役请求抽屉的审批项改为请求记录页;queue 审批人一项改为"展开为队列成员";decision-only 与 record-edit-undo 两项复核后保留缺口/阻塞。 - 为什么改:抽屉已被删除,请求改在记录页打开;queue 审批人已能解析成员。旧条目会让 QA 跑出假 FAIL,或把已删除的行为当作缺陷。 - 风险与回滚:只改 QA 台账 JSON,不碰产品代码,也不进 CI 门禁;回滚即 revert 本 PR。被删的子句(抽屉 ←/→ 漫游、抽屉打开时的键盘让位)随抽屉一起消失,history 行写明了出处。 - 先看:`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's `history` kept as an exact prefix, and exactly one appended row citing its source. Every edit was read against the tree at base `f2fdac5d`. Leads come from slice B's report (comment 6457925443, `out_of_scope_findings` items 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=ID` deep link, which replaces itself in history. - Code: `ui/apps/console/src/pages/system/ApprovalsInboxPage.tsx`, `requestPagePath` and `ApprovalsInboxPage`. - The page itself is `sys_approval_request_detail` (`packages/plugins/plugin-approvals/src/sys-approval-request.page.ts`). Its decision panel draws `sys_approval_request`'s declared actions by their `visible` predicates over `record.viewer` (`sys-approval-request.object.ts`). - The side sheet was deleted in objectui#12484 (ruling C on objectui#12438). It came into this tree with the ui/ import, PR #25825. | item | rev | change | |:--|:--|:--| | `approvals.viewer-gating-submitter-side` | 6→7 | steps[2] and acceptance[0] read the decision panel. The levers are named by their declared labels: Send reminder and Recall for the submitter, none of the five approver levers. The assertion is unchanged. | | `approvals.notification-deep-link` | 7→8 | The deep link lands on the request's record page on both routes (title, steps[3], [4], [7], acceptance[1]–[4], negative[0], source[3]). Two readings change: acceptance[1] may read the landing URL, which keeps the id, and acceptance[4]'s unknown id lands on that id's record page in its not-found state instead of the inbox. A prior verdict on acceptance[1]–[4] does not carry. acceptance[0] (the `actionUrl`) is unchanged. | | `approvals.dynamic-approver-routing` | 3→4 | steps[3] opens Approve in the request page's decision panel. `decisionOutputParams.ts` is added as a source. No clause changed. | | `approvals.inbox-keyboard-flow` | 2→3 | **Dropped, behaviour removed with the drawer:** the ←/→ drawer-to-drawer walk (revision 2's steps[2] and acceptance[4]'s first half) and the list handler's yield to an open drawer sheet (in steps[5] and acceptance[2]). The keyboard effect on main has no ArrowLeft/ArrowRight branch. It yields only to a decide dialog, a focused input and an alertdialog. Enter now opens the request page. acceptance[0] and [4] changed meaning. | | `approvals.approver-resolution-matrix` | 8→9 | The queue leg follows ADR-0142 D6 (PR #26337): see the next section. Also touched: steps[6], acceptance[5] (oracle `log` → `api`), variants[9], and the queue notes in source[0] and source[1]. | | `approvals.decision-only-via-service` | 4→5 | No pin found, so `automated` stays absent. knownGaps[0] now names the layer pins the search found and where a pin could land. No clause changed. | | `records-forms.record-edit-undo` | 4→5 | The BLOCKED premise holds and `blocked` is unchanged. requires[0] says the reading is current. knownGaps[1] records the re-check and the two `undoable` shapes the spec now accepts. No clause changed. | **Queue (ADR-0142 D6).** - A `queue` approver expands to the queue's members at node entry, through the `ownership-queue` service (`approval-service.ts` `resolveApproverSpec`, `expandQueueUsers`). - A queue that expands to nobody warns "approver 'queue:VALUE' expanded to nobody" and adds no slot. - The `queue:VALUE` literal 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'. - The leg gains a staffed arm: planted `sys_queue` and `sys_queue_member` rows (both `managedBy: 'config'`, admin-authored). - The designer note is dropped, because `queue` is no longer `xEnumDeprecated`. **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.ts` and `automation-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 zero `undoable` keys, and no packaged action in `packages/` declares `undoable: true`. - Inline edits still push no Undo op. `ui/packages/core/src/actions/ActionRunner.ts` pushes only an action result's `undo`. - Since the semantic migration `ui-action-undoable-unfulfillable-refused`, `undoable: true` parses only with `operation: 'update'` plus a patch, or with `type: '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`, lock `VERDICT 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`, lock `VERDICT 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`, lock `VERDICT 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 - Nothing here was driven live. Each rewritten clause is read from source at `f2fdac5d`, and its history row says so. Where a clause changed meaning, the row says a prior verdict does not carry. - Not a ledger edit, noted only: the docblock of `ui/apps/console/src/registerApprovalsComponents.tsx` still says `?request=ID` reaches the page's "drawer opener". That is a stale code comment, with no behaviour behind it. - Scope: within `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 merging `origin/main` `a27f889a0`; the incoming commits touched no checklist file): <details><summary>checklist gate and selectors</summary> - `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 assertions` - `node 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 is `records-forms.record-edit-undo`. </details> <details><summary>derived gates (dispatch-gates --commands, 16)</summary> 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)`. </details> This PR was opened by cloud session `session_01QSeKYmtLvHnqZSNJgjpKRv`, dispatched under claim 6461679818. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- _Generated by [Claude Code](https://claude.ai/code/session_01QSeKYmtLvHnqZSNJgjpKRv)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 685d9f3 commit e68669a

2 files changed

Lines changed: 83 additions & 61 deletions

File tree

0 commit comments

Comments
 (0)