Repository navigation
Setup and Studio: suggestions from the 18.3.0 RC browser walkthrough: Setup naming and machine values, invitation and user onboarding, permission-set authoring, dialog focus, Studio first run, validation and flow builders, and publish-panel wording #27521
Description
domain:devx#1 · sunhaolin · session_017xRBcUoS2G4jgqRskpExS7
Suggestions from the 18.3.0 release-candidate browser walkthrough (wave anchor #27377, card W3-UX, tracks 2 and 3). Everything was observed at framework main @ c4c515ad, with the Console built in-repo from that commit, on stock examples/app-showcase with --seed-admin.
- Personas: the seeded admin; a plain member made through the real invite → accept-invitation → register path; two admin-created users.
- Viewports: desktop 1440×900 and phone 390×844.
- Studio: authored in a new package created from Home → New in Studio.
Each row works today but could be clearer. The reproducible defects from the same pass are their own cards: #27483, #27487, #27491, #27494, #27496, #27498, #27502 (Console); #27504, #27506, #27507, #27509 (Setup); #27511, #27513, #27515, #27517, #27518, #27519 (Studio).
Setup
| # | Observed at c4c515a (persona, viewport, path) | Suggestion |
|---|---|---|
| 1 | Admin, desktop. The Setup app has four names: "System Settings" (Home link), "Setup" (app header), "Settings" (app switcher), "Settings" (hub). | One name everywhere. |
| 2 | Admin, desktop, Settings. Help text and badges leak machine values: invite_only / email_domain / open, OS_AUTH_REQUIRE_EMAIL_V…, "recorded in sys_email", sys_ai_trace, OS_FEATURE_FLAGS_AI_ENABLED, a "Tenant" badge, and the Webhooks subtitle "defineStack({ webhooks }) / defineWebhook() … webhook auto-enqueuer". |
Business wording, with the technical detail behind "learn more". |
| 3 | Admin, desktop, Settings. The sidebar says "Email" while the hub card says "Mail Delivery". SMS Delivery and Data Lifecycle are on the hub but missing from the sidebar. | Same names and the same set in both. |
| 4 | Admin, desktop, System Overview and Notifications. The legend shows config_change. The topic approval.requested and object sys_approval_request appear raw. Severity "info" is drawn as an orange badge. The audit object sys_metadata_activation appears raw, and Users carry an "Env-Native" badge. |
Labels for topics, objects and sources; a neutral colour for info. |
| 5 | Admin, desktop. Sharing Rules and Webhooks with zero rows say "No matching records — No records match this view's filter", while Queues says "Nothing here yet — Create your first record". The header tags ("Admin config", "Platform schema", "System-managed", "Identity") are unexplained. | Empty states that say "none yet" plus how to add one; a tooltip on each tag. |
| 6 | Admin, desktop, Invitations → Invite. The toast says "Invitation sent to …" although the stock deployment has no mail transport, and there is no Copy invite link in the row menu or the detail drawer, so the invite dead-ends. | "Invitation created — copy the link to share it" when no mail provider is configured, plus a Copy link action. |
| 7 | Admin, desktop, Invitations. The status values are raw lowercase (pending / accepted / canceled …), while the tabs are title case. | Use the labels. |
| 8 | Admin, desktop, Invite dialog. The Role help text differs by entry point ("Member role within the organization" vs "Role to assign upon acceptance"), and neither explains Owner / Admin / Delegated Admin / External. Change Role's description is the generic "Please provide the required information to continue." and does not name the person. | One help text, with a line per role; name the person in Change Role. |
| 9 | Admin, desktop, Invitations row menu. Resend opens an editable Email/Role form. The Cancel Invitation dialog's two buttons read "Cancel" and "Cancel Invitation". | Resend as a confirm; "Keep invitation" / "Cancel invitation". |
| 10 | Admin, desktop. Invite with an invalid email is not checked client-side, and "Invalid email" shows twice, as a banner and a toast, with the field unmarked. Create User with Email empty says "Either email or phoneNumber is required" (phoneNumber is an API key, and the form has no phone field), and the form shows no required asterisks. |
Inline field errors only; "Email is required"; asterisks as in the Invite dialog. |
| 11 | Invitee, desktop. The plain sign-in page has no hint for invited people. The invite registration form does not pre-fill the invited email. After accepting there is no "you joined" confirmation. | Pre-fill the email; a short welcome after joining. |
| 12 | Admin, desktop, Create User with a typed password. The dialog still says "If a temporary password was generated, copy it now". On the user's forced-change screen, "Current password" would read better as "Temporary password", and the title and body repeat. | Show the copy line only when one was generated; "Temporary password". |
| 13 | Admin, desktop, a user record. Details shows only created/updated, so the saved Locale is invisible. There is no Banned badge or ban reason. "Platform Role: user" is lowercase. The tab strip is cut at 1440 with no overflow cue. | Show Locale, ban state and reason; a label for the platform role; scroll the tab strip with a cue. |
| 14 | Admin, desktop, user record → Permission Sets tab. It shows the API name organization_admin_no_bypass, a set auto-granted on the role change to Admin with no message. |
Show the label; say on the role change what it grants. |
| 15 | Admin, desktop, Users list. Row actions appear only on hover, so the Actions column looks empty. There is no status or role column, so a banned user looks like everyone else. | A visible ⋯; Status and Role columns. |
| 16 | Admin, desktop, New Permission Set. The snake_case Name comes first, with Label second and optional, and Name is not derived from Label. A bad name stacks three messages, including "is not a legal metadata item name" and "does not match the spec — 1 validation error(s)". | Label first, Name derived from it; one plain message. |
| 17 | Admin, desktop and phone, permission set editor. The grid needs sideways scroll at 1440, and the Bulk column is cut with no cue. On a phone the Object column is not sticky. Two fields are both labelled "Owner". With field rows expanded, the header labels do not line up with the columns. | Sticky first column, overflow cue, disambiguated labels, aligned headers. |
| 18 | Admin, desktop, permission set → Add user. The picker lists names only (the same pattern as #27356 row 2 for positions). | Show the email beside the name. |
| 19 | Admin, desktop, Company settings. Country is case-sensitive with maxlength 2: "de" is refused, and "Germany" silently becomes "Ge" and is refused (got "Ge"). Locale and Timezone are free text. Save feedback is otherwise good. |
Pickers for country, locale and timezone. |
| 20 | Admin, desktop and phone, Packaged Automation. The switches change state instantly with no confirmation or toast, including for platform-critical actions such as Ban User. The Object column shows API names. On a phone the Activation column and Clone button are clipped. | A confirm for platform actions and a toast after each switch; object labels; a phone layout. |
| 21 | Admin, desktop, Packages. The showcase (code) package has no Disable button and no reason. Platform packages say "platform kernel package". Disabling an authored package applies with no confirmation, and its delete button says "Delete app" while everything else says "package". Installed Apps reuses the Packages subtitle. | Say why a package cannot be disabled; confirm Disable; consistent nouns. |
| 22 | Admin-created user with locale fr-FR, desktop. The forced-change screen's title and labels are French but the body is English ("You must change your password before continuing."). A wrong current password says English "Invalid password". The Home feed reads Updated User "Carl Edited": Banned et Ban Reason. The Locale help says it is the "Preferred language for this user's notifications", but it switches the whole UI. |
Translate the remaining strings; correct the Locale help text. |
| 23 | Admin, desktop, Invite User and Create User dialogs. On open, focus lands on Cancel with no visible ring. After Esc or Done, focus goes to body rather than back to the button that opened the dialog. Tab order and Esc are otherwise correct. |
Initial focus on the first field; return focus to the opener. |
Studio
| # | Observed at c4c515a (persona, viewport, path) | Suggestion |
|---|---|---|
| 24 | Admin, desktop, Home → New in Studio → New Package. The dialog speaks to developers: "reverse-domain notation", "Object namespace", "SemVer 2.0.0", "Type: app", and the default ID com.default.field-service. The landing copy mentions a "writable base" and an "environment overlay". The "Start with your first object" step after it is clear. |
A name-only first step with the technical fields behind "Advanced". |
| 25 | Admin, desktop, Picklist options editor. The monospace value box comes before Label and is not filled from the label (object and field names are). With three labelled options visible, the banner still says the field "needs at least one option". Each option has a "No kind" dropdown offering sales-only kinds (Open / Won / Lost). |
Label first with the value derived; clear the banner once options exist; hide the kind unless the field drives a path. |
| 26 | Admin, desktop, Validations → Reject the save when…. Fields are listed as record.estimated_hours without labels, and the placeholder is "field / context". The form reads "Script — CEL fail condition", "Rule name (snake_case, unique)" with default validation_1, and "error (rejects the save)". The list-view filter in the same product shows labels. |
Field labels in the picker; a rule name derived from the message; business wording. |
| 27 | Admin, desktop, a record-triggered flow → Update Records node. It does not offer "the record that started this flow"; the author must know to type id with expression record.id. Object is not pre-filled with the trigger object, and keys are free text. A blank expression shows "A value carrying a dialect key is read as an expression envelope… Write { dialect: 'cel', source: '…' }" while Problems says "No problems — this flow is structurally valid." |
A "Triggering record" target; pre-fill the object; field pickers; business wording. |
| 28 | Admin, desktop, Publish panel. Items list raw keys ("+ label + name + sharingModel", "+ config + isDefault + viewKind", "+ fieldGroups + validations" without naming the rule, "+ edges + nodes + status"), and the copy says "atomically" / "(one atomic release)". This widens #27356 row 17 beyond flows. | Name what changed in words ("New view Work Order list", "Validation rule Hours over 40"). |
| 29 | Admin, desktop. Toasts appear top-centre over the object or flow header, covering the name badge, the tabs and the Enable switch. | Bottom or right placement in Studio. |
| 30 | Admin, desktop at 1440. The flow header reads "Trigger: Reco… · Status: Unpu…". Node cards show "START field_service_work_…". The Interfaces rail shows field_service_work_order...., and its header truncates to "FIELD SERVICE · N…". |
Labels instead of API names; wrap or widen. |
| 31 | Admin, desktop, Interfaces. The list-view inspector edits only the default grid; there is no way to create a kanban, calendar or other view type. | An "Add view" with a type choice. |
| 32 | Admin, desktop, object header and form groups. "Scheduling 1 fields". The header says "10 fields" while the canvas shows 2: system fields are counted but not explained. | Pluralise; "2 fields (+8 system)". |
| 33 | Admin, desktop, Add field popover. A disabled Create has no reason and is skipped by Tab. Focus trap, Esc and the inspector's Tab order are otherwise good. | A reason tooltip, focusable when disabled. |
| 34 | Admin, desktop, the read-only showcase package in Studio. It is clearly marked (Read-only chip and banner), but disabled textareas and some number inputs keep live styling, and Publish has no reason tooltip. | Muted styling on disabled inputs; a reason on Publish. |
| 35 | Admin, desktop, after the first publish. Nothing tells the author that members cannot use the new app. The member then sees a good message ("Nothing in Field Service is available to you yet… Ask an administrator to assign you a permission set"). | Point the publish toast to Access. |
| 36 | Admin, desktop, formula field editor. A bare textarea with no field picker. Syntax errors are technical ("Unexpected token: EOF … ^"), and the error line sits under the sticky Remove button. The unknown-field "did you mean estimated_hours?" is good. |
A field picker and plain error text kept clear of the sticky footer. |
| 37 | Admin, phone. The pillar switcher is icon-only, and the package name truncates to "Fie…". There is an honest "Studio is built for a desktop screen." and no horizontal scroll. | Labels under the icons. |
| 38 | Member, desktop, any Studio URL. "You need Studio access to open Studio." with Back to home. It is clean. | Say who grants it (an administrator, in Setup → Permission Sets). |
| 39 | Admin, desktop, Add node menu. Node help is engine prose: HTTP "durable: true… outbox… dead-letter", Connector "registerConnector()", Revise Window "back-edge". This widens #27356 row 15 to the Add node menu. |
Business wording, with the detail behind "learn more". |
Already carded: not raised again
Rows of #27356 still reproducing at c4c515a: 1 (Create User permission set as free text), 3 (a green switch beside "Not running here" naming an env var; now also #27378), 5 (singular titles, API name first), 6 (no Deactivate in the Users row menu), 7 ("Record ID" column shows a name), 9 (__search first in field overrides), 11 (Setup All reports empty state), 12 (Studio reachable only from Home), 13 (overlay label shown, breadcrumb lands on All Metadata Types), 14 (no fields table), 15 (engine prose in flow help; see row 39), 17 (publish dialog wording; see row 28). Row 22 (phone flow canvas fit-to-view) did not reproduce with a 3-node flow, which is inconclusive for larger flows. The invitation status path drawing "canceled" as a later step belongs to the #26612 family.
Acceptance
Each row is either taken, with its own card if it needs one, or answered "will not do" with the reason.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 29, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p3 ·
domain:ui·area:studio· 2026-10-29T11:10Z⛔ Not a claim.
enhancement,pm:queue.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe
Split filed (triage 6495068090):
Row 27's suggestion half (a triggering-record target, the object pre-filled, field pickers) stays here.
Plan:
domain:uiseat 3 takes the Studio rows (24–39) in onePart of #27521PR. Each row will be taken with a pin, carded, or answered will-not-do with a reason.The claim follows.
objectstack-fleet commentedon Oct 29, 2026
domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe
Claim: PM loop round 1
Session:
session_01Utp6CaJoinvGQSbHeDaWBeAccount:
os-billBranch:
claude/project-thread-cot856(the card thread's designated push branch, the recorded platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-27521Domain:
domain:uiSeat:
domain:ui#3File surface: Studio design surface (ui/packages/app-shell/src/views/studio-design/**), metadata-admin Studio inspectors, studio i18n namespace (en/zh, other packs only where the key family has them), tests beside, root changeset (stop on breach; explain in the report)
Container & model:
M,mode:thread,model: TIER_DEFAULT(dispatch-gates --tieron178b5238: no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility: ui code produces the defect | no platform path covers it | every Studio / console author reaches it today
Thread-read: 6511102307
Premise: holds
Serial constraints cleared: none
Scope of this claim: Studio rows 24–39 only (27 = its suggestion half; its defect half is #27799). The PR reads
Part of #27521. Setup rows 1–23 are not claimed here:domain:uiseat 2 takes them as a second pass (row 6 is #27797).Dispatched 2026-10-29T23:42Z to a card thread of the seat's project; the order lives in the project. ⛔ The thread posts no claim and writes no assignee.
Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
Claim: PM loop round 3 · 2026-10-29T23:48Z · a SECOND claim on this card, for the Setup rows 1–23 except row 6 (seat 3's claim 6511168770 holds the Studio rows 24–39; labels and assignee are already right and are not rewritten)
Session:
session_01Utp6CY2n1JmZZKrHgtp9jC(seat; implementation by a card thread,mode:thread)Account:
os-billBranch:
claude/project-thread-uywna1(the card thread's harness push branch, self-reported — the measured platform exception toclaude/issue-N-slug)Worktree:
objectstack-issue-27521-setupDomain:
domain:uiSeat:
domain:ui#2File surface: Setup / admin pages and dialogs under
ui/packages/app-shell/src/**(Setup app, Users, Invitations after #27797, Permission Sets, Company settings, Packaged Automation, Packages), the shared Setup components they render, i18n keys in the ten packs, tests beside, one changeset; ⛔packages/spec/**, every server file,examples/**, the Studio surface (seat 3's); PR carriesPart of #27521(+Fixes #27433if row 18 lands it)Container & model:
M,mode:thread,model: TIER_DEFAULT(dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no (expected; the dev measures from the diff)
Metadata-protocol: none (expected; the dev measures from the diff)
Responsibility: the Setup app's wording, labels, empty states, focus and layout named in rows 1–23 | server and spec strings are out of scope (carded, not changed here) | every administrator using Setup, today
Thread-read: 6511168770
Premise: each row is re-observed on current
mainfirst (measured atc4c515adby the walkthrough); a row no longer reproducing is answered "fixed on main"Serial constraints cleared: the Invitations rows (7–11, 23) wait for #27797 (seat 2, in flight, same surface); row 18 = open card #27433 (taken together if the dev takes it); row 20 is not #27504; seat 3 agreed to the split
Dispatch order:
/mnt/project-files/ui-seat2/dispatch-27521-setup.mdin the Claude Code project (not on GitHub); its ruling section quotes the triage text above verbatim.Generated by Claude Code
fix(studio): plainer Studio authoring for #27521 rows 25-38, with pins
test(studio): pins for #27521 rows 34 and 38
objectstack-fleet commentedon Oct 30, 2026
domain:ui#3 · os-bill · session_01Utp6CbkBiXQKn2AfkfK8tM
os-dev-report
Report of 2026-10-30T01:06Z. Studio rows 24–39 only (Part of #27521); the per-row table is in the PR body.
{ "issue": 27521, "status": "done", "branch": "claude/project-thread-cot856", "pr": "https://github.com/objectstack-ai/objectstack/pull/27830", "head": "eb92b33eb454bb69edbd841f51b88e7d24f4a40e", "session": "session_01Utp6CbkBiXQKn2AfkfK8tM (card thread; Studio rows 24-39)", "premise_still_valid": true, "summary": "Rows taken: 25 (options Label first, value derived from the label until typed, kind picker only on the record-path field), 26 (validation rule name derived from its message until edited; condition builder lists fields by label with the CEL spelling beside it, opt-in labelSubjects; plain type/severity/name labels), 28 wording (no 'atomic' in publish title, toast, confirm note; en+zh), 30 node cards (object label from the host's useObjectCatalog), 32 (header counts own fields + system apart; singular '1 field'), 33 (Add field Create aria-disabled with a described reason), 34 text areas (disabled look), 35 (publish of an app/object says members need a permission set + 'Open Access' action). Row 38 was drafted then reverted: its call site is the Console's StudioRoute.tsx defaultValue, which the i18n call-site gate ties to the en pack, and that file is outside the claim's surface. Cards: 24, 27 (suggestion half), 28 (naming), 29, 31, 36, 39. Already done: 34 Publish reason (objectui#12303). Will not do: 37 (phones unsupported, objectui#12725), 30 header truncation (objectui#13135).", "tests": "First run of the Studio surfaces (studio-design/, metadata-admin/inspectors/, metadata-admin/previews/, preview/, i18n/src/__tests__/, StudioRoute.accessNotice-12035): 38 red in 16 files, all pins of the old copy/behaviour; moved them; 25 affected files + new pins 265/265 green. New pins: ObjectFieldInspector.optionLabelFirst-27521 (9), ConditionBuilder.subjectLabels-27521, ObjectValidationsPanel.ruleNameFromMessage-27521, AddFieldPopover.createReason-27521, FlowCanvas.objectLabel-27521 (2/2 on the final tree), ObjectDefaultInspector.readOnlyLook-27521; appended cases in DataPillar.hiddenSystemFields-11780 and StudioDesignSurface.publishCount-11807. Ablation (row 25, via scripts/ablation-replace.mjs under the lock): anchor `update(i, row.derive ? { label, value: toFieldNameOrEmpty(label) } : { label });` -> `update(i, { label });`, anchor 1 -> 0, blob 722995a9c74e -> 96a6270ca2ae; optionLabelFirst 2 failed | 7 passed ('typing the label fills the value in', 'three labelled new options are three written options'); restored blob == HEAD, git diff HEAD empty. pnpm --filter @object-ui/app-shell type-check on the eb92b33e tree: VERDICT command-exit 0 (the earlier run on the pre-fix tree exited 2 on the FlowCanvas pin's missing required props; fixed in eb92b33e).", "gates": "dispatch-gates --commands: 34 derived (same list re-derived on eb92b33e). Exit codes: node scripts/check-adr-0087-registration.mjs --base origin/main :: 0; --self-test :: 0; check-changeset-no-major --base origin/main :: 0; check-closing-keyword-parity :: 0; --self-test :: 0; check-comment-mask-corpus :: 0; check-empty-changeset --base origin/main :: 0; --self-test :: 0; check-sdui-manifest :: 0; --self-test :: 0; pm/release-rehearsal-clone --self-test :: 0; release-pending-publish --self-test :: 0; pnpm --dir ui exec vitest run scripts/ :: 0 (first run 1: default-value drift for console.studio.accessRequired from row 38, which led to its revert; one re-run overlapped the type-check-coverage closure build and read a half-written spec dist, so it was re-run under the verify lock: 169 files passed, 4902 tests passed); spec check:duration-unit-keys :: 0; check:changeset-gate-self-tests :: 0; check:closed-ceremony-text :: 0; check:cross-package-test-inputs :: 0; check:dispatcher-error-vocabulary :: 0; check:driver-memory-census :: 0; check:engine-double-contract :: 0; check:gitlink-declared :: 0; check:nul-bytes :: 0; check:pm-changeset-deadline-census :: 0; check:published-files :: 0; check:query-options-erasure :: 0; check:refd-timer-probe :: 0; check:skill-identifier-liveness :: 0; check:test-source-alias :: 0; check:tier-file-adoption :: 0; check:type-check-coverage :: 0; check:type-check-debt :: 0; check:undeclared-dep-imports :: 0; check:watch-hint-literal :: 0; check:where-matcher :: 0. --ran: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. Most gates ran on 776df8d5; the head after it changes only the row-38 revert (en/zh pack line, changeset bullet, one deleted pin) and a test's props, and the scripts/ gate ran after the revert. Outside derivation: pnpm --dir ui check:new-line-citations :: 0. CI families: PR #27830 check-runs not yet reported at report time.", "line_budget": "350 changed lines (added + removed) of source, copy and changeset; 759 of tests. Over the ~600 guideline on the test side, mostly new pins; nothing was cut for size.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (fleet-write pr_create #27830: draft, no assignees, no review request; the harness's after-PR assign/review step was skipped per the dispatch order); this report comment via post-stamped. git push is not a REST write.", "deviations": [ "PR body attribution links this card thread (session context), not the seat thread named in the order.", "PR body order: declaration lines (Part of, Clause-②, Metadata-protocol) right after the attribution, then 维护者速读, per os-dev.md.", "Commit trailers: model-free pair per AGENTS.md, not the harness's model-named Co-Authored-By.", "Row 38 not taken although it was bucketed TAKE at first: stopped on the file-surface breach as the claim says (see remainder)." ], "remainder": [ "Row 38 (Studio access refusal names who grants access): change console.studio.accessRequired in locales en/zh, the inline defaultValue in ui/apps/console/src/components/StudioRoute.tsx and the NOTICE constant in its StudioRoute test together (check-i18n-call-site-keys ties the defaultValue to the en pack). Suggested en: 'You need Studio access to open Studio. An administrator can grant it with a permission set in Setup → Permission Sets.'", "docs/qa/platform-checklist/areas/studio-authoring.json still quotes the old '(one atomic release)' toast; outside the file surface." ], "open_questions": [], "out_of_scope_findings": [ "CARD row 24 · title: 'Studio: a name-only first step for New Package, with plain help' · body: The New Package dialog shows ManifestSchema's English .describe() text as help (package-schema.ts 'Help text') and asks for id/namespace up front; the landing overlay copy is pinned by BuilderLanding.environmentOverlayCopy-12171. A first step that asks only for a name and derives the rest, with plain help, is a dialog redesign plus a wording producer in packages/spec. · landing: ui/packages/app-shell studio-design New Package dialog + packages/spec package-schema describe() · dedupe words: new package dialog name only, ManifestSchema describe help, package namespace derive", "CARD row 27 (suggestion half; defect half is #27799) · title: 'Flow Update Records: a Triggering record target with field pickers' · body: In the Update Records node editor the author must type the object and the key names; offer a 'Triggering record' target that pre-fills the object from the trigger and field pickers for the keys. · landing: ui/packages/app-shell metadata-admin FlowNodeInspector update-records editor · dedupe words: update records triggering record, flow node field picker keys, update record object prefill trigger", "CARD row 28 (naming half) · title: 'Studio changes list: name each change in words' · body: Publish and the changes panel name flow-node changes in words since #27432 (carrier of #27356 row 17, flow nodes only); views, validation rules and other types still show keys. Name them by label (a view, a validation rule by its label, keys as words). · landing: ui/packages/app-shell preview/DraftChangesPanel + studio publish summary · dedupe words: draft changes panel change names, publish summary keys as words, validation rule change label", "CARD row 29 · title: 'Studio toasts: anchor near the canvas, not top-centre' · body: Toast placement is console-wide (ConsoleToaster top-centre by objectui#13340; bottom-right refused by objectui#7482). A Studio-only anchor needs a placement decision in shared chrome before code. · landing: ui/apps/console ConsoleToaster (decision first) · dedupe words: studio toast position, ConsoleToaster placement, toast anchor canvas", "CARD row 31 · title: 'Interfaces: Add view with a type choice' · body: The Interfaces list-view inspector has no 'Add view' that asks which type (grid, kanban, calendar…) to create. · landing: ui/packages/app-shell metadata-admin ObjectListViewInspector / Interfaces rail · dedupe words: interfaces add view type, list view inspector add view, new view type picker", "CARD row 36 · title: 'Formula editor: field picker, plain parser errors, error line placement' · body: The formula editor needs a field picker, parser errors in plain words, and the error line kept clear of the footer; InspectorShell does not overlay the footer in code, so the overlap needs a browser read first. · landing: ui/packages/app-shell metadata-admin formula field editor · dedupe words: formula editor field picker, formula parser error plain, formula error footer overlap", "CARD row 39 → fold into #27356 row 15 · title: 'Flow node help in plain words (engine descriptor descriptions)' · body: Node help is the engine's descriptor text (useFlowNodePalette adopts description), so the producer is service-automation http-nodes.ts and plugin-approvals. This widens #27356 row 15, now in flight in the seat's #27356 Studio-rows thread; fold it there rather than filing anew. · carrier: #27356 row 15 · dedupe words: flow node description help, node palette descriptor text, http node description plain" ] }objectstack-fleet commentedon Oct 30, 2026
domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe
Studio rows 24–39 ACCEPT → PR #27830 comment 6512869777 · 2026-10-30T01:42Z
Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
os-dev-report
{ "issue": 27521, "status": "done", "branch": "claude/project-thread-uywna1", "pr": "https://github.com/objectstack-ai/objectstack/pull/27849", "head": "5a54fd9875ae7fe97a162217f2a60276d29064f3", "session": "session_01Utp6CZLnkdSxVfvNuQ6RgB (card thread; seat session_01Utp6CY2n1JmZZKrHgtp9jC)", "premise_still_valid": true, "summary": "Setup rows 1-23 except 6, re-observed on main 561b7642 in Chromium (stock app-showcase --seed-admin, admin). Taken in PR 27849 (ui only, pinned): 1, 4 (info/warning colour), 5 (keyboard-reachable tag tooltip), 12+22 (forced-reset overlay body and 'Temporary password', ten packs), 13 (tab strip scroll + edge fade), 20 (confirm before switching an action off, toast, object label, phone layout), 21 (read-only reason, Disable confirm, 'Delete package', Installed Apps subtitle). Fixed on main: 16 name derivation; 18 by PR 27808 (taken from main at the merge, so no Fixes line). Carded (paragraphs below, the seat files): 2, 3, 4 rest, 10 Create User half, 12 result line, 13 rest, 14, 15 columns, 16 order + stacked messages, 17, 19, 22 rest. Will-not-do: 5 empty states, 15 hover reveal. Rows 7, 8, 9, 10 Invite half, 11, 23 follow #27797 in a separate PR (seat's instruction). PR body carries Refs #27521 per the seat.", "tests": "On head 5a54fd98 after merge + install + full build (114/114): pnpm --dir ui exec vitest run (setup/, PackagesPage*, AssignedUsersSection*, RemediationOverlay*, console/home/, AppSwitcher*, app-shell components/, fields __tests__/, components page-tabs*, i18n/, scripts/) -> Test Files 483 passed | 3 skipped, Tests 9777 passed | 22 skipped, lock VERDICT command-exit 0. Ablation (source-resolved, no dist): ablation-replace on PackagesPage.tsx Disable onClick -> anchor 1->0, blob 032c769d->41626a6b, readOnlyReasonAndDisableConfirm-27521 2 failed / 6 passed; restored blob == HEAD 032c769d, git diff HEAD empty.", "gates": "dispatch-gates --commands (2c0f76c9) derived 34 families, all run, --ran reconciliation: 34 run, 0 NOT-MEASURED. Lines: node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0 | node scripts/check-adr-0087-registration.mjs --self-test :: exit 0 | node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0 | node scripts/check-closing-keyword-parity.mjs :: exit 0 | node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0 | node scripts/check-comment-mask-corpus.mjs :: exit 0 | node scripts/check-empty-changeset.mjs --base origin/main :: exit 0 | node scripts/check-empty-changeset.mjs --self-test :: exit 0 | node scripts/check-sdui-manifest.mjs :: exit 0 | node scripts/check-sdui-manifest.mjs --self-test :: exit 0 | node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0 | node scripts/release-pending-publish.mjs --self-test :: exit 0 | pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0 | pnpm check:changeset-gate-self-tests :: exit 0 | pnpm check:closed-ceremony-text :: exit 0 | pnpm check:cross-package-test-inputs :: exit 0 | pnpm check:dispatcher-error-vocabulary :: exit 0 | pnpm check:driver-memory-census :: exit 0 | pnpm check:engine-double-contract :: exit 0 | pnpm check:gitlink-declared :: exit 0 | pnpm check:nul-bytes :: exit 0 | pnpm check:pm-changeset-deadline-census :: exit 0 | pnpm check:published-files :: exit 0 | pnpm check:query-options-erasure :: exit 0 | pnpm check:refd-timer-probe :: exit 0 | pnpm check:skill-identifier-liveness :: exit 0 | pnpm check:test-source-alias :: exit 0 | pnpm check:tier-file-adoption :: exit 0 | pnpm check:type-check-coverage :: exit 0 | pnpm check:type-check-debt :: exit 0 | pnpm check:undeclared-dep-imports :: exit 0 | pnpm check:watch-hint-literal :: exit 0 | pnpm check:where-matcher :: exit 0 | pnpm --dir ui exec vitest run scripts/ :: exit 0 | pnpm --filter @object-ui/components run type-check :: exit 0 | pnpm --filter @object-ui/fields run type-check :: exit 0 | pnpm --filter @object-ui/i18n run type-check :: exit 0 | pnpm --filter @object-ui/app-shell run type-check :: exit 0 | eslint (changed ui files) :: exit 1 | pnpm --dir ui check:new-line-citations :: exit 0 | eslint (changed ui files, inline config honoured) :: exit 0. One interim red: 'vitest run scripts/' first ran with packages/i18n/ and failed de-quote-pairing-3876 (new de strings quoted); fixed in ed05c2ac, green in the final run. ESLint --no-inline-config on changed ui files: 1 pre-existing error in containers.tsx (react-hooks/static-components, disabled inline on main); with inline config: 0 errors. CI check-runs: in_progress at report time (not waited, per os-dev).", "line_budget": "n/a — no skills/** or governed surface in the diff", "files_changed": 39, "deviations": [ "Harness post-PR assign/review step skipped (dispatch: no assignee, no reviewer). PR activity not subscribed (os-dev dispatch contract over the platform posture).", "PR body says Refs #27521 (seat's instruction 01:07Z) instead of the order's 'Part of #27521'; no Fixes #27433 because PR 27808 landed row 18 first.", "File surface: ui/packages/components (page:tabs renderer + a package-private hook) and ui/packages/fields (semantic colour map) are shared renderers Setup draws, touched for rows 13 and 4; the studio i18n namespace (en, zh) is touched for engine.packages.* keys only, beside seat 3's Studio keys." ], "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "4 — mcp__github__issue_read x4 (27521 get + comments, 27504 get, 27797 get); no write tool", "api_writes": "2 — fleet-write relay pr_create (objectstack#27849, run 40989560767, read-back identical 14131 bytes); post-stamped os-dev-report comment on #27521", "open_questions": [], "out_of_scope_findings": [ "carrier: seat 2 — the carded rows below are row dispositions of this card, not side findings; listed for the seat to file" ] }Filing-ready paragraphs (the seat files them; re-observed at
main@561b7642, stockexamples/app-showcase --seed-admin, admin, Chromium 1440×900: rows 2, 3, 4, 13 tab strip, 14 list, 15, 16, 19 and 20. Rows 10, 12 result line, 13 rest, 14 grant message and 22 rest are the walkthrough's readings atc4c515adwith the source line confirmed onmain, not re-driven here)invite_only/email_domain/openandOS_AUTH_REQUIRE_EMAIL_VERIFICATION=false; Feature Flags readsOS_FEATURE_FLAGS_AI_ENABLED=true; Mail mentionssys_email; the Webhooks subtitle readsdefineStack({ webhooks })/defineWebhook()/ "webhook auto-enqueuer"; an inherited value's badge names the layer "Tenant". Where:packages/services/service-settings/src/manifests/auth.manifest.ts,feature-flags.manifest.ts,mail.manifest.tsand theirtranslations/*; thesourceLabels.tenantstring;packages/plugins/plugin-webhooks/src/sys-webhook.object.tsdescription. Wanted: business wording inhelp, the technical detail behind a "learn more" (a docs link) rather than in the sentence. Reach: every administrator opening Settings, today. Dedupe words: settings help machine values env var.nav_settings_mail) where the hub card says "Mail Delivery"; the hub lists SMS Delivery and Data Lifecycle, the sidebar has neither. Where:packages/platform-objects/src/apps/setup-nav.contributions.ts(Configuration group) against the manifests'titleinservice-settings. Wanted: one name per settings page and the same set in both. Reach: every administrator. Dedupe words: setup nav settings sidebar hub mismatch.config_change, because thesys_audit_log_metricsdataset declaresactionastype: 'string'(packages/platform-objects/src/apps/dashboards/system.datasets.ts); Notifications shows topicapproval.requestedand sourcesys_approval_requestraw (topicandsource_objectareField.textinsys-notification.object.ts), andseverityoptions carry lowercase labels (Field.select(['info','warning','critical'])); Users carry "Env-Native" (sys-user.object.tsidentity-source option). Wanted: labelled dimension values, a topic/object label, title-case option labels. Reach: every administrator on System Overview / Notifications. (The info badge colour is fixed in this PR.)packages/plugins/plugin-auth/src/admin-user-endpoints.ts,badRequest('Either email or phoneNumber is required'));phoneNumberis an API key and the form has no phone field; the dialog shows no required marks because its params are declared optional insys-user.object.ts. Wanted: "Email is required" (or "Email or phone number is required" where phone sign-in is on), and the param marked required when phone sign-in is off. Reach: every administrator creating a user.sys-user.object.ts, two result texts). Wanted: the line only when the server generated one. Reach: every administrator creating a user with a typed password.sys-user.object.ts(record page sections, highlight fields, role option labels). Wanted: Locale, ban state and reason on Details; a label for the platform role. Reach: every administrator opening a user. (The cut tab strip is fixed in this PR.)organization_admin_no_bypass/admin_full_access:sys_user_permission_set.permission_setis a by-name text column withwidget: 'permission-ref', and no list cell reads a registry label for it. Wanted (ui card,@object-ui/fields): a read face forpermission-ref/position-refcells that draws the registry label with the name ontitle. Wanted (server card): the role change that auto-grants a set says so in its result. Reach: every administrator opening a user.sys-user.object.tslist views (all_userscolumns: name, email, phone, email verified, identity source, created). Wanted: Status (banned) and Role columns. Reach: every administrator on Users.packages/spec/src/security/permission.form.tsorders Name before Label and leaves Label optional; wanted Label first and required. (b) ui card,ResourceEditPage: a bad name saves anyway and draws the server refusal ("is not a legal metadata item name"), the client summary ("does not match the spec — 1 validation error(s)") and the inline error; wanted the inline error alone, with the save held while the client validator refuses. Name derivation from Label already works on main. Reach: every administrator creating a set.ui/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx. What happens: sideways scroll at 1440 with the Bulk column cut and no cue; the Object column is not sticky on a phone; two fields are both labelled "Owner"; with field rows expanded the header labels drift from their columns. Wanted: sticky first column, an overflow cue, disambiguated labels, aligned headers. Reach: every administrator editing a set.maxlength=2. Where:packages/services/service-settings/src/manifests/company.manifest.ts(countryistype: 'text'with a two-letter pattern; locale and timezone are text). Wanted: pickers (a select of ISO countries, locale and IANA timezone), with the code stored. Reach: every administrator filling Company.codethe console localises); (b) the Home feed readsUpdated User "Carl Edited": Banned et Ban Reason: the field labels are untranslated becauseplatform-objectsships nofrbundle forsys_user; (c) the Locale help says "Preferred language for this user's notifications" (sys-user.object.ts), but the setting switches the whole UI. Wanted: a coded refusal the console can translate, the missing translations, a corrected help line. Reach: every non-English user. (The forced-change body and field are fixed in this PR.)Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
Landed (Setup rows, seat 2's second claim 6511270445) · 2026-10-30T02:42Z
d07e8d1b6b954ed66c821a81a5d14f3c77018236State: this card stays open and
pm:dispatched. Seat 2 keeps the Invitations rows and re-dispatches them once #27843 is onmain.Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
Release (seat's own claim 6511270445, end of shift) · 2026-10-30T13:58Z
outcomeby mail delivery andsys_invitationgains a servercopy_invitation_linkaction that answers the accept URL (ruling E on #27797) #27843 is closed: PR feat(plugin-auth): an invite answers its mail-delivery outcome, and sys_invitation gains copy_invitation_link #27902 merged at 2026-10-30T04:07Z, merge commitf552fa81f1. So they are claimable now, as one ui PR thatFixes #27521.Resume-from: none(every pushed branch is merged; no unmerged work).pm:dispatched→pm:queue, assignee cleared.Generated by Claude Code