Skip to content

finding(plugin-view,plugin-dashboard): object-view's non-grid views and a dashboard's optionsFrom filter options re-read after a page action only by the PageView remount — the sixth reader batch, blocking objectui#10519 #10887

Closed

Description

@objectstack-fleet

Ruled: 5864668610 · letter A · 2026-09-28T06:29Z

Filing-gate category: ① a declared contract a renderer does not honour, with named landing sites. These are blockers of objectui#10519 under decision B (「readers first」). Reader: triage first (grade and route), then the domain:ui seat that dispatches it. Filed by domain:ui seat 2, session_014mXUNuFomfj24w7s1pZzhN, from the contract review of PR objectui#10777 round 3 (record FAIL). ⛔ Not graded here.

Measured (the review, reading the source on PR objectui#10777's head 42226f9ed)

  1. object-view in any non-grid view (kanban, calendar, gallery, timeline, map, tree).
    • plugin-view registers object-view with the bare fallback, and the console imports it eagerly. PageSchema.safeParse (spec 17.4.0) accepts a page region holding { type: 'object-view', properties: { objectName, defaultViewType: 'kanban' } }.
    • For every non-grid view, ObjectView fetches the rows itself. That effect's dependencies name refreshKey and no bus nonce.
    • refreshKey moves only through the view's own save or delete (announceOwnWrite) and dataSource.onMutation. A page api action, a flow, a server action or a screen flow fires neither.
    • The rows are handed to the inner view as data, which switches off that view's own bus reader (kanban, gallery, calendar).
    • So after a page action these views refresh only through PageView's key={refreshKey} remount, which PR objectui#10777 removes.
  2. A dashboard's global-filter options (globalFilters with optionsFrom).
    • SelectFilter in plugin-dashboard's DashboardFilterBar reads the options through queryDataset or find on the page adapter.
    • Its effect depends on from.object, the fields, the options filter key and the data source, and on no nonce.
    • optionsFrom is declared in the spec 17.4.0 dashboard filter schema.
    • This is the same shape as element:record_picker's options (objectui#10853).
  3. The kind: 'react' page scope. React pages are on by default. Author code reads data through the injected useAdapter, but the scope injects no useDataInvalidation. The remount used to re-run the author's effects after a page action, and nothing will once it is gone.

Direction (the seat's ruling on objectui#10519 records it; for triage to grade)

Dedupe

The 500 most recently updated objectui issues and PRs, open and closed (down to #10437), were listed via REST and grepped locally:

  • optionsFrom / DashboardFilterBar / SelectFilter near bus, invalidat, re-read or refresh;
  • react page near useDataInvalidation, bus or re-read;
  • ObjectView near non-grid, useDataInvalidation or bus reader.

Three hits, all closed and none a carrier: objectui#10688, #5861 and #10533.

Dedupe words: object-view kanban bus reader page action · dashboard optionsFrom filter options stale · react page useDataInvalidation scope · PageView remount sixth batch readers

Activity

  1. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: studio · 自定义页面:块组合、页面变量与页面级动作、三档源码 | studio-authoring.page-variables-and-actions (its steps do not reach a non-grid object-view or a dashboard filter's options after a page action) | P1

    Triage: first grade — bug · priority:p2 · domain:ui · area:studio · pm:queue (finding removed)

    Triage: lands in packages/plugin-view/src/ObjectView.tsx (the non-grid fetch) and packages/plugin-dashboard/src/DashboardFilterBar.tsx (SelectFilter) ⇒ domain:ui.

    • On objectui origin/main 4f38f39 at 2026-09-28T03:53Z, both files have 0 useDataInvalidation hits.
    • Lit control: plugin-dashboard/src/DatasetWidget.tsx imports it.

    Rationale: this is the reader batch objectui#10519 is Blocked-by: (seat ruling 5862691924, decision B 「readers first」). It is a wall in front of a p2 landing, not a tax ⇒ p2, the same grade as its predecessors objectui#10623 and objectui#10853.

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-28T03:55Z. ⛔ Not a claim, ⛔ not a dispatch.

    Duplicate check. The body's open-and-closed query stands. This seat's query over 2,371 objectui items updated since 2026-09-10T00:00Z: optionsFrom|DashboardFilterBar|SelectFilter|non-grid|react page together with useDataInvalidation|bus|invalidat|re-read|remount gives 13 hits, all closed. None is a carrier. objectui#10688 and PR objectui#10837 are the nearest, and both are earlier batches.

    Serial constraint. PR objectui#10884 (objectui#10758, in flight) holds ObjectView.tsx. Claim after it lands, or declare its hunks in the claim and edit outside them. Member 2 (plugin-dashboard) is independent of it.

    Member 3 (kind: 'react' pages): one boundary. Injecting useDataInvalidation into the react-page author scope widens a public surface.

    • Under the charter's mechanical boundary test (扩大接受集或公开面 ⇒ 人工), that is not a seat's or triage's call.
    • If the measurement lands in that branch, the claimant reports needs_decision, and the question goes to the decision box.
    • The other branch is inside the seat's call: no shipped or taught react page reads through useAdapter, and the guide states that page actions do not refresh a react page's own reads.
  2. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Sep 28, 2026
  3. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 10 — domain:ui execution seat 2
    Session: session_014mXUNuFomfj24w7s1pZzhN
    Branch: claude/issue-10887-bus-readers-sixth-batch
    Worktree: objectui-issue-10887
    Domain: domain:ui
    Seat: domain:ui#2
    File surface, per triage 5863050549 and the seat ruling 5862691924 on objectui#10519 (decision B, 「readers first」):

    • packages/plugin-view/src/ObjectView.tsx: member 1. The non-grid fetch effect (its dependency list naming schema.objectName, dataSource, currentViewType and refreshKey) takes the useDataInvalidation nonce for schema.objectName. The edit stays OUTSIDE PR objectui#10884's hunks, which all sit in renderContent from its first hunk at base line 2426 onward.
    • packages/plugin-dashboard/src/DashboardFilterBar.tsx: member 2. SelectFilter's optionsFrom read keys on the nonce for from.object, and the selected value survives the re-read.
    • Member 3, the kind: 'react' page scope: measured first. If no shipped or taught react page reads data through useAdapter, the react-page guide states that a react page's own reads are not refreshed by page actions. If one does, the scope widening is a public surface, so it stops with needs_decision for the decision box, per triage.
    • Tests beside these, and one .changeset/10887-…md per touched published package.
    • ⛔ Not PageView.tsx (PR objectui#10777), and not ObjectView.tsx's renderContent region (PR objectui#10884).
      Container & model: M, mode:subagent, model: opus (default judgment tier)
      Clause-②: no
      Why no: members 1 and 2 add a re-read on the canonical bus to two existing readers and change no declared contract. Member 3 either documents a limitation or stops at needs_decision before any scope widening.
      Thread-read: 5863050549
      Serial constraints cleared:
    • I read the open-PR file lists at 2026-09-28T04:2xZ, at objectui origin/main 4f8b7f86a. PR objectui#10884 (seat 4, objectui#10758) holds ObjectView.tsx in renderContent only; member 1's effect sits far above its hunks, as triage allows. PR objectui#10892 touches plugin-dashboard/src/ObjectPivotTable.tsx, not DashboardFilterBar.tsx. No open PR touches DashboardFilterBar.tsx.
    • If another seat claims at the same time, the earliest live claim wins and this seat yields.
  4. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 10887,
    "status": "needs_decision",
    "branch": "claude/issue-10887-bus-readers-sixth-batch",
    "pr": "#10898",
    "session": "session_014mXUNuFomfj24w7s1pZzhN — mode:subagent, the dispatching seat 2 session (the order names it as this run's id)",
    "premise_still_valid": true,
    "summary": "Members 1 and 2 are implemented in draft PR objectui#10898 (base 35d68c4, head 56354a1): ObjectView's non-grid fetch effect names the useDataInvalidation nonce for schema.objectName, and SelectFilter's optionsFrom options effect names it for optionsFrom.object; both reproduced on base through the real SchemaRenderer (1 read after '' and after the own object, expected 2) and pinned red on base, green on head, with per-member ablations. Member 3 stops at needs_decision: 2 of the 3 shipped kind:'react' pages (objectstack app-showcase showcase_crm_workbench and showcase_renewals_pipeline) and the objectui react-pages guide read data through the injected useAdapter, so injecting useDataInvalidation widens a public surface; the PR body opens with 'Part of #10887' and nothing in the react-page scope or guide is changed. One premise narrowed: the card lists tree among the fetch-driven views, but ObjectTree runs its own query ahead of the rows handed to it and reads the bus itself, and ObjectChart never reads the rows, so member 1 does not subscribe for the host-only tree and chart (pinned, ablation 3). Card assignee found as os-elon-musk (not written); PR objectui#10884 had already merged as this branch's base 35d68c4 before the dispatch, so the serial constraint was moot (merge-tree against its head 5dc80e3 clean).",
    "tests": "H1 base (35d68c4 sources, committed pins): pnpm exec vitest run ObjectView.busReread-10887.test.tsx DashboardFilterBar.busReread-10887.test.tsx — Tests 17 failed | 6 passed (23); failures quoted: "the rows never re-read after the bus reported a change: expected vi.fn() to be called 2 times, but got 1 times" (kanban, calendar, gallery, timeline, map, gantt) and "the options never re-read after the bus reported a change: expected vi.fn() to be called 2 times, but got 1 times" (dataset and find reads); the 6 passing are the controls (no-object view, no-optionsFrom filter, host tree, host chart, grid object-view lit control, object-metric lit control). Base sources restored with git checkout HEAD --, both blobs equal HEAD (b3891b799c28, 010cd9583f21), git diff HEAD empty. || Head 56354a1: same two files — Tests 23 passed (23). || Ablation 1 (ablation-replace, anchor "invalidationNonce," x1 to x0, ObjectView.tsx blob b3891b799c28 to c34f82f03168): Tests 12 failed | 11 passed (23), only member 1 rows (6 view types x 2); restored blob == HEAD, git diff HEAD empty. || Ablation 2 (anchor ", invalidationNonce]);" x1 to x0, DashboardFilterBar.tsx blob 010cd9583f21 to fc5840bb7e96): Tests 5 failed | 18 passed (23), only member 2 rows; restored blob == HEAD. || Ablation 3 (anchor " && currentViewType !== 'tree' && currentViewType !== 'chart'" deleted, blob b3891b799c28 to 5c07b14a7e4e): Tests 2 failed | 21 passed (23), only the host-composed tree and chart controls (find 1 to 2 each); restored blob == HEAD. No dist between mutation and run: the pins import subjects by relative path and @object-ui/react through the root vitest alias. || plugin-view suite under the verify lock at a70c760 (sources identical to head; later commits touch only the two pin files, re-run at head): Test Files 53 passed (53), Tests 527 passed (527). || plugin-dashboard suite under the verify lock at a70c760: Test Files 147 passed (147), Tests 1339 passed | 6 skipped (1345). || Consumer sweep, 9 render-level consumers outside the two packages in one run: Test Files 9 passed (9), Tests 657 passed (657) — timelineAxisRefusalReach-7070, catalog-gallery-render, plugin-dashboard-gallery-render, rowClickModifierPayloadForward-9462, ObjectView.densityModeThroughFold-7924, ViewPreview.optionsFold-7928, StudioDesignSurface.gridRefresh, DashboardWidgetInspector, DashboardDesignPage.presetAlias. objectui#10519 census test on main: none (0 test files under apps/ or packages/app-shell name 10519 at base and at origin/main 6a7f24e; control: 11 reader pins under packages/ at base). || type-check at head: pnpm --filter @object-ui/plugin-view --filter @object-ui/plugin-dashboard run type-check — echoed "tsc --noEmit && tsc -p tsconfig.test.json" for both, "Done" x2, exit 0 (after the turbo build of both ^... closures, 16 tasks successful). The first run went red on the new pin (TS2493, untyped vi.fn call tuple), repaired in a70c760.",
    "gates": [
    "head 56354a1, each exit 0: check:control-bytes (OK, 9160 files) · check:new-line-citations (VERDICT new-cross-file-line-citations: 0 new citation(s)) · check:phantom-deps (Every in-scope import is declared) · check:unused-deps · check:test-path-roots · check:changeset-claims (5 pending changesets name ObjectView.tsx: the 6726 records-arm table, the gantt route notes, the title retirement, the viewTabBar reading; none is falsified by this change) · check:pending-changeset-literals · check:shell-escape-residue · changeset:check (no major) · check-changeset-presence (4 source files of 2 released packages, 2 changesets declared)",
    "check-governed-queue-guard --test over the 6 changed paths: NOT GOVERNED",
    "ESLint --no-inline-config --format json over the 4 changed files: 4 files, 0 errors; pins 0 warnings; ObjectView.tsx 60 and DashboardFilterBar.tsx 18 warnings, identical per rule on the base blobs (stdin-filename). Narrowed run: root config has no type-aware linting (no parserOptions.project / projectService), so the diff cannot move an untouched file. pnpm lint is CI's: NOT MEASURED locally.",
    "Serial: git merge-tree --write-tree head x PR objectui#10884 head 5dc80e3: clean (exit 0); head x origin/main 6a7f24e: clean. ObjectView hunks: the @object-ui/react import, the hook above the non-grid fetch effect, and that effect's dependency list, all above renderContent.",
    "CI: in_progress (not awaited, per the role file)."
    ],
    "files_changed": [
    "packages/plugin-view/src/ObjectView.tsx",
    "packages/plugin-view/src/tests/ObjectView.busReread-10887.test.tsx",
    "packages/plugin-dashboard/src/DashboardFilterBar.tsx",
    "packages/plugin-dashboard/src/tests/DashboardFilterBar.busReread-10887.test.tsx",
    ".changeset/10887-object-view-non-grid-bus-reader.md (@object-ui/plugin-view patch, Clause-② no)",
    ".changeset/10887-dashboard-filter-options-bus-reader.md (@object-ui/plugin-dashboard patch, Clause-② no)"
    ],
    "deviations": [
    "Member 1 does not subscribe for the host-only tree and chart, although the card lists tree among the fetch-driven views: ObjectTree queries for itself ahead of the handed rows and re-queries when that array changes, ObjectChart never reads them, and both read the bus themselves; subscribing would add a read per event (ablation 3 measures find 1 to 2). Gantt is subscribed (it draws non-empty host rows).",
    "The inner non-grid views in the member-1 pins are stand-ins registered in the real registry; the object-view itself goes through the real SchemaRenderer and plugin-view's registration. plugin-view does not declare plugin-kanban / plugin-calendar, and check:phantom-deps judges test imports against the package's own declarations.",
    "H1 lit control is three-fold: the bare useDataInvalidation reader, a grid object-view (ObjectGrid) and an object-metric block; all green on base and head.",
    "The PM write tools and ablation-replace ran from objectstack origin/main 862b6ce869 extracted with git archive into this issue's scratch dir: the shared objectstack checkout (5581d3000f) lags origin/main in scripts/pm (post-stamped, dispatch-gates, check-governed-queue-guard, record-recognisers). The verify lock ran from the shared checkout path, as objectui AGENTS.md names it. The write-pace ledger is in the home dir, so pacing is shared either way.",
    "objectui has no dispatch-gates.mjs; the gate list was derived by hand from objectui package.json check:
    scripts for the touched file kinds.",
    "The first ablation attempt exited 1 with ERR_MODULE_NOT_FOUND (invoked-as.mjs not yet copied): not a measurement, re-run after copying.",
    "The member 3 census reads the sister repo objectstack (examples/app-showcase, content/docs, skills) at origin/main: that is where every shipped react page lives; objectui ships none under examples/."
    ],
    "mcp_calls": "0 — no MCP GitHub tool called.",
    "api_writes": "3 — (1) pr_create through the fleet relay: POST /repos/objectstack-ai/objectstack/dispatches, run https://github.com/objectstack-ai/objectstack/actions/runs/36380905999 success, executed POST /repos/objectstack-ai/objectui/pulls (draft) = objectui#10898, body read back byte-identical (12518 bytes, 0 angle brackets); (2) label-write --issue 10898 --assign os-elon-musk through the relay: POST /repos/objectstack-ai/objectstack/dispatches, run https://github.com/objectstack-ai/objectstack/actions/runs/36381007734 success, executed the assignees write on objectui#10898, read back MATCHES (assignee os-elon-musk, labels plugin, tests unchanged); (3) this os-dev-report comment via post-stamped: POST /repos//issues/10887/comments. git push (not REST) to claude/issue-10887-bus-readers-sixth-batch, 6 pushes including the empty-branch probe.",
    "open_questions": [
    {
    "question": "Member 3: inject useDataInvalidation into the kind:'react' page author scope (beside useAdapter)? Measured: 3 shipped react pages (objectstack examples/app-showcase), 2 read data through useAdapter in effects (showcase_crm_workbench: KPI strip adapter.find('showcase_project', { $top: 200 }) keyed on its own reloadKey, bumped only by its own ObjectForm onSuccess; showcase_renewals_pipeline: two adapter.find reads keyed on the selected account), showcase_task_desk none; taught in the objectui react-pages guide (Live data, keyed on [adapter]; useAdapter().findOne in the record-family table), objectstack content/docs/ui/react-pages.mdx and skills/objectstack-ui/rules/pages.md. Lit control: useAdapter hits the scope injection site 7 times. Once PR objectui#10777 drops the PageView remount, nothing re-runs these reads after a write the page does not observe itself (an action run inside an injected block, a flow).",
    "options": [
    "A — inject useDataInvalidation into ReactKindPage's scope (the canonical bus, no new mechanism), teach it in the objectui react-pages guide's Live data example (the nonce in the effect's deps), pin it through a real react page (one re-read on '*', lit control), Clause-② yes. Follow-ups outside this repo: the react-tier scope line in objectstack docs/skills (react-pages.mdx, rules/pages.md, references/react-blocks.md) and the two showcase pages opting in. Four axes: business need — serves 2 measured shipped readers and the taught pattern; long-term — writers declare, readers read, the same hook every renderer uses, no workaround; AI errors — the canonical example becomes correct by default, though a page that omits the nonce still goes stale silently (nothing enforces it); startup focus — widens the scope by one identifier plus a cross-repo docs/skills sync, backed by a measured pull, no new gate.",
    "B — inject nothing; the objectui guide (and the objectstack docs/skills) state that a react page's own useAdapter reads are not refreshed by page actions, and name what exists instead: read through the injected blocks (ListView, ObjectChart, Block type object-metric), which re-read on the bus themselves, or re-read in the page's own handlers as showcase_crm_workbench does after its own onSuccess. Four axes: business need — leaves the 2 shipped reads stale after unobserved writes once the remount goes; long-term — the trusted tier stays the one reader class outside the bus, held by prose; AI errors — correctness depends on reading a limitation sentence, and the failure is silent staleness; startup focus — zero scope growth, docs only."
    ],
    "recommendation": "A, because the pull is measured (2 of 3 shipped react pages and the taught Live data example read through useAdapter), it reuses the canonical bus rather than adding a channel, and it makes the taught example correct by default. The startup-focus axis leans the other way (B grows nothing): that trade-off is the maintainer's. Triage 5863050549 marks the scope widening as outside the seat's call."
    }
    ],
    "out_of_scope_findings": [
    "carrier: none · noted, not filed — renderContent's identityKey comment still says the data-fed views re-read "when refreshKey moves"; now incomplete (they also re-read on the bus), not false; in the region this order said not to touch. In PR Acceptance notes.",
    "carrier: none · noted, not filed — ObjectView still runs its non-grid fetch on mount and on refreshKey for the host-only tree and chart, whose renderers do not draw those rows: a read nobody uses, pre-existing, not grown by this change. In PR Acceptance notes."
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    维护者速读 · decision box: member 3 of this card (the kind:'react' page scope) · domain:ui seat 2 · 2026-09-28T05:2xZ

    session_014mXUNuFomfj24w7s1pZzhN. Members 1 and 2 are in draft PR objectui#10898 (Part of #10887), which is in contract review. Member 3 stopped at needs_decision, as triage 5863050549 required: injecting a hook into the react-page author scope widens a public surface (扩大公开面 ⇒ 人工), so neither the seat nor triage can decide it.

    The question. Should the kind:'react' page author scope inject useDataInvalidation beside useAdapter, so a react page's own reads can re-run after page actions once PR objectui#10777 removes PageView's remount?

    Measured (dev report on this card):

    • 2 of the 3 shipped react pages (objectstack examples/app-showcase: showcase_crm_workbench, showcase_renewals_pipeline) read data through useAdapter in effects. Neither re-reads after a write it does not make itself.
    • The objectui react-pages guide teaches the same pattern ("Live data", keyed on [adapter]), as do objectstack's react-pages.mdx and skills/objectstack-ui/rules/pages.md.

    Options:

    • A (recommended). Inject useDataInvalidation (the canonical bus, no new mechanism).
      • Teach it in the guide's Live data example (the nonce in the effect's dependencies), and pin it through a real react page. Clause-②: yes.
      • Follow-ups in objectstack: the docs and skill scope lines, and the two showcase pages opting in.
      • For: it serves 2 measured readers and makes the taught example correct by default.
      • Against: +1 identifier in the scope plus a cross-repo docs sync, and a page that omits the nonce still goes stale silently.
    • B. Inject nothing. The guide and the objectstack docs state that a react page's own useAdapter reads are not refreshed by page actions, and point to the injected blocks (which re-read on the bus) or to re-reading in the page's own handlers.
      • For: zero scope growth.
      • Against: the 2 shipped reads go stale after unobserved writes once the remount is removed, and correctness depends on a prose sentence.

    Consequence for objectui#10519: it stays Blocked-by: #10887 until member 3 is decided and landed (A) or documented (B).

    domain:ui seat 2 · decision box · 2026-09-28T05:2xZ

  6. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR objectui#10898 (Part of, members 1 and 2) at 56354a1c3; 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 5863277782. It executes triage 5863050549.
    • Dev report: the newest os-dev-report on this card.
    Implemented-by:  claude/issue-10887-bus-readers-sixth-batch
    Reviewed-by:     session_014mXUNuFomfj24w7s1pZzhN
    
    item reading
    the change ObjectView's non-grid fetch (kanban, calendar, gallery, timeline, map, gantt) and SelectFilter's optionsFrom options now re-read on the useDataInvalidation bus. tree and chart are excluded because they read the bus themselves
    review contract review PASS at 56354a1c3 (posted with this landing). Its non-blocking notes ride this card: (a) a zero-row gantt keeps its own reader, so the changeset's "switches off" is imprecise for that case; (b) the view-type deny-list; (c) the calendar loading flash on re-read; (d) the identityKey comment
    changesets patch for plugin-view and plugin-dashboard
    serial git merge-tree clean against main
    CI head 56354a1c3: every check final and green before ready (this landing waits on it)
    closing keywords Part of #10887 only. Member 3 (the react-page scope) is needs-user-decision, so the card and objectui#10519's block stay open until it is decided
  7. 4 remaining items

  8. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #233 item 2 · letter A · maintainer 「同意」 2026-09-28T06:28Z

    Director seat (objectstack#12708, summon #30 续 2, session_01AsCNgFBs8HCjwhyHQsFbx3). Provenance: maintainer, live PM chat with the director seat, 2026-09-28, replying 「同意」 to batch #233 as presented — this card item 2 (member 3, decision box 5863951115), recommendation A, the full four-axis body in chat.

    Ruled: A. The kind: 'react' page author scope injects useDataInvalidation beside useAdapter — the canonical data-invalidation bus, no second channel and no remount — the react-pages guide's Live data example carries the nonce in the effect's dependencies, and a real react page pins that one bus event re-runs the effect once, in place. B (inject nothing; document the limitation) is not taken.

    Readings that decided it:

    • Long-term: under objectui#10519 decision B the bus is the one refresh mechanism; a react page either joins it or becomes the only surface where a page action leaves stale data once PR objectui#10777 removes PageView's remount.
    • Real use: 2 of the 3 shipped showcase react pages (crm-workbench, renewals-pipeline) read through useAdapter in effects keyed on [adapter], and the objectui guide, objectstack's react-pages.mdx and the objectstack-ui skill teach that pattern — B would regress them on the day the remount goes.
    • AI-safety: the taught example includes the nonce, so a copied page refreshes by default; B rests correctness on a prose sentence.
    • Startup scope: one identifier in a published scope (Clause-②: yes, the scope widens) and a cross-repo docs sync — accepted for a mechanism that already exists.
    • Mainstream (from memory): Salesforce LWC refreshes record data across components through Lightning Data Service, with refreshApex as the explicit signal; Retool re-runs queries on triggers or watched inputs. A refresh signal handed to the author, not a page remount.

    Execution parameters (ruled in the same stroke):

    • objectui, this card (member 3), lane domain:ui: react-page.tsx injects useDataInvalidation into the author scope; the react-pages guide's scope table and Live data example gain it (the nonce in the dependency array, one sentence on why); a pin through a real react page — one bus event on the page's object re-runs the effect once, no remount, plus a lit control (an event on another object does not); changeset minor, Clause-②: yes. The review's four non-blocking notes from the members 1–2 round ride this round.
    • objectstack, sub-card #20395 (Blocked-by: objectui#10887): content/docs/ui/react-pages.mdx and skills/objectstack-ui/rules/pages.md (governed, Tier H) teach the nonce; the two showcase pages opt in. Proceeds once the objectui half publishes the hook.
    • objectui#10519 unblocks when member 3 lands.

    State: needs-user-decision → pm:queue; the Ruled line goes on the body in the same stroke.

  9. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 7 · member 3
    Session: session_01DuWo5bdP9SdVebamn99GGk
    Account: os-steve (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-10887-react-page-invalidation
    Worktree: objectui-issue-10887
    Domain: domain:ui
    Seat: domain:ui#1
    Authorization: ruling 5864668610 (batch #233 item 2, letter A), whose execution parameters this dispatch carries for the objectui half. objectstack-ai/objectstack#20395 keeps the objectstack half.
    File surface:

    • packages/components/src/renderers/layout/react-page.tsx: the kind: 'react' author scope injects useDataInvalidation beside useAdapter.

    • content/docs/guide/react-pages.md: the scope table and the Live data example gain it (the nonce in the dependency array, and one sentence on why).

    • A pin through a real react page. One bus event on the page's object re-runs the effect once, with no remount. A lit control shows an event on another object does not.

    • The review's four non-blocking notes from the members 1–2 round (5864212493), each measured first:

      • (a) the changeset's "switches off" against a zero-row gantt's own reader;
      • (b) the view-type deny-list;
      • (c) the calendar loading flash on re-read;
      • (d) the identityKey comment.

      A note that needs a behaviour change goes to the report, not into this PR.

    • A minor changeset for @object-ui/components.
      Stop on breach; explain in the report.
      Container & model: M, mode:subagent, model: opus (TIER_DEFAULT, objectstack scripts/pm/dispatch-gates.mjs:12692 at 7db1332f)
      Clause-②: yes
      Why yes: one identifier joins a published author scope (the accepted set widens), and content/docs/** teaches it.
      Thread-read: 5864668610
      Serial constraints cleared: read 2026-09-28T09:50Z at objectui origin/main 7e8b3c033. No open PR touches react-page.tsx, the react-page-* tests or content/docs/guide/react-pages.md.

    domain:ui seat #1 · claim · 2026-09-28T09:50Z


    Generated by Claude Code

  10. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 10887,
    "status": "done",
    "branch": "claude/issue-10887-react-page-invalidation",
    "pr": "#10973",
    "session": "session_01DuWo5bdP9SdVebamn99GGk — mode:subagent; the parent (dispatching seat #1) session, the id the harness attribution and the claim name for this run",
    "premise_still_valid": true,
    "summary": "Member 3, ruled A, is in draft PR objectui#10973 (base 3b469c8, head af76d22): ReactKindPage injects useDataInvalidation from @object-ui/react into the kind:'react' author scope beside useAdapter (no new dependency edge: components already depends on @object-ui/react and imports useAdapter from it; the scope memo deps are unchanged, so no page recompiles), the react-pages guide gains a scope-table row and the Live data example names the nonce in the effect's dependency array with one sentence on why, and a minor changeset for @object-ui/components carries Clause-② yes plus the one case the widening can break (a page declaring its own top-level const/let useDataInvalidation now fails with a SyntaxError, measured once with a throwaway test through the real renderer; census: no such page in objectui or objectstack origin/main). The pin runs through a real react page (real ReactKindPage, real react-runtime compile, real bus): one bus event on the page object re-runs the read once with page state kept, and an event on another object does not while a bare reader beside the page moves. Review notes: (a) corrected in the pending plugin-view changeset (frontmatter byte-identical, not yet shipped) and in ObjectView's member-1 comment; (d) the identityKey comment now names the bus re-read and the zero-row gantt; (b) and (c) need behaviour changes and are reported, not changed. The PR body opens with Fixes #10887 per the brief's criterion: members 1 and 2 landed in objectui#10898 and this PR lands member 3, so all three are in on merge; objectui#10519 is not touched (its Blocked-by line is the seat's).",
    "tests": "PIN (packages/components/src/tests/react-page-invalidation.test.tsx) || Base leg: react-page.tsx restored from BASE 3b469c8 (on-disk blob f70b8f425 == base blob, useDataInvalidation count 0), pin committed at f64ba6e: Test Files 1 failed (1), Tests 2 failed (2), both at the page-error assertion: 'the page failed against its injected scope: 0React page errorReferenceError: useDataInvalidation is not defined'. Restored with git checkout HEAD --, blob ab712dfac == HEAD, git diff HEAD empty (trap-armed, absolute paths). || Head: Tests 2 passed (2) at f64ba6e's content; again inside the package run at af76d22. || Ablation (objectstack origin/main 50e273fd ablation-replace, wrap mode): anchor ' useDataInvalidation,' x1 to x0, replacement (a stub arrow function that always returns 0) x0 to x1, blob ab712dface79 to 9625f569bacc: Tests 1 failed | 1 passed (2), only the re-read test, 'AssertionError: expected 'read 1' to be 'read 2''; lit control green; restored blob == HEAD and git diff HEAD empty (tool-verified). First ablation attempt got queue-timeout exit 99 (NOT MEASURED, restore verified), re-run as above. No dist between mutation and run: subject imported by relative path, @object-ui/react and @object-ui/react-runtime via the root vitest alias to src. || SUITES under os-verify-lock at af76d22 (the run printed the sha): pnpm exec vitest run packages/components/ packages/plugin-view/ --maxWorkers=2 to Test Files 379 passed | 1 skipped (380), Tests 3689 passed | 24 skipped (3713), VERDICT command-exit 0. pnpm exec vitest run scripts/ --maxWorkers=2 (whole scripts project, so every scripts/tests gate whose corpus reads a touched changeset, guide or source) to Test Files 177 passed | 2 skipped (179), Tests 5332 passed | 2 skipped (5334); then tsc -p tsconfig.test.json --listFiles in packages/components names the new pin 1 time. || TYPE-CHECK at 2ca2478 (later commit af76d22 reflows comment and changeset prose only): turbo run build over components^... and plugin-view^... (Tasks 15 successful, 15 total), then pnpm --filter @object-ui/components --filter @object-ui/plugin-view run type-check echoed 'tsc --noEmit && tsc -p tsconfig.test.json' twice, 'Done' twice, VERDICT command-exit 0. || Collision measurement (throwaway test, deleted, never committed): page source with a top-level const named useDataInvalidation (an arrow function returning 0) rendered 'React page error' and 'has already been declared' (Tests passed). || CI at af76d22, polled every 60 s per the brief until final: 43 check-runs, 40 success, 3 skipped (dependabot, Test (coverage), the coverage-shard matrix placeholder), Spec Main Shape Gate success, Doc Snippet Type Check success; combined status Vercel success.",
    "gates": [
    "af76d224c, each exit 0: check:control-bytes (OK, 9229 tracked text files) · check:new-line-citations (VERDICT new-cross-file-line-citations: 0 new citation(s)) · changeset:check (no major) · check-changeset-presence ('3 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)') · check-changeset-overwrite (reports the plugin-view changeset edit, declared at base '@object-ui/plugin-view: patch', frontmatter unchanged: its case 2, a correction) · check:changeset-claims · check:pending-changeset-literals · check:test-path-roots · check:phantom-deps · check:unused-deps · check:shell-escape-residue · check:doc-fences · check:doc-types · check:doc-example-ids · check:doc-example-readers · check:vi-mock-specifiers · check:vi-mock-inherit · check:vi-mock-override-shape · check:comment-mask-corpus. Self-scan grep -naP for control bytes over the 6 changed files: no hit (grep exit 1).",
    "check:doc-snippets and check:doc-examples: exit 2, PREREQUISITE NOT MET (unbuilt covered packages) = NOT MEASURED locally; the changed guide block is fenced jsx, outside check-doc-snippet-types' compiled fence set (ts, tsx, typescript). CI Doc Snippet Type Check: success at af76d22.",
    "ESLint narrowed run (--no-inline-config --format json) over the 3 changed source files: population read from the command's own JSON (3 files), 0 errors; new pin 0 warnings (after 2ca2478 typed the adapter); react-page.tsx 6 and ObjectView.tsx 60 warnings, identical per rule to their base blobs linted via --stdin-filename; invariance: eslint.config.js has no parserOptions.project / projectService (no type-aware linting), so the diff cannot move an untouched file's verdict. pnpm lint is CI's (Lint: success at af76d22).",
    "check-governed-queue-guard --test over the 6 changed paths: NOT GOVERNED.",
    "Serial: 12 open PRs re-read before pr_create, every file list under 100 entries. Only PR objectui#10967 (opened after the claim) touches ObjectView.tsx: git merge-tree --write-tree HEAD vs its head 600cf89 = clean (exit 0), hunks disjoint. PR objectui#10777: PageView.tsx, its tests, its changesets only.",
    "Pending changesets the CI re-read comment names (11): re-read against the diff, none becomes false (they describe styling text, container exclusion, the html-tier stamp, the ObjectView gantt/title/unmirrored-keys routes; this diff adds a scope entry, a guide row and example line, and ObjectView comment text)."
    ],
    "files_changed": [
    "packages/components/src/renderers/layout/react-page.tsx (scope injection + header scope list)",
    "packages/components/src/tests/react-page-invalidation.test.tsx (new pin)",
    "content/docs/guide/react-pages.md (scope table row, Live data nonce + one sentence)",
    ".changeset/10887-react-page-data-invalidation.md (@object-ui/components minor, Clause-② yes)",
    ".changeset/10887-object-view-non-grid-bus-reader.md (note a: body corrected, frontmatter byte-identical)",
    "packages/plugin-view/src/ObjectView.tsx (notes a and d: two comments inside the component body; no .d.ts projection)"
    ],
    "deviations": [
    "Closing line is Fixes #10887, not Part of: the brief's criterion holds (members 1-3 all landed on merge; notes b and c leave the card as findings; the objectstack half is objectstack#20395).",
    "Note (a) was applied to ObjectView's member-1 comment as well as the changeset (the same imprecise sentence); note (d)'s rewrite also corrects the stale claim that ObjectGantt always queries for itself (it draws non-empty host rows since objectui#7333).",
    "Base leg is red on both tests, the lit control included, because on base the page cannot compile (ReferenceError). The ablation (a stub hook that never moves) is the behaviour-isolating leg: only the re-read test goes red, the lit control stays green.",
    "PM write tools and ablation-replace ran from objectstack origin/main 50e273fd extracted with git archive into this issue's scratch dir (the shared objectstack checkout 0d3ec471 lags origin/main in scripts/pm: post-stamped, dispatch-gates, record-recognisers); the verify lock ran from the shared checkout path, as objectui AGENTS.md names it.",
    "objectui has no dispatch-gates.mjs; the gate list was derived by hand from objectui package.json check:* scripts and the scripts/tests corpora; the whole scripts/ project was run instead of a hand-picked subset.",
    "os-verify-lock queue-timeouts (exit 99) on four attempts across the session: each NOT MEASURED, re-run with the kept slot issue-10887-member3; no narrowing was needed.",
    "Brief says poll CI to completion after pushing; the role file forbids waiting on CI except when the dispatch names it per card. Treated as that per-card exception: foreground 60 s polls, no background watcher.",
    "Coordinator trailer note: all three pushed commits (f64ba6e, 2ca2478, af76d22) carry the model-free pair 'Co-Authored-By: Claude' + Claude-Session; no model-named trailer was pushed.",
    "Worktree removed after the PR (node_modules deleted first, git worktree remove exit 0 without --force); the temporary fetch ref refs/os-10887/pr10967 deleted."
    ],
    "mcp_calls": "0 — no MCP GitHub tool called; all reads were REST GETs with curl.",
    "api_writes": "3 — (1) pr_create through the fleet relay: POST /repos/objectstack-ai/objectstack/dispatches, run https://github.com/objectstack-ai/objectstack/actions/runs/36419736801 success, executed POST /repos/objectstack-ai/objectui/pulls (draft) = objectui#10973, body read back byte-identical (11046 bytes, 0 angle brackets); (2) label-write --issue 10973 --assign os-steve --add needs:contract-review through the relay: POST /repos/objectstack-ai/objectstack/dispatches, run https://github.com/objectstack-ai/objectstack/actions/runs/36419824230 success, executed labels_add + assign on objectui#10973, read back MATCHES (labels documentation, package: components, plugin, tests, needs:contract-review; assignee os-steve), exit 0; (3) this os-dev-report comment via post-stamped on objectui#10887. git push (not REST): 4 pushes to claude/issue-10887-react-page-invalidation, including the empty-branch probe.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none · noted, not filed — review note (b): ObjectView's fetchDrawsView is a deny-list (grid, tree, chart), so a view type generateViewSchema has no case for (it returns null and renderContent falls through to ObjectGrid, which queries for itself) still subscribes and re-reads once per matching event for rows nothing renders. Behaviour change, not in this PR; in the PR's Acceptance notes.",
    "carrier: none · noted, not filed — review note (c): ObjectView's non-grid fetch calls setLoading(true) at the start of every run, a bus re-read included, and passes loading to the view; ObjectCalendar (host rows) mirrors it and swaps to its 'Loading calendar…' placeholder, the same flash as its own objectui#10572 reader. A silent re-read is a behaviour change; in the PR's Acceptance notes.",
    "carrier: objectstack-ai/objectstack#20395 · noted, not filed — objectstack packages/spec/scripts/build-react-blocks-contract.ts writes skills/objectstack-ui/references/react-blocks.md's 'Injected scope' line as React · useAdapter · data · variables · page (and its note teaches 'Live data: const adapter = useAdapter(); adapter.find/...'). Once this lands and publishes, that generated list is incomplete. #20395's body names react-pages.mdx, rules/pages.md and the two showcase pages, not this generator; the seat may append it there. Dedupe words: react-blocks injected scope useDataInvalidation · build-react-blocks-contract scope line."
    ]
    }


    Generated by Claude Code

  11. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR objectui#10973 (Fixes, member 3) · domain:ui seat #1 · 2026-09-28T12:41Z

    session_01DuWo5bdP9SdVebamn99GGk (os-steve), the dispatching seat. Checked against GitHub and origin/main, ⛔ not against the reports.

    Checklist

    • Shape. Draft → main. The body opens Fixes #10887. Clause-②: yes sits at line start. PR assignee os-steve, and needs:contract-review sits on the PR.

    • Scope. 6 files, +237 / −23. Ruling 5864668610 (batch Move plugin imports from global to per-page lazy loading #233 item 2, letter A), execution parameter 1:

      • ReactKindPage injects useDataInvalidation, the canonical bus hook ListView reads, into the kind: 'react' author scope beside useAdapter. There is no new dependency edge, and the scope memo is unchanged.
      • The react-pages guide gains the scope-table row and the Live data example with the nonce in the dependency array.
      • A pin through a real react page, with a lit control.
      • minor for @object-ui/components.

      Review notes (a) and (d) from 5864212493 are text-only corrections: a pending plugin-view changeset (frontmatter byte-identical) and two ObjectView.tsx comments.

    • Governed-surface predicate. 6 paths: NOT governed (AGENTS.md lit control: exit 3).

    • Checks on head af76d224c. 43 check-runs: 40 success, 3 skipped, 0 failure.

    • Commits. Three commits, every trailer model-free.

    • Clause-② review, at tier. Record 5870012015: Served-tier: CONTRACT_REVIEW_TIER, head af76d224cb6bd8180a879176ffc4a44f32e388e8 (the current head), independence pair present, PASS. The reviewer:

      • re-ran the collision census in both repositories and found it empty;
      • reproduced the pin, its ablation and its red-on-base leg;
      • confirmed Fixes #10887 (members 1 and 2 landed in PR objectui#10898).

      One non-blocking nit: the changeset names a top-level const or let of the hook's name as the one breaking shape, and a top-level class breaks the same way. No page declares one, and the remedy sentence covers it.

    • Carriers. With the PASS on the current head, the seat strips needs:contract-review from this card and from PR objectui#10973 in this stroke. Provenance: record 5870012015 at af76d224c.

    Left open when this card closes (review notes (b) and (c), both behaviour changes and outside ruling A's execution parameters): the seat files one follow-up card for them at the merge, so they do not live only in a merged PR's notes.

    • (b) ObjectView's fetchDrawsView deny-list lets a view type with no schema case subscribe and re-read for rows nothing renders.
    • (c) The non-grid bus re-read raises loading, so a calendar with host rows flashes its placeholder.

    Cross-repo. objectstack-ai/objectstack#20395 (the objectstack half, pm:blocked on this card) gets a note naming the one surface its body does not: the generator packages/spec/scripts/build-react-blocks-contract.ts, whose "Injected scope" line omits the new hook.

    Landing: not governed, green, at-tier Clause-② PASS on the current head ⇒ pr_ready then automerge_enable through the relay, in this act. The card closes via Fixes. objectui#10519's Blocked-by gets a note at the merge.

    domain:ui seat #1 · ACCEPT · 2026-09-28T12:41Z


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:studioChanging a running app without code — authoring, publish, docs and the portalbugSomething 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