Skip to content

QA run · ux-conventions (3/3) · 5b14b7f3 · 2026-10-19 · 1 PASS / 0 PARTIAL / 2 FAIL / 0 BLOCKED / 0 NOT-RUN #24570

Closed

Description

@objectstack-fleet

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 with pnpm objectui:build; packages/console/dist/.objectui-sha stamp equals the pin (pnpm check:console-sha green), 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 at 4016370af3c9 (unit vitest + playwright.live.config.ts against 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

  1. Boot the canonical showcase (stock seed). Sign in through the form as admin@objectos.ai.
  2. Open /_console/apps/com.example.showcase/showcase_task/view/showcase_task.board.
  3. With real pointer events (mouse down → move → up), drag a card from Backlog or To Do onto the Done column (the task_status_flow state machine refuses that transition).
  4. Network: PATCH /api/v1/data/showcase_task/ID body {"status":"done"} → 400 (Invalid task status transition.). Visible UI: error toast with that text; the card reverts; GET /api/v1/data/showcase_task/ID shows the status unchanged.
  5. Read the board's dnd-kit live region ([role=status] with aria-live="assertive", id DndLiveRegion-0, visually hidden): it holds Moved 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=status regions 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.ts onDragEnd returns kanban.dnd.moved whenever 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:

  1. Admin → Studio → any package → Access → Explain access.
  2. User = a member (minted by invite + sign-up), Object = any object, Operation = Read → Explain.
  3. Under Evaluation pipeline → Principal resolution, the Contributed by: chips read org_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:

  1. Open /_console/studio/com.example.showcase/automations?surface=flow%3Ashowcase_resilient_sync (also any record-triggered flow).
  2. Header subtitle reads Trigger: Record updated · showcase_task.
  • Expected: the object label Task (the start-node inspector on the same page shows Task). 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

  1. Open /_console/studio/com.example.showcase/automations?surface=flow%3Ashowcase_resilient_sync.
  2. 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 ownerrorVariable describe (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); A5 blocked(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 objectui 4016370a — the toast reads Draft 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_task has 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 on showcase_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 at 4016370a (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 at 4016370a. Seen, not in the listed variants: Audit Log Object column shows object names, the flow entry-condition field selects show status / previous.status, lookup filter help reads every sys_user record, Explain Object select shows QA 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

  1. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    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.

    Extracted: objectstack-ai/objectui#13054 · ux-conventions.write-feedback · acceptance[3]
    Extracted: objectstack-ai/objectui#13054 · ux-conventions.write-feedback · negative[2]
    Extracted: #24576 · ux-conventions.labels-over-machine-names · acceptance[3]
    Extracted: objectstack-ai/objectui#13056 · ux-conventions.labels-over-machine-names · acceptance[0]
    

    Generated by Claude Code

  2. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    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

  3. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    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

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