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 flow item header at 1024 px: the Read-only chip folds before it is cut to "Rea" #12707
Walked on objectui main efa9cb4fa at 1024 px, Studio › HotCRM › Automations › Enroll Members in Campaign: the item header's tab row reads "Canvas · Variables · Runs · Problems 1 · Debug · [Rea" — the Read-only chip at the row's end is clipped to three letters. objectui#12611 kept the title and the tab labels readable at this width; the chip in the tab row was not in its scope.
Target
The chip in a tab row folds to its icon with a tooltip when the row cannot hold it, and is never clipped mid-word; the tab labels keep nowrap and the row scrolls horizontally as objectui#12611 set.
The same rule for the item headers of the Data and Interfaces pillars (the Unpublished draft chip).
File surface
packages/app-shell/src/views/metadata-admin/ (the pillar item header and its chips), tests beside.
Acceptance
Tests: the chip renders its icon-only form at a 560 px tab row; full form at 800 px.
Screenshot of the flow item header at 1024 px.
pnpm --filter @object-ui/app-shell test green.
Evidence
Screenshots on the temporary branch claude/console-home-login-design-20261016 of objectstack-ai/objectui (commit 0f4e3f4ee, never merged): r4-studio-automations-rail.jpg.
Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff from the 2026-10-16 fourth review: objectui main efa9cb4fa, HotCRM 4f82b815 on platform 18.0.0-next.2, the vite console on :5180 against objectstack dev on :4001, the maintainer's browser pane at 1024 × 768 (dark, en). The maintainer asked for every finding to be filed on the repository it belongs to, verbatim: 「全部立卡,平台问题到 objectui,审计日志核查到 objectstack,HotCRM 转化流程到 hotcrm。」
Claim: PM loop round 3 (priority:p2; filed by the epic PM session from the 2026-10-16 fourth review, on the maintainer's 「全部立卡,平台问题到 objectui…」)
Session: session_01SJn1GEkrbbBQkhGC26wEDw
Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-12707-studio-readonly-chip-fold
Worktree: objectui-issue-12707 (in the cloud session's own container)
Domain: domain:ui
Seat: domain:ui#4
File surface: packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (StudioReadOnlyLink and the item tab rows that place it, about :524 and :7401–7432), packages/app-shell/src/views/studio-design/StudioItemHeader.tsx (only if the fold belongs in the shared header), tests beside them, one .changeset/12707-*.md. The card names views/metadata-admin/; measured on main80863ad, the pillar item header and its chips live under views/studio-design/ (stop on breach; explain in the report)
Container & model: M, mode:cloud, model: opus (cloud on the maintainer's stance 「可以的话,ui 后续开发尽量用云 session,并且要求截图给我看」; lane scope on 「你也可以接ui车道的卡」; batch 3 on 「当前任务处理完,后续并发降到3」, this session's chat, 2026-10-16)
Clause-②: no
Clause-② reason: measured on main80863ad: StudioDesignSurface is on @object-ui/app-shell's entry, but StudioReadOnlyLink and the tab rows are internal, and the fold needs no prop. The tooltip reuses the existing engine.studio.pkg.readonly and engine.studio.pkg.readonlyHint strings. A change that has to add a prop or a published key stops and is reported under deviations, and the seat amends this claim.
Responsibility: n/a — a measured Studio header layout defect
Thread-read: none
Serial constraints cleared: PR #12766 (objectui#12688, another seat) edits StudioDesignSurface.tsx's rail labels, not the item tab rows; whichever lands second merges main. objectui#12611, which set the tab row's nowrap and horizontal scroll and the status chip's icon-first fold, has landed.
Claim: PM loop round 3 · amended (branch: the same tree re-committed without a model-named trailer) (priority:p2; filed by the epic PM session from the 2026-10-16 fourth review, on the maintainer's 「全部立卡,平台问题到 objectui…」)
Session: session_01SJn1GEkrbbBQkhGC26wEDw
Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-12707-studio-readonly-chip-fold-v2 (amended from claude/issue-12707-studio-readonly-chip-fold: the same tree as its head 78306de, re-committed as one commit with the model-free trailer pair objectui AGENTS.md requires, because its three commits carried a trailer naming the model and the queue's squash keeps co-author trailers. The original branch and claude/issue-12707-evidence are left untouched; no history is rewritten.)
Worktree: objectui-issue-12707 (in the cloud session's own container)
Domain: domain:ui
Seat: domain:ui#4
File surface: packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (StudioReadOnlyLink and the item tab rows that place it, about :524 and :7401–7432), packages/app-shell/src/views/studio-design/StudioItemHeader.tsx (only if the fold belongs in the shared header), tests beside them, one .changeset/12707-*.md. The card names views/metadata-admin/; measured on main80863ad, the pillar item header and its chips live under views/studio-design/ (stop on breach; explain in the report)
Container & model: M, mode:cloud, model: opus (cloud on the maintainer's stance 「可以的话,ui 后续开发尽量用云 session,并且要求截图给我看」; lane scope on 「你也可以接ui车道的卡」; batch 3 on 「当前任务处理完,后续并发降到3」, this session's chat, 2026-10-16)
Clause-②: no
Clause-② reason: measured on main80863ad: StudioDesignSurface is on @object-ui/app-shell's entry, but StudioReadOnlyLink and the tab rows are internal, and the fold needs no prop. The tooltip reuses the existing engine.studio.pkg.readonly and engine.studio.pkg.readonlyHint strings. A change that has to add a prop or a published key stops and is reported under deviations, and the seat amends this claim.
Responsibility: n/a — a measured Studio header layout defect
Thread-read: 6222835888
Serial constraints cleared: PR #12766 (objectui#12688, another seat) landed as 41c1d9e; this branch merges main4857cd2 cleanly (git merge-tree). objectui#12611, which set the tab row's nowrap and horizontal scroll and the status chip's icon-first fold, has landed.
{
"issue": 12707,
"status": "done",
"branch": "claude/issue-12707-studio-readonly-chip-fold",
"pr": 12792,
"session": "session_01Umh5XoHZFaBP7A8Kc2g2Jc (dispatched by seat domain:ui#4, session_01SJn1GEkrbbBQkhGC26wEDw)",
"premise_still_valid": true,
"summary": "Premise measured on 80863ad and confirmed. At 1024 px the flow item's tab row is 436 px wide. The full read-only link there is 254 px and the row's scrollWidth is 636, so only 54 px of the link shows: the icon and 'Rea'. The link was not squeezed; it overflowed the row's sideways scroll. The fold is built once. StudioItemHeader's tab row now tells its children which row they sit in (a React context, no new prop), and a new hook, useStudioTabRowFold, measures that row: the tabs' right edge plus the gap, the slot padding and the link's full width, against the row's clientWidth. It re-measures on every render and from a ResizeObserver. StudioReadOnlyLink, which is not exported, uses the hook. When folded it draws a 28 px glyph-only chip; its label stays in the DOM as sr-only text (the accessible name), and its title and href are unchanged. So both tab-row placements fold: Automations, and Access through PermissionMatrixEditor's chrome.chips, which needed no edit to that file. The title-row placements (Data, Interfaces) never fold, because they are outside a tab row. Target 2 was measured first and already holds, so nothing changed there. In a writable package's draft object at a 560 px row, the Unpublished draft chip is 122 px, whole, and inside the row (objectui#12611).",
"tests": "All on HEAD 78306de. New file StudioDesignSurface.readOnlyChipFold-12707.test.tsx: 7/7 passed (`pnpm exec vitest run --maxWorkers=2 packages/app-shell/src/views/studio-design/StudioDesignSurface.readOnlyChipFold-12707.test.tsx`, plus StudioItemHeader.narrowWidth-12611: 2 files, 16 passed). It runs the REAL AutomationsPillar (readOnly, a flow open) with the row geometry stubbed. At 800 px the link is whole. At 560 px: data-folded is set, the label is sr-only, the accessible name is 'Read-only · Customize with an overlay', the title is the readonlyHint sentence, and href is /apps/setup/metadata?package=PKG. Resizing the row folds and unfolds the link. Tabs keep whitespace-nowrap and shrink-0, and the row keeps overflow-x-auto. CONTROLs: the same chip in a title-row actions slot never folds; the Unpublished draft chip keeps shrink-0, whitespace-nowrap and its #12611 fold class. Neighbour pins, 8 files, 53 passed (12611 narrowWidth and narrowChip, 12524 statusPlace, 12453 readOnlyPosture, 12454 tabs, 11124 automationsReadOnly, 11781 readOnlyWording, 12456 accessTabs). Ablations: each mutation was written to disk and checked with grep (anchor-left 0, injected 1), run under a trap that restores with `git checkout HEAD --` and compares the hash against HEAD; after each, `git diff HEAD` was empty. (1) The fold never fires (`setFolded(false && …)`): 3 failed, 4 passed (560, follows-the-row, tab-row probe). Re-run on the final hook: same. (2) The label is never sr-only: 1 failed (560). (3) whitespace-nowrap removed from STUDIO_TAB: 1 failed (tab labels). (4) The tab-row context provider removed: 3 failed. Re-run on the final hook: same. No dist build in this path: the tests import src through relative paths. The CONTROLs were not ablated.",
"gates": "All on 78306de, exit codes captured before any pipe. `pnpm --filter @object-ui/app-shell test`, full, run once with nothing else touching the tree (started detached, waited on with `tail --pid`): EXIT=0, Test Files 1484 passed | 1 skipped (1485), Tests 13945 passed | 9 skipped (13954), Duration 2508s. An earlier full run was stopped by its own PID after the hook was edited mid-run; it was not counted. `pnpm --filter @object-ui/app-shell type-check`: EXIT=0, after building the `@object-ui/app-shell^...` closure (EXIT=0). `pnpm --filter @object-ui/app-shell build`: EXIT=0 ('dist completeness: 1 package(s) complete'). `pnpm exec eslint` on the 3 touched source and test files: EXIT=0, 0 errors. Warnings went from 13 on main to 14: the one new warning is react-refresh only-export-components on the exported hook in StudioItemHeader.tsx, which only affects dev hot reload. `pnpm check:i18n-keys`: EXIT=0. `pnpm check:i18n-drift`: EXIT=0 ('No en value changed'). `node scripts/check-changeset-presence.mjs`: EXIT=0 (1 changeset). `pnpm check:new-line-citations`: EXIT=0 ('0 new citation(s)'). Not run: check:i18n-designer-parity (no keys added) and check:i18n-dead-keys (no keys retired). scripts/check-nul-bytes.mjs does not exist in objectui (MODULE_NOT_FOUND, not a gate result), so I ran the contract's own scan instead: `grep -naP` for control bytes over the 4 changed files found nothing (EXIT=1). objectui has no dispatch-gates.mjs, so there is no `--ran` check here. CI check-runs: none yet, because no PR is open. `git merge-tree HEAD origin/main` (4857cd2, which now includes #12766): clean, so no merge was made.",
"mcp_calls": "4 GitHub MCP calls, all reads: mcp__github__issue_read ×4 (get #12707, get_comments #12707, get #12611, get #12453). Plus 2 claude-code-remote add_repo calls (objectstack and hotcrm, access read; both answered read_available with nothing attached). No write tool was used.",
"api_writes": "0 REST writes. Git pushes only: objectui claude/issue-12707-studio-readonly-chip-fold (the empty branch first, then 14ce373, b661043, 78306de) and objectui claude/issue-12707-evidence (68c14ae, 6012be8). Local-only calls to my own backend on :4417: POST /api/v1/packages created com.acme.probe, and Studio 'Save as draft' created two draft objects. That database was a --fresh temp DB, deleted when the server stopped.",
"open_questions": [
{
"question": "Ruling wording: the folded chip's tooltip and accessible name 'reuse engine.studio.pkg.readonly and engine.studio.pkg.readonlyHint'. As built, the accessible name in both forms is the link's own existing label, engine.studio.pkg.readonlyLink ('Read-only · Customize with an overlay'). The tooltip is the placement's existing title: engine.studio.pkg.readonlyHint on Automations, access.bannerTitleReadOnly on Access.",
"options": [
"A — keep as built. No new key. The name stays the same in both forms and still says where the link goes. It is the same text the 12453 pins already read through textContent.",
"B — when folded, set aria-label to engine.studio.pkg.readonly. That follows the letter of the ruling, but the name then changes between the two forms and drops the 'Customize with an overlay' purpose."
],
"recommendation": "A. Actual business need: the 12453 posture pins already read this label. Long-term soundness: one name across both forms. Preventing AI mistakes: no form-dependent aria-label branch to drift. Startup scope: zero new keys, as the ruling intends."
},
{
"question": "Dispatch versus os-dev.md: the contract file says to open the draft PR and post the os-dev-report comment through the scripts/pm relay. The dispatch says that relay is refused (403) in this container, and that the seat opens the PR.",
"options": [
"A — degraded channel as dispatched: git push only, PR body and title in this report, the seat opens the PR and posts the comment."
],
"recommendation": "A. The contract routes GitHub writes through the relay, the relay is unavailable here, and the dispatch names the substitute, so there is no real conflict, only a recorded one. I made no MCP write calls."
}
],
"out_of_scope_findings": [
"class: a · reach: Studio, writable package, Data, new draft object 'Service Territory Assignment 105' (api chip probe_service_territory_assignment_105). At a 560 px header row the title reads 'Service T…' at about 100 px, and it is already truncated at 1024 px (row 736). The api-name chip and the status chip stay whole, so the long api chip takes the title's room. objectui#12611's target says the title truncates last and keeps at least 200 px; that does not hold when the api chip is long. Evidence: https://github.com/objectstack-ai/objectui/blob/6012be82d1f938b683d7f7faaff15990f77d5baa/docs/design/findings/12707/data-draft-object-row560-light.png?raw=true · dedupe words: studio item header title truncates api chip, 200px title minimum, StudioItemHeader long api name · carrier: none, not filed (for the seat to file)"
],
"deviations": [
"Responsibility for the Access tab-row placement: it lives in views/metadata-admin/PermissionMatrixEditor.tsx, which is outside the claim's file surface. It folds through the context the header provides, so that file is untouched. There is no Access-specific test, because the shared rule is pinned through the Automations pillar and through a probe in StudioItemHeader's tab row.",
"A new export, useStudioTabRowFold, from StudioItemHeader.tsx. That module is not re-exported from the @object-ui/app-shell entry, so it adds no prop and no package-entry surface, and Clause-② stays 'no'.",
"The evidence branch claude/issue-12707-evidence was cut from b661043, a feature-branch commit, before the final refactor. It carries one PNG commit and one re-shoot on the final head 78306de. The draft-object 560 px PNG was taken on 14ce373; the status chip code it shows is the same on main and on HEAD.",
"The first evidence commit used `--no-verify`. The repo configures no hooks (core.hooksPath is empty and there is no .husky), so it skipped nothing.",
"To build the worktree I put the shared /home/user/objectui checkout on a detached HEAD at 80863ad, because a local branch of the claim's name with no commits of its own was checked out there and had to be deleted. The feature worktree /home/user/objectui-issue-12707 is kept in case of a rework round; the evidence worktree was removed after its push.",
"While finding the package list I printed the first 40 characters of two localStorage auth keys from my local dev backend (auth-session-user-id and auth-session-token) to my own terminal. They were for a --fresh temp database that has since been deleted, and they are not environment variables."
],
"files_changed": [
"packages/app-shell/src/views/studio-design/StudioItemHeader.tsx",
"packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx",
"packages/app-shell/src/views/studio-design/StudioDesignSurface.readOnlyChipFold-12707.test.tsx",
".changeset/12707-studio-readonly-chip-fold.md"
],
"screenshots": [
"https://github.com/objectstack-ai/objectui/blob/6012be82d1f938b683d7f7faaff15990f77d5baa/docs/design/findings/12707/automations-enroll-1024-light.png?raw=true",
"https://github.com/objectstack-ai/objectui/blob/6012be82d1f938b683d7f7faaff15990f77d5baa/docs/design/findings/12707/automations-enroll-1024-dark.png?raw=true",
"https://github.com/objectstack-ai/objectui/blob/6012be82d1f938b683d7f7faaff15990f77d5baa/docs/design/findings/12707/automations-enroll-1280-light.png?raw=true",
"https://github.com/objectstack-ai/objectui/blob/6012be82d1f938b683d7f7faaff15990f77d5baa/docs/design/findings/12707/data-object-1024-light.png?raw=true",
"https://github.com/objectstack-ai/objectui/blob/6012be82d1f938b683d7f7faaff15990f77d5baa/docs/design/findings/12707/data-draft-object-row560-light.png?raw=true"
],
"line_budget": "n/a",
"pr_title_draft": "fix(app-shell): the Studio read-only link at a tab row's end folds to its icon instead of being cut to \"Rea\" (objectui#12707)",
"pr_body_draft": "(elided here: it is the body of objectstack-ai/objectui#12792, verbatim apart from the test-evidence heading, which names the PR head)"
}
Relayed by seat domain:ui#4 (session_01SJn1GEkrbbBQkhGC26wEDw) from the cloud session's final message (degraded channel: the session pushed and returned pr: null). At the seat's request the session then re-committed the same tree as one commit on claude/issue-12707-studio-readonly-chip-fold-v2 (9dc644c, git diff 78306de 9dc644c empty), because its three commits carried a trailer naming the model; the amended claim is 6224546508. The seat opened #12792 from that branch and set pr above. Open question 1 is ruled A by the seat (as built: the folded chip's accessible name stays the link's existing label; no key added). The out-of-scope finding is filed as #12791 for triage.
the squash carries only the model-free trailer pair
PNG files in the merge's diff
0
the screenshots stay on claude/issue-12707-evidence (6012be8)
State change: the card closed as completed through Fixes #12707, and pm:dispatched is removed in this act. The cloud session session_01Umh5XoHZFaBP7A8Kc2g2Jc is archived. No contract review is owed (Clause-②: no). The ACCEPT of record is 6224591813 (on the PR); the landing note is 6224762878.
The PR was opened from claude/issue-12707-studio-readonly-chip-fold-v2 (9dc644c, one commit with the model-free trailer pair; the same tree as the first branch's 78306de), per the amended claim 6224546508. The dev's out-of-scope finding (a long api-name chip takes the Data title's room) is #12791, for triage.
Activity
objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 3 (
priority:p2; filed by the epic PM session from the 2026-10-16 fourth review, on the maintainer's 「全部立卡,平台问题到 objectui…」)Session:
session_01SJn1GEkrbbBQkhGC26wEDwAccount:
os-sales(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-12707-studio-readonly-chip-foldWorktree:
objectui-issue-12707(in the cloud session's own container)Domain:
domain:uiSeat:
domain:ui#4File surface:
packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx(StudioReadOnlyLinkand the item tab rows that place it, about :524 and :7401–7432),packages/app-shell/src/views/studio-design/StudioItemHeader.tsx(only if the fold belongs in the shared header), tests beside them, one.changeset/12707-*.md. The card namesviews/metadata-admin/; measured onmain80863ad, the pillar item header and its chips live underviews/studio-design/(stop on breach; explain in the report)Container & model:
M,mode:cloud,model: opus(cloud on the maintainer's stance 「可以的话,ui 后续开发尽量用云 session,并且要求截图给我看」; lane scope on 「你也可以接ui车道的卡」; batch 3 on 「当前任务处理完,后续并发降到3」, this session's chat, 2026-10-16)Clause-②: no
Clause-② reason: measured on
main80863ad:StudioDesignSurfaceis on@object-ui/app-shell's entry, butStudioReadOnlyLinkand the tab rows are internal, and the fold needs no prop. The tooltip reuses the existingengine.studio.pkg.readonlyandengine.studio.pkg.readonlyHintstrings. A change that has to add a prop or a published key stops and is reported underdeviations, and the seat amends this claim.Responsibility: n/a — a measured Studio header layout defect
Thread-read: none
Serial constraints cleared: PR #12766 (objectui#12688, another seat) edits
StudioDesignSurface.tsx's rail labels, not the item tab rows; whichever lands second mergesmain. objectui#12611, which set the tab row'snowrapand horizontal scroll and the status chip's icon-first fold, has landed.objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 3 · amended (branch: the same tree re-committed without a model-named trailer) (
priority:p2; filed by the epic PM session from the 2026-10-16 fourth review, on the maintainer's 「全部立卡,平台问题到 objectui…」)Session:
session_01SJn1GEkrbbBQkhGC26wEDwAccount:
os-sales(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-12707-studio-readonly-chip-fold-v2(amended fromclaude/issue-12707-studio-readonly-chip-fold: the same tree as its head78306de, re-committed as one commit with the model-free trailer pair objectui AGENTS.md requires, because its three commits carried a trailer naming the model and the queue's squash keeps co-author trailers. The original branch andclaude/issue-12707-evidenceare left untouched; no history is rewritten.)Worktree:
objectui-issue-12707(in the cloud session's own container)Domain:
domain:uiSeat:
domain:ui#4File surface:
packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx(StudioReadOnlyLinkand the item tab rows that place it, about :524 and :7401–7432),packages/app-shell/src/views/studio-design/StudioItemHeader.tsx(only if the fold belongs in the shared header), tests beside them, one.changeset/12707-*.md. The card namesviews/metadata-admin/; measured onmain80863ad, the pillar item header and its chips live underviews/studio-design/(stop on breach; explain in the report)Container & model:
M,mode:cloud,model: opus(cloud on the maintainer's stance 「可以的话,ui 后续开发尽量用云 session,并且要求截图给我看」; lane scope on 「你也可以接ui车道的卡」; batch 3 on 「当前任务处理完,后续并发降到3」, this session's chat, 2026-10-16)Clause-②: no
Clause-② reason: measured on
main80863ad:StudioDesignSurfaceis on@object-ui/app-shell's entry, butStudioReadOnlyLinkand the tab rows are internal, and the fold needs no prop. The tooltip reuses the existingengine.studio.pkg.readonlyandengine.studio.pkg.readonlyHintstrings. A change that has to add a prop or a published key stops and is reported underdeviations, and the seat amends this claim.Responsibility: n/a — a measured Studio header layout defect
Thread-read: 6222835888
Serial constraints cleared: PR #12766 (objectui#12688, another seat) landed as
41c1d9e; this branch mergesmain4857cd2cleanly (git merge-tree). objectui#12611, which set the tab row'snowrapand horizontal scroll and the status chip's icon-first fold, has landed.objectstack-fleet commentedon Oct 16, 2026
os-dev-report
{ "issue": 12707, "status": "done", "branch": "claude/issue-12707-studio-readonly-chip-fold", "pr": 12792, "session": "session_01Umh5XoHZFaBP7A8Kc2g2Jc (dispatched by seat domain:ui#4, session_01SJn1GEkrbbBQkhGC26wEDw)", "premise_still_valid": true, "summary": "Premise measured on 80863ad and confirmed. At 1024 px the flow item's tab row is 436 px wide. The full read-only link there is 254 px and the row's scrollWidth is 636, so only 54 px of the link shows: the icon and 'Rea'. The link was not squeezed; it overflowed the row's sideways scroll. The fold is built once. StudioItemHeader's tab row now tells its children which row they sit in (a React context, no new prop), and a new hook, useStudioTabRowFold, measures that row: the tabs' right edge plus the gap, the slot padding and the link's full width, against the row's clientWidth. It re-measures on every render and from a ResizeObserver. StudioReadOnlyLink, which is not exported, uses the hook. When folded it draws a 28 px glyph-only chip; its label stays in the DOM as sr-only text (the accessible name), and its title and href are unchanged. So both tab-row placements fold: Automations, and Access through PermissionMatrixEditor's chrome.chips, which needed no edit to that file. The title-row placements (Data, Interfaces) never fold, because they are outside a tab row. Target 2 was measured first and already holds, so nothing changed there. In a writable package's draft object at a 560 px row, the Unpublished draft chip is 122 px, whole, and inside the row (objectui#12611).", "tests": "All on HEAD 78306de. New file StudioDesignSurface.readOnlyChipFold-12707.test.tsx: 7/7 passed (`pnpm exec vitest run --maxWorkers=2 packages/app-shell/src/views/studio-design/StudioDesignSurface.readOnlyChipFold-12707.test.tsx`, plus StudioItemHeader.narrowWidth-12611: 2 files, 16 passed). It runs the REAL AutomationsPillar (readOnly, a flow open) with the row geometry stubbed. At 800 px the link is whole. At 560 px: data-folded is set, the label is sr-only, the accessible name is 'Read-only · Customize with an overlay', the title is the readonlyHint sentence, and href is /apps/setup/metadata?package=PKG. Resizing the row folds and unfolds the link. Tabs keep whitespace-nowrap and shrink-0, and the row keeps overflow-x-auto. CONTROLs: the same chip in a title-row actions slot never folds; the Unpublished draft chip keeps shrink-0, whitespace-nowrap and its #12611 fold class. Neighbour pins, 8 files, 53 passed (12611 narrowWidth and narrowChip, 12524 statusPlace, 12453 readOnlyPosture, 12454 tabs, 11124 automationsReadOnly, 11781 readOnlyWording, 12456 accessTabs). Ablations: each mutation was written to disk and checked with grep (anchor-left 0, injected 1), run under a trap that restores with `git checkout HEAD --` and compares the hash against HEAD; after each, `git diff HEAD` was empty. (1) The fold never fires (`setFolded(false && …)`): 3 failed, 4 passed (560, follows-the-row, tab-row probe). Re-run on the final hook: same. (2) The label is never sr-only: 1 failed (560). (3) whitespace-nowrap removed from STUDIO_TAB: 1 failed (tab labels). (4) The tab-row context provider removed: 3 failed. Re-run on the final hook: same. No dist build in this path: the tests import src through relative paths. The CONTROLs were not ablated.", "gates": "All on 78306de, exit codes captured before any pipe. `pnpm --filter @object-ui/app-shell test`, full, run once with nothing else touching the tree (started detached, waited on with `tail --pid`): EXIT=0, Test Files 1484 passed | 1 skipped (1485), Tests 13945 passed | 9 skipped (13954), Duration 2508s. An earlier full run was stopped by its own PID after the hook was edited mid-run; it was not counted. `pnpm --filter @object-ui/app-shell type-check`: EXIT=0, after building the `@object-ui/app-shell^...` closure (EXIT=0). `pnpm --filter @object-ui/app-shell build`: EXIT=0 ('dist completeness: 1 package(s) complete'). `pnpm exec eslint` on the 3 touched source and test files: EXIT=0, 0 errors. Warnings went from 13 on main to 14: the one new warning is react-refresh only-export-components on the exported hook in StudioItemHeader.tsx, which only affects dev hot reload. `pnpm check:i18n-keys`: EXIT=0. `pnpm check:i18n-drift`: EXIT=0 ('No en value changed'). `node scripts/check-changeset-presence.mjs`: EXIT=0 (1 changeset). `pnpm check:new-line-citations`: EXIT=0 ('0 new citation(s)'). Not run: check:i18n-designer-parity (no keys added) and check:i18n-dead-keys (no keys retired). scripts/check-nul-bytes.mjs does not exist in objectui (MODULE_NOT_FOUND, not a gate result), so I ran the contract's own scan instead: `grep -naP` for control bytes over the 4 changed files found nothing (EXIT=1). objectui has no dispatch-gates.mjs, so there is no `--ran` check here. CI check-runs: none yet, because no PR is open. `git merge-tree HEAD origin/main` (4857cd2, which now includes #12766): clean, so no merge was made.", "mcp_calls": "4 GitHub MCP calls, all reads: mcp__github__issue_read ×4 (get #12707, get_comments #12707, get #12611, get #12453). Plus 2 claude-code-remote add_repo calls (objectstack and hotcrm, access read; both answered read_available with nothing attached). No write tool was used.", "api_writes": "0 REST writes. Git pushes only: objectui claude/issue-12707-studio-readonly-chip-fold (the empty branch first, then 14ce373, b661043, 78306de) and objectui claude/issue-12707-evidence (68c14ae, 6012be8). Local-only calls to my own backend on :4417: POST /api/v1/packages created com.acme.probe, and Studio 'Save as draft' created two draft objects. That database was a --fresh temp DB, deleted when the server stopped.", "open_questions": [ { "question": "Ruling wording: the folded chip's tooltip and accessible name 'reuse engine.studio.pkg.readonly and engine.studio.pkg.readonlyHint'. As built, the accessible name in both forms is the link's own existing label, engine.studio.pkg.readonlyLink ('Read-only · Customize with an overlay'). The tooltip is the placement's existing title: engine.studio.pkg.readonlyHint on Automations, access.bannerTitleReadOnly on Access.", "options": [ "A — keep as built. No new key. The name stays the same in both forms and still says where the link goes. It is the same text the 12453 pins already read through textContent.", "B — when folded, set aria-label to engine.studio.pkg.readonly. That follows the letter of the ruling, but the name then changes between the two forms and drops the 'Customize with an overlay' purpose." ], "recommendation": "A. Actual business need: the 12453 posture pins already read this label. Long-term soundness: one name across both forms. Preventing AI mistakes: no form-dependent aria-label branch to drift. Startup scope: zero new keys, as the ruling intends." }, { "question": "Dispatch versus os-dev.md: the contract file says to open the draft PR and post the os-dev-report comment through the scripts/pm relay. The dispatch says that relay is refused (403) in this container, and that the seat opens the PR.", "options": [ "A — degraded channel as dispatched: git push only, PR body and title in this report, the seat opens the PR and posts the comment." ], "recommendation": "A. The contract routes GitHub writes through the relay, the relay is unavailable here, and the dispatch names the substitute, so there is no real conflict, only a recorded one. I made no MCP write calls." } ], "out_of_scope_findings": [ "class: a · reach: Studio, writable package, Data, new draft object 'Service Territory Assignment 105' (api chip probe_service_territory_assignment_105). At a 560 px header row the title reads 'Service T…' at about 100 px, and it is already truncated at 1024 px (row 736). The api-name chip and the status chip stay whole, so the long api chip takes the title's room. objectui#12611's target says the title truncates last and keeps at least 200 px; that does not hold when the api chip is long. Evidence: https://github.com/objectstack-ai/objectui/blob/6012be82d1f938b683d7f7faaff15990f77d5baa/docs/design/findings/12707/data-draft-object-row560-light.png?raw=true · dedupe words: studio item header title truncates api chip, 200px title minimum, StudioItemHeader long api name · carrier: none, not filed (for the seat to file)" ], "deviations": [ "Responsibility for the Access tab-row placement: it lives in views/metadata-admin/PermissionMatrixEditor.tsx, which is outside the claim's file surface. It folds through the context the header provides, so that file is untouched. There is no Access-specific test, because the shared rule is pinned through the Automations pillar and through a probe in StudioItemHeader's tab row.", "A new export, useStudioTabRowFold, from StudioItemHeader.tsx. That module is not re-exported from the @object-ui/app-shell entry, so it adds no prop and no package-entry surface, and Clause-② stays 'no'.", "The evidence branch claude/issue-12707-evidence was cut from b661043, a feature-branch commit, before the final refactor. It carries one PNG commit and one re-shoot on the final head 78306de. The draft-object 560 px PNG was taken on 14ce373; the status chip code it shows is the same on main and on HEAD.", "The first evidence commit used `--no-verify`. The repo configures no hooks (core.hooksPath is empty and there is no .husky), so it skipped nothing.", "To build the worktree I put the shared /home/user/objectui checkout on a detached HEAD at 80863ad, because a local branch of the claim's name with no commits of its own was checked out there and had to be deleted. The feature worktree /home/user/objectui-issue-12707 is kept in case of a rework round; the evidence worktree was removed after its push.", "While finding the package list I printed the first 40 characters of two localStorage auth keys from my local dev backend (auth-session-user-id and auth-session-token) to my own terminal. They were for a --fresh temp database that has since been deleted, and they are not environment variables." ], "files_changed": [ "packages/app-shell/src/views/studio-design/StudioItemHeader.tsx", "packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx", "packages/app-shell/src/views/studio-design/StudioDesignSurface.readOnlyChipFold-12707.test.tsx", ".changeset/12707-studio-readonly-chip-fold.md" ], "screenshots": [ "https://github.com/objectstack-ai/objectui/blob/6012be82d1f938b683d7f7faaff15990f77d5baa/docs/design/findings/12707/automations-enroll-1024-light.png?raw=true", "https://github.com/objectstack-ai/objectui/blob/6012be82d1f938b683d7f7faaff15990f77d5baa/docs/design/findings/12707/automations-enroll-1024-dark.png?raw=true", "https://github.com/objectstack-ai/objectui/blob/6012be82d1f938b683d7f7faaff15990f77d5baa/docs/design/findings/12707/automations-enroll-1280-light.png?raw=true", "https://github.com/objectstack-ai/objectui/blob/6012be82d1f938b683d7f7faaff15990f77d5baa/docs/design/findings/12707/data-object-1024-light.png?raw=true", "https://github.com/objectstack-ai/objectui/blob/6012be82d1f938b683d7f7faaff15990f77d5baa/docs/design/findings/12707/data-draft-object-row560-light.png?raw=true" ], "line_budget": "n/a", "pr_title_draft": "fix(app-shell): the Studio read-only link at a tab row's end folds to its icon instead of being cut to \"Rea\" (objectui#12707)", "pr_body_draft": "(elided here: it is the body of objectstack-ai/objectui#12792, verbatim apart from the test-evidence heading, which names the PR head)" }Relayed by seat
domain:ui#4(session_01SJn1GEkrbbBQkhGC26wEDw) from the cloud session's final message (degraded channel: the session pushed and returnedpr: null). At the seat's request the session then re-committed the same tree as one commit onclaude/issue-12707-studio-readonly-chip-fold-v2(9dc644c,git diff 78306de 9dc644cempty), because its three commits carried a trailer naming the model; the amended claim is6224546508. The seat opened #12792 from that branch and setprabove. Open question 1 is ruled A by the seat (as built: the folded chip's accessible name stays the link's existing label; no key added). The out-of-scope finding is filed as #12791 for triage.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Landed · PR #12792 merged as
2368d7aonmain· read 2026-10-16T21:24Zorigin/main2368d7aexport function useStudioTabRowFoldinpackages/app-shell/src/views/studio-design/StudioItemHeader.tsxStudioTabRowContextResizeObserverin the hookuseStudioTabRowFold(ref, label)/data-folded/sr-onlylabel inStudioReadOnlyLink(StudioDesignSurface.tsx)StudioDesignSurface.readOnlyChipFold-12707.test.tsx.changeset/12707-studio-readonly-chip-fold.mdclaude/issue-12707-evidence(6012be8)State change: the card closed as completed through
Fixes #12707, andpm:dispatchedis removed in this act. The cloud sessionsession_01Umh5XoHZFaBP7A8Kc2g2Jcis archived. No contract review is owed (Clause-②: no). The ACCEPT of record is6224591813(on the PR); the landing note is6224762878.The PR was opened from
claude/issue-12707-studio-readonly-chip-fold-v2(9dc644c, one commit with the model-free trailer pair; the same tree as the first branch's78306de), per the amended claim6224546508. The dev's out-of-scope finding (a long api-name chip takes the Data title's room) is #12791, for triage.Generated by Claude Code