Skip to content

Studio copilot: one right slot that shows either the properties or the copilot — properties follow the selection and mark the copilot's drafts; the copilot folds to a strip while properties show; change card v2; the 变更 badge in sync; no 源码 tab; pillar labels kept #12725

Open

Description

@objectstack-fleet

Source

Walked on 2026-10-16 at 1010 × 1119 in Studio › app.hcpl › Interfaces with the AI 副驾 open: the panel takes about 330 px on the right, the properties fold into a 画布 / 属性 tab pair in the canvas, and the record-list preview is left with one and a half columns. StudioAiCopilot.tsx mounts the panel; StudioDesignSurface.tsx line 1758 hides the pillar labels below xl (sr-only xl:not-sr-only).

Rulings (2026-10-16, the epic PM session, verbatim)

  1. 「studio 中其他的设计面板属性都是右侧打开的,你换到 tab 会不会改动太大,是否考虑浮出」 and 「属性好需要考虑选中每个元素的时候也要显示。」 — the properties stay on the right and follow the selection.
  2. 「ai 副驾或者属性面板是否能切换隐藏,这个宽屏的界面好乱。还有我在和ai 讨论的时候估计也不会看属性吧?」 — the floating panel beside a permanent rail was rejected; one right slot shows either the properties or the copilot.
  3. 「源码的选项卡有必要保留吗?未来还有人看吗」 — the canvas has no 源码 tab.
  4. 「按「右栏二选一」定稿」.

Target (StudioRailCopilot and StudioRailProps artboards)

  1. One right slot (360 px at ≥ 1280, 300 px at 1010) with a segmented header 属性 | AI 副驾 (the copilot segment carries a count badge of pending items). ⌘. toggles the slot between the two; the top bar's right-most icon collapses the slot entirely. No floating panel, no overlay dock, no fourth column at any width.
  2. Switching by intent: clicking any canvas element (column, card, field, button) switches the slot to 属性 for that element; Esc or a click on empty canvas returns to the item's own properties. While 属性 shows, the copilot is a 40 px strip at the slot's foot 「AI 副驾 · N 项待确认 · 回到对话 →」; while the copilot shows, the canvas hint reads 「点元素 → 右栏切到属性」.
  3. Properties follow the selection in every pillar; a field or view setting the copilot changed carries a 草稿 chip and a 来源 line (「由 AI 副驾在 2 分钟前作为草稿加入」). The canvas's own tabs go: no 画布 / 源码 / 属性 tabs; one status line above the canvas (「运行态预览 · 含未发布改动」). The item's definition is reachable from its ⋯ menu (查看定义 · 复制 JSON · 重命名 · 删除) and as a diff in the 变更 drawer.
  4. Change card v2 inside the copilot: 「修改方案 · N 项」 with one row per change (+ / ✎ symbol, kind, object · field, machine name and parameters in small type), the amber posture note for a live app with data, 存为草稿 (primary) / 调整; the applied card 「已存为草稿 · N 项」 with 查看变更并发布 / 撤销; the composer with the 「借阅看板 ×」 context chip and the placeholder 「问问数据,或让我改改这个应用…」. Data from objectstack-ai/cloud#2924.
  5. The top bar's 变更 badge counts the copilot's drafts the moment they land; the item header shows 「草稿 · N 项未发布」.
  6. The pillar switcher keeps its labels (数据 / 自动化 / 界面 / 权限) from 1024 px up (lg:not-sr-only instead of xl:); below that, icons with tooltips.

File surface

packages/app-shell/src/views/studio-design/StudioAiCopilot.tsx, StudioDesignSurface.tsx (the right slot, the pillar labels, the canvas status line, the item ⋯ menu), packages/app-shell/src/layout/ChatDock.tsx, the Interfaces preview's selection → properties wiring, tests beside.

Acceptance

  1. Tests: the slot shows the copilot with no properties; selecting a card switches it to that card's properties with the copilot strip at the foot; Esc returns to the view's properties; the 变更 badge equals the draft count; no 源码 tab; pillar labels visible at 1024.
  2. Screenshots at 1010 and 1280 px in both slot modes.
  3. pnpm --filter @object-ui/app-shell test green.

Design

Artboards on the temporary branch claude/console-home-login-design-20261016 of objectstack-ai/objectui, commit 98aab506a (never merged; *.preview.html opens in a browser, *.dc.html is the canvas source): StudioRailCopilot (source) · StudioRailProps (source). The rejected alternative (the floating panel) stays beside them as StudioCopilot for the record. The README beside them records the rulings.

Evidence

