Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

Studio Validations editor on a read-only package: ~20 disabled controls give no reason (no tooltip, no aria-describedby, no keyboard path) #12691

Closed

Description

@objectstack-fleet

Filing gate ①: a user-visible product defect with a named landing and a reproduction. Reach: Studio on a read-only (code) package, reproduced 2/2 after a screenshot confirmed the render.

Reader who acts: the objectui Studio lane seat owning the Validations editor in the Data pillar. Apply the same read-only-reason treatment objectui#12303 gave the Field-properties inspector.

What

On a read-only package, the Studio Validations editor renders about 20 disabled controls with no stated reason:

  • no tooltip on hover;
  • no title or aria-describedby;
  • no keyboard path (Tab never focuses them).

The Publish button and the Enabled toggle on the same page do carry the reason: "Read-only package — switch to or create a writable package to edit."

Reproduction (objectstack main 2034975a, console pin daeb77fc)

  1. As admin, open /_console/studio/com.example.showcase/data?surface=object%3Ashowcase_task.
  2. Click Validations. The rule "Task Status Flow" opens.
  3. Hover the Severity combobox ("error (rejects the save)") for 1.5 s. No [role=tooltip] appears, and no title / aria-describedby / tabindex is set on it or its ancestors.
  4. Tab through the page: no form control receives focus.
  5. Expected: hover and keyboard reach the read-only reason, as Publish and Enabled do.

Dedupe

MCP search_issues on objectstack-ai/objectui, closed included → 11 hits, none matching (by the cloud runner). objectui#12303 names only the Field-properties inspector.

QA-source: objectstack-ai/objectstack#23953 · ux-conventions.disabled-control-reason · clause 0

