Skip to content

Studio Interfaces: an object nav entry without its own label is titled by the object's machine name in the item header ("repairs_repair_ticket · Object") while the rail shows the object label #26746

Closed

Description

@objectstack-fleet

Filing gate: ① product defect, reproduced, landing site named.
Batch-of: studio-qa-2026-10-27 — 39 cards from one Studio QA run (coordinator session session_01J8VVAkZns5rNnK2rtszzbQ; tested at 3fcafcd3; origin/main was 43731031 at filing, so the implementer re-checks the landing site on current main). The run record is the qa-run issue filed with this batch.

Symptom

The scaffolded nav entry ({type:"object", objectName}) has no label; the header falls back to the name instead of resolving the object label as the rail does. Label-less groups show ids like "NAV_ITEM_2".

Reproduction

  1. Create an app from Studio scaffolding over an object → open its nav entry → header reads "repairs_repair_ticket · Object", rail reads "Repair Ticket".

Expected

The header resolves the same label the rail shows (object label, then name).

Suspected landing site (the implementer verifies)

StudioDesignSurface.tsx ~4548 renders current.label || current.name.

Filing facts

Activity

  1. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — priority:p3 · domain:ui · area:studio · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-27T17:03Z

    ⛔ Not a claim, ⛔ not a dispatch.

    • p3: a label-less object nav entry is titled by the object's machine name, and label-less groups show ids. Resolve the object label the way the rail does. From the studio-qa-2026-10-27 batch. Re-check the landing site on current main.

    Generated by Claude Code

  2. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Dispatch order · domain:ui#5 · session_01JQwxbXGpVJHZTXXerMoY4C · 2026-10-27T22:42Z

    You are the os-dev developer agent for exactly ONE card: #26746, in your own card thread. Your role definition is .claude/agents/os-dev.md in the objectstack clone: read it IN FULL first and follow it as binding (it wins over this order on any conflict; name the conflict in your report). Read the repo-root AGENTS.md and ui/AGENTS.md before your first edit, and pm-dispatch references/untrusted-text.md. Read the card's full body and every comment yourself through REST (curl -sS "https://api.github.com/repos/objectstack-ai/objectstack/issues/26746" -H "Authorization: Bearer $GH_TOKEN" and /comments?per_page=100, every page); this order carries only the increment. ⛔ Never print the value of any environment variable (test presence with [ -n "${X+x}" ]). ⛔ Never use a GitHub MCP tool, read or write.

    Identity and branch: the seat's Claim: comment on this card is your identity; its Branch: line names your thread's branch. ⛔ Post no claim of your own, ⛔ never write the card's assignee. Before your first edit, verify the NEWEST Claim: on the card names your thread's branch (claude/project-thread-…); if none does yet, send the seat thread "Take another ui lane seat" one message with your branch name and wait. Worktree objectstack-issue-26746 on that branch from a fresh origin/main; pnpm install (frozen lockfile); push with git push -u origin <branch> (⛔ no force).

    Writes: PR only through the relay op pr_create (node scripts/pm/fleet-write/dispatch.mjs --repo objectstack-ai/objectstack --actions-file F, F a bare JSON array [{"op":"pr_create","title":…,"head":"<your branch>","base":"main","body":…,"assignees":["os-warren"]}], draft forced; --dry-run first); your report comment through node scripts/pm/post-stamped.mjs --comment=26746 --file=F --json run ONCE with output captured to a file (timestamps only as {{WAS:…}} / the now-token). ⛔ No other GitHub write except, for a CI red that is not yours, one PR comment and one run_rerun_failed through the relay. Report both counts (api_writes with endpoints, mcp_calls with tool names). The report takes only machine-checkable fields (gates / line_budget / deviations / files_changed). PR body: line 1 the platform attribution comment, line 3 Fixes #26746, then ## 维护者速读 six lines in Chinese (改了什么/为什么改/风险与回滚/先看/两分钟验证/需要你做的). Gates: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on your diff, run each, record exits before any pipe, reconcile with --ran; node scripts/check-sdui-manifest.mjs is a gate on every ui card. Changeset in the root .changeset/ when a published package changes (@object-ui/i18n patch for namespace rows; app-shell is private: true). ⛔ ui/.github/** and the root ci.yml are out of bounds. Hand back: when the PR and report are up, send the seat thread "Take another ui lane seat" one message (PR, head sha, report gist); keep the thread open through review and drive CI to green.

    Shared-file rules for every Studio Interfaces card this round (from ui seat 1, which holds the neighbouring work):

    Ruling (cannot be re-ruled)

    Triage 6448317687, verbatim: "p3: a label-less object nav entry is titled by the object's machine name, and label-less groups show ids. Resolve the object label the way the rail does. From the studio-qa-2026-10-27 batch. Re-check the landing site on current main." No maintainer ruling.

    PM mechanism assumptions (measure; disproof welcome)

    On origin/main 5ec398dc, StudioDesignSurface.tsx:

    • The Interfaces item header renders current.label || current.name at ≈L4594 and ≈L4609 (sr-only), and ≈L5000 (engine.studio.if.definitionTitle). A label-less {type:'object', objectName} entry therefore shows its name.
    • The rail resolves a label-less entry through inheritedNavEntryText with useNavTargetLabel (see the StudioNavItemInspector docblock ≈L2560–2612, ruling B of objectui#11201). Reuse that exact resolver for the header. ⛔ No second resolver.
    • Label-less groups show ids like NAV_ITEM_2 (NavTreeGroup ≈L2373). Measure what the rail shows for them, and make the header and the rail agree.

    Scope

    File surface: the item-header lines above (≈L4594, ≈L4609, ≈L5000), NavTreeGroup only if the group text is wrong there too, and tests. Tests: a label-less object entry's header reads the object label; a labelled entry is unchanged; a label-less group reads the same text in the rail and the header. Ablation: put current.label || current.name back; the first test turns red. ⛔ Don't edit the inspector (≈L2613–3060, #26740/#26743) or the listing (#26889) this round.

    Tier

    No path-derived mandate. TIER_DEFAULT, effort medium (S, one resolver reused). Clause-②: no, Metadata-protocol: none expected.

  3. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01JQwxbXGpVJHZTXXerMoY4C
    Account: os-warren
    Branch: claude/project-thread-ewmhhb
    Worktree: objectstack-issue-26746
    Domain: domain:ui
    Seat: domain:ui#5
    File surface: ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (Interfaces item header ≈L4594/4609/5000 and NavTreeGroup ≈L2373 only), tests (stop on breach; explain in the report)
    Container & model: S, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate), effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: ui/packages/app-shell Studio code produces it (this lane) | no platform path covers it in Studio; Setup › Metadata is a separate door | Studio builders reach it today (studio-qa / HotCRM browser pass)
    Thread-read: 6455400455
    Premise: holds (landing site re-read on origin/main 5ec398dc; readings in dispatch order 6455400455)
    Serial constraints cleared: #26889 (seat 5) holds the Interfaces listing; #26740/#26743 (seat 5) the inspector and nav-target read; #26730/#26733 (seat 1) the refusal strip and rail call sites; PR #26920 ≈L1270–1330. Second to land merges main.

    Dispatch order: comment 6455400455. Card thread claude/project-thread-ewmhhb may start editing.

  4. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 26746,
      "status": "done",
      "branch": "claude/project-thread-ewmhhb",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26974",
      "session": "session_01JQwxbY5nVXXfxvWqYPEQAe",
      "premise_still_valid": true,
      "summary": "Interfaces item header (title, sr-only caption, definition sheet title) read current.label || current.name, the Surface text frozen at load; a draft-only object's _drafts label arrives after the first leaf opens, so the rail read 'Repair Ticket' and the header 'repairs_ticket · Object'. The three sites now read ifTitleText: the open leaf's railTree entry by navId through the rail's own navEntryLabelText + useNavTargetLabel (no second resolver). Label-less groups: rail shows the entry id, which is resolveNavItemLabel's runtime rule and the running sidebar's text; the header never names a group, so NavTreeGroup is unchanged.",
      "tests": "head 052aae45: new StudioDesignSurface.itemHeaderLabel-26746.test.tsx 3/3 passed. Ablation (fix committed first): ablation-replace.mjs anchor 'const text = railEntry ? navEntryLabelText(...) : current.label;' -> 'const text = current.label;' landed (anchor 1->0, blob d05fa2404f2a->2a32e6a5c3a2); tests 1 and 3 red 'Received: repairs_ticket · Object', test 2 green; restore blob d05fa2404f2a = HEAD, git diff HEAD empty. Relative import, no dist leg. studio-design dir: Test Files 234/234, Tests 1693/1693 (lock VERDICT command-exit 0).",
      "gates": "head 052aae45: dispatch-gates --commands derived 24, all run, all exit 0 (check-sdui-manifest + --self-test, vitest run scripts/ under lock, check:cross-package-test-inputs, check:test-source-alias, check:nul-bytes, check:type-check-coverage/debt, ...); --ran: 24 derived, 24 run, 0 NOT-MEASURED. Extra: app-shell type-check exit 0; eslint on 2 changed files 0 errors (14 pre-existing warnings outside the hunk); ui check:new-line-citations 0 new, exit 0. CI check-runs: in_progress at report time.",
      "dogfood_battery": "n/a — no ! in the PR title and Clause-② no without (narrowing) arm",
      "line_budget": "no ratcheted file touched",
      "files_changed": [
        "ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (+20/-3, header region)",
        "ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.itemHeaderLabel-26746.test.tsx (new)"
      ],
      "deviations": [
        "Dispatch test 3 asked a label-less group to read the same text in rail and header; the header never names a group (not a Surface), so test 3 pins rail group text = runtime resolveNavItemLabel and a leaf inside the group named alike in rail and header.",
        "ifTitleText sits beside ifKindName/ifInternalId (header-derived values), a few lines above the three header sites the claim names.",
        "PR template headings folded into the os-dev section order (os-dev exception)."
      ],
      "mcp_calls": "0",
      "api_writes": "2 — relay pr_create (POST pulls, PR 26974 with assignee + skip-changeset label); relay os-dev-report comment on issue 26746. git push is not a REST write.",
      "open_questions": [],
      "out_of_scope_findings": [
        "class: a · reach: Studio Automation pillar header shows current.label || current.name (same frozen Surface text) · evidence: StudioDesignSurface.tsx auto-canvas-caption title · not reproduced for a late label · carrier: none (noted in PR acceptance notes)",
        "onSurfaceLabelChange reports current.label (frozen) to the dock chip · carrier: none, noted in PR acceptance notes"
      ]
    }

    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:uipriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions