Skip to content

Commit 65b4920

Browse files
test(ui): run the kept Console live specs nightly; delete the stale and duplicated ones (#27294)
<!-- claude-projects-attribution: {"github_login":"os-warren"} --> _Requested by **Warren** · [project thread](https://claude.ai/code/project/chan_01U5RdnAAmkSQmZbqh6FtqZ8?thread=cmsg_01U5RdnAAmkSQmZbqh6FtqZ8MogRN1CAWpndKB1euF4K8n)_ Fixes #25914 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:18 个不在任何 CI 里跑的 Console live spec 逐个实跑;15 个绿的进 Nightly Tiers(一个 vitest 包装 + `ui/package.json` 一行脚本),删掉 2 个过时的红 spec 和 1 个与 showcase 夜间 smoke 重复的 spec,并改正引用它们的检查单条目。 - 为什么改:裁决 Q3 B:过时的删,其余接入 Nightly Tiers,红了由该 job 的 report 步骤自动建卡;MSW 那条空测试已被 #26032 删除,这里顺手去掉它留下的 MSW 报错豁免。 - 风险与回滚:只动测试和检查单,不改产品代码,也不碰 4 个必跑 spec 和 `Live E2E UI` job;夜间 showcase 分片多约 5 分钟;回滚即 revert 本 PR。 - 先看:`examples/app-showcase/test/console-live-specs.live.test.ts`,以及下面的逐 spec 表。 - 两分钟验证:`pnpm --dir ui run test:e2e:live:nightly --list`,预期列出 15 个文件、25 个用例。 - 需要你做的:无,席位落地。 ## What changes Each of the 18 live specs outside `test:e2e:live:ci` was run alone against the workspace showcase backend (`ui/e2e/live/ci/start-backend.sh`, the boot the required job uses) at `origin/main` `1e8e5296`. Both reds were run a second time and failed the same way. | Spec | Result | Outcome | |:--|:--|:--| | `cascading-options` | 2 passed | kept, nightly | | `declared-sharing-rules-reach-13091` | 1 passed | kept, nightly | | `detail-related-list` | failed: `waitForURL(/record/)` timeout | deleted, stale | | `field-conditional-rules` | 1 passed | kept, nightly | | `form-view-subforms` | 1 passed | kept, nightly | | `grid-conditional-rules` | 1 passed | kept, nightly | | `grid-file-upload` | 1 passed | kept, nightly | | `grid-parent-rules` | 1 passed | kept, nightly | | `inline-edit-polish-2572` | 1 passed | kept, nightly | | `list-row-action-cel` | 1 passed | kept, nightly | | `record-history-display` | 1 passed | kept, nightly | | `required-when-submit` | 1 passed | kept, nightly | | `showcase-smoke` | 29 passed (104 s) | deleted, duplicate | | `studio-editor` | 2 passed | kept, nightly | | `studio-object-designer` | 4 passed | kept, nightly | | `studio-record-page` | failed: `blocks.length` 0 | deleted, stale | | `summary-rollup` | 2 passed | kept, nightly | | `user-filters` | 5 passed | kept, nightly | - **Wiring (route A, amendment 6470826683), not Tier H.** - `ui/package.json` gains one script, `test:e2e:live:nightly`, that lists the 15 kept specs. - `examples/app-showcase/test/console-live-specs.live.test.ts` is a `*.live.test.ts` file, so Nightly Tiers already selects it in the showcase shard, which builds the Console and installs Chromium. Its report step files a card on red. - The wrapper follows `showcase-smoke.live.test.ts`: - It boots the backend with `start-backend.sh`. - It builds the Console with `VITE_BASE_PATH=/` into a scratch dir and serves it with `vite preview` plus `DEV_PROXY_TARGET`. The specs `goto` root `/apps/...`, which neither the default `./` base nor the `/_console` copy serves. - It runs the script with a JSON reporter and fails, naming every failing spec, unless all of them passed. - It stops the preview and the backend by PID in `finally`. - No `.github/workflows/**` edit, and `ci.yml` and `ui/.github/**` are untouched. - **`showcase-smoke` is a duplicate.** `examples/app-showcase/e2e/showcase-smoke.spec.ts` already runs nightly through `showcase-smoke.live.test.ts`. - Every one of the deleted spec's 29 surface paths is in the kept spec, which has 49 (`comm -23` of the two path lists is empty; one label changed from "Settings (preference)" to "Settings" on the same path). - The kept spec makes each of the deleted spec's four assertions: no uncaught page error, no leaked "no actions configured" placeholder, non-empty main content, and a chart SVG with width and height above 0. It is stricter on two: it requires a chart width above 200, and it refuses a surface that is still on the boot splash. - **`studio-record-page` is stale.** It expects a record page created in Studio to come back with regions copied from the default layout. Today a new record page is created slotted with no copied regions, by design, so `blocks.length` is 0. - **`detail-related-list` is stale.** It expects a row click to navigate to `/record/`. Today the row's name link opens the record drawer, by design. The related-list behaviours it also touched are pinned by unit tests: `deriveRelatedLists.test.ts`, `buildDefaultPageSchema.test.ts` and `RelatedList.columnIdentityAccessor.test.tsx`. - **The MSW clause.** The vacuous MSW test in `ui/e2e/console-rendering.spec.ts` was already deleted by #26032, so that part of the premise no longer holds. What was left was four ignore entries (`mockServiceWorker`, `MSW`, `Mock Service Worker`, `[MSW]`) that still excused MSW console errors. They are removed: the Console ships no mock service worker, so an MSW error is now a real error. No `msw` declaration and no `public/mockServiceWorker.js` are left in the tree. - **Platform checklist.** Every line that cited a deleted spec was repointed or dropped. Each item gets a revision bump and a `history` entry dated 2026-10-28, with ref #25914. | Item | Revision | Line | Edit | |:--|:--|:--|:--| | `platform-core.metadata-authoring-roundtrip` | 6→7 | acceptance[2].verify | now says the PUT is hand-driven, with no live spec pinning it | | `platform-core.metadata-authoring-roundtrip` | 6→7 | automated.ref | the studio-record-page half is dropped | | `records-forms.related-list-server-pagination` | 9→10 | verify parenthetical | dropped | | `records-forms.related-list-server-pagination` | 9→10 | ref | the detail-related-list sentence is dropped | | `records-forms.related-list-server-pagination` | 9→10 | live browser legs | acceptance[2] joins them | | `records-forms.related-list-server-pagination` | 9→10 | history | cites the three unit pins above | | `studio-authoring.record-page-roundtrip` | 9→10 | verify parenthetical | dropped | | `studio-authoring.record-page-roundtrip` | 9→10 | ref | keeps only `studio-editor`, now nightly, which covers none of acceptance[0], [2] or [3] | | `studio-authoring.record-page-roundtrip` | 9→10 | source line | dropped | | `studio-authoring.custom-page-render-and-blocks` | 1→2 | knownGaps / source | repointed to `examples/app-showcase/e2e/showcase-smoke.spec.ts`; that nightly smoke includes the pages named | | `studio-authoring.page-variables-and-actions` | 1→2 | knownGaps / source | same repoint | | `studio-authoring.custom-page-source-tiers` | 4→5 | knownGaps / source | same repoint | - **Out of scope, flagged for the ledger owner.** `platform-core` acceptance[2] and `studio-authoring.record-page-roundtrip` acceptance[0] still ask for regions "seeded from the default layout". That now holds only for `full` pages. The two history entries say so; the acceptance text is left as it is. ## Why Ruling Q3 B (6435339772): the stale specs are deleted and the rest are wired into Nightly Tiers, so a red files a card. The other clauses of the card are already closed: - Q1 A and ruling D were landed by the devx lane (#27167, #27212 via #27154). - The MSW test went in #26032. This PR closes the last one, hence `Fixes`. ## Verification - The 18-spec measurement held the verify lock for 4m45s with `VERDICT command-exit 0`. The per-spec results are in the table above. - The wrapper ran end to end: `OS_TEST_TIERS=nightly pnpm --filter @objectstack/example-showcase exec vitest run test/console-live-specs.live.test.ts` gave Playwright 25 passed (1.7 min) and vitest 1 passed. It held the lock for 4m27s with VERDICT 0. - `ui/e2e/console-rendering.spec.ts` ran in Chromium against a `/console/` build: 3 passed. - `node scripts/pm/dispatch-gates.mjs --commands` derived 55 commands at the merge of `origin/main` `0d45c0e7`. To those I added: - `pnpm --filter @objectstack/example-showcase typecheck` - `node scripts/nightly-tiers.mjs --check` - `node scripts/check-platform-checklist.mjs --changed-from origin/main` All 58 exited 0. `dispatch-gates --ran`: "55 derived famil(ies) accounted for — 55 run, 0 NOT-MEASURED". `check:dts-closure` and `check:dual-build-cjs-loads` exited 1 and 3 on the first pass for the same reason. Both read built output this worktree had not built: console `plugin.d.ts`, and the `dist` of 7 packages this diff does not touch. Each exited 0 after the build of those packages (`build:plugin` for the console, then `turbo run build`). - `dispatch-gates --tier`: "no path-derived mandate: the surface hits none of the 4 declared glob(s)". Changed lines: 514 (+275 / -239), under the 800 cap. - This is test and CI only, so it ships no changeset (`skip-changeset`). ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. (No `packages/spec` change.) - [x] 2. Every name I added uses the casing for its kind. - [x] 3. No formatter ran; `pnpm lint` passes. (The root eslint, run over the two changed TypeScript files, exits 0.) - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (Nothing publishes: `skip-changeset`.) - [x] 6. `packages/spec` touched: its generated artifacts are regenerated and committed. (Not touched.) - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English. (Except the `维护者速读` block the dispatch order asks for.) - [x] The *Before Submitting* list in CONTRIBUTING.md is done. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01JQwxbXq8B9svQTRonMmTRf --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 0e205fe commit 65b4920

9 files changed

Lines changed: 275 additions & 239 deletions

File tree

‎docs/qa/platform-checklist/areas/platform-core.json‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@
483483
"title": "Metadata authoring round-trip: draft → publish on a WRITABLE package; read-only packages and locked types are server-side refused",
484484
"since": "v16",
485485
"status": "active",
486-
"revision": 6,
486+
"revision": 7,
487487
"priority": "P1",
488488
"surface": "mixed",
489489
"personas": ["seeded admin (admin@objectos.ai / admin123)"],
@@ -519,7 +519,7 @@
519519
{
520520
"clause": "Studio's designer authors through the same pipeline: creating a record page issues PUT /api/v1/meta/page/<name> bound to its object and seeded from the default layout",
521521
"oracle": "network",
522-
"verify": "capture the PUT during Studio create (pinned by objectui e2e/live/studio-record-page.spec.ts, which waits on exactly that request and asserts its body — see automated.ref)",
522+
"verify": "capture the PUT during Studio create (hand-driven: no live spec pins this request)",
523523
"evidence": "the captured PUT"
524524
},
525525
{
@@ -549,7 +549,7 @@
549549
"traps": ["dispatcher-vs-hono-route", "stale-console-bundle"],
550550
"automated": {
551551
"kind": "api",
552-
"ref": "packages/qa/dogfood/test/package-first-authoring.dogfood.test.ts (scores NO clause of this item: it calls protocol.saveMetaItem in-process on a booted CRM stack — the WRITABLE_PACKAGE_REQUIRED refusal with its writable-base control, then the package lifecycle — and drives no /api/v1/meta door, so it is protocol-layer evidence for acceptance[3] only); objectui: e2e/live/studio-record-page.spec.ts (acceptance[2] ONLY: it creates a record page bound to showcase_invoice and asserts the captured PUT /meta/page body's type 'record', its object, and regions seeded with a record:highlights block), e2e/live/studio-object-designer.spec.ts (scores NO clause of this item: its cases drive the object designer and the Studio package switcher, and no clause here scores either)"
552+
"ref": "packages/qa/dogfood/test/package-first-authoring.dogfood.test.ts (scores NO clause of this item: it calls protocol.saveMetaItem in-process on a booted CRM stack — the WRITABLE_PACKAGE_REQUIRED refusal with its writable-base control, then the package lifecycle — and drives no /api/v1/meta door, so it is protocol-layer evidence for acceptance[3] only); objectui: e2e/live/studio-object-designer.spec.ts (scores NO clause of this item: its cases drive the object designer and the Studio package switcher, and no clause here scores either)"
553553
},
554554
"source": [
555555
"packages/runtime/src/route-ledger.ts (PUT /meta/:type/:name, GET /meta/_drafts, GET /meta/:type/:name/published, POST /packages/:id/publish-drafts)",
@@ -563,7 +563,8 @@
563563
{ "revision": 3, "date": "2026-10-16", "change": "steps[1], [3] and [7] and acceptance[0].verify and [5].verify re-pointed (checklist-accuracy findings of QA run #23939, wave #23878). A plain PUT /meta/view/NAME saves state=active, so the draft never appeared in /meta/_drafts — ?mode=draft is required — and a view's name must be qualified OBJECT.view (#23939 used showcase_task.os_qa_view_RUNID). The Studio half now names the create form (/_console/apps/showcase_app/metadata/page/new) and its 'list' default, which has to be set to 'record' for a record page. Not loosened: every clause still scores the same server reads", "ref": "#24036" },
564564
{ "revision": 4, "date": "2026-10-20", "change": "automated.stale.observedIn, partial, why and ownedBy refreshed — the carried note from round 6 of wave anchor #24579 (its report, comment 6280484387), the refresh round 6 made on studio-authoring.record-page-roundtrip in PR #24697. Tier 1 run #24598 re-measured studio-record-page.spec.ts red at the sweep's console pin 4016370af3c9 (0 passed / 1 failed), and the spec is byte-identical at the shipped pin 12dc7b47c340, so the marker first written from #7695 still holds; ownedBy names the family card objectstack-ai/objectui#13104. The why also said studio-object-designer.spec.ts was unaffected; #24598 ran its F1 and F4 red (F2 and F3 passed), and partial now says so. No clause changed", "ref": "#24717" },
565565
{ "revision": 5, "date": "2026-10-20", "change": "automated.stale removed, automated.ref scoped per objectui spec, and acceptance[2].verify's stale note rewritten — round 14 of wave anchor #24579 (18.0 sweep), on the objectui pointer 6284006658. objectui#13132 (objectui 0b36ffa) repaired both specs the stale record named, and the console pin moved to 616df6598b42 (PR #24829), which contains 0b36ffa. studio-record-page.spec.ts: blob 181b2562c18d at the old pin 12dc7b47c340, 3844a60ccd79 at both 0b36ffa and 616df6598b42; it now sets Page type to record and picks the object from the Object combobox. studio-object-designer.spec.ts: blob 5967807df335, then 58a7f1cbf024 at both; F1 and F4 repaired. objectui measured its whole live suite at 0b36ffa as 61 passed (11.0m) on the shipped showcase; no live run exists at 616df6598b42, so the verdict there is NOT MEASURED. Re-read at the new pin, the ref keeps only what this record claimed: studio-record-page.spec.ts asserts acceptance[2], the clause the stale record sent to hand-driving, and studio-object-designer.spec.ts, on which no clause here rests, now says so. The dogfood pin is unchanged. No clause changed", "ref": "#24857" },
566-
{ "revision": 6, "date": "2026-10-20", "change": "automated.ref and acceptance[3].verify narrowed — checklist-accuracy finding of QA run #24840 (18.0 sweep round 4, Tier 1 at 307ce4c4: acceptance[3]'s verify names the dogfood pin as covering the PUT door), round 15 of wave anchor #24579. Re-read at base b1676441ba, after round 14's ref edit: package-first-authoring.dogfood.test.ts calls protocol.saveMetaItem in-process on a booted CRM stack and never PUT /api/v1/meta. By RUNNER rule 6 (a pin scores only the layer it drives) it scores no clause of this item, and the ref and acceptance[3].verify now say so. The objectui studio-record-page.spec.ts keeps acceptance[2]. No clause changed", "ref": "#24891" }
566+
{ "revision": 6, "date": "2026-10-20", "change": "automated.ref and acceptance[3].verify narrowed — checklist-accuracy finding of QA run #24840 (18.0 sweep round 4, Tier 1 at 307ce4c4: acceptance[3]'s verify names the dogfood pin as covering the PUT door), round 15 of wave anchor #24579. Re-read at base b1676441ba, after round 14's ref edit: package-first-authoring.dogfood.test.ts calls protocol.saveMetaItem in-process on a booted CRM stack and never PUT /api/v1/meta. By RUNNER rule 6 (a pin scores only the layer it drives) it scores no clause of this item, and the ref and acceptance[3].verify now say so. The objectui studio-record-page.spec.ts keeps acceptance[2]. No clause changed", "ref": "#24891" },
567+
{ "revision": 7, "date": "2026-10-28", "change": "automated.ref and acceptance[2].verify drop ui/e2e/live/studio-record-page.spec.ts, deleted by the triage of the live specs that ran in no CI lane (ruling Q3 B): measured red on the workspace backend at 1e8e5296, alone, twice: a Studio-created record page is saved kind slotted with no copied regions unless the author picks full (fd73f2b3, the page createSeed in ui/packages/app-shell/src/views/metadata-admin/anchors.ts; both outcomes unit-pinned in anchors.page-seed.test.ts beside it), so the spec's seeded-regions assertion reads a superseded design. acceptance[2] is hand-driven again. Its clause still reads 'seeded from the default layout', which now holds only for a page the author creates full; that clause is left for the ledger's owner. No clause changed", "ref": "#25914" }
567568
]
568569
},
569570
{

‎docs/qa/platform-checklist/areas/records-forms.json‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,7 +1537,7 @@
15371537
"title": "Related lists derive from the relationship and page on the server — never fetch every child row — and are read-gated on both ends",
15381538
"since": "v16",
15391539
"status": "active",
1540-
"revision": 9,
1540+
"revision": 10,
15411541
"priority": "P1",
15421542
"surface": "browser",
15431543
"personas": [
@@ -1584,7 +1584,7 @@
15841584
{
15851585
"clause": "related lists are DERIVED from the relationship declaration with no hand-built page: the Account detail auto-renders them (Projects is the pinned example)",
15861586
"oracle": "dom",
1587-
"verify": "after screenshot, the related tabs exist on the stock detail page (pinned by objectui e2e/live/detail-related-list.spec.ts)",
1587+
"verify": "after screenshot, the related tabs exist on the stock detail page",
15881588
"evidence": "detail screenshot"
15891589
},
15901590
{
@@ -1616,7 +1616,7 @@
16161616
],
16171617
"automated": {
16181618
"kind": "e2e",
1619-
"ref": "objectui: e2e/live/detail-related-list.spec.ts — acceptance[2] ONLY (the relationship-derived Projects related list on the Account detail page: Northwind's detail renders a Projects tab whose panel shows the projects' status labels). packages/qa/dogfood/test/related-list-server-paging-and-gate.dogfood.test.ts, at the REST data door the related list reads through (GET /api/v1/data/showcase_contact scoped by the Northwind filter) on the showcase as shipped, pins the server halves: acceptance[1] and negative[1] (the filtered read holds the 26 seeded contacts; $top=10 pages at $skip 0, 10 and 20 each answer total 26 and return 10, 10 and 6 rows with no id repeated or skipped), acceptance[4] (each served child re-reads by its own id with the same row) and acceptance[5] with negative[2] (a member staffed contributor is refused the identical query 403 with no rows; a member staffed manager reads it 200 with rows). acceptance[0] and negative[0] (the console's own top/skip on every child request), the pager text, acceptance[3] (the Invoices tab's authored title and columns) and the Contacts tab's absence for the contributor stay live browser legs: they are judged on the console's requests and rendered detail page, which no HTTP pin reaches, and the card's ruling adds no Playwright lane (#26573)"
1619+
"ref": "packages/qa/dogfood/test/related-list-server-paging-and-gate.dogfood.test.ts, at the REST data door the related list reads through (GET /api/v1/data/showcase_contact scoped by the Northwind filter) on the showcase as shipped, pins the server halves: acceptance[1] and negative[1] (the filtered read holds the 26 seeded contacts; $top=10 pages at $skip 0, 10 and 20 each answer total 26 and return 10, 10 and 6 rows with no id repeated or skipped), acceptance[4] (each served child re-reads by its own id with the same row) and acceptance[5] with negative[2] (a member staffed contributor is refused the identical query 403 with no rows; a member staffed manager reads it 200 with rows). acceptance[0] and negative[0] (the console's own top/skip on every child request), the pager text, acceptance[2] (the relationship-derived Projects tab on Northwind's detail page and its status labels), acceptance[3] (the Invoices tab's authored title and columns) and the Contacts tab's absence for the contributor stay live browser legs: they are judged on the console's requests and rendered detail page, which no HTTP pin reaches, and the card's ruling adds no Playwright lane (#26573)"
16201620
},
16211621
"source": [
16221622
"#3358 §4 (evidence run captured exactly this trace)",
@@ -1679,7 +1679,8 @@
16791679
"date": "2026-10-27",
16801680
"change": "automated.ref names the dogfood pin for the server halves of acceptance[1], [4], [5] and negative[1], [2] (#26573 slice 4), and says why acceptance[0], [3], negative[0] and the rendered halves stay live browser legs. No clause changed",
16811681
"ref": "#26573"
1682-
}
1682+
},
1683+
{ "revision": 10, "date": "2026-10-28", "change": "automated.ref and acceptance[2].verify drop ui/e2e/live/detail-related-list.spec.ts, deleted by the triage of the live specs that ran in no CI lane (ruling Q3 B): measured red on the workspace backend at 1e8e5296, alone, twice: a row's name link now opens the record drawer (the record-open preference, #26681) and the spec waited for the /record/ID route it no longer navigates to. acceptance[2] joins the live browser legs the ref lists; its derivation, own-tab promotion and option-label cells stay unit-pinned in objectui (deriveRelatedLists.test.ts, buildDefaultPageSchema.test.ts, RelatedList.columnIdentityAccessor.test.tsx). The dogfood pin is unchanged. No clause changed", "ref": "#25914" }
16831684
]
16841685
},
16851686
{

0 commit comments

Comments
 (0)