Repository navigation
Commit b3ec89f
docs(qa): wave-3 accuracy slice S1 — records-forms.json (#28352)
Part of #27377
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:平台测试清单 `docs/qa/platform-checklist/areas/records-forms.json` 里 19
个条目和 1 个区域配方的文字,按 18.3.0 第三波跑测记录(#27441、#27438、#27481)的勘误改成与当前代码一致;每个条目
revision +1,main 的 history 原样保留并追加一行。
- 为什么改:#27377
的提取义务——跑测发现的清单准确性问题要落回账本,否则下一轮跑测会照着过时步骤把正常产品判红或判阻塞(例如去找已删除的 Related
页签、已退役的 split 表单)。
- 风险与回滚:只改 docs/qa 下一个 JSON,不发布、不动产品代码;条款只变得更精确或更强(form-view-gallery 新增
acceptance[5] 拒收条款,追加在末尾不挪编号),回滚即 revert 本 PR。
- 先看:form-view-gallery(删 split
变体、新增拒收条款)、related-list-server-pagination(改指记录页 v3
的正文表格与侧栏卡片)、record-discussion-mentions(流的排序方向、单库成员的 sys_comment 授权)。
- 两分钟验证:`pnpm check:platform-checklist`,预期末行为 `check-platform-checklist:
OK — 16 areas, 352 items`。
- 需要你做的:无,席位落地。
## What changes
One file, `docs/qa/platform-checklist/areas/records-forms.json`. Each
touched item: `revision` +1, main's `history` kept as an exact prefix,
one appended row citing its run record and #27377. Every edit
re-verified against origin/main `a0f865491d` (the census compared at
`501c864dd5`). The row numbers are the seat census's.
| item | census row | old → new, in brief | record |
|---|---|---|---|
| form-view-gallery r5→r6 | 98 | `split` variant, and "an overlaid
drawer/modal renders simple" → form `type` is simple/tabbed/wizard since
18.3.0 (ADR-0050, #27305); split, drawer and modal are refused by name,
scored by steps[3] and a new acceptance[5]; presentations stay on
task-desk.page.ts | #27441 |
| record-discussion-mentions r12→r13 | 100, 101, 201, 202 |
"oldest-first"; four FeedFilterMode values "on the record detail"; no
sys_comment grant on the single boot → "in time order", newest-first on
the v3 stream and oldest-first on an authored `record:discussion` panel;
the filter is driven on Project Detail's panel; the single-boot member
gets the grant too | #27441 (also #27438) |
| action-location-matrix r16→r17 | 102 | visible `'!record.done'`;
showcase_reopen_task unnamed → `has(record.done) && record.done !=
true`; Reopen listed as Mark Done's mirror | #27441 |
| field-group-visible-when r10→r11 | 103 | no pre-fill → pre-fill a
member value (details `hideEmpty` defaults to true) | #27441 |
| field-unique-enforcement r12→r13 | 171 | `PUT
/api/v1/meta/object/qa_unique` → `qauniq_item` under a package declaring
namespace `qauniq`, install spelled | #27438 |
| comment-reactions-and-edit-stamps r4→r5 | 172 | "through the metadata
door" → `PUT /api/v1/meta/permission/NAME` with the sys_comment /
sys_comment_reaction grants, then the bind | #27438 |
| delete-behavior-matrix r4→r5 | 173 | zoo row without its required
`f_master_detail` → a third account and a project parent first | #27438
|
| predicate-relationship-traversal r5→r6 | 174 | "none can be
provisioned" → the runtime-only scratch substitute spelled, with the
member's 403 parent read as control | #27438 |
| list-view-capabilities r7→r8 | 194, 195 | string sort `'estimate_hours
desc'` → the array sort reaching `sort=-estimate_hours`; select not-done
rows for Mark Done | #27438 |
| related-list-server-pagination r10→r11 | 196 | shared Related tab,
page size 5, "Page 1 of 6" → body tables + compact cards at the column
tiers; paging in the enlarged view, 25 a page, "Page 1 of 2" | #27438 |
| gantt-interactions r7→r8 | 197 | locked-leaf drag "not run-proven,
blocked(fixture)" → the run-proven `lockField: 'done'` overlay recipe;
only the auto-schedule half stays blocked | #27438 |
| conditional-rules-grid r10→r11 | 199, 200 | amount "client-computed,
stored as sent"; "flip to paid and save" → amount is server-computed;
lock/unlock driven on the unsaved header Status | #27438 |
| form-dirty-guard r6→r7 | 203 | "11 it() cases" → 11 literals, 14 tests
(a describe.each over two forms) | #27438 |
| conditional-rules-header r7→r8 | 204, 205 | "open INV-1003 (paid) …
tax_rate read-only"; N1 unscoped → the lock is read on INV-1001's form
with Status set to Paid, unsaved; N1 scoped to a PATCH that leaves
status paid | #27438 |
| action-param-widgets r5→r6 | 206, 207 | richtext→editor, date→date
input → RichTextField's textarea; the date-picker widget | #27438 |
| encrypted-field-behavior r6→r7 (steps[0] only) | 213 | "provider-wired
boot (`os serve`)" → `os dev` (spawns `serve --dev`) wires
LocalCryptoProvider too | #27438 |
| field-type-constraints r5→r6 | 211, 212 | string length with no
carrier; lookupFilters as the boundary carrier → `name` (maxLength 200);
the dependsOn carrier shows the existence-only boundary | #27438 |
| field-type-matrix r7→r8 | 215 | "47 on the form"; location "structured
inputs" → 47 TYPES over 49 f_* fields plus `name`; location's single
`latitude, longitude` input | #27438 |
| v18-semantic-defaults r5→r6 | 216 | `pnpm dev -- --fresh`; no seeding
step → any own-port boot (`objectstack dev --fresh --no-compile` for a
shared tree); seed more than 50 rows first | #27438, #27481 |
| area recipe `qa-crm-import-console` | 208 | teardown "delete
ui/e2e/live/.auth/" → plus the one-state-path-per-tree warning; the
change is recorded in the recipe's `provenance` (recipes carry no
revision) | #27438 |
## Tests
No product code and no test changed, so no package test is owed. The
ledger gate and the derived local gate families ran on the final head
`6ccf9e18a9`; see Verification.
## Acceptance notes
- **Held, not raced: `records-forms.crud-roundtrip` steps[6] (census row
137).** Open PR #28116 edits crud-roundtrip steps[5], which is the line
next to steps[6], plus record-edit-undo and field-history-tracking.
Bumping crud-roundtrip here would race it textually. The finding still
holds at `a0f865491d`; it can land after #28116.
- **#28116 will re-stale two items edited here.** It retires the column
tiers, the tab tier and the related rail, and moves the timeline stream
into a 动态 panel and tab. When it lands, record-discussion-mentions
steps[5]/[11] and related-list-server-pagination steps[1]–[3] need
another re-point. They describe origin/main today.
- **Skipped by order (UNCLEAR in the census):** form-view-gallery
steps[0] and steps[6] (row 99, waits on a re-measure after #28066);
encrypted-field-behavior A3/N1 (row 209, a RUNNER rule-6 ruling);
bulk-select-all-matching (row 161, a UX ruling). FIXED upstream,
skipped: rows 136, 166, 210, 214.
- **GAP rows left parked:** 135, 153, 154, 155, 156. Row 157
(write-time-option-and-element-shape-judgement): the
`OS_ALLOW_UNLINTED_METADATA_WRITES=1` recipe is already in its
requires[2], so no edit. Row 158: the seeding allowance was already in
requires[2]; the v18 edit now names the seeding step.
- **Where the edit departs from the record's suggested wording, source
decided:**
- import-console teardown: the record suggested a copied config with its
own storageState. At `a0f865491d` that cannot work:
`ui/e2e/live/global-setup.ts` writes the fixed
`e2e/live/.auth/state.json` with no env override. The teardown
prescribes one runner per tree instead.
- conditional-rules-header N1: the record said the lock is "judged on
the stored row". `isReadonlyWhenLocked` binds the merged record, and the
item says that.
- related-list-server-pagination: a compact card names 3 rows at
`a0f865491d` (5 at the run's `c4c515ad`).
- **Observation, not filed:**
`docs/adr/0050-form-layout-vs-presentation.md`'s status line still reads
Proposed, while `view.zod.ts` cites the acceptance ruling 6464210455.
This is documentation lag with no runtime reach.
## Verification
All on head `6ccf9e18a9` (branch merged with origin/main). Exit codes
were captured before any pipe.
<details><summary>pnpm check:platform-checklist: exit 0</summary>
```text
check-platform-checklist: OK — 16 areas, 352 items (347 active, 1 planned); coverage: 40 kinds mapped, 3 waived; traps: 19 documented, 19 in use; provisioning: 10 area recipes, 15 item references resolved (2 area-qualified), 10/10 recipes referenced; ... symbol anchors: 1068/1078 (10 on the named residual), 18 file floors held
```
</details>
<details><summary>dispatch-gates derived families (16): all exit 0,
reconciled with --ran</summary>
```text
node scripts/check-adr-links.mjs :: exit 0
node scripts/check-adr-links.mjs --self-test :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0 (first run exit 3, prerequisite: formula + lint unbuilt; built, re-run)
pnpm check:ci-filter-parity :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:platform-checklist :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:watch-hint-literal :: exit 0
✓ 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>
<details><summary>NOT MEASURED</summary>
form-dirty-guard's 14-test count comes from source: 8 it() literals plus
a 3-case describe.each over two forms. The run's 14/14 is the record's.
A local `pnpm exec vitest run
packages/plugin-form/src/discardGuard.test.tsx` from ui/ exited 1 before
any test ran ("Failed to resolve import @objectstack/spec/data" — spec
dist not built in this worktree). That is a prerequisite miss, not a
test result.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QSeKYmTYfaPbLQD4BJfomW)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent a7bdac4 commit b3ec89f
1 file changed
Lines changed: 217 additions & 98 deletions
0 commit comments