Full records-forms area run of the checklist-test skill — all 32 runnable items driven against a live showcase + vendored console (6 opus subagents, one isolated boot each). Supersedes the api-subset run #7399. 4 real regressions (all in the vendored console / objectui), each reproduced ≥2× with root cause. Convention labels: qa-run + bug (labels not yet created in this repo).
Result: 15 PASS · 12 PARTIAL · 4 FAIL · 1 BLOCKED (of 32 runnable; +1 pre-blocked import-job-undo-cancel fixture). Screenshots were judgment aids only — this report is text; every verdict rests on a server-truth/network/test oracle.
Environment
| |
|---|
| framework | a86db175 — branch claude/platform-test-checklist-ocwugl (PR #7304) |
| console | vendored dist built from objectui 09987b68 (.objectui-sha) |
| app · driver | showcase · SqlDriver(better-sqlite3) · fresh isolated file DB + port per item · admin@objectos.ai |
| browser | Playwright/Chromium (executablePath pin) · console loaded via localhost (trusted-origin) |
🔴 FAIL — 4 regressions (all in the vendored console / objectui)
1. upload-guard-blocks-confirm — image param has no client-side max-size guard
p_cover (declared maxSize 5 MB) accepts an oversized file: a 6.3 MB PNG fires a full presigned → PUT → complete upload with no rejection, while p_attachments (10 MB) correctly rejects >10 MB with zero uploads. Reproduced 2×.
Repro: Field Zoo → Specimen–Full row → run "Action Param Gallery"; set a >5 MB image on Cover image (p_cover). Expected: rejected before any upload (like p_attachments for >10 MB). Actual: full upload + preview, no "5.0 MB" error. Root cause: the image-param widget lacks the client maxSize guard the file-param widget has.
2. kanban-drag-persistence — rejected drag doesn't roll the card back
An illegal Kanban drag (Backlog→In Progress) is correctly rejected server-side (PATCH 400 invalid_transition, toast shown, server stays backlog), but the card stays stuck in the target column until a manual reload. Reproduced 3× (switcher + dedicated Board view).
Repro: showcase_task → Kanban; drag a Backlog card onto In Progress. Expected: card returns to Backlog on the 400. Actual: card stuck in In Progress >5 s. Root cause: objectui plugin-kanban/src/ObjectKanban.tsxhandleCardMove gates revert-on-failure behind if (!hasExternalData); the ListView-hosted (console) path has hasExternalData=true, so rollback is skipped.
3. saved-view-management — renaming a draft view doesn't persist
Create-kanban / pin / delete all work (200), but rename of a freshly-created draft view is rejected and silently lost; set-default fires no write at all. Reproduced 2×.
Repro: create a Kanban view via the + tab (draft), then tab menu → Rename. Expected: new label persists. Actual: client updateView GETs the base view withoutpreview=draft → 404 → treats as create → writes an invalid partial {label,name,object} → PUT → 422; re-read (preview=draft) still shows the old label. Root cause: objectui data-objectstack/src/index.tsupdateView() reads the base view without preview=draft then writes an invalid partial.
4. bulk-select-all-matching — Clear leaves row checkboxes ticked (#3056 drift)
Clicking Clear in the bulk-actions bar empties the toolbar but leaves the row checkboxes data-state="checked" (header stays indeterminate) — stranded ticks with no toolbar. Reproduced 2×.
Repro: showcase_contact list → tick 3 rows → click Clear. Expected: bar and checkboxes both reset. Actual: bar removed, checkboxes stay checked. Root cause: objectui plugin-grid/src/ObjectGrid.tsxonClearSelection does setSelectedRows([]) + setSelectAllMatching(false) but omits the setSelectionResetKey bump that resetSelection() (delete/dispatch paths) performs.
Note: this item's cross-page-banner clauses (0/1/2/4) are blocked(fixture) — no seeded object exceeds the 100-row page window and no view exposes pageSizeOptions, so "select all matching" is unreachable in the stock console.
🟡 Notable finding inside PARTIAL
object-hook-lifecycle — hook ['log'] capability output is not observable. Hook bodies fire ([BodyRunner] hook fired) and don't throw, but the named log lines (ctx.log.info("task completed: …"), "project over budget: …") never appear even at --log-level debug. Hook lifecycle + condition semantics are all correct (beforeInsert defaults/trim, afterUpdate two-root previous.done gating #4784, total-record merge, fail-closed condition #4775). Clauses 2/4/5 are partial only because their named-log oracle can't be captured. Worth a separate look at body-runner.tslog:engineCtx.logger wiring.
Full verdict table (32 runnable + 1 pre-blocked)
| item | pri · surface | verdict |
|---|
| validation-rule-type-matrix | P1 api | ✅ pass (6 rule types, exact codes) |
| named-import-mapping | P2 api | ✅ pass (mapped + idempotent + 404) |
| field-type-matrix | P1 mixed | ✅ pass (dogfood 46/46 + widgets + mask + refs) |
| conditional-rules-header | P1 mixed | ✅ pass (requiredWhen/readonlyWhen/visibleWhen both ends) |
| conditional-rules-grid | P1 browser | ✅ pass (row-scoped required + parent-lock + receipt ref) |
| master-detail-atomic-save | P1 browser | ✅ pass (single atomic /batch, roll-up, all-or-nothing) |
| related-list-server-pagination | P1 browser | ✅ pass (paged child queries, 403-vs-200 both persona) |
| action-param-widgets | P1 mixed | ✅ pass (10 real widgets, malformed bag rejected) |
| import-wizard-encoding-and-hints | P2 browser | ✅ pass (GBK + required-hint + degrade + live import) |
| form-dirty-guard | P2 browser | ✅ pass (prompt iff dirty; discardGuard 14/14) |
| adhoc-filter-sort-builder | P1 browser | ✅ pass (merge under AND, per-user key, uf__tab, #1964) |
| concurrent-edit-conflict | P1 mixed | ✅ pass (OCC 409 both surfaces, 1 PATCH 2 keys, occSave 8/8) |
| lookup-picker-create-new | P2 browser | ✅ pass (nested create, real id adopt, scoped $search, both-sides) |
| field-type-constraints | P1 mixed | ✅ pass (8/8; 2 non-enforcement gaps recorded honestly) |
| encrypted-field-behavior | P1 mixed | ✅ pass (ciphertext, read-mask, no-op echoed-mask, fail-closed pins) |
| crud-roundtrip | P0 browser | 🟡 partial — clone RLS-404 / enable.clone:false blocked(fixture) |
| list-view-capabilities | P1 browser | 🟡 partial — server $skip unreachable (no object >100-row page) |
| view-type-gallery | P1 browser | 🟡 partial — map basemap env-blocked; kanban summarize-total; smoke env |
| form-view-gallery | P1 browser | 🟡 partial — tabbed/wizard/split/drawer/modal have no UI opener (fixture) |
| cascading-options | P1 mixed | 🟡 partial — role-gate allow-side: 'admin' position never seeded |
| action-location-matrix | P1 browser | 🟡 partial — record_header/more/related unreachable on stock page; global_nav unproven |
| gantt-interactions | P2 browser | 🟡 partial — auto-schedule/lock/veto need fixtures (matches knownGaps) |
| calendar-interactions | P1 browser | 🟡 partial — quick-create needs project; real-403 unreachable |
| record-discussion-mentions | P1 browser | 🟡 partial — mention-bell/recipient-scoping need a 2nd real user |
| grid-personalization | P2 browser | 🟡 partial — column resize/reorder not reproduced; rowColor has no colors map |
| object-hook-lifecycle | P1 mixed | 🟡 partial — ['log'] output not observable (see finding); scratch-hook fixtures |
| cascading-multilevel-and-clear | P1 mixed | 🟡 partial — clear-on-switch flaky; recorded gaps; 3-level fixture |
| upload-guard-blocks-confirm | P2 browser | 🔴 fail — p_cover 5 MB guard missing |
| kanban-drag-persistence | P2 browser | 🔴 fail — no rollback on rejected drag |
| saved-view-management | P2 browser | 🔴 fail — draft view rename lost |
| bulk-select-all-matching | P2 browser | 🔴 fail — Clear leaves checkboxes ticked (#3056) |
| record-edit-undo | P2 browser | ⛔ blocked — automation-input trap (undo toast unsurfaceable; unit-pinned) |
| import-job-undo-cancel | P1 browser | ⛔ pre-blocked (fixture) — not run |
Fixture gaps to close (make more clauses runnable)
- A seeded object >100 rows (or a view exposing
pageSizeOptions) → unlocks list-view $skip + the whole bulk-select-all-matching cross-page banner. - Bind an
admin position to the seeded admin (or point the gate at a seeded position) → cascading-options allow-side. - A second sign-up-able user →
record-discussion-mentions bell/recipient; related-list RLS both-sides (already worked around); non-admin gates. - Wire UI openers for the tabbed/wizard/split/drawer form views →
form-view-gallery. - Gantt view with
dependenciesField/lockField/parentField; a scratch throwing/duplicate-event hook; a 3-level cascade object; a rowColor.colors map.
Screenshots
None — every clause rests on an api/network/log/test oracle or DOM-after-screenshot. Per RUNNER.md the report is text-only; the 4 fails carry reproduction rules above instead of images.
Full
records-formsarea run of thechecklist-testskill — all 32 runnable items driven against a live showcase + vendored console (6 opus subagents, one isolated boot each). Supersedes the api-subset run #7399. 4 real regressions (all in the vendored console / objectui), each reproduced ≥2× with root cause. Convention labels:qa-run+bug(labels not yet created in this repo).Result: 15 PASS · 12 PARTIAL · 4 FAIL · 1 BLOCKED (of 32 runnable; +1 pre-blocked
import-job-undo-cancelfixture). Screenshots were judgment aids only — this report is text; every verdict rests on a server-truth/network/test oracle.Environment
a86db175— branchclaude/platform-test-checklist-ocwugl(PR #7304)09987b68(.objectui-sha)localhost(trusted-origin)🔴 FAIL — 4 regressions (all in the vendored console / objectui)
1.
upload-guard-blocks-confirm— image param has no client-side max-size guardp_cover(declaredmaxSize5 MB) accepts an oversized file: a 6.3 MB PNG fires a fullpresigned → PUT → completeupload with no rejection, whilep_attachments(10 MB) correctly rejects >10 MB with zero uploads. Reproduced 2×.Repro: Field Zoo → Specimen–Full row → run "Action Param Gallery"; set a >5 MB image on Cover image (
p_cover). Expected: rejected before any upload (likep_attachmentsfor >10 MB). Actual: full upload + preview, no "5.0 MB" error. Root cause: the image-param widget lacks the clientmaxSizeguard the file-param widget has.2.
kanban-drag-persistence— rejected drag doesn't roll the card backAn illegal Kanban drag (Backlog→In Progress) is correctly rejected server-side (
PATCH 400 invalid_transition, toast shown, server staysbacklog), but the card stays stuck in the target column until a manual reload. Reproduced 3× (switcher + dedicated Board view).Repro: showcase_task → Kanban; drag a Backlog card onto In Progress. Expected: card returns to Backlog on the 400. Actual: card stuck in In Progress >5 s. Root cause: objectui
plugin-kanban/src/ObjectKanban.tsxhandleCardMovegates revert-on-failure behindif (!hasExternalData); the ListView-hosted (console) path hashasExternalData=true, so rollback is skipped.3.
saved-view-management— renaming a draft view doesn't persistCreate-kanban / pin / delete all work (200), but rename of a freshly-created draft view is rejected and silently lost; set-default fires no write at all. Reproduced 2×.
Repro: create a Kanban view via the
+tab (draft), then tab menu → Rename. Expected: new label persists. Actual: clientupdateViewGETs the base view withoutpreview=draft→ 404 → treats as create → writes an invalid partial{label,name,object}→PUT→ 422; re-read (preview=draft) still shows the old label. Root cause: objectuidata-objectstack/src/index.tsupdateView()reads the base view withoutpreview=draftthen writes an invalid partial.4.
bulk-select-all-matching— Clear leaves row checkboxes ticked (#3056 drift)Clicking Clear in the bulk-actions bar empties the toolbar but leaves the row checkboxes
data-state="checked"(header staysindeterminate) — stranded ticks with no toolbar. Reproduced 2×.Repro: showcase_contact list → tick 3 rows → click Clear. Expected: bar and checkboxes both reset. Actual: bar removed, checkboxes stay checked. Root cause: objectui
plugin-grid/src/ObjectGrid.tsxonClearSelectiondoessetSelectedRows([]) + setSelectAllMatching(false)but omits thesetSelectionResetKeybump thatresetSelection()(delete/dispatch paths) performs.Note: this item's cross-page-banner clauses (0/1/2/4) are blocked(fixture) — no seeded object exceeds the 100-row page window and no view exposes
pageSizeOptions, so "select all matching" is unreachable in the stock console.🟡 Notable finding inside PARTIAL
object-hook-lifecycle— hook['log']capability output is not observable. Hook bodies fire ([BodyRunner] hook fired) and don't throw, but the named log lines (ctx.log.info("task completed: …"),"project over budget: …") never appear even at--log-level debug. Hook lifecycle + condition semantics are all correct (beforeInsert defaults/trim, afterUpdate two-rootprevious.donegating #4784, total-record merge, fail-closed condition #4775). Clauses 2/4/5 are partial only because their named-log oracle can't be captured. Worth a separate look atbody-runner.tslog:engineCtx.loggerwiring.Full verdict table (32 runnable + 1 pre-blocked)
enable.clone:falseblocked(fixture)'admin'position never seededproject; real-403 unreachable['log']output not observable (see finding); scratch-hook fixturesFixture gaps to close (make more clauses runnable)
pageSizeOptions) → unlockslist-view$skip + the wholebulk-select-all-matchingcross-page banner.adminposition to the seeded admin (or point the gate at a seeded position) →cascading-optionsallow-side.record-discussion-mentionsbell/recipient;related-listRLS both-sides (already worked around); non-admin gates.form-view-gallery.dependenciesField/lockField/parentField; a scratch throwing/duplicate-event hook; a 3-level cascade object; arowColor.colorsmap.Screenshots
None — every clause rests on an
api/network/log/testoracle or DOM-after-screenshot. Per RUNNER.md the report is text-only; the 4 fails carry reproduction rules above instead of images.