diff --git a/docs/qa/platform-checklist/areas/platform-core.json b/docs/qa/platform-checklist/areas/platform-core.json index 1f07836da2..3824df08e3 100644 --- a/docs/qa/platform-checklist/areas/platform-core.json +++ b/docs/qa/platform-checklist/areas/platform-core.json @@ -416,7 +416,7 @@ "title": "Metadata authoring round-trip: draft → publish on a WRITABLE package; read-only packages and locked types are server-side refused", "since": "v16", "status": "active", - "revision": 4, + "revision": 5, "priority": "P1", "surface": "mixed", "personas": ["seeded admin (admin@objectos.ai / admin123)"], @@ -452,7 +452,7 @@ { "clause": "Studio's designer authors through the same pipeline: creating a record page issues PUT /api/v1/meta/page/ bound to its object and seeded from the default layout", "oracle": "network", - "verify": "capture the PUT during Studio create. ⚠ Drive it by hand: the pin (objectui e2e/live/studio-record-page.spec.ts, which waits on exactly that request) is STALE against the current surface — it fills the Object control as an input when it is now a role=combobox button — see automated.stale", + "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)", "evidence": "the captured PUT" }, { @@ -482,16 +482,7 @@ "traps": ["dispatcher-vs-hono-route", "stale-console-bundle"], "automated": { "kind": "api", - "ref": "packages/qa/dogfood/test/package-first-authoring.dogfood.test.ts; objectui: e2e/live/studio-record-page.spec.ts, e2e/live/studio-object-designer.spec.ts", - "stale": { - "since": "2026-08-11", - "observedIn": "#24598", - "ref": "#7753 item 6", - "partial": "objectui: e2e/live/studio-record-page.spec.ts (whole), and e2e/live/studio-object-designer.spec.ts cases F1 and F4 (no clause here rests on them)", - "why": "STALE, NOT RED — studio-record-page.spec.ts fills the Object control as an input when it is now a `role=combobox` button, so it fails against the CURRENT surface rather than against a product defect. Re-measured at the 18.0 sweep: Tier 1 run #24598 ran it at the sweep's console pin 4016370af3c9, 0 passed / 1 failed; at the shipped pin 12dc7b47c340 the spec is byte-identical (the same blob at both pins), so it is still stale there. First observed by #7695 on 2026-08-11. The dogfood pin (package-first-authoring) is unaffected. studio-object-designer.spec.ts is NOT unaffected, as this marker used to say: #24598 ran it with F2 and F3 passing and F1 and F4 failing as stale cases (F1 opens an app no stock boot loads; F4 expects no banner for a picklist with no option source), and it is byte-identical at 12dc7b47c340 too. No clause here cites it. object-designer-roundtrip's 4th ref, from the same class, was already repaired (package-create moved to /_console/studio).", - "runnerRule": "The Studio-designer clause here (clause 3, 'creating a record page issues PUT /api/v1/meta/page/') must be driven by hand — capture the PUT in the browser — until the spec is re-pointed; do not cite its output and do not score its failure as this item's FAIL. Every other clause keeps its own oracle.", - "ownedBy": "objectui — re-pointing the two specs is objectstack-ai/objectui#13104 (the family card for the eleven live specs that are stale or red at the console pin, both of these among them), the cross-repo half of #7753; reported, not edited from this repo" - } + "ref": "packages/qa/dogfood/test/package-first-authoring.dogfood.test.ts; 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)" }, "source": [ "packages/runtime/src/route-ledger.ts (PUT /meta/:type/:name, GET /meta/_drafts, GET /meta/:type/:name/published, POST /packages/:id/publish-drafts)", @@ -503,7 +494,8 @@ { "revision": 1, "date": "2026-08-07", "change": "initial — grounds the Studio authoring pipeline end-to-end with both deny gates as first-class clauses", "ref": "claude/platform-test-checklist-ocwugl" }, { "revision": 2, "date": "2026-08-11", "change": "annotated the objectui e2e/live/studio-record-page.spec.ts half of this item's automated.ref as STALE (run #7695): it fills the Object control as an input when it is now a role=combobox button, so it fails against the current surface, not against a defect. The Studio-designer clause now says drive it by hand until the spec is re-pointed; the dogfood pin and studio-object-designer.spec.ts are unaffected. Re-pointing lives in objectui (cross-repo half of #7753 item 6)", "ref": "#7753" }, { "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" }, - { "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" } + { "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" }, + { "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" } ] }, { diff --git a/docs/qa/platform-checklist/areas/records-forms.json b/docs/qa/platform-checklist/areas/records-forms.json index c9c69fafe8..15452d5cc9 100644 --- a/docs/qa/platform-checklist/areas/records-forms.json +++ b/docs/qa/platform-checklist/areas/records-forms.json @@ -419,7 +419,7 @@ "title": "List-view capability matrix: filter, search, sort, pagination, saved views, inline edit, export, visualization switcher, bulk/row actions, conditional formatting", "since": "v15", "status": "active", - "revision": 5, + "revision": 6, "priority": "P1", "surface": "browser", "personas": [ @@ -493,7 +493,7 @@ { "clause": "inline edit persists through the API — the PATCH carries only the edited cell and a post-reload re-read shows it, with untouched fields unchanged", "oracle": "api", - "verify": "diff full-row reads before/after the cell edit (same contract objectui e2e/live/inline-edit-polish-2572.spec.ts pins on Project)", + "verify": "diff full-row reads before/after the cell edit (objectui e2e/live/inline-edit-polish-2572.spec.ts pins the PATCH half only, on a Project record page's inline edit — see automated.ref)", "evidence": "the two reads + the PATCH body" }, { @@ -533,16 +533,7 @@ ], "automated": { "kind": "e2e", - "ref": "objectui: e2e/live/saved-view-filter.spec.ts, e2e/live/user-filters.spec.ts, e2e/live/inline-edit-polish-2572.spec.ts; packages/qa/dogfood/test/showcase-search.dogfood.test.ts (scores NO clause of this item: it pins search.cross-field-object-search's matching — Northwind / retail — not acceptance[2]'s CJK 'huaning' recall, QA runs #24572 and #24598)", - "stale": { - "since": "2026-10-19", - "observedIn": "#24598", - "ref": "#24579 §2", - "partial": "objectui: e2e/live/user-filters.spec.ts (4 of its 6 cases) and e2e/live/inline-edit-polish-2572.spec.ts ONLY — saved-view-filter.spec.ts passed", - "why": "RED AT THE PIN, AS STALE SPECS — not product defects. Tier 1 run #24598 at the sweep's console pin 4016370af3c9: user-filters.spec.ts 2 passed / 4 failed, inline-edit-polish-2572.spec.ts 0 / 1, saved-view-filter.spec.ts 1 / 0; the round-1 record #24572 names the causes. user-filters' filter-tabs, visualization-switcher and lookup-quick-filter cases assert pre-ADR-0053 showcase metadata — the default All Tasks list carries no in-view tab row (status presets are named views), its switcher offers six visualizations including timeline and gantt, and the tabular view declares no userFilters (examples/app-showcase/src/ui/views/task.view.ts) — and its hollow-view case asks for a cell role where the grid exposes gridcell. inline-edit-polish-2572 expects the approval lock after its budget edit, but the budget flow's manager_review step is deliberately unlocked (lockRecord false, examples/app-showcase/src/automation/flows/index.ts), and the spec consumes its own fixture (it needs a fresh database). Re-read at the shipped pin 12dc7b47c340: both specs' bytes are unchanged and the showcase metadata they contradict is unchanged at objectstack 92ce3af404, so both are still stale there.", - "runnerRule": "Cite saved-view-filter.spec.ts for acceptance[1] as before. Do NOT cite user-filters.spec.ts or inline-edit-polish-2572.spec.ts, and do NOT score their failures as this item's FAIL: drive acceptance[5] (inline edit) and acceptance[7] (the six-entry switcher) by hand, with every other clause.", - "ownedBy": "objectui — re-pointing both specs at the current surface is objectui's half, recorded on wave anchor #24579 §2; this repository reports it and does not edit the spec" - } + "ref": "objectui: e2e/live/saved-view-filter.spec.ts (acceptance[1]), e2e/live/user-filters.spec.ts (acceptance[7]'s whitelist half ONLY: its visualization-switcher case reads exactly Grid, Kanban, Gallery, Calendar, Timeline and Gantt in the All Tasks Display popover, then switches to Kanban and reads only the trigger's label, so 'each re-renders the SAME task records' is driven by hand. Its lookup quick-filter case, which this item's stale record named, is retired: objectui 0b36ffa deleted it because the shipped showcase declares no lookup user filter, so no ref here cites it), e2e/live/inline-edit-polish-2572.spec.ts (acceptance[5]'s PATCH half ONLY, carrier-neutrally on a Project record page's inline edit, not this item's grid cell: the PATCH carries the edited budget and not the untouched spent. It never re-reads the row, so the re-read half is driven by hand); packages/qa/dogfood/test/showcase-search.dogfood.test.ts (scores NO clause of this item: it pins search.cross-field-object-search's matching — Northwind / retail — not acceptance[2]'s CJK 'huaning' recall, QA runs #24572 and #24598)" }, "source": [ "examples/app-showcase/src/ui/views/task.view.ts#inlineEdit (saved views, sort string form, inlineEdit, exportOptions, bulk/row actions, allowedVisualizations)", @@ -581,6 +572,12 @@ "date": "2026-10-20", "change": "automated.stale added — §2 theme \"objectui live e2e is not green at its own pin\" of wave anchor #24579 (18.0 sweep). Tier 1 run #24598 at the sweep's console pin 4016370af3c9: user-filters.spec.ts 2 passed / 4 failed and inline-edit-polish-2572.spec.ts 0 / 1, both stale against the shipped showcase (causes from QA run #24572; #24616 drove the item by hand); saved-view-filter.spec.ts passed and stays cited. Re-read at the shipped pin 12dc7b47c340: both specs are byte-identical and the metadata they contradict is unchanged. No clause changed", "ref": "#24697" + }, + { + "revision": 6, + "date": "2026-10-20", + "change": "automated.stale removed, automated.ref scoped per objectui spec, and acceptance[5].verify narrowed — 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. user-filters.spec.ts: blob aa52b2b8de2a at the old pin 12dc7b47c340, ab50146bcfd0 at both 0b36ffa and 616df6598b42; the tabs case moved to the Task Triage page, the switcher is read through the Display popover, the grid's cells are gridcells, and the lookup quick-filter case is retired (the shipped showcase declares no lookup user filter). inline-edit-polish-2572.spec.ts: blob 84e0677df02e, then 4cc1557d475f at both; it creates its own project and asserts the lock at exec_review. 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, both repaired specs assert less than the clauses the stale record sent to hand-driving: the switcher case reads the six entries but switches only to Kanban and reads no records (acceptance[7]'s whitelist half), and inline-edit-polish asserts the PATCH's keys on a Project record page but never re-reads the row (acceptance[5]'s PATCH half). So the ref and acceptance[5].verify narrow to those halves. saved-view-filter.spec.ts (blob 94a201c63a0a at all three) keeps acceptance[1]. No clause changed", + "ref": "#24857" } ] }, @@ -812,7 +809,7 @@ "title": "Header-level conditional rules: visibleWhen / requiredWhen / readonlyWhen on invoice fields, enforced on BOTH ends", "since": "v16", "status": "active", - "revision": 3, + "revision": 4, "priority": "P1", "surface": "mixed", "personas": [ @@ -888,16 +885,7 @@ ], "automated": { "kind": "e2e", - "ref": "objectui: e2e/live/required-when-submit.spec.ts (acceptance[0]: a requiredWhen-required Issued On blocks submit with its field error) + e2e/live/field-conditional-rules.spec.ts (acceptance[0]'s required marker, acceptance[2]'s client lock and acceptance[3] — stale at the pin, see automated.stale). No pin covers acceptance[1], [4] or [5]: e2e/live/list-row-action-cel.spec.ts, cited here until revision 3, gates the task list's Mark Done row action, not the paid invoice's Edit / Delete gating acceptance[4] scores, so it was dropped", - "stale": { - "since": "2026-10-19", - "observedIn": "#24598", - "ref": "#24579 §2", - "partial": "objectui: e2e/live/field-conditional-rules.spec.ts ONLY — required-when-submit.spec.ts passed", - "why": "RED AT THE PIN, AS A STALE SPEC — not a product defect. Tier 1 run #24598 at the sweep's console pin 4016370af3c9: field-conditional-rules.spec.ts failed, required-when-submit.spec.ts passed. The spec expects tax_rate to be a disabled input once Status is paid; the form renders a readonlyWhen-locked field as read-only text, so no disabled input is there to find (round-1 record #24572). Re-read at the shipped pin 12dc7b47c340: the spec's bytes are unchanged, objectui packages/fields is unchanged, and the form renderer's only change between the pins is the fail-closed field-group gate (objectui#13055), so it is still stale there.", - "runnerRule": "Cite required-when-submit.spec.ts for acceptance[0]. Do NOT cite field-conditional-rules.spec.ts or score its failure as this item's FAIL: drive acceptance[2]'s client half and acceptance[3] by hand, with every other clause.", - "ownedBy": "objectui — re-pointing field-conditional-rules.spec.ts at the current surface is objectui's half, recorded on wave anchor #24579 §2; this repository reports it and does not edit the spec" - } + "ref": "objectui: e2e/live/required-when-submit.spec.ts (acceptance[0]: a requiredWhen-required Issued On blocks submit with its field error) + e2e/live/field-conditional-rules.spec.ts (acceptance[0]'s required marker, acceptance[2]'s client lock and acceptance[3], on the New Invoice dialog as Status flips: Issued On's required marker, tax_rate's input giving way to the read-only field group at paid, and paid_on mounted, and required, only at paid). No pin covers acceptance[1], [4] or [5]: e2e/live/list-row-action-cel.spec.ts, cited here until revision 3, gates the task list's Mark Done row action, not the paid invoice's Edit / Delete gating acceptance[4] scores, so it was dropped" }, "source": [ "examples/app-showcase/src/data/objects/invoice.object.ts#userActions (the B2 rules + userActions gating, with server-semantics comments)", @@ -922,6 +910,12 @@ "date": "2026-10-20", "change": "automated.ref narrowed, automated.stale added and acceptance[4].verify corrected — §2 themes \"pins that cover no full clause\" and \"objectui live e2e is not green at its own pin\" of wave anchor #24579 (18.0 sweep). Tier 1 run #24598 at the sweep's console pin 4016370af3c9: required-when-submit.spec.ts passed (acceptance[0]); field-conditional-rules.spec.ts failed as a stale spec (cause from QA run #24572; #24616 drove the item by hand); list-row-action-cel.spec.ts passed but gates the task list's Mark Done, not the invoice's Edit / Delete, so it is dropped and acceptance[4].verify no longer says it pins the clause. Re-read at the shipped pin 12dc7b47c340: the stale spec is byte-identical and its cause holds. No clause text changed", "ref": "#24697" + }, + { + "revision": 4, + "date": "2026-10-20", + "change": "automated.stale removed — round 14 of wave anchor #24579 (18.0 sweep), on the objectui pointer 6284006658. objectui#13132 (objectui 0b36ffa) repaired field-conditional-rules.spec.ts, the one spec the stale record named, and the console pin moved to 616df6598b42 (PR #24829), which contains 0b36ffa. Its blob is c37a93cdc839 at the old pin 12dc7b47c340 and 4e8c3d6ebec3 at both 0b36ffa and 616df6598b42: at paid it now expects tax_rate's input gone and the read-only field group shown, and an editable input again at sent and draft. 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 spec asserts all three clauses the ref claims for it (acceptance[0]'s required marker, acceptance[2]'s client lock and acceptance[3]), so the ref keeps them and its stale note gives way to what the spec drives. required-when-submit.spec.ts keeps acceptance[0]. No clause changed", + "ref": "#24857" } ] }, @@ -1060,7 +1054,7 @@ "title": "Cascading and gated select options: dependsOn + per-option visibleWhen, client narrows / server rejects", "since": "v16", "status": "active", - "revision": 4, + "revision": 5, "priority": "P1", "surface": "mixed", "personas": [ @@ -1091,7 +1085,7 @@ { "clause": "dependsOn gates the dependent field until its driver has a value, and changing the driver re-filters the offered set live, clearing a now-invalid selection", "oracle": "dom", - "verify": "after screenshots, enumerate the offered options at each country state (pinned by objectui e2e/live/cascading-options.spec.ts: 'province options re-filter live as country changes, and the stale value clears')", + "verify": "after screenshots, enumerate the offered options at each country state (the re-filter and the clear are pinned by objectui e2e/live/cascading-options.spec.ts: 'province options re-filter live as country changes, and the stale value clears'; the state before any country is chosen is not — see automated.ref)", "evidence": "option enumerations + screenshots" }, { @@ -1130,16 +1124,7 @@ ], "automated": { "kind": "e2e", - "ref": "objectui: e2e/live/cascading-options.spec.ts", - "stale": { - "since": "2026-10-19", - "observedIn": "#24598", - "ref": "#24579 §2", - "partial": "objectui: e2e/live/cascading-options.spec.ts, its re-filter case ONLY — the server out-of-set case passed", - "why": "RED AT THE PIN, AS A STALE CASE — not a product defect. Tier 1 run #24598 at the sweep's console pin 4016370af3c9: cascading-options.spec.ts 1 passed / 1 failed. Its re-filter case (the one that also proves the stale value clears) waits for md-form-submit, a test id only MasterDetailForm renders, but showcase_cascade has no child object, so its New form is a flat ModalForm (round-1 record #24572). Re-read at the shipped pin 12dc7b47c340: the spec's bytes are unchanged, md-form-submit is still MasterDetailForm-only, and no showcase object references showcase_cascade at objectstack 92ce3af404, so the case is still stale there.", - "runnerRule": "Cite the server out-of-set case for acceptance[1]. Do NOT cite the re-filter case or score its failure as this item's FAIL: drive acceptance[0] by hand, with every other clause.", - "ownedBy": "objectui — re-pointing the re-filter case at the current surface is objectui's half, recorded on wave anchor #24579 §2; this repository reports it and does not edit the spec" - } + "ref": "objectui: e2e/live/cascading-options.spec.ts — its re-filter case pins acceptance[0]'s re-filter and clear halves ONLY (on the New form, country cn offers gd and zj, us offers ca and tx, and the chosen Zhejiang leaves the province trigger). It never reads the province before a country is chosen, so 'gates the dependent field until its driver has a value' is driven by hand. Its server case pins acceptance[1] (the out-of-set POST answers 400 VALIDATION_FAILED naming province with invalid_option, the in-set one 201). No pin covers acceptance[2], [3] or [4]" }, "source": [ "examples/app-showcase/src/data/objects/cascading-select.object.ts (the B3 / #1583 fixture, with both-sides contract in its header comment)", @@ -1170,6 +1155,12 @@ "date": "2026-10-20", "change": "automated.stale added — §2 theme \"objectui live e2e is not green at its own pin\" of wave anchor #24579 (18.0 sweep). Tier 1 run #24598 at the sweep's console pin 4016370af3c9: cascading-options.spec.ts's re-filter case failed as a stale case (cause from QA run #24572; #24616 drove the item by hand) and its server out-of-set case passed and stays cited. Re-read at the shipped pin 12dc7b47c340: byte-identical, still stale. No clause changed", "ref": "#24697" + }, + { + "revision": 5, + "date": "2026-10-20", + "change": "automated.stale removed, automated.ref scoped per case and acceptance[0].verify narrowed — round 14 of wave anchor #24579 (18.0 sweep), on the objectui pointer 6284006658. objectui#13132 (objectui 0b36ffa) repaired the re-filter case the stale record named, and the console pin moved to 616df6598b42 (PR #24829), which contains 0b36ffa. cascading-options.spec.ts: blob 648d5c917d19 at the old pin 12dc7b47c340, 5f65228948b7 at both 0b36ffa and 616df6598b42; the case now waits for the flat ModalForm's modal-form-footer instead of md-form-submit. 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 case asserts less than acceptance[0], which the stale record sent to hand-driving: it enumerates province under cn and under us and sees Zhejiang leave the trigger, but never reads the province before a country is chosen. So the ref and acceptance[0].verify narrow to the re-filter and clear halves. The server case keeps acceptance[1]. No clause changed", + "ref": "#24857" } ] }, @@ -1178,7 +1169,7 @@ "title": "Master + line items save as one atomic batch, with server-side roll-up", "since": "v16", "status": "active", - "revision": 6, + "revision": 7, "priority": "P1", "surface": "browser", "personas": [ @@ -1251,16 +1242,7 @@ ], "automated": { "kind": "e2e", - "ref": "objectui: e2e/live/master-detail.spec.ts (acceptance[0], carrier-neutrally: the showcase 'New Project + Tasks' page, one showcase_task child staged through the per-row form, not this item's invoice grid with two lines), e2e/live/form-view-subforms.spec.ts. Dropped at revision 5: e2e/live/summary-rollup.spec.ts, which rolls showcase_task's estimate_hours up into showcase_project (total_estimate as a SUM, task_count as a COUNT) through a direct POST /api/v1/batch, reading both back after that create and again after a child delete. It never opens the invoice form and never reads invoice.total, the roll-up acceptance[2] scores, so it asserts no clause of this item (Tier 1 run #24598 scored acceptance[2] not-run on it for that carrier mismatch)", - "stale": { - "since": "2026-10-19", - "observedIn": "#24598", - "ref": "#24579 §2", - "partial": "objectui: e2e/live/form-view-subforms.spec.ts ONLY — master-detail.spec.ts and summary-rollup.spec.ts passed", - "why": "RED AT THE PIN, AS A STALE SPEC — not a product defect. Tier 1 run #24598 at the sweep's console pin 4016370af3c9: form-view-subforms.spec.ts failed; the other two passed. Its 'Line Items' text locator also matches the master-detail dialog's screen-reader-only description (\"Enter the record and its line items, then save.\", objectui packages/plugin-form/src/ModalForm.tsx), so Playwright's strict mode refuses the locator before the form is driven (round-1 record #24572). Re-read at the shipped pin 12dc7b47c340: the spec's bytes and that description are unchanged, so it is still stale there.", - "runnerRule": "Cite master-detail.spec.ts for acceptance[0] as before. Do NOT cite form-view-subforms.spec.ts or score its failure as this item's FAIL: drive acceptance[4] by hand, with every clause no passing spec covers.", - "ownedBy": "objectui — re-pointing form-view-subforms.spec.ts at the current surface is objectui's half, recorded on wave anchor #24579 §2; this repository reports it and does not edit the spec" - } + "ref": "objectui: e2e/live/master-detail.spec.ts (acceptance[0], carrier-neutrally: the showcase 'New Project + Tasks' page, one showcase_task child staged through the per-row form, not this item's invoice grid with two lines), e2e/live/form-view-subforms.spec.ts (acceptance[4] ONLY: the stock New Invoice dialog renders the relationship-derived Line Items section, found by its heading, and its line grid). Dropped at revision 5: e2e/live/summary-rollup.spec.ts, which rolls showcase_task's estimate_hours up into showcase_project (total_estimate as a SUM, task_count as a COUNT) through a direct POST /api/v1/batch, reading both back after that create and again after a child delete. It never opens the invoice form and never reads invoice.total, the roll-up acceptance[2] scores, so it asserts no clause of this item (Tier 1 run #24598 scored acceptance[2] not-run on it for that carrier mismatch)" }, "source": [ "#3358 §4", @@ -1303,6 +1285,12 @@ "date": "2026-10-20", "change": "acceptance[0].verify and automated.ref narrowed to what master-detail.spec.ts asserts — round 8's finding (iii) for wave anchor #24579 (18.0 sweep; round 8's report 6281776167, carried by the seat's ACCEPT 6281811723). The spec drives showcase_project_workspace ('New Project + Tasks') with one task child staged through the per-row form, not the invoice grid with two lines that steps[1] and [2] drive. Tier 1 run #24598 at the sweep's console pin 4016370af3c9 ran it 2/2 green and scored acceptance[0] pass on it. The clause names no carrier (master and children in one atomic batch, the child ops referencing the parent), and the spec's two tests assert exactly that on their own carrier: the first batch the save sends opens with the populated parent op and carries the child op whose project is {$ref: 0}. So, under round 6's theme-B rule, a pin that asserts a full clause is kept and narrowed, not dropped. The spec is byte-identical at 4016370af3c9 and at the shipped pin 12dc7b47c340. No clause changed", "ref": "#24752" + }, + { + "revision": 7, + "date": "2026-10-20", + "change": "automated.stale removed and automated.ref scoped for form-view-subforms.spec.ts — round 14 of wave anchor #24579 (18.0 sweep), on the objectui pointer 6284006658. objectui#13132 (objectui 0b36ffa) repaired form-view-subforms.spec.ts, the one spec the stale record named, and the console pin moved to 616df6598b42 (PR #24829), which contains 0b36ffa. Its blob is 4f2a95b529f3 at the old pin 12dc7b47c340 and 9485f378abd7 at both 0b36ffa and 616df6598b42: it now finds the Line Items section by its heading role, so the dialog's screen-reader-only description no longer collides with the locator. 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, it asserts acceptance[4], the clause the stale record sent to hand-driving, and the ref now names that scope and no wider one. master-detail.spec.ts keeps acceptance[0]. No clause changed", + "ref": "#24857" } ] }, @@ -1311,7 +1299,7 @@ "title": "Related lists derive from the relationship and page on the server — never fetch every child row — and are read-gated on both ends", "since": "v16", "status": "active", - "revision": 6, + "revision": 7, "priority": "P1", "surface": "browser", "personas": [ @@ -1390,15 +1378,7 @@ ], "automated": { "kind": "e2e", - "ref": "objectui: e2e/live/detail-related-list.spec.ts — acceptance[2] ONLY (the relationship-derived Projects related list on the Account detail page), and stale at the pin (automated.stale). No pin covers the paging, pager-total, relatedList-config, row-navigation or read-gate clauses (acceptance[0], [1], [3], [4], [5])", - "stale": { - "since": "2026-10-19", - "observedIn": "#24598", - "ref": "#24579 §2", - "why": "RED AT THE PIN, AS A STALE SPEC — not a product defect. Tier 1 run #24598 at the sweep's console pin 4016370af3c9: detail-related-list.spec.ts 0 passed / 1 failed. It clicks an Accounts row and waits for a ?recordId= query, but the row now opens the full record page at /record/ID (round-1 record #24572). Re-read at the shipped pin 12dc7b47c340: the spec's bytes are unchanged, and the row-navigation path did not change between the pins (ObjectView's navigation-mode code is unchanged, and the record-surface derivation it calls, packages/spec/src/data/record-surface.ts, is unchanged since the sweep subject), so it is still stale there.", - "runnerRule": "Do NOT cite this spec or score its failure as this item's FAIL: drive every clause by hand, acceptance[2] included (QA run #24616 did).", - "ownedBy": "objectui — re-pointing detail-related-list.spec.ts at the current surface is objectui's half, recorded on wave anchor #24579 §2; this repository reports it and does not edit the spec" - } + "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). No pin covers the paging, pager-total, relatedList-config, row-navigation or read-gate clauses (acceptance[0], [1], [3], [4], [5])" }, "source": [ "#3358 §4 (evidence run captured exactly this trace)", @@ -1443,6 +1423,12 @@ "date": "2026-10-20", "change": "automated.ref narrowed and automated.stale added — §2 themes \"pins that cover no full clause\" and \"objectui live e2e is not green at its own pin\" of wave anchor #24579 (18.0 sweep). Tier 1 run #24598 at the sweep's console pin 4016370af3c9: detail-related-list.spec.ts, the only pin, failed as a stale spec (cause from QA run #24572; #24616 passed the item by hand). When green it pins acceptance[2] alone, so the ref now says so. Re-read at the shipped pin 12dc7b47c340: byte-identical, still stale. No clause changed", "ref": "#24697" + }, + { + "revision": 7, + "date": "2026-10-20", + "change": "automated.stale removed — round 14 of wave anchor #24579 (18.0 sweep), on the objectui pointer 6284006658. objectui#13132 (objectui 0b36ffa) repaired detail-related-list.spec.ts, the only pin, and the console pin moved to 616df6598b42 (PR #24829), which contains 0b36ffa. Its blob is 48a1d10e59da at the old pin 12dc7b47c340 and f12f7237fd6f at both 0b36ffa and 616df6598b42: it now reads the record id from the /record/ID route a Northwind row opens, and finds the primary Projects list in its own tab. 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, it asserts acceptance[2], the one clause the ref claims, so the ref keeps it and loses its stale note. No clause changed", + "ref": "#24857" } ] }, @@ -2355,7 +2341,7 @@ "title": "User-built FilterBuilder/SortBuilder toolbar merges with the view filter, restores across nav, and reproduces rows from the URL", "since": "v16", "status": "active", - "revision": 5, + "revision": 6, "priority": "P1", "surface": "browser", "personas": [ @@ -2427,16 +2413,7 @@ ], "automated": { "kind": "e2e", - "ref": "objectui: e2e/live/user-filters.spec.ts — acceptance[4] ONLY: its dropdown-selection case pins the uf_ half (a uf_priority selection survives a reload), and the uf__tab half rests on its filter-tabs case, stale at the pin (automated.stale). No pin covers acceptance[0]–[3]: e2e/live/saved-view-filter.spec.ts, cited here until revision 5, pins a saved view's stored filter alone, not the toolbar merge acceptance[0] scores, so it was dropped", - "stale": { - "since": "2026-10-19", - "observedIn": "#24598", - "ref": "#24579 §2", - "partial": "objectui: e2e/live/user-filters.spec.ts, 4 of its 6 cases — the dropdown-selection case passed", - "why": "RED AT THE PIN, AS A STALE SPEC — not a product defect. Tier 1 run #24598 at the sweep's console pin 4016370af3c9: user-filters.spec.ts 2 passed / 4 failed. The failing filter-tabs case asserts pre-ADR-0053 metadata — an in-view tab row on the default All Tasks list, which carries none because status presets are named views (examples/app-showcase/src/ui/views/task.view.ts) — so acceptance[4]'s uf__tab half has no green pin; the round-1 record #24572 names the causes. Re-read at the shipped pin 12dc7b47c340: the spec's bytes and that metadata are unchanged at objectstack 92ce3af404, so it is still stale there.", - "runnerRule": "Cite the dropdown-selection case for acceptance[4]'s uf_ half only. Do NOT cite the failing cases or score them as this item's FAIL: drive acceptance[4]'s uf__tab half and acceptance[0]–[3] by hand.", - "ownedBy": "objectui — re-pointing the filter-tabs case at the current surface is objectui's half, recorded on wave anchor #24579 §2; this repository reports it and does not edit the spec" - } + "ref": "objectui: e2e/live/user-filters.spec.ts — acceptance[4] ONLY: its dropdown-selection case pins the uf_ half (a uf_priority selection survives a reload), and its filter-tabs case, now on the Task Triage interface page, pins the uf__tab half (picking the urgent tab writes uf__tab=urgent, and it survives a reload). No pin covers acceptance[0]–[3]: e2e/live/saved-view-filter.spec.ts, cited here until revision 5, pins a saved view's stored filter alone, not the toolbar merge acceptance[0] scores, so it was dropped" }, "source": [ "objectui: packages/plugin-list/src/ListView.tsx (buildEffectiveFilter, convertFilterGroupToAST, mergeFilterNodes; $filter + $orderby assembly)", @@ -2475,6 +2452,12 @@ "date": "2026-10-20", "change": "automated.ref narrowed and automated.stale added — §2 themes \"pins that cover no full clause\" and \"objectui live e2e is not green at its own pin\" of wave anchor #24579 (18.0 sweep). Tier 1 run #24598 scored every clause not-run on its pins at the sweep's console pin 4016370af3c9 (QA run #24616 then passed the item by hand; #24572 names the stale causes): saved-view-filter.spec.ts pins a saved view's filter alone, not the toolbar merge acceptance[0] scores, so it is dropped; user-filters.spec.ts pins acceptance[4]'s uf_ half, and its uf__tab half rests on the stale filter-tabs case. Re-read at the shipped pin 12dc7b47c340: the spec is byte-identical and still stale. No clause changed", "ref": "#24697" + }, + { + "revision": 6, + "date": "2026-10-20", + "change": "automated.stale removed — round 14 of wave anchor #24579 (18.0 sweep), on the objectui pointer 6284006658. objectui#13132 (objectui 0b36ffa) repaired user-filters.spec.ts, and the console pin moved to 616df6598b42 (PR #24829), which contains 0b36ffa. Its blob is aa52b2b8de2a at the old pin 12dc7b47c340 and ab50146bcfd0 at both 0b36ffa and 616df6598b42: the filter-tabs case now drives the tabs element on the Task Triage interface page (ADR-0053), and the lookup quick-filter case is retired. 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 two cases the ref claims assert acceptance[4]'s two halves as it says (uf_priority=urgent and uf__tab=urgent each survive a reload), so the ref keeps acceptance[4] and loses its stale note. No case this item cites was retired. No clause changed", + "ref": "#24857" } ] }, @@ -3849,7 +3832,7 @@ "title": "Cascade clear-semantics and the server boundary: stale-child clear on parent change, the WRITTEN-value server gate, and where cascade scope is client-only", "since": "v16", "status": "active", - "revision": 4, + "revision": 5, "priority": "P1", "surface": "mixed", "personas": [ @@ -3927,16 +3910,7 @@ ], "automated": { "kind": "e2e", - "ref": "objectui: e2e/live/cascading-options.spec.ts (client clear-on-change); packages/objectql/src/validation/rule-validator.option-visibility.test.ts (server WRITTEN-value gate)", - "stale": { - "since": "2026-10-19", - "observedIn": "#24598", - "ref": "#24579 §2", - "partial": "objectui: e2e/live/cascading-options.spec.ts, its re-filter case (the client clear-on-change half this ref names) ONLY — its server out-of-set case and the objectql pin passed", - "why": "RED AT THE PIN, AS A STALE CASE — not a product defect. Tier 1 run #24598 at the sweep's console pin 4016370af3c9: cascading-options.spec.ts 1 passed / 1 failed, rule-validator.option-visibility.test.ts passed. Its re-filter case (the one that also proves the stale value clears) waits for md-form-submit, a test id only MasterDetailForm renders, but showcase_cascade has no child object, so its New form is a flat ModalForm (round-1 record #24572). Re-read at the shipped pin 12dc7b47c340: the spec's bytes are unchanged, md-form-submit is still MasterDetailForm-only, and no showcase object references showcase_cascade at objectstack 92ce3af404, so the case is still stale there.", - "runnerRule": "Cite rule-validator.option-visibility.test.ts for acceptance[1] and acceptance[2] as before. Do NOT cite the re-filter case or score its failure as this item's FAIL: drive acceptance[0] by hand, with every clause no passing pin covers.", - "ownedBy": "objectui — re-pointing the re-filter case at the current surface is objectui's half, recorded on wave anchor #24579 §2; this repository reports it and does not edit the spec" - } + "ref": "objectui: e2e/live/cascading-options.spec.ts (acceptance[0]'s client clear-on-change, through its re-filter case: country cn offers gd and zj, us offers ca and tx, and the chosen Zhejiang leaves the province trigger. It never submits, so 'the stale province is not carried into the submit' is driven by hand); packages/objectql/src/validation/rule-validator.option-visibility.test.ts (server WRITTEN-value gate: acceptance[1], and acceptance[2]'s unwritten child through its 'does not check a field the patch never wrote' case)" }, "source": [ "packages/objectql/src/validation/rule-validator.ts#evaluateOptionVisibility (evaluateOptionVisibility — WRITTEN-value only via `!(name in data) continue`; a predicate that cannot be evaluated refuses the write as rule_violation / unevaluable (ADR-0137 D2), except a system write with no acting user whose predicate reads one; invalid_option/option_unavailable)", @@ -3970,6 +3944,12 @@ "date": "2026-10-20", "change": "automated.stale added — §2 theme \"objectui live e2e is not green at its own pin\" of wave anchor #24579 (18.0 sweep). Tier 1 run #24598 at the sweep's console pin 4016370af3c9: cascading-options.spec.ts's re-filter case, the clear-on-change half this ref names, failed as a stale case (cause from QA run #24572; #24616 drove the item by hand); the objectql pin passed and stays cited. Re-read at the shipped pin 12dc7b47c340: byte-identical, still stale. No clause changed", "ref": "#24697" + }, + { + "revision": 5, + "date": "2026-10-20", + "change": "automated.stale removed and automated.ref scoped per pin — round 14 of wave anchor #24579 (18.0 sweep), on the objectui pointer 6284006658. objectui#13132 (objectui 0b36ffa) repaired the cascading-options.spec.ts re-filter case the stale record named, and the console pin moved to 616df6598b42 (PR #24829), which contains 0b36ffa. Its blob is 648d5c917d19 at the old pin 12dc7b47c340 and 5f65228948b7 at both 0b36ffa and 616df6598b42; the case now waits for the flat ModalForm's modal-form-footer instead of md-form-submit. 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 case asserts acceptance[0]'s re-filter and cleared trigger but never submits, so the ref says the submit half is driven by hand. The objectql pin's scope (acceptance[1] and acceptance[2]), which only the stale record's runnerRule carried, moves into the ref unchanged. No clause changed", + "ref": "#24857" } ] }, @@ -4510,7 +4490,7 @@ "title": "Per-field trackHistory: a tracked edit lands the ADR-0052 §5b old→new timeline summary with display values, an untracked edit does not, and object-level enable.trackHistory gates the History tab and derived history op both ways", "since": "v15", "status": "active", - "revision": 4, + "revision": 5, "priority": "P1", "surface": "mixed", "personas": [ @@ -4577,16 +4557,7 @@ ], "automated": { "kind": "unit", - "ref": "packages/plugins/plugin-audit/src/audit-lookup-summary.test.ts (reference titles + read plan); audit-option-label-summary.test.ts (option labels); objectui e2e/live/record-history-display.spec.ts (tab display contract, cited by crud-roundtrip)", - "stale": { - "since": "2026-10-19", - "observedIn": "#24598", - "ref": "#24579 §2", - "partial": "objectui e2e/live/record-history-display.spec.ts ONLY — the two plugin-audit pins passed", - "why": "SKIPPED AT THE PIN, AS A STALE SPEC — not a product defect. Tier 1 run #24598 at the sweep's console pin 4016370af3c9: record-history-display.spec.ts 0 passed / 0 failed / 1 skipped. It skips unless the live backend serves app-todo's todo_task, on the premise that the showcase declares no object with enable.trackHistory; the showcase now does (showcase_account, examples/app-showcase/src/data/objects/account.object.ts), so against this item's fixture app it never runs. Re-read at the shipped pin 12dc7b47c340: the spec's bytes are unchanged, so it still skips there. Even run against app-todo it pins the History tab's display contract, which negative[3] assigns to records-forms.crud-roundtrip, not a clause of this item.", - "runnerRule": "Cite the two plugin-audit pins as before. Do NOT cite record-history-display.spec.ts here: drive acceptance[2]'s tab gating by hand.", - "ownedBy": "objectui — re-pointing record-history-display.spec.ts at the current surface is objectui's half, recorded on wave anchor #24579 §2; this repository reports it and does not edit the spec" - } + "ref": "packages/plugins/plugin-audit/src/audit-lookup-summary.test.ts (reference titles + read plan); audit-option-label-summary.test.ts (option labels); objectui e2e/live/record-history-display.spec.ts (the History tab's display contract, which negative[3] assigns to records-forms.crud-roundtrip. It claims no clause of this item: it opens showcase_account's History tab but never reads the task detail, so acceptance[2]'s gating is driven by hand)" }, "source": [ "packages/plugins/plugin-audit/src/audit-writers.ts#planTrackedLookupReads (planTrackedLookupReads), (renderTrackedChangeSummary — ADR-0052 §5b, #7230/#7289 localization), (zero-reads-by-default plan)", @@ -4618,6 +4589,12 @@ "date": "2026-10-20", "change": "line citations re-pointed — the comma-range spelling that round 7 of wave anchor #24579 named (18.0 sweep; round 7's report 6281433885, out_of_scope_findings[1]). fixtures.requires[1] and source[3] cited line 60 of the showcase task.object.ts in the comma-range spelling (authored in 45397edf53 as the list 49 and 60). At that commit 49 and 60 were the trackHistory flags of the task's status and priority fields; at this base both have moved by a line. Both citations now anchor task.object.ts#Task and name the two fields. The spelling is what #13786's strip left when it removed only the first range of a ':A,B' list, and the line-citation limb reads only the colon spellings, so no gate caught it. Where the surrounding words still describe the range the strip removed, the new citation names that code too. No clause's assertion changed", "ref": "#24752" + }, + { + "revision": 5, + "date": "2026-10-20", + "change": "automated.stale removed — round 14 of wave anchor #24579 (18.0 sweep), on the objectui pointer 6284006658. objectui#13132 (objectui 0b36ffa) repaired record-history-display.spec.ts, the one spec the stale record named, and the console pin moved to 616df6598b42 (PR #24829), which contains 0b36ffa. Its blob is 2c4d8a674f81 at the old pin 12dc7b47c340 and 7ebc45106cff at both 0b36ffa and 616df6598b42: it now targets showcase_account, the showcase's enable.trackHistory object, with no app-todo skip guard. 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, it asserts the History tab's display values on showcase_account (crud-roundtrip's contract, per negative[3]) and opens no task detail, so it still claims no clause here, and the ref now says so. The two plugin-audit pins keep their scope. No clause changed", + "ref": "#24857" } ] }, diff --git a/docs/qa/platform-checklist/areas/studio-authoring.json b/docs/qa/platform-checklist/areas/studio-authoring.json index cf4f7573a5..d79190d441 100644 --- a/docs/qa/platform-checklist/areas/studio-authoring.json +++ b/docs/qa/platform-checklist/areas/studio-authoring.json @@ -96,7 +96,7 @@ "title": "Object designer round-trip: field add/edit/reorder persists to metadata, identifiers derive and survive typing", "since": "v16", "status": "active", - "revision": 6, + "revision": 7, "priority": "P1", "surface": "mixed", "personas": ["admin"], @@ -113,7 +113,7 @@ "open the object designer on the writable package: /_console/apps/setup/metadata/object/new?package=PKG (PKG = the writable package's id; note its namespace NS, from GET /api/v1/packages). ⛔ Not /_console/apps/com.objectstack.studio/…: the studio app is not loaded on a stock boot (RUNNER.md environment facts), so that route renders inside another app's chrome", "TYPE the object name NS_repair_asset character by character (never .fill — the F2 per-keystroke-sanitisation bug only reproduces when typed) and confirm both underscores survive. The NS_ prefix is required: in a namespaced writable package the publish gate refuses an unprefixed object name (NAMESPACE_PREFIX). Type the name after the label, or re-check it before saving — objectui#12680: typing the Label after a hand-typed name overwrites it and drops the prefix", "add a Text field, set its label to 'Asset Code', blur — the API name input must derive asset_code (F3)", - "add a Picklist field and author its 3 real options, THEN add one EMPTY option row; wait out the debounced live validation — no validation banner may appear for the empty row (F4). ⚠ Order matters: with NO real option yet the select-needs-options banner fires, legitimately — the empty rows ARE dropped, so the field has no options — which collides with a literal 'no banner' (and with objectui F4's toHaveCount(0) the same way). Assert the empty-row half with real options present", + "add a Picklist field and author its 3 real options, THEN add one EMPTY option row; wait out the debounced live validation — no validation banner may appear for the empty row (F4). ⚠ Order matters: with NO real option yet the select-needs-options banner fires, legitimately — the empty rows ARE dropped, so the field has no options — which collides with a literal 'no banner' (objectui F4, as repaired at 0b36ffa, gives its picklist one real option first for this reason). Assert the empty-row half with real options present", "Save (the first save; the editor then autosaves every later edit — its Auto-save toggle defaults on, objectui ResourceEditPage.tsx metadata-admin:autosave — so later 'Save draft' steps are implicit), Publish; GET /api/v1/meta/object/NS_repair_asset and record the full field list and its order", "reopen the designer: rename one picklist value, drag-reorder the fields (native HTML5 drag-and-drop: Playwright's dragTo moves a row, raw mouse moves do not — automation-input), let the autosave land, and Publish again", "GET /api/v1/meta/object/NS_repair_asset again — the rename AND the new field order must be in the persisted metadata, not just the canvas", @@ -149,16 +149,7 @@ "an API name frozen at field_N after its label was set pre-save is audit finding 2 regressed — FAIL, but confirm against a fresh objectui build first: the vendored /_console bundle may predate the derive-on-blur fix the e2e now pins" ], "traps": ["stale-console-bundle", "automation-input"], - "automated": { "kind": "e2e", "ref": "objectui: e2e/live/studio-object-designer.spec.ts", - "stale": { - "since": "2026-10-19", - "observedIn": "#24598", - "ref": "#24579 §2", - "partial": "objectui: e2e/live/studio-object-designer.spec.ts cases F1 and F4 ONLY — F2 and F3 passed", - "why": "RED AT THE PIN, AS STALE CASES — not a product defect. Tier 1 run #24598 ran the spec at the sweep's console pin 4016370af3c9: 2 passed (F2, F3), 2 failed (F1, F4); the round-1 record #24571 names the causes. F4 adds a picklist and one empty option row with no real option and expects no metadata-validation banner, which contradicts acceptance[3]'s own judging order: a select with no option source is refused at parse (packages/spec/src/data/field.zod.ts, options), so that banner is correct. F1 opens /apps/com.objectstack.studio, an app no stock boot loads (RUNNER.md environment facts). Re-read at the shipped pin 12dc7b47c340: the spec's bytes are unchanged and both causes hold — field.zod.ts is unchanged between the objectstack builds the two pins consume (2c9bf9430a11 and f4755a68a797), and the studio app is still not default-loaded at objectstack 92ce3af404.", - "runnerRule": "Cite F3 for acceptance[1]'s designer half (the derived API-name input) and F2 for acceptance[2]. Do NOT cite F4 or F1, and do NOT score their failure as this item's FAIL: drive acceptance[3] by hand in the clause's order (the 3 real options first, then the empty row), and acceptance[0] and acceptance[1]'s stored-column half by hand as before. F1 asserts no clause of this item.", - "ownedBy": "objectui — re-pointing F1 and F4 at the current surface is objectui's half, recorded on wave anchor #24579 §2; this repository reports it and does not edit the spec" - } }, + "automated": { "kind": "e2e", "ref": "objectui: e2e/live/studio-object-designer.spec.ts — F3 pins acceptance[1]'s designer half (the API-name input derives asset_code from the label on blur) and F2 pins acceptance[2] (a name typed character by character keeps its underscore). F4 pins acceptance[3]'s banner half ONLY: it gives the picklist one real option, not three, adds an empty row and finds no metadata-validation banner after the debounce, but it never publishes or reads the stored options, so 'the PUBLISHED picklist carries exactly the 3 authored options' is driven by hand. F1 (a package created from the Studio surface's switcher appears in it without a reload) asserts no clause of this item. No pin covers acceptance[0] or acceptance[1]'s stored-column half" }, "source": [ "objectui: e2e/live/studio-object-designer.spec.ts (F1–F4, the objectui#1926 regression classes: per-keystroke sanitisation, label→api-name derivation, empty picklist row, switcher refresh)", "docs/audits/2026-07-studio-package-create-ux-dogfood.md (finding 2 — field API name did not follow the label at audit time)", @@ -195,6 +186,12 @@ "date": "2026-10-20", "change": "automated.stale added — §2 theme \"objectui live e2e is not green at its own pin\" of wave anchor #24579 (18.0 sweep). Tier 1 run #24598 ran studio-object-designer.spec.ts at the sweep's console pin 4016370af3c9: F2 and F3 passed, F1 and F4 failed as stale cases (causes from QA run #24571; #24604 drove acceptance[0], acceptance[3] and negative[0] by hand). Re-read at the shipped pin 12dc7b47c340: the spec is byte-identical and both causes hold. The ref keeps the spec, F2 and F3 still citable. No clause changed", "ref": "#24697" + }, + { + "revision": 7, + "date": "2026-10-20", + "change": "automated.stale removed, automated.ref scoped per case, and steps[3]'s note on F4 corrected — round 14 of wave anchor #24579 (18.0 sweep), on the objectui pointer 6284006658. objectui#13132 (objectui 0b36ffa) repaired studio-object-designer.spec.ts, and the console pin moved to 616df6598b42 (PR #24829), which contains 0b36ffa. The spec's blob is 5967807df335 at the old pin 12dc7b47c340 and 58a7f1cbf024 at both 0b36ffa and 616df6598b42: F1 now creates the package through the Studio surface's switcher (/studio/PKG/data) and F4 gives the picklist one real option before the empty row, so both stale causes are gone, and the stale record, which named only F1 and F4, goes with them. 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 the clauses this record let a runner cite or sent to hand-driving: F3 for acceptance[1]'s designer half, F2 for acceptance[2], and F4 for acceptance[3]'s banner half only (one real option, no publish, no meta read). F1 asserts no clause here. No clause changed", + "ref": "#24857" } ] }, @@ -275,7 +272,7 @@ "title": "Record-page authoring round-trip: created bound to its object, seeded from the default layout, block-edited, published, rendered", "since": "v16", "status": "active", - "revision": 6, + "revision": 7, "priority": "P1", "surface": "mixed", "personas": ["admin (authors)", "end user (opens the record). On stock no non-admin persona reads showcase_contact (auditor.demo is refused 'You don't have access to Contact records', QA run #24604), so the viewer is the admin unless a grant is provisioned — e.g. a member bound to the `manager` position, whose showcase_manager set reads showcase_contact (examples/app-showcase/src/security/permission-sets.ts); record which"], @@ -290,7 +287,7 @@ "open /_console/apps/showcase_app/metadata/page/new and fill the create form: Label 'Invoice Page ' (slugifies into Name), set Page type = record (the create form defaults Page type to list — objectui metadata-admin anchors.ts, the page createSchema), Object showcase_contact (fixtures.requires[0]); Save", "capture the PUT /api/v1/meta/page/ request the save issues", "assert the draft body: type:'record', object:'showcase_contact', and regions seeded NON-empty from the object's synthesized default detail page (the page resource's createSeed hook) including a record:highlights block — never a blank canvas (ADR-0034 / objectui#1541)", - "open the page editor (/apps/showcase_app/metadata/page/): the Basics, Data Context and Advanced panels render (the layout is edited on the canvas, not in a Layout section — see acceptance[1]'s stale-pin note), and 'Add block' opens the block-type picker", + "open the page editor (/apps/showcase_app/metadata/page/): the Basics, Data Context and Advanced panels render (the layout is edited on the canvas, not in a Layout section — see acceptance[1].verify), and 'Add block' opens the block-type picker", "add a block (e.g. Card), Save draft, Publish through the ResourceEditPage draft/publish chrome", "GET /api/v1/meta/page/: the published regions must include the added block", "open a showcase_contact record as the end user (personas[1]): the page assignment (usePageAssignment) renders the authored page over the synthesized default", @@ -300,13 +297,13 @@ { "clause": "the created page persists bound to its object with PRE-SEEDED regions — record:highlights present, regions non-empty", "oracle": "network", - "verify": "the captured PUT body has type:'record', object:'showcase_contact', Array.isArray(regions) with blocks including record:highlights. ⚠ Drive this by hand: the pin (objectui e2e/live/studio-record-page.spec.ts) is STALE against the current surface — it fills the Object control as an input when it is now a role=combobox button — see automated.stale", + "verify": "the captured PUT body has type:'record', object:'showcase_contact', Array.isArray(regions) with blocks including record:highlights (pinned carrier-neutrally by objectui e2e/live/studio-record-page.spec.ts, which binds showcase_invoice — see automated.ref)", "evidence": "the captured PUT payload" }, { "clause": "the page editor exposes block authoring: the picker offers schema-backed block kinds (Card, Section, Record details)", "oracle": "dom", - "verify": "after a screenshot confirms the editor rendered, the Add-block dialog lists the three kinds. ⚠ Drive this by hand: the pin (objectui e2e/live/studio-editor.spec.ts) is STALE — it targets a 'Layout' heading that no longer exists and a shipped page the editor correctly locks — see automated.stale", + "verify": "after a screenshot confirms the editor rendered, the Add-block dialog lists the three kinds. No pin in automated.ref covers this clause: objectui e2e/live/studio-editor.spec.ts asserts the same picker (Card, Section, Record details) on an editable copy of the shipped showcase_project_workspace page, and is not in the ref. Until objectui 0b36ffa that spec was stale: it looked for a 'Layout' section heading the page form no longer renders (the layout is edited on the canvas) and opened a shipped page the editor correctly locks", "evidence": "screenshot + dialog DOM read" }, { @@ -328,20 +325,11 @@ "traps": ["stale-console-bundle", "hydration-race", "automation-input"], "automated": { "kind": "e2e", - "ref": "objectui: e2e/live/studio-record-page.spec.ts", - "stale": { - "since": "2026-08-11", - "observedIn": "#24598", - "ref": "#7753 item 6", - "why": "STALE, NOT RED — the spec fails against the CURRENT surface, not against a product defect. `studio-record-page.spec.ts` fills the Object control as an input when it is now a `role=combobox` button; `studio-editor.spec.ts` (cited in source, and the pin behind the Add-block clause) targets a 'Layout' heading that no longer exists, plus a SHIPPED page the editor correctly locks. Neither is reporting a regression. Re-measured at the 18.0 sweep: Tier 1 run #24598 ran it at the sweep's console pin 4016370af3c9, 0 passed / 1 failed; re-read at the shipped pin 12dc7b47c340, the spec's bytes are unchanged and nothing on the page create path changed between the pins (the only ResourceEditPage change is the declaration-only gate for sharing rules), so it is still stale there. First observed by #7695 on 2026-08-11; #7753 closed without the objectui half landing.", - "runnerRule": "Do NOT satisfy this item by citing these specs' output, and do NOT score their failure as a FAIL of this item — drive the clauses by hand (browser + the captured PUT) until the specs are re-pointed. A stale ref left unmarked costs a red run every time the area is exercised, which is how a stale ref turns into ignored signal.", - "ownedBy": "objectui — re-pointing the specs at the current surface is a cross-repo half of #7753, reported not edited from this repo", - "seeAlso": "the same class, already repaired: object-designer-roundtrip's 4th automated ref failed only because package-create moved to /_console/studio; that contract passes on the current surface" - } + "ref": "objectui: e2e/live/studio-record-page.spec.ts — acceptance[0] ONLY, carrier-neutrally: it creates a record page bound to showcase_invoice (not this item's showcase_contact) and asserts the captured PUT body's type 'record', its object, and regions seeded with a record:highlights block. It covers no other clause. objectui e2e/live/studio-editor.spec.ts, which drives the Add-block picker acceptance[1] scores, is cited in source[1] and has never been in this ref" }, "source": [ - "objectui: e2e/live/studio-record-page.spec.ts (#1541, ADR-0034 — create bound + seeded regions, asserted off the PUT payload) — ⚠ STALE against the current surface, see automated.stale", - "objectui: e2e/live/studio-editor.spec.ts (page editor sections + Add-block picker contract) — ⚠ STALE against the current surface, see automated.stale" + "objectui: e2e/live/studio-record-page.spec.ts (#1541, ADR-0034 — create bound + seeded regions, asserted off the PUT payload)", + "objectui: e2e/live/studio-editor.spec.ts (page editor sections + Add-block picker contract)" ], "history": [ { "revision": 1, "date": "2026-08-07", "change": "new item: record-page authoring round-trip pinned to the two objectui live e2e specs (create-seeded draft, block picker) and extended to the publish + end-user render sides they do not cover", "ref": "claude/platform-test-checklist-ocwugl" }, @@ -369,6 +357,12 @@ "date": "2026-10-20", "change": "automated.stale.observedIn and automated.stale.why refreshed — §2 theme \"objectui live e2e is not green at its own pin\" of wave anchor #24579 (18.0 sweep). Tier 1 run #24598 re-measured studio-record-page.spec.ts red at the sweep's console pin 4016370af3c9 (0 passed / 1 failed; QA runs #24571 / #24604 drove the clauses by hand), and a re-read at the shipped pin 12dc7b47c340 finds the spec byte-identical and its create path unchanged, so the marker first written from #7695 still holds. No clause changed", "ref": "#24697" + }, + { + "revision": 7, + "date": "2026-10-20", + "change": "automated.stale removed, automated.ref scoped to acceptance[0], and the stale notes in acceptance[0].verify, acceptance[1].verify, steps[3], source[0] and source[1] 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-editor.spec.ts: blob e442b4c1a29e, then 19f9cc131654 at both; it now edits a copy of showcase_project_workspace and reads the layout on the canvas. 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, studio-record-page.spec.ts asserts acceptance[0], the one clause the ref claims (carrier-neutrally, on showcase_invoice). studio-editor.spec.ts was never in the ref, so acceptance[1] stays driven by hand rather than widening the ref. No clause changed", + "ref": "#24857" } ] },