Skip to content

Hosted console UX defects from the 2026-09-28 cloud E2E: assistant FAB covers send, failed comment shown as sent, raw 403 on dashboards, wrong assistant scope chip, empty 执行过程 blocks, Studio edit offered on control-plane pages #10899

Description

@hotlong

Source

Two local end-to-end runs on 2026-09-28, both starting from sign-up. Run one used cloud 96eb092f with objectui pin efead6c6. Run two used objectui main 35d68c4c with objectstack main 862b6ce8. Each defect below reproduced on objectui main unless marked otherwise. This card collects the objectui halves of findings tracked under epic objectstack-ai/cloud#2440; the cloud halves live on the cloud cards named per item.

Items (each can land alone)

  1. The in-app assistant's floating button covers the composer's send button.

    • Where: an app page (e.g. an AI-built app's list) with the assistant panel open via 「打开…助手」.
    • What happens: the round FAB at the bottom-right sits on top of the panel's send button. Only the Enter key sends.
  2. A failed record comment is shown as sent. This is the objectui half of objectstack-ai/cloud#2431.

    • Where: the record detail 「讨论」 panel. On a tenant where sys_comment is not registered, POST /api/v1/data/sys_comment returns 404.
    • What happens: the comment still renders and the count becomes 「讨论 (1)」, with no error. It is gone after a reload.
    • Expected: a failed write shows a localized error and does not render as sent. Also, when the object does not exist, do not render the panel, or say that it is unavailable.
  3. A dashboard 403 renders as a raw English exception.

    • Where: a dataset widget the viewer may not read.
    • What happens: the card shows Dataset query failed: 403 Forbidden — [Analytics] Access denied: reading "y8bc_customer" is not permitted for this user. The list view already renders a localized 「无权访问」 empty state; the widget should do the same.
    • Related: objectstack-ai/cloud#2439 is the underlying permission bug.
  4. The assistant scope chip says 「新建应用」 inside an app.

    • Where: the header chip of the in-app assistant while inside app 「客户管理」.
    • What happens: it reads 「构建 · 新建应用」 while the build proposal correctly targets the existing app (the Studio copilot shows 「客户管理」). The chip should name the current app.
  5. Empty 「执行过程」 blocks in the AI copilot.

    • What happens: after each tool step the conversation renders an italic 「执行过程」 placeholder with a large empty area. The Studio replay also orders steps differently from the live run.
  6. The control-plane console offers Studio editing to a non-platform-admin. This is the objectui half of objectstack-ai/cloud#2434 item 1.

    • Who: a signed-up org owner who is not a platform admin.
    • What happens: on cloud pages (/_console/apps/cloud_control/page/welcome, pricing) this user sees 「在 Studio 中编辑」 (pencil) and 「在 Studio 中设计」 (hammer). They open the control plane's own page metadata editor, which offers 「新建」.
    • Ask: whether the gate belongs in the console (hide the affordance without the permission) or in the server-side permission set is the dev's first reading. Report the producer.
  7. Marketplace labels an older version as an update.

    • Carried from objectstack-ai/cloud#2432 acceptance item 3. That card's PR (objectstack-ai/cloud#2442) fixes only the cloud-side review gate.
    • Where: the environment marketplace detail page.
    • What happens: it shows 「已安装 · v1.1.0 / 有可用更新 → v1.0.0」.
    • Producer, per the chore(deps): bump @objectstack/spec from 14.3.0 to 14.6.0 #2432 dev (read at objectui pin efead6c6): packages/app-shell/src/console/marketplace/MarketplacePackagePage.tsx. cloudUpdateAvailable (~L620–624) and the env picker's hasUpdate (~L939–940) compare installed vs latest approved with !== instead of version order.
    • Expected: an "update" appears only for a higher version.

Acceptance

Each item is either fixed with a test, or reported with the producer named when that producer is outside objectui.

Activity

  1. added
    bugSomething isn't working
    pm:epicParent delegated to a dedicated epic PM — other PMs never dispatch into its subtree
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Sep 28, 2026
  2. self-assigned this
    on Sep 28, 2026
  3. hotlong commented on Sep 28, 2026

    @hotlong
    ContributorAuthor

    Claim: PM loop round 2 (epic objectstack-ai/cloud#2440)
    Session: 786273a0-0246-4bb2-b026-bb37ba5d7295
    Branch: claude/issue-10899-hosted-console-ux-defects
    Worktree: ~/Documents/GitHub/objectui-issue-10899
    Domain: domain:ui (direct-dispatch route), reserved via pm:epic
    Seat: epic PM for objectstack-ai/cloud#2440 (seat 1)
    File surface: packages/app-shell/** (assistant panel / FAB layout, record discussion panel, dataset widget error state, assistant scope chip, conversation step rendering, marketplace package page version compare, Studio affordance gating) and packages/plugin-* only where an item provably lives, plus their tests (stop on breach; explain in the report)
    Container & model: L, mode:subagent, model: opus (default judgment tier)
    Clause-②: no
    Thread-read: none
    Serial constraints cleared: objectui#10893 (in flight) owns packages/auth/ only (disjoint). The open objectui PRs were scanned for the item files at dispatch time; overlaps, if any, are listed above this claim in the PM output and are named in the dispatch.

    Direct dispatch by the maintainer, verbatim: 「使用专题派发解决这些问题」 / 「把并发上限提到 5,其余卡一起派」 (epic session, 2026-09-28).

  4. hotlong commented on Sep 28, 2026

    @hotlong
    ContributorAuthor

    os-dev-report
    {
    "issue": 10899,
    "status": "needs_decision",
    "branch": "claude/issue-10899-hosted-console-ux-defects",
    "pr": "#10924",
    "session": "session_786273a0-0246-4bb2-b026-bb37ba5d7295",
    "premise_still_valid": true,
    "summary": "Draft PR #10924 carries six commits, one per item, each with a pin, an ablation and a patch changeset. Item 7: marketplace update means higher SemVer precedence at both call sites. Item 1: the FAB renders only while the dock is collapsed. Item 6: the page pencil and top-bar hammer also require manage_metadata from /me/permissions. The producer is the console: the rig control DB shows the owner holds only organization_admin_no_bypass (manage_org_users, setup.access, setup.write), so the server answer was right and the console ignored it. Item 2: a comment/reply lands only after its sys_comment write resolves; a failure shows a localized toast and the composer keeps the draft. An existing feed pin that asserted the swallowed failure is rewritten. Item 3: queryDataset throws a typed AnalyticsForbiddenError on 403 PERMISSION_DENIED, and DatasetWidget renders a localized no-access state. Item 5a: no activity note or action bar on prose-less step turns that already show a tool row. Still open, and the reason the PR says Refs rather than Fixes: item 4 (chip) needs a decision that reverses an ADR-0057 A1.b line, and item 5b (replay ordering) is root-caused but not changed.",
    "tests": "HEAD d8969d4. Suites: vitest run over app-shell, plugin-chatbot, plugin-dashboard, data-objectstack, plugin-detail, i18n: Test Files 1409 passed / 2 skipped, Tests 14850 passed / 23 skipped, exit 0. Build: turbo build of the six packages plus the app-shell dependency closure, 29/29 successful, exit 0. Type-check: turbo type-check for the six packages, 6/6 successful, exit 0. Gates, all exit 0: check:i18n-keys, check:i18n-drift, check:i18n-dead-keys, check:new-line-citations (0 new; a first run counted 1727 from untracked log files inside the worktree, the logs were moved out and it was re-run), check:control-bytes, check-changeset-presence (6 changesets / 6 packages), check-changeset-no-major, check-governed-queue-guard --test (NOT GOVERNED). Lint narrowed to the diff: eslint --no-inline-config over the 33 changed ts/tsx files; each pre-existing file has the same error/warning counts at HEAD as at merge base 9f0c84a (the only errors are 4 pre-existing no-console in data-objectstack index.ts); new files 0 errors; type-aware lint is off, so untouched files are unaffected. Ablations: each fix reverted on disk with a marker count, then restored via git checkout HEAD with git diff HEAD empty. Item 7: 1 red. Item 1: 1 red. Item 6: 2 red. Item 2 host: 3 red. Item 2 composers: run exits 1 on unhandled rejections while the draft assertions still pass (the draft was kept by accident before). Item 3: 2 red. Item 5: 2 red. The first composer ablation was a no-op (zsh did not split the path list); it was redone with an array and that run is the one reported. The shared verify lock was never taken: the wrapper reported UNLOCKED, no usable flock on this host. NOT MEASURED: in-browser verification. The PM rig was only observed via its screenshots and read-only sqlite reads.",
    "mcp_calls": "0",
    "api_writes": "3 REST writes: POST pulls (gh pr create --draft, #10924); PR assignee hotlong (gh pr edit --add-assignee); POST issues/10899/comments (this os-dev-report). Plus git pushes of the branch (not REST).",
    "open_questions": [
    {
    "question": "Item 4: inside app X, should the in-app assistant dock bind its build conversation to X so the header chip names X instead of the unbound label 新建应用? Today the dock uses the app-less product-only scope and sends no packageId, so the chip is truthful: the thread is unbound. ADR-0057 Amendment A1.b records that the dock keeps the legacy product-only key.",
    "options": [
    "A: when the dock mounts inside an authorable app (package not com.objectstack.*) and the resolved agent is build, pass editPackageId = that package and scope app:PKG:build. The chip, the empty state and the agent context all name X, and the dock, /ai/build?package=X and the Studio copilot share one thread. Maximize would go to /ai/build?package=X. Existing ambient build threads stay reachable in the /ai sidebar. Reverses the A1.b line; ask stays ambient.",
    "B: keep the ambient thread and change the unbound chip wording in the dock. Cosmetic. The agent still guesses the target app."
    ],
    "recommendation": "A. Business need: the E2E maker was inside 客户管理 and meant it, and the agent had to guess the target. Long-term: A1 already says the app axis is always present for build, and A finishes that on the one surface still missing it. AI-error prevention: a declared write target replaces inference, which is the A1 defect-1 fix. Startup focus: A reuses editPackageId and chatConversationScope, adding no new surface. B is a patch that leaves the guessing in place. It changes a decided ADR line, so it needs the maintainer."
    },
    {
    "question": "Item 5b: the Studio replay orders steps differently from the live run. Measured in the rig tenant DB (ai_messages, read-only): the user's 确认,开始搭建。 (turn dh2L) was persisted at 04:36:39Z while the previous proposal turn (EFYj) was still persisting its todo_write and final prose at 04:36:42-44Z. The store orders by created_at, id across turns (cloud packages/service-ai/src/conversation/objectql-conversation-service.ts, MESSAGE_ORDER), so the replay interleaves the two turns. Which fix?",
    "options": [
    "A (cloud): order a conversation's messages by turn (first-seen turn_id), then created_at within the turn, so a replay is faithful however turns overlap",
    "B (objectui): keep the proposed-plan card's build/adjust buttons disabled while the proposing turn is still streaming, so turns cannot overlap from this entry point",
    "C: both"
    ],
    "recommendation": "C, with A as the producer fix: a replay must be faithful whatever the client sent. B is a cheap objectui guard that also stops a confirm racing a still-streaming plan turn. Each belongs in its own card. It is not in this PR because it is a separate producer (cloud) plus a behaviour change on the plan card."
    }
    ],
    "out_of_scope_findings": [
    "class: a · reach: named producer: RecordDetailView handleToggleReaction still ends in update(...).catch(() => {}), so a failed reaction write stays shown as applied (same optimistic shape as item 2) · evidence: its own comment says 'A failed update silently keeps the optimistic UI change' · dedupe words: reaction write failure silent, sys_comment reactions optimistic, handleToggleReaction catch",
    "carrier: none (承接者:无) · noted, not filed: the ThreadedReplies reply input renders only under an item with replyCount above 0, and no sys_comment read sets replyCount, so a loaded discussion never offers a reply affordance. Dormant or unreached, so recorded in the PR Acceptance notes only.",
    "carrier: none (承接者:无) · noted, not filed: other admin-role-only authoring affordances (ObjectView view add/rename/delete/pin, ReportView editor, ObjectDataPage) do not read manage_metadata. Same class as item 6, not measured on the control plane. Dedupe words: isAdmin without manage_metadata, useCanAuthorMetadata coverage, control plane authoring affordance",
    "carrier: none (承接者:无) · noted, not filed: ObjectChart's dataset path, DatasetReportRenderer and DashboardFilterBar still show the refusal message, now the typed English AnalyticsForbiddenError text, instead of a localized no-access state. The card named only the dashboard tile.",
    "rig observation, not objectui: the owner's control-plane grants are cloud_control_plane_member ([]) + organization_admin_no_bypass; item 6's producer-side answer is correct as is, and cloud#2434 item 1 needs nothing more from the server for the two affordances fixed here."
    ]
    }


    Generated by Claude Code

  5. hotlong commented on Sep 28, 2026

    @hotlong
    ContributorAuthor

    Review: ACCEPT (PR #10924 at d8969d4bc, Refs #10899, six of seven items)

    Implemented-by: os-dev subagent of session 786273a0-0246-4bb2-b026-bb37ba5d7295
    Reviewed-by: epic PM, session 786273a0-0246-4bb2-b026-bb37ba5d7295 (objectstack-ai/cloud#2440)

    Landed. Each item has its own commit, pin, ablation and changeset:

    • Item 1: the FAB renders only while the dock is collapsed.
    • Item 2: a comment or reply lands only after its sys_comment write resolves; a failure shows a localized toast and the draft is kept. The existing test that asserted the swallowed failure was rewritten, which is correct: it pinned the behaviour the ruling on cloud#2431 forbids.
    • Item 3: a typed AnalyticsForbiddenError renders a localized no-access state.
    • Item 5a: no empty 「执行过程」 blocks.
    • Item 6: Studio bridges require manage_metadata from /me/permissions. The producer is the console: the server's grants were already right, measured read-only on the rig control DB.
    • Item 7: "update" now means higher SemVer precedence.

    The path surface has no governed files. CI was 23 green and 0 red at review time.

    Remaining on this card. It stays OPEN.

    • Item 4, binding the dock's build thread to the current app: this reverses ADR-0057 Amendment A1.b, so it is escalated to the maintainer in the epic session. The outcome will be recorded here.
    • Item 5b, replay ordering, is split into two producer cards: objectstack-ai/cloud#2455 (order the conversation store by turn) and Proposed-plan card actions are clickable while the proposing turn is still streaming, which overlaps turns #10925 (keep plan-card actions disabled while their turn streams).
    • Folded in, same family as item 2: RecordDetailView handleToggleReaction ends in update(...).catch(() => {}), so a failed reaction write stays shown as applied.

    The other noted gaps (reply affordance, other isAdmin-only authoring affordances, remaining analytics refusal renderers) stay in the PR's Acceptance notes.

    Landing: ready + auto-merge.

  6. hotlong commented on Sep 28, 2026

    @hotlong
    ContributorAuthor

    Maintainer ruling on item 4 (epic session, 2026-09-28, verbatim): 「绑定当前应用(推荐)」.

    The dock's build thread binds to the current authorable app, reversing ADR-0057 A1.b.

    Moved to its own card: #10926. It carries two pieces:

    • the ADR amendment as a separate governed draft PR, for the maintainer to merge;
    • the code PR.

    It is queued for the domain:ui lane. Epic PM, session 786273a0-0246-4bb2-b026-bb37ba5d7295.

  7. hotlong commented on Sep 28, 2026

    @hotlong
    ContributorAuthor

    Waiting state (epic PM, session 786273a0-0246-4bb2-b026-bb37ba5d7295, 2026-09-28T08:1xZ).

    PR #10924 is ready, and auto-merge is armed. Its only red is the required Spec Main Shape Gate (TS1360 at packages/types/src/__tests__/report-chart-query-spec-parity.test.ts:747, compiled against objectstack df3ba164a). The PR touches no packages/types file.

    This is the repo-wide red tracked in #10916, dispatched to os-steve with PRs in flight. objectui main's last gate run was green only because it predates that spec move.

    Blocked-by: #10916

    Nothing to change on this PR. It lands when the gate is fixed and re-run.

  8. hotlong commented on Sep 28, 2026

    @hotlong
    ContributorAuthor

    Landed: PR #10924 merged as ac15833eb1. Verified that objectui main contains it.

    Release: session 786273a0-0246-4bb2-b026-bb37ba5d7295 (epic PM). The landing was partial (Refs), so this card stays OPEN and returns to the domain:ui lane queue with one item left, the one folded in above: RecordDetailView handleToggleReaction ends in update(...).catch(() => {}), so a failed reaction write stays shown as applied.

    The card's other open items are already carried elsewhere:

    Cloud reach for everything merged here comes with the .objectui-sha move on objectstack-ai/cloud#2441.

  9. removed their assignment
    on Sep 28, 2026
  10. added and removed
    pm:epicParent delegated to a dedicated epic PM — other PMs never dispatch into its subtree
    on Sep 28, 2026
  11. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 19 (serial) — domain:ui execution seat 2
    Session: session_014mXUNuFomfj24w7s1pZzhN
    Branch: claude/issue-10899-reaction-write-failure
    Worktree: objectui-issue-10899
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: the one item the epic PM's release 5869011976 left on this card. RecordDetailView's handleToggleReaction ends its sys_comment write in an empty catch that discards the error, so a failed reaction write stays shown as applied.

    • packages/app-shell/src/views/RecordDetailView.tsx: a failed reaction write no longer stays shown. The toggled reaction returns to how it was before the click, and a localized error says so, following this card's item 2 (comments: detail.commentFailed, PR objectui#10924). The write leaves the state updater it currently runs inside.
    • Pins under packages/app-shell/src/ next to the existing feed pins: a rejected write reverts and toasts, and a resolved write keeps the toggle.
    • The i18n packs only if a new catalogue key is added. A '@object-ui/app-shell': patch changeset.
    • ⛔ The reaction storage shape ({ emoji: userIds[] }, with its __other__ padding) is not changed here. That is the later reaction-endpoint work the code comment names.
      Container & model: S, mode:subagent, model: opus (default judgment tier)
      Clause-②: no
      Why no: renderer behaviour only. No declared type, accepted key or export moves.
      Thread-read: 5869011976
      Serial constraints cleared:
    • Dispatch is serial, and this is the one card in development. PR objectui#11014 (objectui#10975) has passed review and is in its landing, which does not count.
    • I read the open-PR file lists at 2026-09-28T17:4xZ, at objectui origin/main ad0310fb57 (8 open PRs). Only PR objectui#11012 touches RecordDetailView.tsx: two citation comments in its permission docblocks, far from the reaction handler, so the hunks are disjoint.
    • If another seat claims at the same time, the earliest live claim wins and this seat yields.
  12. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 10899,
    "status": "done",
    "branch": "claude/issue-10899-reaction-write-failure",
    "pr": "#11017",
    "session": "session_014mXUNuFomfj24w7s1pZzhN (mode:subagent; the dispatching seat's id)",
    "premise_still_valid": true,
    "summary": "Premise held at objectui main ad0310f: handleToggleReaction issued the sys_comment update inside the setFeedItemsByRecord updater and ended it in .catch(() => {}). The toggle is now computed in the click handler (pure toggleOwnReaction) and the one update is issued there. A refused write rolls the row back to the newest recorded reaction set whose write was not refused, only while the row still shows what the handler put there, and raises toast.error(t('detail.reactionFailed')), a new key beside detail.commentFailed in all ten packs. The stored { emoji: userIds[] } shape and other padding are unchanged (storedReactionShape). No data source or no feedRecordKey: early return, no toast. Card assignee at read: os-elon-musk; PR objectui#11017 is draft, assignee os-elon-musk; CI at head fd543fa was in_progress at report time (42 runs: 21 success, 3 skipped, 18 in progress, 0 red).",
    "tests": "Pins in RecordDetailView.reactionWriteFailure-10899.test.tsx (6 rows). Base ad0310f: 'Tests 4 failed | 2 passed (6)'. The red rows were: rejected update puts reaction back plus localized toast; both-rejected rollback; remove-own restores in place; StrictMode one write ('expected vi.fn() to be called 1 times, but got 2 times'). The green rows were: earlier-rejected-later-stored; CONTROL resolved keeps toggle. Head: 'Tests 6 passed (6)'. Ablation A (from committed 27df953) replaced the refusal branch with a no-op, the discarding catch. The anchor count went 1 to 0 and the injected count 0 to 1, re-read from disk. Result 'Tests 3 failed | 3 passed (6)'; the three refusal-handling rows turned red. Restore: blob 1ee5cb64c8 == HEAD, git diff HEAD empty. Ablation B replaced find(s.outcome !== failed) with find(s.outcome === stored), anchor 1 to 0. Result 'Tests 1 failed | 5 passed (6)'; the choice pin (earlier rejected, later stored) turned red. Restore verified the same way. Probes of the two plain rollback options, as one-off mutations of settle, each restored to the HEAD blob: plain inverse toggle 'Tests 3 failed | 3 passed' (both-rejected: 2 toasts; earlier-rejected-later-stored: shows 👍 1, losing a stored reaction; remove-own: chip returns last). Plain snapshot-if-unchanged 'Tests 2 failed | 4 passed' (both-rejected: stays '👍 2'; earlier-rejected-later-stored: toast though nothing lost). Suite at 27df953, under the lock: vitest run --maxWorkers=2 packages/app-shell/ packages/i18n/ plus six out-of-package tests that import or read RecordDetailView.tsx. Result 'Test Files 945 passed | 1 skipped (946)', 'Tests 10130 passed | 22 skipped (10152)', VERDICT command-exit 0. Final HEAD fd543fa differs by comment lines only. There: turbo build of i18n and app-shell 29/29; app-shell and i18n type-check exit 0; commentWriteFailure, feedRecordScope and reactionWriteFailure pins 'Tests 17 passed (17)', VERDICT command-exit 0. tsc -p tsconfig.test.json --listFiles lists the new pin (1 of 867 app-shell test files).",
    "gates": [
    "check-changeset-presence exit 0: 12 source file(s) of 2 released package(s) changed, 1 changeset",
    "check-changeset-no-major exit 0",
    "check:changeset-claims exit 0, report-only: 6661 (en.ts console.nav) and 7997 (RecordDetailView.tsx DetailView retirement) paragraphs read, still true",
    "check:pending-changeset-literals exit 0",
    "check:new-line-citations: VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0",
    "check:control-bytes exit 0 (9299 tracked text files)",
    "check:i18n-keys exit 0; check:i18n-drift exit 0 (1 key added, 0 en values changed)",
    "check:vi-mock-specifiers / vi-mock-inherit / vi-mock-override-shape / test-path-roots exit 0",
    "all above at fd543fa",
    "lint narrowed, eslint --no-inline-config --format json over the 12 changed .ts/.tsx files: population = eslint.config.js files block '**/*.{ts,tsx}'; json reports 12 files; RecordDetailView.tsx 0 errors / 112 warnings at base and head with identical per-rule counts; new pin 0 / 6 (no-explicit-any); packs 0 / 0; type-aware linting not enabled (no parserOptions.project or projectService), so no untouched file's verdict can move; repo-wide lint is CI's",
    "eager closure, console build base vs head: eagerGzipBytes 3179019 -> 3179395 (+376), raw +1039, eager chunks 330 -> 330; RecordDetailView chunk +319 gz, rest +-1..8 hash churn; check:eager-closure exit 1 on both base ('0.0 KB over the 3104.5 KB budget') and head ('0.4 KB over')",
    "git merge-tree --write-tree: vs origin/main e9ca14c exit 0 clean; vs PR objectui#11012 head 8fe632d exit 0 clean",
    "CI at fd543fa: in_progress (42 check-runs: 21 success, 3 skipped, 18 in_progress, 0 failure)"
    ],
    "files_changed": [
    "packages/app-shell/src/views/RecordDetailView.tsx",
    "packages/app-shell/src/views/RecordDetailView.reactionWriteFailure-10899.test.tsx (new)",
    "packages/i18n/src/locales/{en,zh,ja,ko,de,fr,es,pt,ru,ar}.ts (detail.reactionFailed)",
    ".changeset/10899-failed-reaction-write-reverts.md (app-shell patch, i18n patch)"
    ],
    "deviations": [
    "Rollback: the snapshot option, but the snapshot restored is the newest set a write stored or may still store, not the pre-click set. Both plain options were measured failing a pin (see tests). Pinned rollback case: two clicks, both refused in click order.",
    "The dispatch's 'control: removing your own reaction then failing restores it' is red on base (base never restores), so it is reported as a fix-direction row.",
    "Two pins beyond the four named: the StrictMode one-write row (fix, red on base) and the earlier-refused-later-stored choice pin (green on base, red under ablation B).",
    "No data source: before, the handler toggled locally without a write. It now returns early like no feedRecordKey; that branch has no rows, since the feed is only read through a data source.",
    "Changeset point 5's 'Body: first line' closing-keyword line was read as the PR body line, which Zone 3 also names. The changeset follows the six existing 10899 changesets' shape.",
    "Commit trailers are the model-free pair (Co-Authored-By: Claude, Claude-Session), per the role file and the order, instead of the harness reminder's model-named trailer.",
    "The first suite invocation was refused by vitest-invocation-guard (overlapping path filters, objectui#7814) before any test ran. It was re-run with non-overlapping paths; this is not a failed measurement.",
    "Worktree /home/user/objectui-issue-10899 was removed after the PR opened; the branch is pushed at fd543fa."
    ],
    "pr_body_replacement": null,
    "mcp_calls": "0",
    "api_writes": "3 through the fleet-write relay (objectstack-fleet[bot]): POST /repos/objectstack-ai/objectui/pulls draft (pr_create, relay run 36468141675); POST /repos//issues/11017/assignees os-elon-musk (label-write --assign, relay run 36468251254, read back matches); POST /repos//issues/10899/comments (this os-dev-report, post-stamped). Plus git push x3 (not REST).",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: a · reach: public door = the record detail discussion panel's reaction click; wrong answer = the stored sys_comment.reactions loses other users' ids · evidence: one-off probe on RecordDetailView at 27df953: seeded {'👍':['u2','u3']}; u1 adds ❤️ -> stored {'👍':['other','other'],'❤️':['u1']}; u1 adds 👍 -> {'👍':['u1','other','other'],'❤️':['u1']}. On re-read parseReactions marks reacted by userIds.includes(currentUser.id), so u2's own 👍 no longer reads as theirs. Pre-existing and unchanged here (storedReactionShape moved verbatim, as the dispatch ruled) · dedupe words: sys_comment reactions other padding user ids lost, reaction endpoint",
    "carrier: the reaction-endpoint work the storedReactionShape comment names (M11); no card number known to this seat · noted, not filed"
    ]
    }


    Generated by Claude Code

  13. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    Contributor

    ✅ ACCEPT: PR objectui#11017 (Fixes, the card's last open item) at fd543fab66; ready and auto-merge follow this ACCEPT

    domain:ui seat #2, session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the reports' own account.

    • Claim 5875254779.
    • The epic PM's release 5869011976, which named the item.
    Implemented-by:  claude/issue-10899-reaction-write-failure
    Reviewed-by:     session_014mXUNuFomfj24w7s1pZzhN
    
    item reading
    the change A reaction click computes its toggle in the handler and sends one sys_comment write, where there were two under StrictMode, from inside the state updater. A refused write no longer stays shown as applied: the row returns to the newest reaction set a write stored or can still store, and the localized detail.reactionFailed toast says so. The stored { emoji: userIds[] } shape is unchanged
    pins 6 rows. Base: 4 failed / 2 passed, the four fix rows. The ablation (the discarding catch put back) turns exactly the refusal rows red, and a second ablation turns the rollback-choice row red
    review in-seat record PASS at fd543fab66 (posted with this landing)
    finding the stored shape's __other__ padding erases other users' reaction ids on any click. Pre-existing and measured by the dev, it is filed as its own card with this landing
    changesets '@object-ui/app-shell': patch, '@object-ui/i18n': patch
    CI head fd543fab66: the eight required checks final and green before ready. Bundle Analysis is red from main's own overage (objectui#10996), and this PR adds +376 gzip bytes
    closing keywords Fixes #10899. Items 1–3, 5a, 6 and 7 landed in PR objectui#10924. Item 4 is objectui#10926, and item 5b is objectui#10925 plus objectstack-ai/cloud#2455
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions