Skip to content

Studio shows machine names where labels exist: Explain access principal chips and result banner, and the list-view Columns chips #12693

Closed

Description

@objectstack-fleet

Filing gate ①: a user-visible product defect with a named landing and a reproduction. Reach: two Studio surfaces, each reproduced 2/2.

Reader who acts: the objectui Studio lane seat. Render each chip below through its metadata label, falling back to the name only when no label exists. Both surfaces fall under the same checklist clause, so they are folded into one card.

What

Two Studio surfaces show machine names where labels exist.

(a) Explain access.

  • Path: Studio → any package → Access → Explain access, with User = a member and Object = any, then Explain.
  • The Principal card's "Positions:" and "Permission sets:" chips show org_member, showcase_member_default…, and the result banner reads Read on "uxscratch_widget".
  • Labels exist: GET /api/v1/meta/position/org_member → "Organization Member".
  • POST /api/v1/security/explain returns names only in principal.positions / permissionSets, so the client must resolve the labels.

(b) List-view Columns chips.

  • In a scratch package: Studio → Interfaces → create an app with "Add this package's objects as menu items", then select the object's nav item.
  • Properties → LIST VIEW → Columns chips read the field names (title, owner_ref). The labels are "Widget Name" and "Owner Ref". No title attribute is set.

Measured on objectstack main 2034975a with console pin daeb77fc. This is outside the closed objectui#11862.

Dedupe

MCP search_issues on objectstack-ai/objectui, closed included → 5 hits, none matching (by the cloud runner).

QA-source: objectstack-ai/objectstack#23953 · ux-conventions.labels-over-machine-names · 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:11Z

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

    • Why p3: machine names show where labels exist, on two Studio surfaces.
    • Lane: domain:ui. Render through the metadata label, and fall back to the name only when no label exists.
  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 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 7 (priority:p3; triage grade 6218511386)
    Session: session_011K9g23W67dy2zwnyzaoB6o
    Account: os-tesla
    Branch: claude/issue-12693-studio-labels-over-names
    Worktree: objectui-issue-12693 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: two Studio surfaces that show machine names where labels exist (the card's (a) and (b)).

    • (a) Explain access: packages/app-shell/src/views/metadata-admin/AccessExplainPanel.tsx, the Principal card's position and permission-set chips (near :652 / :662 at main 3288c12) and the result banner's object name. The explain answer carries names only, so the panel resolves each label through the metadata the console already reads, and falls back to the name when there is no label.
    • (b) List-view Columns chips: the Columns chips the Interfaces pillar's LIST VIEW properties draw (packages/app-shell/src/views/studio-design/ObjectListViewInspector.tsx and the chip renderer it uses, packages/app-shell/src/views/metadata-admin/previews/FieldsListEditor.tsx, if that is where the chip text is drawn): each chip reads the field's label, with the name kept reachable (for example as its title).
    • tests beside them;
    • one .changeset/12693-*.md for @object-ui/app-shell.

    Outside the surface: the explain request and its server answer, the stored list-view columns (still field names), the other FieldsListEditor callers' behaviour beyond the chip text, and any new language-pack or dictionary key.

    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: chips and a banner draw labels where they drew names; no prop, export or key changes. If FieldsListEditor needs a new prop for the labels and it is exported from the package entry, line 2 becomes Clause-②: yes and the body says so.
    Responsibility: Studio's access explainer and its list-view inspector (@object-ui/app-shell) | objectui#11862 (closed) fixed other Studio label surfaces; the explain answer carries names only, so the console resolves labels | every admin reading an access explanation or a list view's columns in Studio
    Thread-read: 6218511386
    Serial constraints cleared: read at objectui main 3288c12. No open PR names AccessExplainPanel.tsx, ObjectListViewInspector.tsx or FieldsListEditor.tsx (every open PR's file list was read: #12818, #12828, #12830, #12831 and the bot PRs). In-flight area:studio work is disjoint: this seat's objectui#12780 (flow-node-config), objectui#12690 (ResourceEditPage.tsx, metadata-admin/i18n.ts, RuntimeDraftBar.tsx) and objectui#12691 (ObjectValidationsPanel.tsx), and seat-held objectui#12768 (the directory page).


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12693,
      "status": "done",
      "branch": "claude/issue-12693-studio-labels-over-names",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12834",
      "session": "session_015kCbN56VCRd8vb5pXvVMcf",
      "premise_still_valid": true,
      "summary": "(a) AccessExplainPanel: the Principal card's position and permission-set chips now draw each item's metadata label (new local CitedItemChip), with the name on the chip's title. The labels come from one unscoped client.list('position') and one client.list('permission') per run, made only when a cited name is still unlabelled, mirroring the objectui#11862 lookUpPeople pattern. No second resolver and no per-chip request. The verdict banner names the object by the label the panel's own object-picker list (objectOptions) already holds. A label-less, unknown or failed-list name stays the name. (b) The LIST VIEW Columns chips are FieldsListEditor rows. A row whose column carries no label of its own now draws the field label from the catalog the inspector already passes in (objectFieldsOverride). FieldListRow sets title to the field name when it differs from the label. The stored columns stay field names. All hypotheses held, live: H1 (explain answers names only), H2 (the unscoped lists label every cited name, platform ones included), H3 (the chip text was colLabel(c) = the bare name) and H4 (columns unchanged). The live check below is the evidence.",
      "tests": "At HEAD bfc7f7c (after merging origin/main b524150), `pnpm exec vitest run --maxWorkers=3` over the family listed below gave EXIT=0, 'Test Files 87 passed (87) · Tests 619 passed (619)'. The family is 87 files: a git grep over packages/apps/scripts/__tests__ test files for AccessExplainPanel, ObjectListViewInspector, FieldsListEditor, FieldListRow, ViewColumnPanes, ViewVariantInspector, ViewColumnInspector or ReportDefaultInspector, plus the app-shell files naming security/explain, plus the 2 new files. New tests: AccessExplainPanel.citedLabels-12693.test.tsx (7) and FieldsListEditor.fieldLabels-12693.test.tsx (4). ABLATION was run with the fix committed at b1cdf4a, using a trap-guarded mutation script with on-disk grep -c proof per leg. No dist is involved: the tests import source by relative path. Leg A (chip text = name, banner = decision.object; injected=1 removed=0): citedLabels 4 failed / 3 passed. Leg B (row label back to labelOf; injected=1 removed=0): fieldLabels 4 failed / 4. Leg C (row title removed; removed=0): fieldLabels 2 failed / 2 passed. Restored by `git checkout HEAD --`, then hash-object equal to HEAD blob: AccessExplainPanel.tsx 0ebd5463, FieldsListEditor.tsx 49eddac3, ViewColumnPanes.tsx 13b55ca5; `git diff HEAD` empty. Caveat: the 'reads each type once' test goes red under leg A only because it waits for label text. It does not independently prove the once-per-run claim. LIVE READING was taken on e2e/live/ci/start-backend.sh (published @objectstack/*@18.0.0-next.2 showcase, :4693), with this branch's console on :5793 and a detached 3288c12 console on :5794, admin principal, Explain on showcase_task. BEFORE: banner 'Read on “showcase_task”'; chips platform_admin, org_owner, …, showcase_member_default, member_default; Projects LIST VIEW columns name, account, status, …. AFTER: banner 'Read on “Task”'; chips 'Platform Admin [title=platform_admin]' … 'Showcase Member (Default) [title=showcase_member_default]' … 'Member — Standard Access [title=member_default]'; columns 'Project Name [title=name]', 'Account [title=account]', … 'End Date [title=end_date]'. PNGs are at claude/issue-12693-evidence 701dfd34 under evidence/12693/ (a-explain, b-columns, b-page, each before/after).",
      "gates": "Local, exit codes captured before any pipe, re-run on HEAD bfc7f7c. The base `pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build` ran on b1cdf4a (BUILD_EXIT=0, under os-verify-lock). After the merge, `pnpm --filter @object-ui/app-shell type-check` gave lock VERDICT command-exit 0 with 0 TS errors (tsc --noEmit and tsconfig.test.json). The first type-check, on b1cdf4a, gave TC_EXIT=2 with TS2554 in my test's stub; that was fixed in 96c563a. 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 ('VERDICT new-cross-file-line-citations: 0 new citation(s)') · node scripts/check-changeset-presence.mjs 0 ('1 changeset(s): .changeset/12693-studio-labels-over-names.md') · eslint on the 5 changed files 0 (7 warnings, all on pre-existing lines outside my hunks). The control-byte self-scan over the diff found no hits. `node scripts/check-nul-bytes.mjs` exited 1 with MODULE_NOT_FOUND; the script exists only in objectstack, so that is NOT MEASURED, not a failure. Not run: dispatch-gates --ran, which has no objectui counterpart. CI families: PR not opened yet, so no check-runs to cite; the seat reads them after opening. Narrowing declared: security/explain hits outside app-shell (plugin-grid/detail/view/calendar/kanban/gantt/tree, apps/console) were not run locally, because their code is not on this diff. CI runs the farm.",
      "mcp_calls": "2 — mcp__github__issue_read (get, get_comments) on objectui#12693; no write tool",
      "api_writes": "0",
      "open_questions": [
        {
          "question": "Where the label comes from on (a): the unscoped metadata `position` / `permission` lists, using string labels only, with no i18n-bundle layer on top.",
          "options": [
            "A: the list rows' `label`, as the Access pillar's rail reads permission sets",
            "B: route through useObjectLabel / an i18n resolver as well"
          ],
          "recommendation": "A, which is what was done. Business need: the card's ask is metadata labels, and live lists carry them for every cited name. Long term: it reuses the read the console already makes rather than adding a second resolver (the brief's ban). AI-error axis: a non-string label is not drawn, so off-spec metadata cannot pass as a label. Scope: no new surface."
        },
        {
          "question": "(b) is fixed in the shared FieldsListEditor, so the metadata-admin View variant / column inspectors that mount it also draw field labels on their rows.",
          "options": [
            "A: keep it in the shared editor (one place, every Columns row reads the same)",
            "B: thread a label prop from ObjectListViewInspector only"
          ],
          "recommendation": "A, which is what was done. The claim scopes those callers' chip text in and their other behaviour out, and only chip text and a title changed. B would add a prop and leave two Columns lists that disagree."
        },
        {
          "question": "Unscoped panel (no packageId): the banner falls back to the object name, because the object list is loaded only when scoped.",
          "options": [
            "A: leave it; Studio always passes packageId (StudioDesignSurface mounts it with packageId)",
            "B: add a client.get('object', name) read for the unscoped mount"
          ],
          "recommendation": "A. No measured caller mounts it unscoped with a result to label, and the startup-focus axis says add nothing without demand."
        }
      ],
      "out_of_scope_findings": [
        "class: a · reach: public door, Studio → Access → Explain access → any result; measured live at bfc7f7c, the pipeline's 'Contributed by' chips under each layer still print platform_admin, showcase_member_default … (a-explain-after.png). Evidence: AccessExplainPanel's layer contributors map draws `c.name`. It is the same labels-over-names family as this card, and CitedItemChip plus itemLabels could serve it, but the card and the claim name only the Principal chips and the banner. Dedupe words: explain contributors chips machine names, contributed by labels, access explain layer contributors",
        "carrier: none · noted in Acceptance notes, not filed (the seat decides whether it joins the labels-over-machine-names family card)"
      ]
    }

    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, #12834.

    The seat's answers:

    • Open question 1 (label source): A, the metadata lists' string labels. It is the read the Access pillar already makes, once per run and only when needed; no second resolver.
    • Open question 2 (shared editor): A. Only the row text and a title change, so every Columns list reads the same; ViewColumnPanes.tsx (FieldListRow) is the chip renderer the claim names.
    • Open question 3 (unscoped mount): A, leave it. Studio always mounts the panel with a packageId.
    • The "Contributed by" chips finding is recorded, not filed: it is the same family and a measured public-door reach, but the seat is signing off at the maintainer's word and names it in the sign-off ledger for the next seat or triage to card.
    • The seat read the diff at bfc7f7c: 6 files, +380/−10. lookUpItemLabels lists a type only when a cited name is unlabelled and keeps string labels only; the banner reads objectOptions; FieldsListEditor prefers a column's own label, then the catalog label, then the name. The stored columns and the explain request are unchanged. Clause-②: no stands.
    • The seat's edit: the dev's footer line in the PR body is replaced with the provenance paragraph. Next: CI on bfc7f7c, then the ACCEPT.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 1 · session_011K9g23W67dy2zwnyzaoB6o · 2026-10-17T01:27Z

    • Merged: PR fix(app-shell): Studio draws labels, not names, on the explain access chips and banner and the list-view Columns rows (objectui#12693) #12834 landed through the merge queue as main cda4076be5, with one parent, 35ef750. 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 f3a7b87 to the reviewed head 2808bc0, changed line for changed line in each of the 7 files (+384/−12). Positive control at the merge commit: FieldsListEditor.tsx declares const fieldLabelByName = React.useMemo( at :103.
    • Card: closed completed by Fixes #12693. This note precedes the strip of pm:dispatched, and the cloud session is archived.
    • Next, outside this card: none filed. The explain dialog's "Contributed by" chips under each layer still print machine names, as recorded in the acceptance.

    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