Repository navigation
QA run · ux-conventions (3/3) · 5b14b7f3 · 2026-10-19 · 1 PASS / 0 PARTIAL / 2 FAIL / 0 BLOCKED / 0 NOT-RUN #24570
Description
Run record for the 18.0 release sweep, selector ux-conventions (resolved with node scripts/checklist-select.mjs area:ux-conventions --json), plan B (Tier 1 + Tier 2; Tier 3 deferred).
Environment fingerprint
- framework:
5b14b7f3ad8e2e0786d228772f473d07b36b2477(objectstack-ai/objectstack main), working tree clean - console:
.objectui-sha=4016370af3c9c9dafec2bc5299afd8e8079701b8, built withpnpm objectui:build;packages/console/dist/.objectui-shastamp equals the pin (pnpm check:console-shagreen), so the stale-console-bundle trap is ruled out for every console observation - app: showcase (examples/app-showcase), canonical boot
OS_PORT=PORT pnpm -C examples/app-showcase exec objectstack dev --ui --seed-admin -p PORT -d file:/tmp/qa18/ITEM/data.db; every hand-driven item had its own port and file DB (listed per item below); seed:--seed-admin(admin@objectos.ai) + showcase seed + per-item scratch fixtures - Tier 1 pins: vitest per package against the same tree (
pnpm exec vitest run FILES), 97 framework files / 2209 tests, 0 failed; objectui-side pins run inside a clone of objectui at4016370af3c9(unit vitest +playwright.live.config.tsagainst a showcase boot on :47431 through the objectui console dev server), RUNNER option (b) - browser: Playwright with
/opt/pw-browsers/chromium, own context per persona, sign-in through the form - timestamps: 2026-10-19, environment prep 12:26–12:43 UTC, testing 12:43–13:53 UTC; Tier 2 items were driven in parallel by sub-runners (≤ 3–4 browser items at once), each on its own port/DB
Scope
Selector ux-conventions → 3 runnable item(s). Blocked items hidden by the resolver were not run (no --include-blocked).
Tiering (checklist-test SKILL §1): Tier 1 = item carries automated.ref (pin run, cited); Tier 2 = unpinned P0/P1 (hand-driven); Tier 3 = unpinned P2 (deferred, not-run).
| item | priority | surface | tier | revision | item verdict |
|---|---|---|---|---|---|
ux-conventions.write-feedback |
P1 | browser | 2 | 3 | fail |
ux-conventions.disabled-control-reason |
P1 | browser | 2 | 3 | pass |
ux-conventions.labels-over-machine-names |
P1 | browser | 2 | 3 | fail |
Per-clause verdicts
A = acceptance[n], N = negative[n]. Tier 1 rule: a clause is pass only when a passing pin covers it (server-side oracles, or clauses the ref names); clauses a ref says it does not cover, and UI-oracle clauses a server-side pin cannot see, are not-run. Evidence is text from the oracle — no images.
ux-conventions.write-feedback — fail (hand-driven (port 47441 · file:/tmp/qa18/wf/data.db · member minted via invite + sign-up))
| clause | verdict | evidence |
|---|---|---|
| A0 | pass | every landed write showed feedback within ~2 s, each paired with a server read: create 201 (admin + member); inline Save All PATCH 200 → 1 row saved; bulk delete 2× DELETE 200 → Deleted 2 Task records; kanban move PATCH 200 (card in new column + toast); Mark Done 200 → Task marked done.; Invite User 200 → Invitation sent to the invitee email; Approve 200 → Approved "EXP-2001"; import 200 → 2 created; Studio autosave/publish/discard 200 with feedback; settings PUT 200 → Settings saved |
| A1 | pass | success strings name the subject/count/label; the Discard row (expected FAIL, objectui#12690) now reads Draft discarded: QA Widget — no longer reproduces |
| A2 | pass | declared successMessage equals the shown text for Mark Done and Invite User |
| A3 | FAIL | refused kanban move: PATCH /api/v1/data/showcase_task/ID {status:done} → 400, error toast Invalid task status transition., card reverts, GET unchanged — but the board's role=status live region (DndLiveRegion, aria-live assertive) announces Moved CARD to Done. in the same window. (Required-empty shape: browser block with named errors, no request — holds) |
| A4 | pass | no-op editor (Esc / same value) sends no PATCH and shows no modified state |
| A5 | blocked(fixture) | no stock surface offers Undo (incl. the import background-job result screen) |
| N0 | pass | required-field refusal shows no success toast |
| N1 | pass | same evidence as A4 |
| N2 | FAIL | same live-region evidence as A3 |
ux-conventions.disabled-control-reason — pass (hand-driven (port 47442 · file:/tmp/qa18/dc/data.db))
| clause | verdict | evidence |
|---|---|---|
| A0 | pass | hover reasons: Archive Not available for this record (admin + member); Studio Publish and flow Enabled toggle Read-only package — switch to or create a writable package to edit.; field inspector and validation editor show the panel reason; import Next has the adjacent banner naming the unmapped required field |
| A1 | pass | each disabled control or a focusable wrapper (tabindex 0 + aria-describedby) resolves to non-empty text and is reached by Tab; tooltip on focus — the expected FAILs objectui#12303 and #12691 no longer reproduce (2 fresh loads each) |
| A2 | pass | reasons specific except Archive (documented generic fallback) |
| N0 | pass | enabled controls carry no reason tooltip |
| N1 | skipped | out of scope — those controls are gated by removal, not disabled |
ux-conventions.labels-over-machine-names — fail (hand-driven (port 47443 · file:/tmp/qa18/lm/data.db · scratch package com.qa18.lmscratch))
| clause | verdict | evidence |
|---|---|---|
| A0 | FAIL | 12 rows pass (incl. the expected FAILs objectui#12693 (a) and (b), which no longer reproduce). Two new rows show machine names where labels exist: (a) Studio Access → Explain access → Principal resolution Contributed by chips read org_member / everyone / showcase_member_default / member_default (GET /api/v1/meta/position/org_member → Organization Member; /meta/permission/member_default → Member — Standard Access); (b) Studio flow header reads Trigger: Record updated · showcase_task while the object label Task exists (the start-node inspector shows Task). 2 fresh loads each |
| A1 | pass | people shown by name (Explain principal, Created by, audit Actor) |
| A2 | pass | machine names shown beside labels are small/muted/monospace |
| A3 | FAIL | Studio flow inspector, Try/Catch node Error Variable help text names a TypeScript type (… a TryCatchErrorValue: nodeId, message …); source packages/services/service-automation/src/builtin/try-catch-node.ts:75 (the spec's own describe in control-flow.zod.ts does not carry it) |
| N0 | pass | the one machine-name header seen (an unlabeled not-yet-existing list view) is the authoring/no-label case the negative excludes |
| N1 | skipped | not applicable on this run |
Reproduction rules (one per fail)
ux-conventions.write-feedback · acceptance[3] + negative[2] — a refused kanban move is announced as a success to assistive technology
- Boot the canonical showcase (stock seed). Sign in through the form as
admin@objectos.ai. - Open
/_console/apps/com.example.showcase/showcase_task/view/showcase_task.board. - With real pointer events (mouse down → move → up), drag a card from Backlog or To Do onto the Done column (the
task_status_flowstate machine refuses that transition). - Network:
PATCH /api/v1/data/showcase_task/IDbody{"status":"done"}→ 400 (Invalid task status transition.). Visible UI: error toast with that text; the card reverts;GET /api/v1/data/showcase_task/IDshows the status unchanged. - Read the board's dnd-kit live region (
[role=status]witharia-live="assertive", idDndLiveRegion-0, visually hidden): it holdsMoved CARD to Done.
- Expected: a refused move must not announce a completed move — no success claim in any feedback region in the same capture window (the item's step 2 names
role=statusregions explicitly). Actual: the live region claims the move. - Reproduced 3× on fresh loads. Automation self-check: real pointer events; mechanism read in objectui source at the pin —
packages/plugin-kanban/src/kanbanDndAnnouncements.tsonDragEndreturnskanban.dnd.movedwhenever the target column differs from the home column, synchronously and independent of the write outcome. - Disposition: product defect (objectui, plugin-kanban). Extracted at close-out.
ux-conventions.labels-over-machine-names · acceptance[0] — two Studio surfaces show machine names where labels exist
(a) Explain access — Principal resolution:
- Admin → Studio → any package → Access → Explain access.
- User = a member (minted by invite + sign-up), Object = any object, Operation = Read → Explain.
- Under Evaluation pipeline → Principal resolution, the
Contributed by:chips readorg_member,everyone,showcase_member_default,member_default.
- Expected: labels (
GET /api/v1/meta/position/org_member→Organization Member;GET /api/v1/meta/permission/member_default→Member — Standard Access), name secondary if shown. Actual: machine names only. 2 fresh loads.
(b) Studio flow header:
- Open
/_console/studio/com.example.showcase/automations?surface=flow%3Ashowcase_resilient_sync(also any record-triggered flow). - Header subtitle reads
Trigger: Record updated · showcase_task.
- Expected: the object label
Task(the start-node inspector on the same page showsTask). 2 fresh loads. - Disposition: product defect (objectui, Studio). Extracted at close-out (one card for the family).
ux-conventions.labels-over-machine-names · acceptance[3] — platform help text names a TypeScript type
- Open
/_console/studio/com.example.showcase/automations?surface=flow%3Ashowcase_resilient_sync. - Click the Push with retry (try/catch) node; read the inspector's Error Variable help text.
- Actual:
Variable holding the caught error in the catch region — a \TryCatchErrorValue`: `nodeId`, `message`, and `iteration` / `item` …— a TypeScript type name in the normal authoring form (not the Advanced JSON editor). Source:packages/services/service-automation/src/builtin/try-catch-node.tsline 75 (the node'sconfigSchemadescription). The spec's ownerrorVariabledescribe (packages/spec/src/automation/control-flow.zod.ts`) does not carry it. - Expected: plain-language help with no type name. 2 fresh loads.
- Disposition: product defect (objectstack, service-automation). Extracted at close-out.
Derived item verdicts
ux-conventions.write-feedback— fail (A3, N2); A5blocked(fixture): no stock surface offers Undo.ux-conventions.disabled-control-reason— pass.ux-conventions.labels-over-machine-names— fail (A0 two new rows, A3).
Checklist-accuracy findings / fixture gaps (for the wave anchor card)
- write-feedback
knownGaps[1]: the Studio Discard row is no longer an expected FAIL at objectui4016370a— the toast readsDraft discarded: QA Widget(label) and the confirm uses the label; move it to a regression row and check whether objectui#12690 can close. - write-feedback:
showcase_taskhas no create-time validation rule, so "break a validation rule on create" is driven through the update-time state machine (kanban move); the member persona holds no update/delete onshowcase_task(direct PATCH → 403), so the member inline-edit / bulk-delete / kanban rows cannot be driven on stock. - write-feedback: package create and object "Save as draft" give navigation feedback, no toast — not listed variants.
- disabled-control-reason
knownGaps[1]: the expected FAILs objectui#12303 (field inspector) and objectui#12691 (validation editor) no longer reproduce at4016370a(focusable described panel wrapper + tooltip on focus) — move them to regression rows. - labels-over-machine-names
knownGaps[0]: the expected FAILs objectui#12693 (a) and (b) no longer reproduce at4016370a. Seen, not in the listed variants: Audit Log Object column shows object names, the flow entry-condition field selects showstatus/previous.status, lookup filter help readsevery sys_user record, Explain Object select showsQA Widget (qalm_widget)at equal weight — a future revision decides scope.
Hand-off
Every item of this selector has a verdict.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 19, 2026
Close-out — extraction (checklist-test SKILL §5). Every FAIL of this record has a disposition: all three are product defects, extracted below. Checklist-accuracy findings and fixture gaps in the body are handed to the wave's anchor card through the dispatch session; none is extracted.
Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Parked-on: #24579 · this record's checklist-accuracy findings, fixture gaps, partial coverage gaps and not-run handover (wave anchor §2–§4)
Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Closure complete (checklist-test §5): every FAIL in this record has a disposition (the
Extracted:/Parked-on:lines above), and its partial coverage gaps and not-run handover are parked on #24579.Closed by: the 18.0 QA wave dispatch session
session_01CfRDy7SuTfUqaTu2AEH2Hi, on the maintainer's instruction there on 2026-10-19, verbatim 「qa-run的卡片处理完的是不是可以关闭」.Generated by Claude Code