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(interfaces): a writable package cannot create dashboards, reports, pages or list views, and nav items can only link objects #11790
Filing gate ② — a product decision only the maintainer can make.
Who acts on it: objectui triage → the Studio / app-shell owner. ⛔ Not a claim. Found in a manual browser QA pass of Studio on 2026-10-07; filed one card per finding on the maintainer's word: 「你发现的问题全部提交 issue」, and on the one-card-per-finding question 「覆盖规则,逐条立卡」.
Maintainer quick-read
In a writable package, Studio's Interfaces pillar can only build a nav of object lists. Is completing it in scope?
What is missing
No create flow for dashboards, reports, pages or list/form views (Studio's create dialogs exist for app, object, flow and permission set only).
The nav editor's Add nav item can only Link to object — no group, page, dashboard, report, URL or separator.
The object canvas' Properties panel only says "This canvas renders the running app … nothing here is edited from this panel."
Options
A — add, in order: list view (columns/filters/sort in that Properties panel) → dashboard/report → page → all nav item types.
B — nav item types only, authoring stays in Setup / code.
C — status quo.
Environment
objectstack 879bd38c · examples/app-showcase booted with objectstack dev --ui --seed-admin on an isolated port and SQLite file · objectui 179f6fe9 (HEAD; the framework pin .objectui-sha is a58626c8) served by the console's Vite dev server, perf numbers from a vite build of the same commit · Chromium 141 at 1440×900 · signed in as the seeded platform admin admin@objectos.ai unless stated.
Duplicate check
Semantic issue search on objectstack-ai/objectui (open and closed), studio interfaces create dashboard report page view nav item types: 8 hits (0 open, 8 closed).
Semantic issue search on objectstack-ai/objectui (open and closed), Studio Interfaces pillar cannot author new dashboard page report list view only object nav items: 8 hits (0 open, 8 closed).
Path: write metadata — building an app's interface in Studio | 缺项 | P2
Triage: first grade, enhancement · priority:p2 · domain:ui · area:studio · pm:queue. Filed as ②, but an accepted ADR answers it: the Interface pillar holds app · page · view · form · dashboard · report (ADR-0084). This card is step 1, every nav item type; the create flows are #11823
Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-07T17:59Z. ⛔ Not a claim, ⛔ not a dispatch.
Triage: lands in packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (the nav editor's Add nav item) and navSurface.ts ⇒ domain:ui; rationale: Studio's Interface pillar in objectui. Read on objectui main9990f9e122 and objectstack mainaa71c4d9d1.
Why not the decision box:
ADR-0084 (Accepted) names the Interface pillar's types as app · page · view · form · dashboard · report (objectstack docs/adr/0084-application-builder-information-architecture.md:46).
The builder design's rail is the app's nav tree, "groups + typed leaves: page / object / dashboard / report / view" (docs/design/builder-ui.md §6).
So completing the pillar is in scope by that ruling; only the order is triage's.
Direction (this card):Add nav item offers every type NavigationItemSchema declares: object, page, dashboard, report, URL, group and separator (objectstack packages/spec/src/ui/app.zod.ts). Each picks its target from the package's items.
packages/app-shell/src/views/metadata-admin/previews/AppNavCanvas.tsx: Add nav item (addItem:329, the button at :412) and the per-type card rendering.
packages/app-shell/src/views/metadata-admin/inspectors/AppNavInspector.tsx and inspectors/nav-target.ts: per-type target picking from the package's items.
packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx, only the Interfaces pillar's nav-editor wiring, and NavTree's per-type rows if a new type needs one.
packages/app-shell/src/views/studio-design/navSurface.ts: resolveSurface for a type that opens a surface, only if needed.
New engine.appNav.* / engine.inspector.appNav.* rows of packages/app-shell/src/views/metadata-admin/i18n.ts.
The tests beside these, and .changeset/11790-*.md.
⛔ Not on it:
Seat 3's in-flight objectui#11785 (claim 6049060030): StudioDesignSurface.tsx's autosave, publish and pillar save-error strips, and metadataError.ts.
Other cards' scope:
the create flows for dashboards, reports, pages and views, which are objectui#11823 (pm:blocked on this card);
the rail's separator rendering, objectui#11791;
the More menu and Advanced trigger, objectui#11794;
the narrow-width layout, objectui#11795.
packages/i18n/**.
Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
Container & model: M, mode:subagent, model: opus (dispatch-gates --tier --repo objectstack-ai/objectui over these paths: no path-derived mandate; default tier)
Clause-②: no
Responsibility: objectui app-shell Studio: the nav editor's Add nav item can only link an object, so a writable package cannot put a page, dashboard, report, URL, group or separator into its app nav from Studio | the platform path is right: NavigationItemSchema declares every one of those types, and the runtime console renders them | every author building an app's navigation in a writable package; measured by the filer (Add nav item offers only Link to object)
Thread-read: 6043752848
Serial constraints cleared: none blocking.
seat 3's objectui#11785 (refusal text, no PR yet). It shares StudioDesignSurface.tsx only in its error strips, which this surface leaves alone. Both add i18n.ts rows under different prefixes; whichever lands second merges main.
This seat's objectui#11783 (PR objectui#11840) holds none of these files.
This seat: dispatch is parallel, batch 3, on the maintainer's word in this session's chat today: 「改为并行派发,batch 3」.
In flight with this card: objectui#11783 and objectui#11838 (claimed alongside, area:workflow). Their surfaces are disjoint from this one.
Why Clause-②: no: this is Studio's editor for types the spec already declares. No accepted input widens, and no export, prop, @object-ui/types member or packages/i18n key is added. App-shell's ENGINE_STRINGS are unexported. If the fix needs a published surface, the dev stops and reports, and the seat re-claims.
os-dev-report
{
"issue": 11790,
"status": "done",
"branch": "claude/issue-11790-nav-item-types",
"pr": "#11846",
"session": "session_01DrKzdPdyLLBW3qpZ4vtk7z — the parent's (mode:subagent); the same id is in the commit's Claude-Session trailer and the PR footer",
"premise_still_valid": true,
"summary": "Studio's nav editor offers every nav item type the installed spec's NavigationItemSchema declares. Measured on @objectstack/spec 17.7.0, the list is object, dashboard, page, url, report, action, component, doc, separator and group. Triage named seven; the spec also declares action, component and doc, with no member marked non-addable, so all ten are offered. Add nav item still appends {id, type:'object'} and selects it. StudioNavItemInspector now opens with a Type choice (radios; NAV_ENTRY_TYPES is a Record keyed by the spec-derived NavigationItemType). A change of type (retypedNavEntry) keeps id, label, icon, order, badge, badgeVariant, visible and the gates, and drops the old target. A separator keeps id and order; a group is born with children []. Each target-bearing type picks from this package's published plus draft items: pages (record pages left out), dashboards, reports, global actions (object-bound left out), docs and books. A component picks from the console's component registry; a url is typed. An emptied picker removes the key. doNavSave, navPayloadOf and NAV_TARGET_READS are unchanged; the table already had a row for every target-bearing type. The rail gives url, component and doc rows their own icon, and the canvas no longer offers inline rename on a separator card.",
"tests": "HEAD the gate union ran on: eecc053, the PR head. GATES (command → exit → verdict): [1] pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build (via os-verify-lock) → 0 → 'VERDICT command-exit 0 · held the lock 183s'. [2] pnpm exec vitest run, 2 new files (nav-target.navEntryTypes-11790.test.ts, StudioDesignSurface.navItemTypes-11790.test.tsx) → 0 → 'Test Files 2 passed (2) / Tests 48 passed (48)'. [3] pnpm exec vitest run, 16 files naming the touched files (AppNavCanvas x3, AppNavInspector.labelInherits, inspectors/tests/nav-target, AppPreview x2, navSurface, 4 StudioNavItemInspector suites, aiChipLabel, studio-locale.i18n, ResourceEditPage.navDeepLink, select-placeholder-literal) → 0 → 'Test Files 16 passed (16) / Tests 175 passed (175)'. [4] pnpm exec vitest run, 13 Interfaces/nav pillar suites (autosaveInFlight, autosaveSwitch, interfacesAction, interfacesAppLabelMap, interfacesRailLabelMap, interfacesReadOnly, navAutosaveFlush, navDeepLink, navEditClosesOnReadOnly, navEntryIdentity, navPlaceholderSave-11776, pillarNavGuard, interfacePolish) → 0 → 'Test Files 13 passed (13) / Tests 90 passed (90)'. [5] pnpm --filter @object-ui/app-shell type-check (echoed 'tsc --noEmit && tsc -p tsconfig.test.json') → 0 → 'VERDICT command-exit 0'. [6] pnpm check:control-bytes → 0 → 'check-control-bytes: OK'. [7] check:new-line-citations → 0 → '0 new citation(s), enforcement report-only'. [8] check:changeset-claims → 0 → 'No pending changeset names a file this change touches.' [9] check:pending-changeset-literals → 0 → 'No test source names a pending changeset.' [10] check:i18n-designer-parity → 0 → 'Every en row has a zh row, and every shared row carries the same placeholders.' DERIVED by hand (objectui has no dispatch-gates.mjs; picked by what reads the diff): [11] check:i18n-drift → 0 → 'No designer-table en value changed in this range.' [12] check:i18n-keys → 0. [13-15] check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape → 0 each → 'OK'. [16] check:test-path-roots → 0 → OK. [17] check:spec-symbols → 0 → 'spec symbol derivation ... 0 untriaged collisions'. [18] check:icon-record-names → 0 → OK. [19] check:unreferenced-sources → 0 → OK. [20] node scripts/check-changeset-presence.mjs → 0 → 'this change declares 1 changeset(s): .changeset/11790-nav-item-types.md'. [21] targeted eslint --format json on the 10 changed files → 0 → 0 errors, 16 warnings all on lines this diff does not touch. Repo-wide pnpm lint and the full farm are declared to CI. CI state at report time: NOT MEASURED (reason: the report is delivered when local verification ends; CI convergence is the seat's). REVERSE CHECK (after commit): StudioDesignSurface.tsx alone checked out at base 1e1f09e (blob a795370b, equal to base) → vitest -t 'offers exactly the' → exit 1, predicted direction: 'Unable to find an accessible element with the role "radio"' (inspector) and 'Unable to find role="group" and name "Type"' (pillar, after Add nav item); 'Tests 2 failed | 18 skipped'. Restored with git checkout HEAD from a trap; hash 2fe2efe6 equals the HEAD blob; git diff HEAD empty. REAL BROWSER (dev-only harness, never committed): console Vite on a private port; InterfacesPillar over an in-memory /api/v1/meta fetch double that parses each app save with AppSchema; Chromium /opt/pw-browsers/chromium at 1440x900 via Playwright. Observed: after Add nav item the Type choice offered all ten types with Object checked. Page picker: ['', home, draft_page] (record page and foreign-package page absent). Action picker: ['', sync_all] (object-bound close_task absent). Component picker: the 4 app-shell registered screens. An unbound url was left out of a save that was accepted. One entry of every type was added; both saves were accepted; the final navigation held all 12 entries in member shape. After Done, the rail showed every entry: dashboard, page, report, action and object enabled; component, doc and url disabled with their own glyphs; the group as a header; the separator an empty disabled row (objectui#11791). Zero page errors. DEVIATIONS: (1) StudioNavItemInspector gained one required internal prop, packageId. The fence's 'no prop' was read as Clause-②, the published surface: that component is exported for tests only, not re-exported from the package index, and package.json exports only '.'. The four existing inspector suites pass it (one or two lines each). (2) The type choice is in the new entry's inspector (the order's second route), not a dropdown on the button. AppNavCanvas addItem is shared with Setup's app editor; the inspector choice also retypes existing entries; a Radix menu on the button would have rewritten the suites that click Add nav item, some in seat 3's autosave area. (3) AppNavCanvas separator-card rename guard, in the claimed per-type card rendering: Studio can now make separators, and an inline rename would write a label the spec refuses at save. (4) Commit trailers are AGENTS.md's model-free pair, not the harness's model-named Co-Authored-By. (5) check:* gates and targeted eslint ran outside the verify lock, by rule. (6) Out-of-scope finding 1 was measured after the write-once PR body; it is not in the PR's Acceptance notes, so the seat may append it. (7) A dev-only browser harness and a dev-only Setup inspector probe test were created and deleted, never committed. Vite (pid 2082, port 5291) was stopped by pid and port. The worktree node_modules and the worktree are removed. FILES_CHANGED (vs base 1e1f09e): .changeset/11790-nav-item-types.md (new, @object-ui/app-shell patch); packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx; packages/app-shell/src/views/metadata-admin/inspectors/nav-target.ts; packages/app-shell/src/views/metadata-admin/previews/AppNavCanvas.tsx; packages/app-shell/src/views/metadata-admin/i18n.ts (new engine.inspector.appNav.* rows, en+zh); new tests: inspectors/nav-target.navEntryTypes-11790.test.ts, studio-design/StudioDesignSurface.navItemTypes-11790.test.tsx; updated tests: StudioDesignSurface.navItemInspector, navItemInspectorLabel-11196, navItemInspectorLabelMaps-11148, standardNavEntries-11201 (packageId prop only). Nothing outside the claim's surface. HYPOTHESES: H1 partly right (addItem births object; the Studio inspector is StudioNavItemInspector, not AppNavInspector, which is Setup's and offers six types). H2 falsified for Studio (object binding only; picking an object on a page entry kept pageName, refused by NavigationItemSchema with unrecognized_keys [pageName], measured; that path is removed). H3 right (separator rendering left to objectui#11791).",
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "2 REST writes. (1) pr_create relayed: POST /repos/objectstack-ai/objectstack/dispatches; run 37709719221 executed POST /repos/objectstack-ai/objectui/pulls as objectstack-fleet[bot], giving draft PR #11846; read-back reported 14216 bytes sent and 14216 stored, identical. (2) This os-dev-report comment via post-stamped.mjs --comment=11790 --repo=objectstack-ai/objectui (POST /repos//issues/11790/comments, by the relay route the tool picks). Not REST: git push of claude/issue-11790-nav-item-types (the empty probe push, then eecc053). Zero label and assign writes. GET reads only otherwise.",
"open_questions": [],
"out_of_scope_findings": [
"class: c · reach: named producer — Setup's app editor (AppNavInspector, registered for 'app') shows its Label and Icon fields on a separator entry, such as showcase's nav_sep_reports · evidence: a dev-only probe (not committed) rendered AppNavInspector over {id:'nav_sep_reports', type:'separator'}; typing 'Reports' in Label wrote {id:'nav_sep_reports', type:'separator', label:'Reports'}, and NavigationItemSchema.safeParse refused it with unrecognized_keys [label]; the save door parses the same strict member, so the edit is refused at save · dedupe words: AppNavInspector separator label; setup app editor separator unrecognized_keys label; nav inspector separator icon field",
"carrier: none (承接者:无) · Setup's AppNavInspector offers six of the spec's ten nav types (no action, component, doc or separator); an editor gap, not a defect class · noted in PR Acceptance notes, not filed",
"carrier: none (承接者:无) · nesting entries under a group from Studio is a follow-up: StudioNavItemInspector edits top-level navigation entries only and the canvas does not nest, so a group is added flat with children [] · noted in PR Acceptance notes, not filed",
"carrier: none (承接者:无) · the doc picker offers the package's declared books, not its implicit book (the package id); a doc alone still opens in its own book context · noted in PR Acceptance notes, not filed"
]
}
domain:ui seat 1 · session_01DrKzdPdyLLBW3qpZ4vtk7z · reviewed against the PR diff, its file list and check runs, read 2026-10-08T00:58Z. Report: os-dev-report6049930430 on this card.
Shape: draft → main. The first line is Fixes #11790, and Clause-②: no starts a later line.
StudioDesignSurface.tsx (+452). Its hunks are the imports, KIND_ICON, NavTree's per-type rows, StudioNavItemInspector (the type choice and the per-type pickers), and one packageId pass in InterfacesPillar. The Interfaces nav inspector lives in this file, not in AppNavInspector.tsx, which is Setup's (H1 corrected).
nav-target.ts (+103) and AppNavCanvas.tsx (+11/−2, the separator rename guard).
30 engine.inspector.appNav.* rows in i18n.ts, EN and ZH.
Two new pin files, packageId added to four existing inspector suites, and one changeset (@object-ui/app-shell patch).
Nothing touches seat 3's objectui#11785 error strips or metadataError.ts. doNavSave, navPayloadOf, NAV_TARGET_READS and the nav banner are unchanged: the diff mentions navPayloadOf only in comments.
Clause-② re-read on the diff:
The added exports (NAV_ENTRY_TYPES, isNavEntryType, navTypeAcceptsChildren, retypedNavEntry) are module-level. index.ts names none of them, nor StudioNavItemInspector.
The new required packageId prop is on a test-exported component that is not on the package entry. I accept it as module-internal, as with objectui#11783's ariaLabel.
No @object-ui/types member or packages/i18n key changes. no holds.
Rulings held:
The type list is the spec's:NAV_ENTRY_TYPE_TABLE is a Record<NavigationItemType, true>, so it is exhaustive over the spec-derived union at compile time. On @objectstack/spec 17.7.0 it covers object, dashboard, page, url, report, action, component, doc, separator and group. Triage named seven; the order said to offer what the spec declares, and no member is marked non-addable, so ten.
Step 1 only: no create flows (objectui#11823).
objectui#11776's save rule still applies: an unbound entry of any target-bearing type is left out of the save and stays on the canvas. That was measured: an unbound url was left out of an accepted save.
Mechanism checked on the diff:
retypedNavEntry keeps id, label, icon, order, badge, badgeVariant, visible and the gates, and drops the old type's target. A separator keeps id/order only, and a group is born with children: [].
The old path that let a page entry keep pageName beside a picked object, which the spec refuses with unrecognized_keys, is removed (H2, measured).
Pickers read this package's published and draft items, leaving out record pages and object-bound actions.
The canvas no longer offers inline rename on a separator, whose spec member has no label.
Declared deviations, accepted:
The type choice sits in the entry's inspector (radios), not in a menu on Add nav item. addItem is shared with Setup's app editor, and the inspector choice also retypes existing entries.
A group is added flat: the Studio canvas does not nest, which is noted as a follow-up.
Tests:
Pins: 48 rows in two new files, covering the exact type list, retype key-keeping, the per-type pickers, and a spec-valid save per type.
Reverse check:StudioDesignSurface.tsx at base turned the type-list rows red in the predicted direction (no radio, no Type group). The restore was proven by blob hash.
Local runs: 29 suites and 265 tests green across the touched and Interfaces/nav files. app-shell type-check green. check:i18n-designer-parity, check:i18n-drift and check:spec-symbols green.
Real browser:
all ten types are offered;
the pickers leave out the record page, foreign pages and object-bound actions;
one entry of each type was saved, and both saves were accepted;
every entry shows in the rail. The separator's empty disabled row is objectui#11791's.
Overlap re-read: since the PR's base 1e1f09e, main (455c646) took this seat's objectui#11840. It shares only i18n.ts, in different rows. An in-memory git merge-tree with main is clean.
CI at eecc053: 42 runs, still converging at this read: 28 green, 3 expected skips, 11 in progress, none red. The PR waits to be queued until every check completes.
Out-of-scope findings:
Filed by this seat: Setup's app editor (AppNavInspector) shows Label and Icon on a separator entry. Typing a label writes {type: 'separator', label}, which NavigationItemSchema refuses with unrecognized_keys [label]. This was measured through the real component; the PR body was written before it was measured.
Noted, not filed:
Setup's editor offers six of the ten types;
nesting under a group from Studio;
the doc picker offers declared books, not a package's implicit book.
PR assignee: set by this seat to huangyiirene, the card's assignee.
Merged through the merge queue at 2026-10-08T01:24:09Z, after it was queued at 2026-10-08T01:07:34Z.
CI on head eecc053 before queueing: 40 of 43 check runs passed, and the 3 skipped are the expected ones.
The one remaining run, Changeset Fixed Group Check, still read status: in_progress on the API.
It carried conclusion: success and a completed_at, every job step read completed success, and its workflow run (CI) read completed success. That is a stale status field, not a running check.
check-governed-merges.mjs read 0 of 11 paths governed and 1325 changed lines, under the human-merge threshold.
Content check:
59ce048 is one squash commit on parent 455c646. It changes 11 files, +1283/−42, the same as the PR.
10 of the 11 files are blob-identical to the reviewed head eecc053.
i18n.ts also carries this seat's objectui#11840 rows, which landed between this PR's base 1e1f09e and its merge. Its per-file patch-id matches: 24598a26… in the PR and in the squash. The whole diff's patch-id matches too (e207e46e…).
The landed bytes are the reviewed change. The merge queue ran CI on the combined tree.
On main: NAV_ENTRY_TYPE_TABLE hits inspectors/nav-target.ts.
Card: closed completed by the PR's Fixes. pm:dispatched was removed and read back.
Landing window: after 00:40Z, the only other objectui card closed is objectui#11811 (seat 2's PR objectui#11841, 00:48Z). This PR closes only this card.
On record:
The ACCEPT (6049961212) held the spec's ten types.
It also accepted two declared deviations: the type choice sits in the entry's inspector, and a group is added flat.
Released by this landing:
objectui#11823 (create flows, step 2) carried Blocked-by: objectstack-ai/objectui#11790. This seat's unblock sweep returns it to pm:queue.
objectui#11791 (the rail's separator row) was fenced as serial behind this card. It is free.
Activity
objectstack-fleet commentedon Oct 7, 2026
Path: write metadata — building an app's interface in Studio | 缺项 | P2
Triage: first grade,
enhancement·priority:p2·domain:ui·area:studio·pm:queue. Filed as ②, but an accepted ADR answers it: the Interface pillar holds app · page · view · form · dashboard · report (ADR-0084). This card is step 1, every nav item type; the create flows are #11823Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-07T17:59Z. ⛔ Not a claim, ⛔ not a dispatch.Triage: lands in
packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx(the nav editor's Add nav item) andnavSurface.ts⇒domain:ui; rationale: Studio's Interface pillar in objectui. Read on objectuimain9990f9e122and objectstackmainaa71c4d9d1.docs/adr/0084-application-builder-information-architecture.md:46).docs/design/builder-ui.md§6).pm:blockedon this card.NavigationItemSchemadeclares: object, page, dashboard, report, URL, group and separator (objectstackpackages/spec/src/ui/app.zod.ts). Each picks its target from the package's items.StudioDesignSurface.tsx(5,547 lines) is also edited by studio(interfaces): the nav rail draws a separator item as an unlabeled disabled row and ignores badge #11791, studio: navigation details — More holds only Access, Advanced trigger renames itself, no search in Automations, raw ids/names where labels belong, silent redirect without Studio access #11794 and studio: unusable below tablet width, and the flow canvas does not fit-to-view on resize #11795. Claim after the in-flight one lands, or declare the overlap.Clause-②: no. Patch changeset in objectui.objectstack-fleet commentedon Oct 8, 2026
Claim: PM loop round 8
Session:
session_01DrKzdPdyLLBW3qpZ4vtk7zAccount:
huangyiireneBranch:
claude/issue-11790-nav-item-typesWorktree:
objectui-issue-11790Domain:
domain:uiSeat:
domain:ui#1File surface (line numbers on
1e1f09e):packages/app-shell/src/views/metadata-admin/previews/AppNavCanvas.tsx: Add nav item (addItem:329, the button at:412) and the per-type card rendering.packages/app-shell/src/views/metadata-admin/inspectors/AppNavInspector.tsxandinspectors/nav-target.ts: per-type target picking from the package's items.packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx, only the Interfaces pillar's nav-editor wiring, andNavTree's per-type rows if a new type needs one.packages/app-shell/src/views/studio-design/navSurface.ts:resolveSurfacefor a type that opens a surface, only if needed.engine.appNav.*/engine.inspector.appNav.*rows ofpackages/app-shell/src/views/metadata-admin/i18n.ts..changeset/11790-*.md.⛔ Not on it:
6049060030):StudioDesignSurface.tsx's autosave, publish and pillar save-error strips, andmetadataError.ts.pm:blockedon this card);packages/i18n/**.Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
Container & model:
M,mode:subagent,model: opus(dispatch-gates --tier --repo objectstack-ai/objectuiover these paths: no path-derived mandate; default tier)Clause-②: no
Responsibility:
objectui app-shell Studio: the nav editor's Add nav item can only link an object, so a writable package cannot put a page, dashboard, report, URL, group or separator into its app nav from Studio | the platform path is right: NavigationItemSchema declares every one of those types, and the runtime console renders them | every author building an app's navigation in a writable package; measured by the filer (Add nav item offers only Link to object)Thread-read: 6043752848
Serial constraints cleared:
noneblocking.StudioDesignSurface.tsxis also on objectui#11791, studio: navigation details — More holds only Access, Advanced trigger renames itself, no search in Automations, raw ids/names where labels belong, silent redirect without Studio access #11794 and studio: unusable below tablet width, and the flow canvas does not fit-to-view on resize #11795. All three are stillpm:queue, so none is in flight. Fold-or-serial: serial, none folded; each is a different defect shape.area:studioin flight:StudioDesignSurface.tsxonly in its error strips, which this surface leaves alone. Both addi18n.tsrows under different prefixes; whichever lands second mergesmain.area:records), build(deps): Bump next from 16.3.6 to 16.3.8 in /apps/site in the npm_and_yarn group across 1 directory #11844 (dependabot), chore: release packages (next) #11600 and feat(cli):objectui validateandobjectui checkjudge through the strict authoring face (objectui#5250, slice A) #11069. None touches these files. Read 2026-10-08T00:16Z.batch3, on the maintainer's word in this session's chat today: 「改为并行派发,batch 3」.area:workflow). Their surfaces are disjoint from this one.Why
Clause-②: no: this is Studio's editor for types the spec already declares. No accepted input widens, and no export, prop,@object-ui/typesmember orpackages/i18nkey is added. App-shell'sENGINE_STRINGSare unexported. If the fix needs a published surface, the dev stops and reports, and the seat re-claims.objectstack-fleet commentedon Oct 8, 2026
os-dev-report
{
"issue": 11790,
"status": "done",
"branch": "claude/issue-11790-nav-item-types",
"pr": "#11846",
"session": "session_01DrKzdPdyLLBW3qpZ4vtk7z — the parent's (mode:subagent); the same id is in the commit's Claude-Session trailer and the PR footer",
"premise_still_valid": true,
"summary": "Studio's nav editor offers every nav item type the installed spec's NavigationItemSchema declares. Measured on @objectstack/spec 17.7.0, the list is object, dashboard, page, url, report, action, component, doc, separator and group. Triage named seven; the spec also declares action, component and doc, with no member marked non-addable, so all ten are offered. Add nav item still appends {id, type:'object'} and selects it. StudioNavItemInspector now opens with a Type choice (radios; NAV_ENTRY_TYPES is a Record keyed by the spec-derived NavigationItemType). A change of type (retypedNavEntry) keeps id, label, icon, order, badge, badgeVariant, visible and the gates, and drops the old target. A separator keeps id and order; a group is born with children []. Each target-bearing type picks from this package's published plus draft items: pages (record pages left out), dashboards, reports, global actions (object-bound left out), docs and books. A component picks from the console's component registry; a url is typed. An emptied picker removes the key. doNavSave, navPayloadOf and NAV_TARGET_READS are unchanged; the table already had a row for every target-bearing type. The rail gives url, component and doc rows their own icon, and the canvas no longer offers inline rename on a separator card.",
"tests": "HEAD the gate union ran on: eecc053, the PR head. GATES (command → exit → verdict): [1] pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build (via os-verify-lock) → 0 → 'VERDICT command-exit 0 · held the lock 183s'. [2] pnpm exec vitest run, 2 new files (nav-target.navEntryTypes-11790.test.ts, StudioDesignSurface.navItemTypes-11790.test.tsx) → 0 → 'Test Files 2 passed (2) / Tests 48 passed (48)'. [3] pnpm exec vitest run, 16 files naming the touched files (AppNavCanvas x3, AppNavInspector.labelInherits, inspectors/tests/nav-target, AppPreview x2, navSurface, 4 StudioNavItemInspector suites, aiChipLabel, studio-locale.i18n, ResourceEditPage.navDeepLink, select-placeholder-literal) → 0 → 'Test Files 16 passed (16) / Tests 175 passed (175)'. [4] pnpm exec vitest run, 13 Interfaces/nav pillar suites (autosaveInFlight, autosaveSwitch, interfacesAction, interfacesAppLabelMap, interfacesRailLabelMap, interfacesReadOnly, navAutosaveFlush, navDeepLink, navEditClosesOnReadOnly, navEntryIdentity, navPlaceholderSave-11776, pillarNavGuard, interfacePolish) → 0 → 'Test Files 13 passed (13) / Tests 90 passed (90)'. [5] pnpm --filter @object-ui/app-shell type-check (echoed 'tsc --noEmit && tsc -p tsconfig.test.json') → 0 → 'VERDICT command-exit 0'. [6] pnpm check:control-bytes → 0 → 'check-control-bytes: OK'. [7] check:new-line-citations → 0 → '0 new citation(s), enforcement report-only'. [8] check:changeset-claims → 0 → 'No pending changeset names a file this change touches.' [9] check:pending-changeset-literals → 0 → 'No test source names a pending changeset.' [10] check:i18n-designer-parity → 0 → 'Every en row has a zh row, and every shared row carries the same placeholders.' DERIVED by hand (objectui has no dispatch-gates.mjs; picked by what reads the diff): [11] check:i18n-drift → 0 → 'No designer-table en value changed in this range.' [12] check:i18n-keys → 0. [13-15] check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape → 0 each → 'OK'. [16] check:test-path-roots → 0 → OK. [17] check:spec-symbols → 0 → 'spec symbol derivation ... 0 untriaged collisions'. [18] check:icon-record-names → 0 → OK. [19] check:unreferenced-sources → 0 → OK. [20] node scripts/check-changeset-presence.mjs → 0 → 'this change declares 1 changeset(s): .changeset/11790-nav-item-types.md'. [21] targeted eslint --format json on the 10 changed files → 0 → 0 errors, 16 warnings all on lines this diff does not touch. Repo-wide pnpm lint and the full farm are declared to CI. CI state at report time: NOT MEASURED (reason: the report is delivered when local verification ends; CI convergence is the seat's). REVERSE CHECK (after commit): StudioDesignSurface.tsx alone checked out at base 1e1f09e (blob a795370b, equal to base) → vitest -t 'offers exactly the' → exit 1, predicted direction: 'Unable to find an accessible element with the role "radio"' (inspector) and 'Unable to find role="group" and name "Type"' (pillar, after Add nav item); 'Tests 2 failed | 18 skipped'. Restored with git checkout HEAD from a trap; hash 2fe2efe6 equals the HEAD blob; git diff HEAD empty. REAL BROWSER (dev-only harness, never committed): console Vite on a private port; InterfacesPillar over an in-memory /api/v1/meta fetch double that parses each app save with AppSchema; Chromium /opt/pw-browsers/chromium at 1440x900 via Playwright. Observed: after Add nav item the Type choice offered all ten types with Object checked. Page picker: ['', home, draft_page] (record page and foreign-package page absent). Action picker: ['', sync_all] (object-bound close_task absent). Component picker: the 4 app-shell registered screens. An unbound url was left out of a save that was accepted. One entry of every type was added; both saves were accepted; the final navigation held all 12 entries in member shape. After Done, the rail showed every entry: dashboard, page, report, action and object enabled; component, doc and url disabled with their own glyphs; the group as a header; the separator an empty disabled row (objectui#11791). Zero page errors. DEVIATIONS: (1) StudioNavItemInspector gained one required internal prop, packageId. The fence's 'no prop' was read as Clause-②, the published surface: that component is exported for tests only, not re-exported from the package index, and package.json exports only '.'. The four existing inspector suites pass it (one or two lines each). (2) The type choice is in the new entry's inspector (the order's second route), not a dropdown on the button. AppNavCanvas addItem is shared with Setup's app editor; the inspector choice also retypes existing entries; a Radix menu on the button would have rewritten the suites that click Add nav item, some in seat 3's autosave area. (3) AppNavCanvas separator-card rename guard, in the claimed per-type card rendering: Studio can now make separators, and an inline rename would write a label the spec refuses at save. (4) Commit trailers are AGENTS.md's model-free pair, not the harness's model-named Co-Authored-By. (5) check:* gates and targeted eslint ran outside the verify lock, by rule. (6) Out-of-scope finding 1 was measured after the write-once PR body; it is not in the PR's Acceptance notes, so the seat may append it. (7) A dev-only browser harness and a dev-only Setup inspector probe test were created and deleted, never committed. Vite (pid 2082, port 5291) was stopped by pid and port. The worktree node_modules and the worktree are removed. FILES_CHANGED (vs base 1e1f09e): .changeset/11790-nav-item-types.md (new, @object-ui/app-shell patch); packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx; packages/app-shell/src/views/metadata-admin/inspectors/nav-target.ts; packages/app-shell/src/views/metadata-admin/previews/AppNavCanvas.tsx; packages/app-shell/src/views/metadata-admin/i18n.ts (new engine.inspector.appNav.* rows, en+zh); new tests: inspectors/nav-target.navEntryTypes-11790.test.ts, studio-design/StudioDesignSurface.navItemTypes-11790.test.tsx; updated tests: StudioDesignSurface.navItemInspector, navItemInspectorLabel-11196, navItemInspectorLabelMaps-11148, standardNavEntries-11201 (packageId prop only). Nothing outside the claim's surface. HYPOTHESES: H1 partly right (addItem births object; the Studio inspector is StudioNavItemInspector, not AppNavInspector, which is Setup's and offers six types). H2 falsified for Studio (object binding only; picking an object on a page entry kept pageName, refused by NavigationItemSchema with unrecognized_keys [pageName], measured; that path is removed). H3 right (separator rendering left to objectui#11791).",
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "2 REST writes. (1) pr_create relayed: POST /repos/objectstack-ai/objectstack/dispatches; run 37709719221 executed POST /repos/objectstack-ai/objectui/pulls as objectstack-fleet[bot], giving draft PR #11846; read-back reported 14216 bytes sent and 14216 stored, identical. (2) This os-dev-report comment via post-stamped.mjs --comment=11790 --repo=objectstack-ai/objectui (POST /repos//issues/11790/comments, by the relay route the tool picks). Not REST: git push of claude/issue-11790-nav-item-types (the empty probe push, then eecc053). Zero label and assign writes. GET reads only otherwise.",
"open_questions": [],
"out_of_scope_findings": [
"class: c · reach: named producer — Setup's app editor (AppNavInspector, registered for 'app') shows its Label and Icon fields on a separator entry, such as showcase's nav_sep_reports · evidence: a dev-only probe (not committed) rendered AppNavInspector over {id:'nav_sep_reports', type:'separator'}; typing 'Reports' in Label wrote {id:'nav_sep_reports', type:'separator', label:'Reports'}, and NavigationItemSchema.safeParse refused it with unrecognized_keys [label]; the save door parses the same strict member, so the edit is refused at save · dedupe words: AppNavInspector separator label; setup app editor separator unrecognized_keys label; nav inspector separator icon field",
"carrier: none (承接者:无) · Setup's AppNavInspector offers six of the spec's ten nav types (no action, component, doc or separator); an editor gap, not a defect class · noted in PR Acceptance notes, not filed",
"carrier: none (承接者:无) · nesting entries under a group from Studio is a follow-up: StudioNavItemInspector edits top-level navigation entries only and the canvas does not nest, so a group is added flat with children [] · noted in PR Acceptance notes, not filed",
"carrier: none (承接者:无) · the doc picker offers the package's declared books, not its implicit book (the package id); a doc alone still opens in its own book context · noted in PR Acceptance notes, not filed"
]
}
objectstack-fleet commentedon Oct 8, 2026
Review: ACCEPT — PR objectui#11846 (head
eecc053)domain:uiseat 1 ·session_01DrKzdPdyLLBW3qpZ4vtk7z· reviewed against the PR diff, its file list and check runs, read 2026-10-08T00:58Z. Report:os-dev-report6049930430on this card.Shape: draft →
main. The first line isFixes #11790, andClause-②: nostarts a later line.Scope: 11 files, +1283/−42, inside claim
6049484420's surface:StudioDesignSurface.tsx(+452). Its hunks are the imports,KIND_ICON,NavTree's per-type rows,StudioNavItemInspector(the type choice and the per-type pickers), and onepackageIdpass inInterfacesPillar. The Interfaces nav inspector lives in this file, not inAppNavInspector.tsx, which is Setup's (H1 corrected).nav-target.ts(+103) andAppNavCanvas.tsx(+11/−2, the separator rename guard).engine.inspector.appNav.*rows ini18n.ts, EN and ZH.packageIdadded to four existing inspector suites, and one changeset (@object-ui/app-shellpatch).Nothing touches seat 3's objectui#11785 error strips or
metadataError.ts.doNavSave,navPayloadOf,NAV_TARGET_READSand the nav banner are unchanged: the diff mentionsnavPayloadOfonly in comments.Clause-② re-read on the diff:
exports (NAV_ENTRY_TYPES,isNavEntryType,navTypeAcceptsChildren,retypedNavEntry) are module-level.index.tsnames none of them, norStudioNavItemInspector.packageIdprop is on a test-exported component that is not on the package entry. I accept it as module-internal, as with objectui#11783'sariaLabel.@object-ui/typesmember orpackages/i18nkey changes.noholds.Rulings held:
NAV_ENTRY_TYPE_TABLEis aRecord<NavigationItemType, true>, so it is exhaustive over the spec-derived union at compile time. On@objectstack/spec17.7.0 it covers object, dashboard, page, url, report, action, component, doc, separator and group. Triage named seven; the order said to offer what the spec declares, and no member is marked non-addable, so ten.urlwas left out of an accepted save.Mechanism checked on the diff:
retypedNavEntrykeepsid,label,icon,order,badge,badgeVariant,visibleand the gates, and drops the old type's target. A separator keepsid/orderonly, and a group is born withchildren: [].pageentry keeppageNamebeside a picked object, which the spec refuses withunrecognized_keys, is removed (H2, measured).label.Declared deviations, accepted:
addItemis shared with Setup's app editor, and the inspector choice also retypes existing entries.Tests:
StudioDesignSurface.tsxat base turned the type-list rows red in the predicted direction (noradio, noTypegroup). The restore was proven by blob hash.app-shelltype-check green.check:i18n-designer-parity,check:i18n-driftandcheck:spec-symbolsgreen.Overlap re-read: since the PR's base
1e1f09e,main(455c646) took this seat's objectui#11840. It shares onlyi18n.ts, in different rows. An in-memorygit merge-treewithmainis clean.CI at
eecc053: 42 runs, still converging at this read: 28 green, 3 expected skips, 11 in progress, none red. The PR waits to be queued until every check completes.Out-of-scope findings:
AppNavInspector) shows Label and Icon on a separator entry. Typing a label writes{type: 'separator', label}, whichNavigationItemSchemarefuses withunrecognized_keys [label]. This was measured through the real component; the PR body was written before it was measured.PR assignee: set by this seat to
huangyiirene, the card's assignee.Generated by Claude Code
objectstack-fleet commentedon Oct 8, 2026
Landed: PR objectui#11846 →
main59ce048domain:uiseat 1 ·session_01DrKzdPdyLLBW3qpZ4vtk7z· verified 2026-10-08T01:25Z.eecc053before queueing: 40 of 43 check runs passed, and the 3 skipped are the expected ones.Changeset Fixed Group Check, still readstatus: in_progresson the API.conclusion: successand acompleted_at, every job step readcompleted success, and its workflow run (CI) readcompleted success. That is a stale status field, not a running check.check-governed-merges.mjsread 0 of 11 paths governed and 1325 changed lines, under the human-merge threshold.59ce048is one squash commit on parent455c646. It changes 11 files, +1283/−42, the same as the PR.eecc053.i18n.tsalso carries this seat's objectui#11840 rows, which landed between this PR's base1e1f09eand its merge. Its per-file patch-id matches:24598a26…in the PR and in the squash. The whole diff's patch-id matches too (e207e46e…).main:NAV_ENTRY_TYPE_TABLEhitsinspectors/nav-target.ts.completedby the PR'sFixes.pm:dispatchedwas removed and read back.6049961212) held the spec's ten types.Blocked-by: objectstack-ai/objectui#11790. This seat's unblock sweep returns it topm:queue.Generated by Claude Code
feat(app-shell): Studio's nav editor offers every nav item type the s…
docs(qa): a repeatable Studio task benchmark — repair-ticket scenario…