Screenshots on the same branch and commit: ai-studio-books-21-rows-1010px.jpg · ai-studio-kanban-preview.jpg · ai-copilot-modify-plan.jpg.

Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff from the 2026-10-16 build of a library-lending app (package app.hcpl) on the test1016 tenant at https://os-4e4qa4.objectos.app (staging, zh-CN, the maintainer's browser pane at 1010 × 1119). The maintainer named the repositories, verbatim: 「部分前端功能代码在 objectui 后端在 onjectstack」.

Body refreshed 2026-10-16T15:56Z: the floating-panel design this card was filed with was replaced by the right-slot design per the maintainer's rulings above; title, Target, File surface, Acceptance and Design rewritten; Source and Evidence unchanged.

Activity

  1. added
    enhancementNew feature or request
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    on Oct 16, 2026
  2. changed the title [-]Studio copilot: a floating panel over the canvas that never takes the properties rail; the rail follows the selection and marks the copilot's draft changes; change card v2; the 变更 badge in sync; pillar labels kept[/-] [+]Studio copilot: one right slot that shows either the properties or the copilot — properties follow the selection and mark the copilot's drafts; the copilot folds to a strip while properties show; change card v2; the 变更 badge in sync; no 源码 tab; pillar labels kept[/+] on Oct 16, 2026
  3. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 11, serial · a partial claim, Part of #12725 (priority:p2; filed with its rulings by the epic PM session, no triage comment on the card)
    Session: session_011K9g23W67dy2zwnyzaoB6o
    Account: os-tesla
    Branch: claude/issue-12725-studio-right-slot
    Worktree: objectui-issue-12725 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: the Studio right slot, items 1, 2, 3 (the canvas half) and 6 of the card's Target. Line numbers are on main 4b3d6ed.

    • packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx:
      • The right slot: one slot that shows either 属性 or AI 副驾 (item 1). It has a segmented header, ⌘. to toggle the two, and the top bar's collapse.
      • Switching by intent (item 2): selecting a canvas element shows its properties; Esc, or a click on empty canvas, returns to the item's own properties. While 属性 shows, the copilot folds to its 40 px strip.
      • The canvas half of item 3:
        • the inspector's 源码 / 属性 tabs go (inspectorTab, :3216, :4591);
        • one status line sits above the canvas;
        • the item's definition is reachable from the item header's ⋯ menu (查看定义 · 复制 JSON · 重命名 · 删除 as the card draws it, reusing whatever rename and delete the header already offers).
      • The pillar labels from 1024 px up (item 6: sr-only xl:not-sr-only → lg:, :1787).
    • packages/app-shell/src/views/studio-design/StudioAiCopilot.tsx and packages/app-shell/src/layout/ChatDock.tsx, only as far as the copilot moves into the shared slot and gains its folded strip. The ChatDock's other hosts keep their behaviour.
    • The new copy goes in the designer table (metadata-admin/i18n.ts, en and zh rows).
    • Tests beside the existing StudioDesignSurface.* and StudioAiCopilot.* families.
    • One .changeset/12725-*.md for @object-ui/app-shell.

    Not this claim; the card stays open for them, Part of #12725 (they need the copilot's draft provenance and objectstack-ai/cloud#2924's payload, which this seat cannot read):

    • item 3's 草稿 chip and 来源 line on a copilot-changed setting;
    • item 4, change card v2;
    • item 5, the 变更 badge counting the copilot's drafts as they land.

    The PR carries Part of #12725, not Fixes. On merge the seat releases the card back to pm:queue with these items named.

    Outside the surface:

    • the copilot's conversation, agent and request paths;
    • the console's own ChatDock hosts;
    • every other pillar's editors;
    • objectui#12724's AI build cards.

    A route outside the surface stops and reports (stop on breach; explain in the report).
    Container & model: L, mode:cloud, model: opus (default tier; no path-derived mandate; sized L for an 8.5k-line surface file and two hosts)
    Clause-②: no
    Clause-② reason: Studio's own chrome is rearranged. No spec key, exported prop, export or language-pack key changes; the new copy goes in the metadata-admin designer table, and StudioDesignSurface / StudioChatDock keep their exported signatures.
    Responsibility: n/a — a ruled design change (the maintainer's 「按「右栏二选一」定稿」, quoted in the card)
    Thread-read: none
    Serial constraints cleared: read at objectui main 4b3d6ed. No open non-bot PR exists, and the bot PRs touch no source file. The in-flight domain:ui cards held by other seats (objectui#12843, #12816, #12809, #12795) name console Home, the Approvals inbox, the splash and the console sidebar, not Studio's design surface or the ChatDock. The last changes to StudioDesignSurface.tsx are this seat's PR #12849 (objectui#12718) and PR #12792 (objectui#12707), both merged. The seat holds no other card in flight (serial mode; objectui#12726 was released to pm:retriage as a duplicate of objectui#11815).


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12725,
      "status": "done",
      "branch": "claude/issue-12725-studio-right-slot",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12863",
      "session": "session_01RHosmNCrzgLTBGywhN5wSv",
      "premise_still_valid": true,
      "summary": "Partial claim delivered (items 1, 2, 6 and the canvas half of item 3); the PR body opens with 'Part of #12725'. Studio now has one right slot (StudioRightSlot): it shows 属性 or AI 副驾, 300 px below 1280 and 360 px from 1280. It has a segmented header, ⌘./Ctrl+. switches the two halves, and the top bar's right-most icon hides it, remembered under the existing Studio sessionStorage key. While 属性 shows, the copilot folds to a 40 px strip at the slot's foot. The Interfaces pillar portals its inspector into the slot. Selecting a canvas element (a dashboard widget or page block through onSelectionChange, or a nav entry in nav editing) switches the slot to 属性. Esc or a click on empty canvas returns to the item's own properties. The canvas lost its 画布/源码/属性 tabs (the folded center tabs and the source page's Source/Properties tabs) for one status line. The item's ⋯ menu opens 查看定义 (a source page's code editor, or any other item's document as JSON) and 复制 JSON; a new page opens on its definition. Pillar names show from lg (1024 px). The copilot's conversation, agent, scope and requests are unchanged: StudioChatDock keeps its name and props and becomes the slot's body; it reports {available, planPending} up to the slot.",
      "tests": "Full package on merged head bd0e3d5 (merge of origin/main 024d446): `pnpm --filter @object-ui/app-shell test` → EXIT=0, 'Test Files 1534 passed | 1 skipped (1535) · Tests 14511 passed | 9 skipped (14520)'. Earlier on 8c3773b+tests: `vitest run packages/app-shell/src/views/studio-design packages/app-shell/src/layout` → 302 passed / 2134 tests. Baseline before any edit at 4b3d6ed: 303 files / 2131 tests green. New test files: StudioDesignSurface.rightSlot-12725 (12 tests: copilot with no properties; selection → 属性 with the strip at the foot; Esc and an empty-canvas click return to the item's own properties; ⌘./Ctrl+. and the top-bar toggle under the Studio key only; the plan-pending marker; no canvas tabs plus the ⋯ definition; lg pillar labels; controls for an own-aside pillar, no copilot served, and an injected aiSlot); __tests__/studioRightSlot-12725 (8 tests); __tests__/studioCopilotSlotBody-12725 (3 tests). Ablation (the tests import src, so there was no dist step): each mutant was applied to committed HEAD by an anchored replace that refuses unless the anchor hits exactly once, and restored with `git checkout HEAD -- PATH`. Each restore was proved by blob == HEAD blob 712c7d0 and an empty `git diff HEAD`. Results: A1 no showProps → 5 red; A2 Esc off → 1 red; A3 empty-click off → 1 red; A4 lg→xl → 2 red (rightSlot + narrowHeader); A5 default mode props → 2 red; A6 ⌘. off → 1 red; A7 ⋯ menu removed → 3 red; A8 a tab injected into the source-page properties → 1 red. The A1 restore leg first failed: a script bug after `shift` restored the wrong path. The blob guard reported RESTORE FAILED; I restored by hand, verified blob 712c7d0 == HEAD, fixed the script, and the restore legs for A2–A8 passed. Re-pointed pins, each with its reason in a comment: InterfacesPillar.foldedToggle-12611 → renamed slotGutter-12611 (the dot pin becomes 'a selection calls showProps and the inspector is in the slot'; the 16 px gutter moves with the slot; CONTROL classic 24 px). selectionLeafScope (the folded center-tab reading → the canvas status line stops naming a selection the new leaf lacks). sourcePage-12522, interfacesReadOnly-11136, interfacesCreatePage-11823 (the editor moved from the Source tab to the definition sheet; the 'folded layout' variants became 'properties in the right slot'). narrowHeader-12509 (xl → lg). autosaveSwitch-11232 (no Properties tab to open). accessSegment-12452, createAppAccessibleName, createAppOpensInterfaces-11794 (findByRole('banner') → the shell header's test id, because testing-library reads the aside's header as a second banner). navDraftLabels-11862 (the fake client gains withPreviewDrafts; the inspector is now always mounted). studioChatDockPersistence → renamed studioCopilotSlotBody-12725. Deleted, with where each pin went: centerTab.ts and __tests__/centerTab.test.ts pinned nextCenterTab (a target appearing → Properties, a target clearing → Canvas, steady state keeps the user's tab). That rule is gone with the folded tabs: the appear edge is now showProps on the selection's identity (rightSlot 'selecting an element…' and slotGutter 'a selection asks…'); the clear edge is Esc and empty-click returning to the item's own properties (rightSlot); the leaf-change half lives in selectionLeafScope. The steady-state 'never fight the user' rule holds by construction: showProps fires only when the selection identity changes, and rightSlot's strip test shows the copilot stays chosen while the selection stands. __tests__/wideViewport.test.tsx pinned WIDE_VIEWPORT_BREAKPOINT = 1280 and the inclusive boundary of useIsWideViewport, which decided canvas-beside-properties versus tabs. No window width decides between them any more, so that rule no longer applies. The 1280 line survives as the slot's width step (xl:w-[360px]), pinned in studioRightSlot-12725 'is 300 px wide, 360 px from 1280'. useIsNarrowerThan and AUTOMATIONS_CONFIG_FOLD_WIDTH stay in wideViewport.ts, pinned by AutomationsPillar.narrowRow-11795 (green).",
      "gates": "Local, captured before any pipe, on bd0e3d5: `pnpm --filter '@object-ui/app-shell^...' build` VERDICT command-exit 0; `pnpm --filter @object-ui/app-shell type-check` EXIT=0 (0 'error TS'); check:i18n-keys 0; check:i18n-drift 0; check:i18n-dead-keys 0 (report-only; the one Studio candidate, engine.studio.if.previewIsRuntime, predates this change); check:i18n-designer-parity 0; `vitest run packages/i18n/src/__tests__` 0 (83 files, 1321 passed); 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 ('25 source file(s) of 1 released package(s) changed … declares 1 changeset'); eslint --no-inline-config on the changed .ts/.tsx files 0 errors (warnings: the same rule set as the base file, one exhaustive-deps warning removed). `node scripts/check-nul-bytes.mjs` → MODULE_NOT_FOUND: that script exists only in objectstack, so this is not a gate reading. I ran the equivalent scan instead (`grep -naP` over control bytes on the changed files): clean. `dispatch-gates.mjs --commands/--ran` is not present in objectui; the list above was derived by hand from package.json and ci.yml per the brief. The CI farm is not yet read: no PR exists.",
      "mcp_calls": "0",
      "api_writes": "0 — git push only: claude/issue-12725-studio-right-slot (8c3773b, then bd0e3d5) and the evidence branch claude/issue-12725-evidence (72d4957, evidence/12725/ with 26 PNGs and a README). No PR, comment, label or MCP write.",
      "open_questions": [
        {
          "question": "Item 3 says properties follow the selection 'in every pillar'. This claim wires Interfaces only; Data (data-field-inspector), Automations (auto-config-aside / auto-config-drawer) and Access keep their own asides, so beside them the slot shows the copilot alone (a 4th column when both are open, as before). Move them into the slot in a follow-up?",
          "options": [
            "A: follow-up card: each pillar claims the slot (useStudioRightSlot) and portals its StudioInspector, the same seam this PR adds",
            "B: leave them; Interfaces only"
          ],
          "recommendation": "A, because the seam is already built and generic: claimProps plus a portal target. The ruling 「studio 中其他的设计面板属性都是右侧打开的」 asks for it, and Data and Automations each mount one StudioInspector, so each pillar is a small, bounded edit."
        },
        {
          "question": "Clicking a card, column or field in an object/view leaf's canvas (the maintainer's 借阅看板) cannot select anything: StudioCanvasPreviewProps, a published face exported from the package, carries no onSelectionChange by contract. Such a leaf keeps its own properties (ObjectListViewInspector) in the slot.",
          "options": [
            "A: a separate card adds an optional selection channel to StudioCanvasPreviewProps (Clause-② yes)",
            "B: accept view-level properties only"
          ],
          "recommendation": "A, because the card's own example (a kanban card selected) needs it. It changes a published prop, so it is outside this Clause-② no claim."
        },
        {
          "question": "The 'N 项待确认' count has no source in objectui: the only signal is the boolean usePlanApprovalPending (objectui#11666). The strip and the segment show a marker ('方案待确认') instead of a number, which follows the brief's H5 fallback. Keep it until objectstack-ai/cloud#2924's payload supplies a count?",
          "options": [
            "A: keep the boolean marker now; the count lands with item 4/5",
            "B: hide the marker until a count exists"
          ],
          "recommendation": "A, because it is a real, already-published signal. A count needs cloud#2924's draft provenance."
        }
      ],
      "out_of_scope_findings": [
        "class: none (observation) · ChatDockLauncher (packages/app-shell/src/layout/ChatDock.tsx) has no shipped host after this move (the console retired it in P3b; Studio was its last). Retiring it would orphan the language-pack key console.ai.dock.open (Clause-② yes), which this claim rules out, so it stays with a comment saying no surface mounts it. ChatDockPanel's children override and useChatDockState's persistWidthKey option likewise lost their only consumer. · carrier: Acceptance notes · dedupe words: ChatDockLauncher zero consumer, console.ai.dock.open",
        "class: none (observation) · packages/app-shell/src/views/ObjectView.tsx:1360 has a doc comment naming useIsWideViewport, which this change retired; comment only, outside the surface · carrier: Acceptance notes · dedupe words: useIsWideViewport stale comment",
        "class: none (observation, not a regression) · at 1010 px the Interfaces item header crushes the title (only the kind chip shows, and the Design/Run toggle clips) because the canvas column is about 470 px; before, with the 340 px dock, it was narrower still (evidence before-copilot-1010-dashboard.png vs after-copilot-1010-dashboard.png) · carrier: Acceptance notes · dedupe words: Studio item header 1010 truncation",
        "class: none (observation) · after Esc, the clicked dashboard widget keeps a blue ring (focus, not selection: the slot already shows the dashboard's own properties); live reading after-copilot-1010-esc.png · carrier: Acceptance notes · dedupe words: dashboard widget focus ring after deselect"
      ]
    }

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

    The seat's answers:


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed (partial) · domain:ui seat 1 · session_011K9g23W67dy2zwnyzaoB6o · 2026-10-17T06:48Z

    • Merged: PR feat(app-shell): Studio right slot shows the properties or the copilot (objectui#12725, part) #12863 landed through the merge queue as main 34354a4b6d, with one parent, 1aa622a. 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 024d446 to the reviewed head bd0e3d5, changed line for changed line in each of the 28 files (+1644/−915).
    • Positive control at the merge commit: packages/app-shell/src/views/studio-design/StudioRightSlot.tsx exists, and the pillar labels in StudioDesignSurface.tsx read lg:not-sr-only.
    • Landed here: items 1, 2 and 6 of the Target, and the canvas half of item 3. The PR carried Part of #12725, so the card stays open.

    Release: session_011K9g23W67dy2zwnyzaoB6o (seat domain:ui#1, account os-tesla) releases claim 6229552663. Cause: a partial landing. Destination: pm:queue, assignee cleared, for the remainder below. Re-claim from the queue; a claim on the remainder starts from main.

    The remainder of #12725:

    1. Item 3, the other pillars. Properties follow the selection on Data, Automations and Access too. Each pillar claims the right slot through the seam PR feat(app-shell): Studio right slot shows the properties or the copilot (objectui#12725, part) #12863 added (useStudioRightSlot / claimProps plus a portal target) instead of its own aside. Clause-②: no; no external dependency.
    2. Item 2, inside an object or view leaf. Selecting a kanban card, a column or a field in the canvas needs an optional selection channel on the published StudioCanvasPreviewProps. That is Clause-②: yes and owes one CONTRACT_REVIEW_TIER review.
    3. Item 3, the copilot's marks: the 草稿 chip and the 来源 line on a setting the copilot changed. They need the copilot's draft provenance per field.
    4. Item 4, change card v2, and item 5, the 变更 badge counting the copilot's drafts as they land. Both need objectstack-ai/cloud#2924's payload. Until then the strip carries the boolean plan-pending marker (objectui#11666), not a count.

    Recorded, not filed (the PR's Acceptance notes):

    • ChatDockLauncher has no shipped host;
    • a stale useIsWideViewport comment in ObjectView.tsx;
    • the 1010 px item-header truncation, not a regression;
    • the focus ring after Esc.

    The cloud session is archived.


    Generated by Claude Code

  6. 65 remaining items

  7. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #13100 @ 3667f86c72f12af8e4b0e31d1de5d2df183aa3e2 · domain:ui seat 2 (session_01XVp19E1MYUTFM3dnkwz8gB) · Part of #12725

    • Contract review: PASS, 6280220194.
      • The reader is exactly the engine's keep rule (objectstack 2ec6827962): longest prefix, [] governs all, absent means not recorded. DraftChange is derived from the spec's GetMetaItemResponse.
      • The surface option is 'studio' | 'api', sent once, with copilot unsendable at the type level, and Omitted on delete.
      • All 15 Studio draft saves under views/studio-design/** carry surface: 'studio' (census on the head).
      • The layered read is added only when the draft carries a copilot entry. Marks are drawn only for by: 'copilot', with the time computed from at.
      • The three ablations distinguish.
    • Deviation (1), "an entry under the key marks it": accepted. The review verified it against the engine's mergeDraftChanges, which drops every entry at or under a changed path, so the feared mis-mark cannot occur. Governing-only would leave the commonest copilot edit (one property of a published field) unmarked. The spec pointer 6254786917 reads the same way.
    • Deviations (2)–(3) accepted. Ruling 1 is confirmed on source by pin ancestry; the live read is owed at the first staging copilot draft. The element marks render as a chip list, because the inline rows live in metadata-admin/**.
    • Changeset: @object-ui/data-objectstack minor, @object-ui/app-shell minor. Clause-②: yes.
    • CI: all 36 check-runs completed on the head, 33 passed and 3 skipped.
    • Path fork: no governed path, 1177 changed lines. Seat landing.
    • Findings, all on this card's remainder (named in the release after the merge):
      • the Permissions pillar's draft save (PermissionMatrixEditPage, views/metadata-admin/PermissionMatrixEditor.tsx) sends no surface. It should state 'studio' only under the Studio host (embedded + packageId), because the same component serves metadata-admin;
      • the README paragraph AGENTS.md Add automated testing infrastructure and CI/CD workflows #2 owes: @object-ui/data-objectstack's getDraft plus the three readers, and the surface save option;
      • inline element marks in the field-multi / FieldsListEditor rows (metadata-admin widgets);
      • Acceptance notes: the layered read fires on any copilot entry, not only on array settings, which is within the claim's wording (a one-line tightening is optional).

    Next: ready + auto-merge; landing is verified by content on main, then the card is released to pm:queue with the remainder.


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed (partial) · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB

    • Merged: PR feat(data-objectstack,app-shell): mark the copilot's drafted settings in Studio's properties, from draftChanges (objectui#12725) #13100 through the merge queue as main 3bcf314e79 (Part of #12725).
    • Verified by content: 20 of the 21 files have the same blob at 3bcf314e79 as at the accepted head 3667f86c72. The 21st, metadata-admin/i18n.ts, also carries objectui#13096 (633ef99a3f), which landed on main first. Its sorted changed lines from merge-base to head equal those of the merge commit against its first parent, so the PR's hunks landed exactly. The merge message carries no model identifier.
    • Landed:
      • @object-ui/data-objectstack reads draftChanges (readDraftChanges, governingDraftChange, draftChangesUnder) and sends ?surface=studio on Studio's draft saves (all 15 under views/studio-design/**);
      • the Data pillar's field rail and ObjectListViewInspector draw the 草稿 chip and 「由 AI 副驾在 N 分钟前作为草稿加入」 for the copilot's drafted settings, and mark the array elements the copilot added.

    Release: session_01XVp19E1MYUTFM3dnkwz8gB (seat domain:ui#2, account baozhoutao) releases claim 6279105929. Cause: a partial landing. Destination: pm:queue, assignee cleared. Re-claim from the queue; a claim on the remainder starts from main.

    The remainder of #12725:

    1. The Permissions pillar's draft save (PermissionMatrixEditPage, views/metadata-admin/PermissionMatrixEditor.tsx) sends no surface, so a person's permission edit in Studio is recorded as api. Send 'studio' only under the Studio host (embedded + packageId), because the same component serves metadata-admin.
    2. Docs (AGENTS.md Add automated testing infrastructure and CI/CD workflows #2): a @object-ui/data-objectstack README paragraph covering getDraft plus the three draftChanges readers, and the surface save option.
    3. Inline element marks in the field-multi / FieldsListEditor rows (metadata-admin widgets). Today the marks render as a chip list under the widget.
    4. Live reading: the first real copilot draft on staging, to confirm the copilot's by: 'copilot' stamp reaches the marks. Cloud's writers pass surface: 'copilot' ([PM seat] repo:cloud · seat 2 — ⏳ vacant objectstack#24145).

    Optional: tighten the layered read to fire only when a copilot entry is on an array setting.


    Generated by Claude Code

  9. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 14 · a partial claim, Part of #12725, the remainder in release 6280467303, items 1–3 (priority:p2). Item 4, the live staging reading, is not reachable from this seat and stays on the card.
    Session: session_01XVp19E1MYUTFM3dnkwz8gB
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12725-draft-marks-rest
    Worktree: objectui-issue-12725e
    Domain: domain:ui
    Seat: domain:ui#2
    File surface:

    • packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx: its draft save sends surface: 'studio' only under the Studio host (embedded + packageId). Under metadata-admin it sends none.
    • packages/data-objectstack/README.md: one paragraph covering getDraft plus readDraftChanges / governingDraftChange / draftChangesUnder, and the surface save option.
    • The field-multi / FieldsListEditor widget rows under views/metadata-admin/**, and the ObjectListViewInspector / Data rail call sites that feed them: the copilot element mark drawn inline in the row, replacing the chip list under the widget.
    • Tests beside them.
    • One .changeset/12725-draft-marks-rest.md.

    Stop on breach; explain in the report.
    Container & model: S, mode:subagent, model: opus (default tier; no path-derived mandate)
    Clause-②: no, unless a widget's exported prop changes; the report states which (a README paragraph and internal call sites)
    Responsibility: n/a — a ruled design item (the remainder of the maintainer's 「按「右栏二选一」定稿」)
    Thread-read: 6280467303
    Serial constraints cleared: objectui#12725's PR #13100 (3bcf314) landed. The in-flight objectui#13097 touches AppContent.tsx / nav gates only. No open objectui PR touches these files (read at 00:34Z).
    Claimed at: 2026-10-20T00:34Z


    Generated by Claude Code

  10. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 12725,
    "status": "done",
    "branch": "claude/issue-12725-draft-marks-rest",
    "pr": "#13106",
    "session": "session_01XVp19E1MYUTFM3dnkwz8gB",
    "premise_still_valid": true,
    "summary": "Items 1-3 of the remainder landed as draft PR #13106 (Part of #12725; item 4, the live staging reading, stays on the card). (1) PermissionMatrixEditPage's package-draft save adds surface:'studio' only when packageId and embedded are both set, i.e. Studio's Access pillar; metadata-admin mounts it with type+name only and states no surface. (2) data-objectstack README gains one paragraph: getDraft's envelope, extractDraftBody, readDraftChanges / governingDraftChange / draftChangesUnder, and the surface save option. (3) field-multi and FieldsListEditor/FieldListRow take an optional copilotAdded set and draw the copilot Draft chip inside each marked row; ObjectListViewInspector passes the set instead of the DraftElementList chip list, which had no other caller and was removed. Optional item 4 (tighter layered read) left as it is: ancestor paths and the record-shaped config prefix make it more than one condition.",
    "tests": "Under os-verify-lock, vitest --maxWorkers=1. New pins: PermissionMatrixEditor.saveSurface-12725.test.tsx (real AccessPillar and real MetadataResourceEditPage over a real MetadataClient; Studio leg getAll('surface') == ['studio'], metadata-admin leg == []) and previews/copilotAddedRowMark-12725.test.tsx (both widgets: mark in marked rows, none in published rows; with no prop, markup equals markup for a set marking nothing it holds). Re-pointed: ObjectListViewInspector.copilotMarks-12725 (chip list moved into the widget rows, so the pins read in-row chips by data-draft-of in list-view-kanban-fields / list-view-columns, plus a row-placement assert) and PermissionMatrixEditor.layersUnsaved-11799 (exact query now ends in &surface=studio because it mounts packageId+embedded). Family: 71 files naming or importing the touched modules: first run 1 failed (that 11799 pin), 754 passed; after the update it passed (6/6). 9 more AccessPillar/PermissionMatrixEditPage files: 48/48 passed. At final head 233c059: 5 new or edited files, 29/29 passed. Closure build @object-ui/app-shell^... exit 0. app-shell type-check (tsc --noEmit && tsc -p tsconfig.test.json, which types the tests) exit 0 at 233c059, after fixing a missing conditionScope in the new widget test's context. data-objectstack type-check exit 0. Whole package dirs app-shell and data-objectstack are declared to CI. Ablation, through objectstack scripts/ablation-replace.mjs in wrap mode (anchor 1 to 0, blob changed; restore blob == HEAD, git diff HEAD empty), at 16e61a3: (1) surface:'studio' unconditional: metadata-admin leg red, 1 failed / 1 passed, restored 3694a08e82af; (2a) field-multi row mark dropped: 3 failed / 8 passed, restored 65bf9276b19b; (2b) FieldListRow row mark dropped: 2 failed / 9 passed, restored 0f892bab3c4b. No build/dist step was needed: the tests import src by relative path.",
    "mcp_calls": "0",
    "api_writes": "2 relay strokes (POST /repos/objectstack-ai/objectstack/dispatches, each executed as objectstack-fleet[bot]): pr_create = POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos//issues/13106/assignees [baozhoutao]; comment = POST /repos//issues/12725/comments (this report). Plus git pushes of the branch (not REST).",
    "gates": "at 233c059 — exit 0: check:phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, new-line-citations; check-hand-rolled-comment-mask 0; check-changeset-fixed 0; check-changeset-presence 0; check:spec-floors 1 (15 findings, all [no-artifact], 0 others: recorded, not fixed); eslint --no-inline-config over the 10 changed .ts/.tsx files (JSON format, 10 files): exit 0, 0 errors, 73 warnings, none on an added line; the config is not type-aware, so the narrowing cannot move an untouched file's verdict; governed-queue-guard --test over the 12 paths: NOT GOVERNED. CI: in_progress at report time.",
    "files_changed": [
    ".changeset/12725-draft-marks-rest.md",
    "packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx",
    "packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.saveSurface-12725.test.tsx",
    "packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.layersUnsaved-11799.test.tsx",
    "packages/app-shell/src/views/metadata-admin/widgets.tsx",
    "packages/app-shell/src/views/metadata-admin/previews/FieldsListEditor.tsx",
    "packages/app-shell/src/views/metadata-admin/previews/ViewColumnPanes.tsx",
    "packages/app-shell/src/views/metadata-admin/previews/copilotAddedRowMark-12725.test.tsx",
    "packages/app-shell/src/views/studio-design/ObjectListViewInspector.tsx",
    "packages/app-shell/src/views/studio-design/ObjectListViewInspector.copilotMarks-12725.test.tsx",
    "packages/app-shell/src/views/studio-design/StudioDraftMark.tsx",
    "packages/data-objectstack/README.md"
    ],
    "deviations": [
    "File surface: StudioDraftMark.tsx is outside the claim's literal list. The edit there deletes DraftElementList, which ruling 3 leaves with no caller, and widens DraftChip's of-prop doc. I made the edit rather than stopping because the chip list being replaced lives in that file; named in the PR's Acceptance notes.",
    "Lock vs gates conflict in the order: the Lock section forbids whole-package-directory runs, while the Gates section asks for each touched package's dir under the lock. I followed the Lock section: families only, both full dirs declared to CI.",
    "The changeset is app-shell: patch, because app-shell already carries a pending minor from 12725-draft-marks.md. data-objectstack has a README change only, which ships no source, so it is not in the changeset (check-changeset-presence green).",
    "Clause-②: no. copilotAdded sits on WidgetProps / FieldsListEditorProps / FieldListRow, and none of them is exported from @object-ui/app-shell (exports '.' only; src/index.ts re-exports none of them and has no export *)."
    ],
    "open_questions": [],
    "out_of_scope_findings": []
    }


    Generated by Claude Code

  11. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #13106 @ 233c059e1ce8001b634d9a2b3a21e573d02f1b7b · domain:ui seat 2 (session_01XVp19E1MYUTFM3dnkwz8gB) · Part of #12725

    • Clause-②: no. copilotAdded sits on WidgetProps / FieldsListEditorProps / FieldListRow, none of which is on @object-ui/app-shell's entry (checked). The README is docs. No contract review is owed, and the seat read the diff.
    • Seat review against the remainder items 1–3 (release 6280467303, claim 6280491887):
    • Pins:
      • both hosts are mounted for real over a real MetadataClient: Studio sends ['studio'] once, metadata-admin sends [];
      • the row marks are pinned in both widgets;
      • two existing pins were re-pointed with reasons;
      • three ablations, each restore proven by blob.
    • Deviation accepted: StudioDraftMark.tsx (deleting the now-orphan DraftElementList) is in the same Studio family as the claim. Optional item 4 (a tighter layered read) was left as it is; the reason is given in the report.
    • Changeset: @object-ui/app-shell patch (the README ships no source).
    • CI: all 36 check-runs completed on the head, 33 passed and 3 skipped.
    • Path fork: no governed path, 376 changed lines. Seat landing.
    • Findings: none new. Item 4 of the remainder (the live staging reading of a real copilot draft) stays on the card.

    Next: ready + auto-merge; landing is verified by content on main.


    Generated by Claude Code

  12. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Maintainer-action: on staging, have the Studio copilot draft a change to an object's field (and one kanban card field). Confirm that the field rail and the view properties show the 草稿 chip with 「由 AI 副驾在 N 分钟前作为草稿加入」, then close this card. If no mark shows, re-open it to pm:queue with what the draft read answered.

    Landed (partial, last code round) · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB

    Release: session_01XVp19E1MYUTFM3dnkwz8gB (seat domain:ui#2, account baozhoutao) releases claim 6280491887. Cause: code complete; one action outside GitHub remains. Destination: pm:awaiting-maintainer, assignee cleared.


    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

No one assigned

    Labels

    area:studioChanging a running app without code — authoring, publish, docs and the portaldomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpm:awaiting-maintainerpriority:p2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions