You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Studio All-metadata item page: on a locked item the Properties panel shown with nothing selected disables every control with no reason on hover, keyboard focus or screen reader #29897
Filing gate: ① a user-visible experience defect, a QA run clause fail (ux-conventions.disabled-control-reason acceptance[0], [1], [2]), reach: the Studio All-metadata item page, measured on 3 and 2 fresh loads.
Business reason: the convention is that a disabled control says why, on hover, on keyboard focus and to a screen reader, so an admin knows whether to switch package, customize, or stop. #29081, #29206 and #29203 brought the field, flow-node and flow-edge inspectors into line, and the node inspector on this same page now explains itself; but the default Properties panel (nothing selected) on a locked item still greys every control silently, and Tab never reaches them. A keyboard or screen-reader user gets no reason at all; the only sentence is a page banner not associated with the controls.
Reader who acts: the triage seat, then a domain:ui implementer in ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx. QA suggestion only: area:studio.
Duplicate search (incl. closed): ResourceEditPage disabled reason → 22 hits, inspectorReadOnlyReason → 3, locked item disabled controls no reason Studio → 55. Nearest: #29079 (closed by #29203, the scoped node inspector on this page), #28985 / #29077 (closed, flow node and edge inspectors), #28986 (closed, field inspector display-patch). #29203 says it deliberately left the unselected default inspector unchanged; none covers it.
Open /_console/studio/~all/metadata/object/showcase_task, or /_console/apps/setup/metadata/flow/showcase_task_completed (redirects to /_console/studio/~all/metadata/flow/showcase_task_completed). The page banner reads "This item is locked and cannot be edited or deleted."
With nothing selected on the canvas, the Properties panel's controls are disabled: object page Name, Label, Plural label, Icon, Description, Exposure posture, the Required capabilities toggles; flow page Type* (button#mdf-type).
Hover each for 1 s; Tab through the panel; read the accessible description.
Expected: a tooltip with the lock reason on hover, and a focusable wrapper Tab reaches whose aria-describedby carries the reason (as the node inspector on the same page does since #29203). Actual: no tooltip, Tab never reaches the controls or a wrapper, no aria-describedby, no title, no described focusable ancestor. Reproduced 3 of 3 fresh loads (flow) and 2 of 2 (object); control: a writable-package item renders the panel enabled.
Mechanism
ResourceEditPage.tsx passes DefaultInspectorComponent only readOnly={formReadOnly} (~L3566–3580), and SchemaForm likewise (~L3594, ~L3622); inspectorReadOnlyReason (~L2625) reaches only the scoped inspector (~L3561).
Read fresh. Measured on 3 and 2 fresh loads: on a locked item, the Studio All-metadata Properties panel disables every control with no reason on hover, focus or screen reader. The ux-conventions.disabled-control-reason clauses fail. p2: the platform checklist stays red until it is fixed.
Claim: PM loop round 1 · 2026-11-03T15:50Z
Session: session_01WGufziRkHRHwEC3eQwnrwx (card thread; dispatching seat session_01WGufzjDyeFwq6AuFu3vwTd)
Account: os-support-ai
Branch: claude/project-thread-mdirva (platform-assigned to the card thread; it can push only this branch)
Worktree: objectstack-issue-29897
Domain: domain:ui
Seat: domain:ui#1
File surface: ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx (inspector / SchemaForm readOnly region only), the default inspector and SchemaForm components if they need a reason prop, their tests, one root .changeset/ file (stop on breach; explain in the report)
Container & model: S/M, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate), effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: ui code produces it (domain:ui) | no platform path covers it | every Studio/Console user who reaches the surface named in the card body
Thread-read: 6601926088
Premise: holds (re-read on origin/main21510bba: the code the card names is unchanged)
Serial constraints cleared: #29901 (same file, SaveStatusIndicator region) is held unclaimed and dispatches after this card lands; no other domain:ui claim touches this file
Order: /mnt/project-files/ui-orders/29897.md · maintainer scope 「车队可以继续派发了,只派发 p1 p2 ,总并发不超过 20」 (2026-11-03T15:40Z)
{
"issue": 29897,
"status": "done",
"branch": "claude/project-thread-mdirva",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29958",
"session": "session_01WGufziRkHRHwEC3eQwnrwx",
"premise_still_valid": true,
"summary": "ResourceEditPage now wraps the panels it draws itself in the existing InspectorReadOnlyReason wrapper with the same inspectorReadOnlyReason the scoped inspector gets: the registered default inspector shown with nothing selected, the generic SchemaForm beside a canvas, and the SchemaForm of a page with no canvas. A locked item's Properties panel is a tab stop described by the reason and the trigger of a tooltip with it; a writable item renders as before. PM assumption measured: MetadataDefaultInspectorProps takes no reason prop; the host-side wrap needs none, so no registered-inspector contract changed and no implementer (dashboard, view, page, report, object, dataset, action, hook) was touched. Diff stays inside the inspector region (serial #29901 untouched).",
"tests": "New top-level describe in ResourceEditPage.inspectorReadOnlyReason-29079.test.tsx (real page, real ObjectDefaultInspector and SchemaForm): locked object and locked flow x {described tab-stop group named Properties holding disabled controls; hover on a disabled control opens tooltip with the lock reason; Tab from page top lands on the panel and opens it}, plus CONTROL writable object (panel live, no wrapper). File: 13 passed (13). Full app-shell suite (vitest --maxWorkers=3 packages/app-shell/): 2166 files passed, 1 skipped; 19243 tests passed, 9 skipped; exit 0. Ablation via scripts/ablation-replace.mjs (reason prop to undefined, anchor 1 to 0, blob a324e465 to 520890e8): 6 failed / 7 passed, exactly the six new locked cases red, control and the six #29079 cases green; restored blob == HEAD, git diff HEAD empty. Source is read by the test directly (relative import), no dist in the path.",
"gates": "At head d9aae973 (merge base 21510bba): app-shell closure build 64/64 exit 0; app-shell build exit 0; app-shell type-check (tsc and tsconfig.test.json) exit 0; eslint on both touched files 0 errors, 51 pre-existing warnings, none on changed lines; check-sdui-manifest exit 0; dispatch-gates --commands derived 35 families, all 35 run, all exit 0; dispatch-gates --ran: 35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN. CI check-runs on PR 29958: in_progress at report time (not awaited, per contract).",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "2 — mcp__github__issue_read get (card body), mcp__github__issue_read get_comments (claim check); no write tools",
"api_writes": "3 — git push (branch claude/project-thread-mdirva, 2 pushes), relay pr_create (PR 29958, draft, no assignees, body read back identical 8007 bytes), this os-dev-report comment via post-stamped.mjs",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · noted, not filed — the generic SchemaForm renders text inputs readonly rather than disabled, so on a locked flow they still take focus themselves; the reason reaches them only through the described panel group (PR Acceptance notes).",
"carrier: none · noted, not filed — a page with no canvas in view mode (writable, not editing) still draws no reason; it offers an Edit button, and inspectorReadOnlyReason deliberately returns none there."
]
}
merged by the merge queue at 2026-11-03T19:50Z, merge commit 04cbdf78b6 (one requeue: the first queue run's lint checkout timed out after 20 min, infra)
origin/main content
git grep -c InspectorReadOnlyReason origin/main -- ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx: 3 (0 at 40fa4335), the page-level wraps are in
ACCEPT 6611358434 · card closed by Fixes #29897 (completed); pm:dispatched removed in this stroke. #29901 (same file) is now unblocked for dispatch.
Activity
objectstack-fleet commentedon Nov 3, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p2 ·
domain:ui·pm:queue· 2026-11-03T10:57Z⛔ Not a claim.
ux-conventions.disabled-control-reasonclauses fail. p2: the platform checklist stays red until it is fixed.Generated by Claude Code
objectstack-fleet commentedon Nov 3, 2026
domain:ui#1 · os-support-ai · session_01WGufzjDyeFwq6AuFu3vwTd
Claim: PM loop round 1 · 2026-11-03T15:50Z
Session:
session_01WGufziRkHRHwEC3eQwnrwx(card thread; dispatching seatsession_01WGufzjDyeFwq6AuFu3vwTd)Account:
os-support-aiBranch:
claude/project-thread-mdirva(platform-assigned to the card thread; it can push only this branch)Worktree:
objectstack-issue-29897Domain:
domain:uiSeat:
domain:ui#1File surface:
ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx(inspector /SchemaFormreadOnly region only), the default inspector andSchemaFormcomponents if they need a reason prop, their tests, one root.changeset/file (stop on breach; explain in the report)Container & model:
S/M,mode:thread,model: TIER_DEFAULT(dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility: ui code produces it (
domain:ui) | no platform path covers it | every Studio/Console user who reaches the surface named in the card bodyThread-read: 6601926088
Premise: holds (re-read on
origin/main21510bba: the code the card names is unchanged)Serial constraints cleared: #29901 (same file,
SaveStatusIndicatorregion) is held unclaimed and dispatches after this card lands; no otherdomain:uiclaim touches this fileOrder:
/mnt/project-files/ui-orders/29897.md· maintainer scope 「车队可以继续派发了,只派发 p1 p2 ,总并发不超过 20」 (2026-11-03T15:40Z)objectstack-fleet commentedon Nov 3, 2026
domain:ui#1 · os-support-ai · session_01WGufziRkHRHwEC3eQwnrwx
os-dev-report
Stamp: 2026-11-03T17:44Z
{ "issue": 29897, "status": "done", "branch": "claude/project-thread-mdirva", "pr": "https://github.com/objectstack-ai/objectstack/pull/29958", "session": "session_01WGufziRkHRHwEC3eQwnrwx", "premise_still_valid": true, "summary": "ResourceEditPage now wraps the panels it draws itself in the existing InspectorReadOnlyReason wrapper with the same inspectorReadOnlyReason the scoped inspector gets: the registered default inspector shown with nothing selected, the generic SchemaForm beside a canvas, and the SchemaForm of a page with no canvas. A locked item's Properties panel is a tab stop described by the reason and the trigger of a tooltip with it; a writable item renders as before. PM assumption measured: MetadataDefaultInspectorProps takes no reason prop; the host-side wrap needs none, so no registered-inspector contract changed and no implementer (dashboard, view, page, report, object, dataset, action, hook) was touched. Diff stays inside the inspector region (serial #29901 untouched).", "tests": "New top-level describe in ResourceEditPage.inspectorReadOnlyReason-29079.test.tsx (real page, real ObjectDefaultInspector and SchemaForm): locked object and locked flow x {described tab-stop group named Properties holding disabled controls; hover on a disabled control opens tooltip with the lock reason; Tab from page top lands on the panel and opens it}, plus CONTROL writable object (panel live, no wrapper). File: 13 passed (13). Full app-shell suite (vitest --maxWorkers=3 packages/app-shell/): 2166 files passed, 1 skipped; 19243 tests passed, 9 skipped; exit 0. Ablation via scripts/ablation-replace.mjs (reason prop to undefined, anchor 1 to 0, blob a324e465 to 520890e8): 6 failed / 7 passed, exactly the six new locked cases red, control and the six #29079 cases green; restored blob == HEAD, git diff HEAD empty. Source is read by the test directly (relative import), no dist in the path.", "gates": "At head d9aae973 (merge base 21510bba): app-shell closure build 64/64 exit 0; app-shell build exit 0; app-shell type-check (tsc and tsconfig.test.json) exit 0; eslint on both touched files 0 errors, 51 pre-existing warnings, none on changed lines; check-sdui-manifest exit 0; dispatch-gates --commands derived 35 families, all 35 run, all exit 0; dispatch-gates --ran: 35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN. CI check-runs on PR 29958: in_progress at report time (not awaited, per contract).", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "2 — mcp__github__issue_read get (card body), mcp__github__issue_read get_comments (claim check); no write tools", "api_writes": "3 — git push (branch claude/project-thread-mdirva, 2 pushes), relay pr_create (PR 29958, draft, no assignees, body read back identical 8007 bytes), this os-dev-report comment via post-stamped.mjs", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: none · noted, not filed — the generic SchemaForm renders text inputs readonly rather than disabled, so on a locked flow they still take focus themselves; the reason reaches them only through the described panel group (PR Acceptance notes).", "carrier: none · noted, not filed — a page with no canvas in view mode (writable, not editing) still draws no reason; it offers an Edit button, and inspectorReadOnlyReason deliberately returns none there." ] }objectstack-fleet commentedon Nov 3, 2026
domain:ui#1 · os-support-ai · session_01WGufzjDyeFwq6AuFu3vwTd
ACCEPT → PR #29958 comment 6611358434 · head
d9aae973· 2026-11-03T17:49Z. Landing waits for every check green on that head.objectstack-fleet commentedon Nov 3, 2026
domain:ui#1 · os-support-ai · session_01WGufzjDyeFwq6AuFu3vwTd
Landed · PR #29958 ·
04cbdf78b6· 2026-11-03T19:51Z04cbdf78b6(one requeue: the first queue run's lint checkout timed out after 20 min, infra)origin/maincontentgit grep -c InspectorReadOnlyReason origin/main -- ui/packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx: 3 (0 at40fa4335), the page-level wraps are inACCEPT 6611358434 · card closed by
Fixes #29897(completed);pm:dispatchedremoved in this stroke. #29901 (same file) is now unblocked for dispatch.