Activity

  1. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, bug · priority:p3 · domain:ui · area:studio · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T15:10Z

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch.

    • Why p3: disabled controls give no reason (accessibility). The read-only state itself is right.
    • Lane: domain:ui. Apply objectui#12303's read-only-reason treatment to the Validations editor.
  2. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Oct 16, 2026
  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 7 (priority:p3; triage grade 6218493223)
    Session: session_011K9g23W67dy2zwnyzaoB6o
    Account: os-tesla
    Branch: claude/issue-12691-validations-readonly-reason
    Worktree: objectui-issue-12691 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: the Studio Data pillar's Validations editor on a read-only package.

    • packages/app-shell/src/views/studio-design/ObjectValidationsPanel.tsx (ObjectValidationsPanel, which takes disabled from its mount): on a read-only package the editor states the existing reason (engine.studio.pkg.readonlyHint, "Read-only package — switch to or create a writable package to edit.") so hover and keyboard reach it, by the treatment objectui#12303 gave the Field-properties inspector and Publish / Enabled already wear (a tooltip wrapper and an aria-describedby reason);
    • its mount in StudioDesignSurface.tsx (viewMode === 'rules', near :6152 at main 33ee9de) only if the reason must be passed down;
    • tests beside them;
    • one .changeset/12691-*.md for @object-ui/app-shell.

    Outside the surface: the other Data pillar panels (Settings, Hooks, Actions), which take the same disabled; the read-only state itself (triage: "The read-only state itself is right"); and any new language-pack or dictionary key (the reason string exists).

    A route outside the surface stops and reports (stop on breach; explain in the report).
    Container & model: S, mode:cloud, model: opus (default tier; no path-derived mandate)
    Clause-②: no
    Clause-② reason: a disabled editor gains a stated reason through an existing string. No prop, export or key changes. If the reason must reach the panel as a new prop, the prop is module-internal to app-shell (the panel is not exported); if it turns out exported, line 2 becomes Clause-②: yes and the body says so.
    Responsibility: the Studio Data pillar's Validations editor (@object-ui/app-shell ObjectValidationsPanel) | objectui#12303 gave the Field-properties inspector the read-only-reason treatment; Publish and the Enabled toggle on the same page already carry it | every admin who opens a code package's object rules in Studio
    Thread-read: 6218493223
    Serial constraints cleared: read at objectui main 33ee9de. No open PR names ObjectValidationsPanel.tsx or StudioDesignSurface.tsx (every open PR's file list was read: #12818, #12822, #12823, #12824, #12825, #12826, #12827). The in-flight area:studio cards are disjoint: this seat's objectui#12780 (flow-node-config and its tests) and objectui#12690 (ResourceEditPage.tsx, metadata-admin/i18n.ts), and seat-held objectui#12768 (the metadata directory page).


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12691,
      "status": "done",
      "branch": "claude/issue-12691-validations-readonly-reason",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12833",
      "session": "session_01KRbDaSjHueddhNPJ9LH6Pd",
      "premise_still_valid": true,
      "summary": "On a read-only package, the body of the Validations rule editor now gets the read-only-reason treatment that objectui#12303 gave the Field properties rail. The body is a focusable group named by the panel title. It is described by an sr-only copy of engine.studio.pkg.readonlyHint, and it opens a tooltip with that reason on hover or focus. The controls stay disabled, and a writable package renders exactly as before. The change is in ObjectValidationsPanel.tsx only: the panel already has the locale and the disabled flag, so the StudioDesignSurface mount is unchanged. No new key, prop or export. H1 confirmed: at 33ee9de the editor controls carry no title, aria-describedby or tab stop; live Tab lands on BODY and hover shows no tooltip. H2 measured: #12303 used ONE wrapper for a panel with many controls (the rail body: role=group, tabIndex 0, aria-describedby pointing at an sr-only span, TooltipTrigger asChild), not one per control, so this reuses that shape. H3 confirmed: the en and zh rows exist and are reused.",
      "tests": "New file ObjectValidationsPanel.readOnlyReason-12691.test.tsx: `pnpm exec vitest run packages/app-shell/src/views/studio-design/ObjectValidationsPanel.readOnlyReason-12691.test.tsx` gives 'Tests 7 passed (7)', VERDICT command-exit 0, at 158ee06. Covered: in en-US and zh-CN, the body is described by the reason and named by the panel title, and holds at least 6 disabled controls; hovering the disabled Severity picker opens a tooltip with the reason; Tab from the rule list lands on the described body and the tooltip opens; CONTROL on a writable package: no data-disabled-reason, no aria-describedby, reason text absent, controls enabled. Ablation: the panel was replaced with its 33ee9de blob (data-disabled-reason count 0, readonlyHint count 0, with a trap to restore) and the run gave 'Tests 6 failed | 1 passed (7)', VERDICT command-exit 1. Only the CONTROL stayed green, as expected. Restored with `git checkout HEAD --`: hash-object 4722e2f4c80e equals the HEAD blob 4722e2f4c80e, and `git diff HEAD` is empty. The test imports the panel through a relative src path, so no dist step applies. Families: every test under packages/, apps/ and scripts/__tests__ that names ObjectValidationsPanel, readonlyHint, ReadOnlyReason or StudioDesignSurface (182 files) gives 'Test Files 182 passed (182) / Tests 1518 passed (1518)', VERDICT command-exit 0, on head 700571b after the merge. Live reading (e2e/live/ci/start-backend.sh on :4612 with published @objectstack/cli@18.0.0-next.2 showcase@e5136ff10f1a, console vite on :5612, page /studio/com.example.showcase/data?surface=object%3Ashowcase_task, Validations tab): BEFORE (33ee9de blob swapped in, then restored with hash equal to HEAD): hover tooltip [], Tab focus BODY. AFTER: hover tooltip ['Read-only package — switch to or create a writable package to edit.'], Tab focus DIV role=group, described by the same reason, tooltip open. PNGs are on claude/issue-12691-evidence@f19092a under evidence/12691/ (before-hover, before-tab, after-hover, after-tab); the probe logs were gitignored and are quoted here.",
      "gates": "Every exit code was captured before any pipe. On head 700571b: `pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build && pnpm --filter @object-ui/app-shell type-check`, VERDICT command-exit 0 (the type-check script name was echoed). Whether type-check includes the test files was not counted with --listFiles; vitest ran them. check:i18n-keys 0, check:i18n-dead-keys 0, check:changeset-claims 0 ('No pending changeset names a file this change touches'), changeset:check 0, check:test-path-roots 0, check:spec-symbols 0, check:new-line-citations 0 ('0 new citation(s)'), `node scripts/check-changeset-presence.mjs` 0 ('2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'). eslint on the 2 changed files: exit 0, 0 errors, 1 warning (react-hooks/set-state-in-effect in pre-existing panel code, not in this diff). The gate list was derived by hand from package.json and ci.yml (objectui has no dispatch-gates.mjs). CI check-runs: NOT MEASURED, reason: no PR yet; the seat opens it.",
      "mcp_calls": "3 — mcp__github__issue_read (get, get_comments) on #12691, plus ToolSearch to load it. All reads, no write tool.",
      "api_writes": "0 REST writes. git pushes: claude/issue-12691-validations-readonly-reason (new branch, 700571b) and claude/issue-12691-evidence (new branch, f19092a, one commit on top of 700571b).",
      "open_questions": [
        {
          "question": "Tooltip placement: side=left, align=start copies the #12303 rail. In this two-pane layout the tooltip sits over the top of the rule list (the panel header) while it is open. Keep it, or use side=top?",
          "options": [
            "A keep side=left (one pattern, matches #12303)",
            "B side=top for this panel only"
          ],
          "recommendation": "A, because the brief bars a second pattern and the overlap only lasts while the tooltip is open. after-hover.png shows it."
        }
      ],
      "out_of_scope_findings": [
        "class: a (suspected, not reproduced) · reach: none measured: Settings, Hooks and Actions get the same `disabled={readOnly}` at their StudioDesignSurface mounts, and the claim lists them as outside the surface. Whether their disabled controls give a reason was not read live · evidence: the mount props ObjectSettingsPanel / ObjectHooksPanel / ObjectActionsPanel disabled={readOnly} next to the rules mount · dedupe words: read-only reason, Settings panel, Hooks panel, Actions panel, disabled controls · carrier: none, noted only",
        "carrier: none · noted, not filed: the eslint react-hooks/set-state-in-effect warning in ObjectValidationsPanel.tsx predates this diff"
      ]
    }

    Posted by the domain:ui seat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) verbatim from the cloud session's final message, because a cloud session cannot comment from its container. The seat filled pr with the draft PR it opened, #12833.

    The seat's answers:


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 1 · session_011K9g23W67dy2zwnyzaoB6o · 2026-10-17T00:56Z

    • Merged: PR fix(app-shell): the Studio Validations editor says why it is read-only, to hover and to the keyboard (objectui#12691) #12833 landed through the merge queue as main d0a00d7950, with one parent, 2ff84f8. It is an ancestor of origin/main.
    • Verified by content: the merge commit's own diff equals the PR's diff from its merge-base 4839f5c to the reviewed head 700571b, changed line for changed line in each of the 3 files (+187/−4). Positive control at the merge commit: ObjectValidationsPanel.tsx declares const readOnlyReasonId = React.useId();.
    • Card: closed completed by Fixes #12691. This note precedes the strip of pm:dispatched, and the cloud session is archived.
    • Next, outside this card: none filed. Whether the Settings, Hooks and Actions panels state their read-only reason stays unmeasured, as recorded in the acceptance; objectui#12718 (StudioDesignSurface.tsx) no longer waits on this card's surface.

    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

Labels

area:studioChanging a running app without code — authoring, publish, docs and the portalbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions