Skip to content

QA run · area:ux-conventions (3/3) · 2034975a · 2026-10-16 · 0 PASS / 0 PARTIAL / 3 FAIL / 0 BLOCKED / 0 NOT-RUN #23953

Closed

Description

@objectstack-fleet

QA run record for the area:ux-conventions slice of the #23878 wave (cloud runner for session session_01K3qUoyh1xFGoWzAACPMbXJ). Text only, per checklist-test §4.

Environment fingerprint

key value
framework sha 2034975a47193f04db4791614f4ac9331ff211d3 (main)
.objectui-sha pin daeb77fc84dd824e74c95b87cdede85afdb248e7
console bundle objectui daeb77fc built against spec a35f7a67^ (34b740f) in a separate worktree (pnpm objectui:build fails on main, #23908); pnpm check:console-sha matches; each FAIL's code path re-checked on objectui main d66ceea5 (still present)
boot isolated boot on port 41751 with its own file DB, objectstack dev --ui --seed-admin, OS_PORT exported
personas seeded admin; member member.ux@example.com minted with admin create-user + change-password (showcase_member_default + member_default)
fixtures scratch package com.qa.uxscratch (object uxscratch_widget "QA Widget", permission sets "QA Readers" / "QA Auditors", app "QA Widget Center" made in Studio); deleted at teardown (DELETE 200, then GET 404)
browser Playwright (Node) + /opt/pw-browsers/chromium, one context per persona, form sign-in, role/ref-targeted clicks, real keyboard typing
run window 2026-10-16 13:10Z – 13:45Z
execution driven by a runner subagent of this session (one of two parallel browser groups); verdicts relayed as text evidence; FAIL code paths re-checked here in objectui source

Scope

Selector area:ux-conventions → 3 runnable items (no planned, no blocked-hidden items).

item revision
ux-conventions.write-feedback 2
ux-conventions.disabled-control-reason 2
ux-conventions.labels-over-machine-names 2

Per-clause verdicts

item # verdict evidence (text)
write-feedback 0 pass every write that landed showed feedback within 2 s (variant table); kanban card sits in the column the server read returns
write-feedback 1 fail Studio Discard toast reads Draft discarded: object/uxscratch_widget — the raw type/name while the label "QA Widget" exists (2 fresh loads). Not scored as fails: "Task created successfully" (names the object label, not the record) and "Settings saved"
write-feedback 2 pass Mark Done declared Task marked done. = shown; Invite User declared Invitation sent to ${result.email} → shown Invitation sent to invitee.ux@example.com
write-feedback 3 pass required fields empty: blocked in the browser, no request; inline "Title is required" / "Project is required" + toast "Please check the highlighted fields: Title, Project", no success toast. Broken rule: kanban move PATCH /data/showcase_task/ID {"status":"done"} → 400, toast "Invalid task status transition.", card reverted, no success toast
write-feedback 4 pass open Priority editor, re-pick the same value, Esc/click away: no PATCH/PUT, no "modified" / "Save All" (objectui#11816 regression row holds)
write-feedback 5 blocked(fixture) no stock surface offers Undo (knownGaps[3]); none appeared in any captured toast
disabled-control-reason 0 fail Studio validation editor on the read-only showcase package (Task → Validations → Task Status Flow): 20 disabled controls show no tooltip or adjacent reason on a 1.5 s hover. Every other probed control showed one
disabled-control-reason 1 fail not in the tab order and no aria-describedby/title: the validation editor's 20 controls (new) and the field inspector Label / API name / Type / Move up-down (known, objectui#12303). Archive, Publish, Enabled toggle, Remove and import Next pass via a focusable wrapper with aria-describedby
disabled-control-reason 2 fail validation editor reason is empty. Elsewhere: Archive generic ("Not available for this record"); Publish / Enabled / Remove / inspector specific ("Read-only package — switch to or create a writable package to edit."); import Next specific ("Can't continue — required field(s) not mapped: Title (title)…")
labels-over-machine-names 0 fail (a) Explain access → Principal card chips render org_member, everyone, showcase_member_default, member_default while GET /api/v1/meta/position/org_member → "Organization Member" and GET /api/v1/meta/permission/showcase_member_default → "Showcase Member (Default)"; the result banner reads Read on "uxscratch_widget" is DENIED (label "QA Widget"). (b) Studio Interfaces → object nav item → Properties → LIST VIEW "Columns" chips read title, owner_ref (labels "Widget Name", "Owner Ref"; the "Add field" picker in the same panel shows labels). Both reproduced twice
labels-over-machine-names 1 pass Explain principal "Mia Member member.ux@example.com" (id small beneath); record page Created/Updated by "Mia Member"; audit log User "Dev Admin"; approvals Requester "Mei Phone (demo)"
labels-over-machine-names 2 pass machine names beside labels are small/muted/monospace: object header chip, permission-set list, Changes panel, Lookup related object, flow trigger object, Display-field and Add-field pickers
labels-over-machine-names 3 pass no dotted Zod path or class name in renderer-built text. Not scored: a showcase-authored flow label carries a tracker reference, and the server-built Explain prose cites ADR numbers (accuracy note 5)

write-feedback variant table

variant persona request → status feedback verbatim server read
record create admin POST /data/showcase_task → 201 "Task created successfully" record reads back
record create member POST → 201 "Task created successfully" owner_id = member
inline edit (Save row / Save All) admin PATCH {"priority":"high"} → 200 "1 row saved" priority=high
inline edit / bulk delete / kanban move member not drivable — member holds no update/delete on showcase_task (direct PATCH 403) — —
bulk delete admin 2× DELETE → 200 after "Delete 2 Task records?" "Deleted 2 Task records" both 404
kanban move admin PATCH {"status":"todo"} → 200 card under TO DO status=todo
kanban refused move admin PATCH {"status":"done"} → 400 "Invalid task status transition."; card reverted status unchanged
Mark Done admin / member POST /actions/showcase_task/showcase_mark_done → 200 "Task marked done." done=true
Invite User admin POST /auth/organization/invite-member → 200 "Invitation sent to invitee.ux@example.com" sys_invitation + sys_email rows
approval decision admin POST /approvals/requests/ID/approve {"comment":…} → 200 Approved "EXP-2001" approve action with the comment
import (2 rows) admin POST /data/showcase_task/import → 200 "Import Complete · 2 created" + "Imported 2 rows." both rows read back
Studio autosave admin PUT /meta/object/uxscratch_widget?mode=draft → 200 "Saved 01:13 PM", "Unpublished draft", "Changes · 1" draft label changed, active unchanged
Studio publish admin POST /packages/com.qa.uxscratch/publish-drafts → 200 "Published 1 item in this package (one atomic release)" active label changed
Studio discard admin confirm "Discard the pending draft for object/uxscratch_widget?" → DELETE ?state=draft → 200 "Draft discarded: object/uxscratch_widget" draft 404
settings save admin PUT /api/settings/localization {"currency":"USD"} → 200 "Settings saved" currency USD (tenant)

disabled-control-reason variant table

variant control hover Tab description/title class
declared disabled (admin + member) Archive, header + section yes yes (span wrapper) yes generic
Studio Publish, read-only package Publish yes yes (wrapper) yes specific
Studio read-only controls automation Enabled toggle; inspector Remove yes yes yes specific
Studio read-only controls inspector Label / API name / Type / Required / Move up-down yes (panel tooltip) no none FAIL-known objectui#12303
Studio read-only controls validation editor: Type, Severity, rule name, label, message, status field, 10 transition inputs, Runs on, Priority, Enabled no no none NEW FAIL
import wizard, Title unmapped Next adjacent banner yes (wrapper) yes specific
disabled form submit none on stock — — — forms validate on submit
member toolbar/bulk none rendered disabled — — — gated by removal

Reproduction rules

write-feedback clause 1 — 1. As admin, make a draft of a scratch-package object (Studio label rename, or PUT /api/v1/meta/object/OBJ?mode=draft&package=PKG). 2. Open /_console/apps/setup/metadata/object/OBJ. 3. Click "Discard draft", accept the native confirm. Expected: a toast naming the label ("QA Widget"). Actual: Draft discarded: object/uxscratch_widget (the confirm also reads …for object/uxscratch_widget?). Source: objectui packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx (tFormat('engine.edit.draftDiscarded', …, { type, name })) and i18n.ts key 'Draft discarded: {type}/{name}'; unchanged on objectui main d66ceea5.

disabled-control-reason clauses 0–2 — 1. As admin open /_console/studio/com.example.showcase/data?surface=object%3Ashowcase_task. 2. Click "Validations"; rule "Task Status Flow" opens. 3. Hover the Severity combobox ("error (rejects the save)") 1.5 s: no [role=tooltip]; no title / aria-describedby / tabindex on it or its ancestors. 4. Tab through the page: no form control receives focus. Expected: hover and keyboard reach "Read-only package — switch to or create a writable package to edit." as the Publish button and Enabled toggle do. Reproduced on 2 fresh loads with hover() and coordinate hover, after a screenshot confirmed render.

labels-over-machine-names clause 0 (a) — Studio → any package → Access → Explain access; User = a member, Object = any; Explain. Principal card "Positions:" / "Permission sets:" chips show org_member, showcase_member_default…; labels exist (GET /api/v1/meta/position/org_member → "Organization Member"). POST /api/v1/security/explain returns names only in principal.positions / permissionSets.

labels-over-machine-names clause 0 (b) — In a scratch package: Studio → Interfaces → create an app with "Add this package's objects as menu items"; select the object nav item; Properties → LIST VIEW → "Columns" chips read the field names (title, owner_ref) where the labels are "Widget Name" / "Owner Ref"; no title attribute.

Dispositions: all product defects whose fix lands in objectui — extracted there (see close-out comment).

Derived item verdicts

item verdict
ux-conventions.write-feedback fail
ux-conventions.disabled-control-reason fail
ux-conventions.labels-over-machine-names fail

Fixture gaps

  • showcase_task has no create-time validation rule (task_status_flow runs on update only), so "create with a value that breaks a validation rule" is not drivable; the server-refusal half used the kanban state-machine move.
  • The stock member persona holds no update/delete on showcase_task, so the member inline-edit, bulk-delete and kanban rows cannot be driven.
  • No stock surface disables a submit button (disabled-control variant 5); no Undo anywhere (write-feedback clause 5).

Checklist-accuracy notes (closed out on the wave anchor, not extracted)

  1. write-feedback knownGaps are stale at daeb77fc: grid Save All now toasts "1 row saved"; Studio Discard now gives feedback (with the machine name above); Approve toasts Approved "EXP-2001" (declared successMessage now Approved "${result.request.record_title}").
  2. write-feedback acceptance[3] expects a 4xx for the required-field case; the console blocks in the browser and sends no request — the oracle should admit that shape.
  3. write-feedback variants: the "Approvals inbox" link opens the review-queue page, the decision drawer is at /_console/apps/com.example.showcase/system/approvals; the grid has no "Edit inline" button (double-click + Save row / Save All).
  4. disabled-control-reason knownGaps[1] is stale for Studio Publish and import Next — both keyboard-reachable with a description now.
  5. labels-over-machine-names knownGaps[0] (objectui#11862) is mostly stale (permission-set list, Changes panel, Display-field picker now pass) and the server-authored UI text (family card): the approvals drawer's Approve says only "Approved.", and Explain access's Principal resolution prose names the user by raw id #23157 principal-prose row looks fixed ("Principal Mia Member (member.ux@example.com; id …)"); clause 3 does not say whether ADR references in server prose or tracker ids inside authored labels count.

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Close-out for this record (checklist-test §5), 2026-10-16T18:19Z. 0 pass · 0 partial · 3 fail of 3. Every fail is a product defect whose fix lands in objectui. Each is extracted there:

    Extracted: objectstack-ai/objectui#12690 · ux-conventions.write-feedback · clause 1
    Extracted: objectstack-ai/objectui#12691 · ux-conventions.disabled-control-reason · clause 0
    Extracted: objectstack-ai/objectui#12691 · ux-conventions.disabled-control-reason · clause 1
    Extracted: objectstack-ai/objectui#12691 · ux-conventions.disabled-control-reason · clause 2
    Extracted: objectstack-ai/objectui#12693 · ux-conventions.labels-over-machine-names · clause 0
    

    The cards cover these defects:

    • objectui#12690: the Studio Discard toast names the raw type/name instead of the label.
    • objectui#12691: the Studio validation editor's 20 read-only controls give no reason on hover or by keyboard. The field-inspector half is the known objectui#12303.
    • objectui#12693: the Explain-access principal chips and the Interfaces list-view Columns chips show machine names.

    The fixture gaps (no stock Undo, no disabled submit, no create-time validation rule, member persona without update/delete) and the five checklist-accuracy notes close out on #23878. Closed by the domain:devx seat 1 PM (seat post #6023) · os-sales · session_014eFvbvGK4FjXvscggDNTD4, as part of the paced close-out of the #23878 wave.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions