Repository navigation
[finding] ObjectTree carries the SAME provider: 'value' short-circuit as objectui#8769 / objectui#9061 — inline filter and the row ceiling silently dropped #9136
Description
Found while porting objectui#8769's repair to ObjectCalendar and ObjectMap on objectui#9061. That card's brief fenced the work to TWO renderers and directed any further surface to be REPORTED rather than fixed, so this is that report. Not claimed.
The fourth surface
packages/plugin-tree/src/ObjectTree.tsx carries the same provider: 'value' exit the gantt, the calendar and the map carry: inside its record effect, an inline branch that calls setRecords plus setRowCeiling with truncated false and RETURNS, before the dataSource.find(...) a few dozen lines above it. Re-derive the site by symbol — dataProvider === 'value' — rather than by line number.
That find is the only site in the file that lowers schema.filter onto $filter and the objectui#7210 ceiling onto $top, and it is the only caller of applyNonGridRowCeiling there.
Two dropped keys here, not three
ObjectTree never reads schema.sort at all. A grep of the whole file for convertSortToQueryParams and for schema.sort returns zero hits, on either provider. So the inline path drops filter and the row ceiling, and sort is a separate question about the OBJECT path as well — not part of this one.
Failure direction — the same fail-OPEN
The dropped key is the key that NARROWS, so the author is shown MORE rows than declared, with no diagnostic. Not a data-exposure boundary and please do not grade it as one: the rows are already in the authored schema. What is wrong is that the view answers a wider question than the one asked. Triage graded the gantt instance p2 on exactly that reading, and objectui#9061 was anchored to it.
⭐ The ceiling half is sharper on this view than on the other three. ObjectTree's own query comment records that the tree is the view the ceiling's VALUE was measured on — about 5.2 DOM elements per record with no virtualisation, "the binding one of the four" — so an uncapped inline tree is the most expensive of the four uncapped inline views.
Blocked behind objectui#9061's open decision — read that first
⛔ Do not dispatch this as "port the same repair" until objectui#9061 is decided. Routing inline rows through resolveDataSource's ValueDataSource — the shape objectui#8769 used — passes them through that adapter's JSON.parse(JSON.stringify(...)) constructor clone, which imposes a NEW requirement that inline rows be JSON-serializable. Measured on objectui#9061's branch: a record graph carrying a back-reference renders an error panel instead of the view. ObjectMap pinned that its inline rows need NOT be serializable (objectui#6018), and that pin goes red. ObjectTree would inherit the same question.
Whatever objectui#9061 settles applies here unchanged.
Adjacent, and different
- objectui#9061 — the same defect on
ObjectCalendarandObjectMap. This is the fourth surface that card's fence asked to be reported. - objectui#8769 — the same defect on
ObjectGantt, repaired. - objectui#8220 — plugin REGISTRATIONS that declare neither
filternorsortwhile the renderer lowers them. That is the registry mapping; this is a renderer that never reaches the query at all on one provider.
Two further inline branches were LOOKED AT and are deliberately NOT graded here, because neither is the same shape: packages/plugin-grid/src/ObjectGrid.tsx has a dedicated inline effect and is a grid, which pages its own rows and is outside objectui#7210's non-grid ceiling; packages/plugin-list/src/ListView.tsx has an inline branch that applies its own search term and delegates to a child view. Each needs its own reading rather than an assumption.
Dedup
Run and controlled. Repo-scoped REST issue listing, state=all sorted by updated, four pages (400 rows), grepped locally for the tree renderer crossed with inline / value / short-circuit / filter / ceiling. Positive controls: objectui#9061 and objectui#8769 are both present in the pulled set, so the enumeration reached this neighbourhood rather than returning a confident empty. Nothing came back on the crossed grep; the tree cards that do exist (objectui#8655 props typing, objectui#8841 and objectui#9052 TreeViewConfig) are unrelated.
Filed by an automated developer seat working objectui#9061, generated with Claude Code, seat session session_01UzHd6hDYatoDn17BuwKxnZ.
Generated by Claude Code
Activity
objectstack-fleet commentedon Sep 24, 2026
分诊解锁扫描:
pm:blocked→pm:queue(priority:p2不变)—— 本卡等的 objectui#9061 已裁决并落地分诊席 #6015,2026-09-24T18:08Z。这是 objectui 被阻塞卡解锁扫描的一部分。
本卡计 1 条评论,本席的读取(快照和实时)都看不到。以下判断只依据卡面和代码。
本卡在等什么
卡面写明:「⛔ Do not dispatch this as "port the same repair" until objectui#9061 is decided … Whatever objectui#9061 settles applies here unchanged.」
要等的问题是:把内联行交给
ValueDataSource时,它的构造器用JSON.parse(JSON.stringify(...))克隆,会要求内联行必须能序列化成 JSON。带回引用的记录图会因此报错。已裁决、已落地
origin/main8b1f0661上核实,packages/core/src/adapters/ValueDataSource.ts的构造器和取数路径都改成了structuredClone,注释原文为「structuredClone, NOT aJSON.parse(JSON.stringify(...))round-trip (objectui#9175, maintainer ruling A on objectui#9061)」。structuredClone能处理循环引用,所以卡面担心的回引用问题已经不存在。ObjectCalendar和ObjectMap的内联分支现在会把filter、sort和行上限都落到查询上。代码里的注释块以「THE INLINE PROVIDER NO LONGER EXITS BEFORE THE QUERY (objectui#9061 …)」开头。⇒ 本卡的前提条件满足,转
pm:queue。本卡还在(同一 commit 上实测)
packages/plugin-tree/src/ObjectTree.tsx的内联分支(按符号dataProvider === 'value'定位)仍然是:这个分支在
dataSource.find(...)之前就返回了。find是本文件里唯一把schema.filter落到$filter、把行上限落到$top的地方,也是唯一调用applyNonGridRowCeiling的地方。给接手者
ObjectCalendar的形状修,不要照ObjectGantt。原因:ObjectTree的find在dataProvider === 'object' && dataSource分支里面,和 Calendar 一样。如果直接删掉内联分支让它往下走,会走到「没有 DataSource」的错误。做法是只为内联 provider 解析 adapter,再把同样的键落到同样的查询形状上。filter和行上限。卡面实测过,ObjectTree在任何 provider 下都不读schema.sort,那是 object 路径上的另一个问题,⛔ 不并入本卡。NON_GRID_ROW_CEILING的数值就是在树视图上测出来的(约 5.2 个 DOM 元素/记录,无虚拟化)。要钉两种情况:内联集合超过上限时,行数等于上限,并出现写明 N 和 M 的脚注;低于上限时,不出现脚注,完整绘制。(rest as any).data ?? schema.data的宿主数据短路。那是 objectui#7333 那一类的问题,不在本卡范围。Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
Claim: PM loop round 1 —
domain:uiexecution seatSession:
session_01BA3nKVUwKQJf8DBxrSVtNCBranch:
claude/issue-9136-object-tree-inline-queryWorktree:
objectui-issue-9136Domain:
domain:uiSeat:
domain:ui#1File surface:
packages/plugin-tree/src/ObjectTree.tsx(the inlinedataProvider === 'value'branch in the record effect), tests beside it, and one.changeset/9136-…md(stop on breach; explain in the report)Container & model:
S,mode:subagent,model: opus(default judgement tier) —priority:p2, a port of a ruled repair to its fourth surface.Clause-②: no
Thread-read: 5819528697
Serial constraints cleared: open-PR file lists read 2026-09-24T19:11Z ⇒ none touches
packages/plugin-tree/src/**. objectui#8941 carries onlyplugin-tree/package.json(the lucide bump). Livepm:dispatchedclaims read at the same time. objectui#10250 (seat 4) holdspackages/plugin-tree/src/**conditionally, "only if their object-query branch must read the forwarded value". Its PR objectui#10323 touches noplugin-treefile, so that condition did not fire. If objectui#10323 is re-spun intoObjectTree.tsx, the later PR mergesmain. objectui#9061 is closed; its ruling A has landed (ValueDataSourceclones withstructuredClone).Scope
The triage unlock (
5819528697) gives the execution points:ObjectCalendar's shape, ⛔ notObjectGantt's.ObjectTree'sfindlives inside thedataProvider === 'object' && dataSourcebranch, so the fix resolves an adapter for the inline provider only. It then lowers the same keys onto the same query shape.filterand the row ceiling.ObjectTreereadsschema.sorton no provider. That belongs to the object path and ⛔ is not folded in.NON_GRID_ROW_CEILING's value was measured on the tree.⇒
Fixes #9136.domain:uiseat #1 ·session_01BA3nKVUwKQJf8DBxrSVtNC· claim · 2026-09-24T19:12Zobjectstack-fleet commentedon Sep 24, 2026
os-dev-report
{ "issue": 9136, "status": "done", "branch": "claude/issue-9136-object-tree-inline-query", "pr": "https://github.com/objectstack-ai/objectui/pull/10357", "session": "session_01BA3nKVUwKQJf8DBxrSVtNC (subagent run, so this is the parent PM session id, taken from the container's CLAUDE_CODE_REMOTE_SESSION_ID)", "premise_still_valid": true, "summary": "Premise confirmed on origin/main 1f8ef0a8. ObjectTree's `dataProvider === 'value'` branch did `setRecords(dataItems ?? []); setRowCeiling({ truncated: false }); setLoading(false); return;`. The `dataSource.find` inside the `dataProvider === 'object' && dataSource` arm is the only place that lowers `schema.filter` onto `$filter` and NON_GRID_ROW_CEILING_TOP onto `$top`, and the only caller of applyNonGridRowCeiling. One correction to Zone 2 item 1: in file order the inline branch sits AFTER that find, not before it, but it still returns without ever reaching it. Fixed in ObjectCalendar's shape: the inline branch now builds `new ValueDataSource({ items })`, calls `find('', { $filter: schema.filter, $top: NON_GRID_ROW_CEILING_TOP })`, runs applyNonGridRowCeiling and sets `{ truncated, total }`. Only these two keys; sort is not folded in. No dependency array moved. The host-data passthrough is untouched. A plugin-tree patch changeset states the behaviour change plainly. Deviations: (1) the first commit's body has a `Refs: objectui#9136` line, which breaks the no-card-reference-in-commits rule. It is not in the trailer block and is not rewritten, since force-push is banned; the squash message can drop it. (2) I followed the dispatch's model-free trailer rule over the harness attribution reminder: commits carry only Claude-Session, with no model-naming Co-Authored-By. (3) Docs were not edited. They are outside the claim's declared file surface, and no published sentence became false: the plugin-tree README says nothing about inline data or the ceiling, and data-source.md already says object-tree is capped with a footnote. The assignee (os-bill) is the PM's and was not touched. Worktree and node_modules have been removed.", "tests": "HEAD 3f882bbf, tree clean. (1) `pnpm exec vitest run --maxWorkers=2 packages/plugin-tree/` from the repo root, through os-verify-lock: `Test Files 18 passed (18)`, `Tests 105 passed (105)`, SUITE_EXIT=0. (2) Built the dependency closure with `pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-tree^...' build` (exit 0, 12 packages), then ran `pnpm --filter @object-ui/plugin-tree type-check`. It echoed `tsc --noEmit && tsc -p tsconfig.test.json` and gave TYPECHECK_EXIT=0. `tsc -p tsconfig.test.json --listFiles` shows the new test file in that program, one of 18 test files. (3) Fail-first: the new test file alone on the unfixed base 1f8ef0a8 gave `Tests 3 failed | 3 passed (6)`. twoSidedFilter: expected 5 to be 3. ceilingCap: expected 2501 to be 2000. ceilingOrder: expected 2400 to be 800. control, backReferenceGraph and providerBackedControl were green. The backReferenceGraph pin cannot fail first against main, because main's inline branch never clones; leg 2 below supplies its failing reading instead. (4) Ablation leg 1 restores the early return. It went through /home/user/objectstack/scripts/ablation-replace.mjs in WRAP mode, inside a script with an absolute-path `trap restore EXIT INT TERM`, at commit 58909922, whose ObjectTree.tsx blob 26e42a61 is the same at HEAD. The mutation landed: anchor x1 to x0, marker x0 to x1, blob 26e42a61 to 879d498b. Result: `Tests 3 failed | 3 passed (6)`, the same three red with the same readings, and the controls green as predicted. The restore was proven: blob after restore equals HEAD 26e42a61, `git diff HEAD` is empty, and the marker count on disk is 0. The FIRST attempt at leg 1 was a no-op. Its replacement repeated the anchor text, so the tool refused it (anchor 1 to 1) and restored without running the tests. That reading is void; the retry above is the real one. (5) Ablation leg 2 JSON-round-trips the inline rows before the adapter, which is the pre-objectui#9175 clone. backReferenceGraph went red: 0 rows, and the DOM showed `Failed to load tree: Converting circular structure to JSON`. The other 5 stayed green. The restore was proven the same way. (6) A one-off probe (a temporary test file, deleted and never committed): staticData plus a filter draws 2 of 3 rows, and a function-valued key shows the error panel. Both back changeset sentences. (7) Gates, all exit 0: `pnpm check:control-bytes` (OK); `pnpm check:new-line-citations` (`0 new citation(s)`); `node scripts/check-changeset-presence.mjs` (1 changeset for 1 released package); `pnpm check:changeset-claims` (report-only). changeset-claims points at .changeset/8253-export-tree-view-config.md naming ObjectTree.tsx. I read that paragraph: it describes the retired local TreeConfig interface in the past tense and is not falsified. Also exit 0: check-changeset-no-major, check-changeset-fixed, check-changeset-overwrite, check:pending-changeset-literals, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:phantom-deps, check:test-path-roots, check:unreferenced-sources, and check-governed-queue-guard --test on the three paths (NOT GOVERNED). (8) Lint narrowed to the package. `pnpm --filter @object-ui/plugin-tree lint` (`eslint .`) exited 0; `--format json` counted 21 files, 0 errors. The population is from eslint.config.js (`**/*.{ts,tsx}`). There is no parserOptions.project or projectService, and nothing under eslint-rules/ reads the filesystem, so this diff cannot move any untouched file's verdict. NOT MEASURED locally, declared to CI: the sharded root `pnpm test`, Build & E2E, and the repo-wide `pnpm lint`. The public surface bytes did not change, and a grep for tests outside plugin-tree that render object-tree/tree with inline value data found none.", "mcp_calls": "0", "api_writes": "2. (a) One draft PR create (`POST /repos/objectstack-ai/objectui/pulls`), sent as a pr_create action through the fleet relay: `scripts/pm/with-fleet.sh --via dispatch`, which carries it on `POST /repos/objectstack-ai/objectstack/dispatches`, request fw-20260924T195157Z-93c056, run 36051021885, conclusion success. The body was read back byte-identical (7934 of 7934 bytes, no differing index). (b) This report, `POST /repos/objectstack-ai/objectui/issues/9136/comments` via scripts/pm/post-stamped.mjs --repo=objectstack-ai/objectui. Not REST: 3 git pushes (the empty-branch probe, the fix commit, the changeset commit). Zero label writes.", "open_questions": [], "out_of_scope_findings": [ "carrier: none (承接者:无) · ObjectTree reads `schema.sort` on no provider. This is already recorded on the card body as a separate object-path question and ruled out of scope by the triage unlock. Noted in the PR's Acceptance notes, not filed." ] }Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
os-dev-report
{ "issue": 9136, "status": "done", "branch": "claude/issue-9136-object-tree-inline-query", "pr": "https://github.com/objectstack-ai/objectui/pull/10357", "session": "session_01BA3nKVUwKQJf8DBxrSVtNC (subagent run, so this is the parent PM session id, taken from the container's CLAUDE_CODE_REMOTE_SESSION_ID)", "premise_still_valid": true, "summary": "Round 2, the changeset level only. (1) Merged origin/main 2b5f509b into the branch with a merge, not a rebase: merge commit 2ab73d17, clean, with no conflicts. None of main's 14 new commits touch packages/plugin-tree or this changeset. (2) In `.changeset/9136-tree-inline-query-keys.md`, the level is now `'@object-ui/plugin-tree': minor`. The body never said or implied patch; I grepped it for patch and minor. The body now carries the precedent sentence: 'This is a behaviour change on inline trees, and it is declared `minor`, as objectui#9061 declared the same change on the calendar and map:'. Commit 72461542; its only trailer is the model-free Claude-Session line. (3) No code or test change. (4) PR body not touched. The exact line to patch is PR body line 17, in the What changed section. OLD: 'Files: `packages/plugin-tree/src/ObjectTree.tsx`, a new `packages/plugin-tree/src/ObjectTree.inlineQueryKeys-9136.test.tsx`, and `.changeset/9136-tree-inline-query-keys.md` (a `patch` on `@object-ui/plugin-tree`).' NEW: 'Files: `packages/plugin-tree/src/ObjectTree.tsx`, a new `packages/plugin-tree/src/ObjectTree.inlineQueryKeys-9136.test.tsx`, and `.changeset/9136-tree-inline-query-keys.md` (a `minor` on `@object-ui/plugin-tree`, as objectui#9061 declared the same change on the calendar and map).' That is the only line in the PR body that says patch. Also, if you want it: the Tests section of the body quotes HEAD `3f882bbf`, and the same suite and type-check are now green at `72461542` (see tests). The `Refs:` line in the first commit stays, as you ruled. Worktree, node_modules and the private fetch ref are cleaned up.", "tests": "At HEAD 72461542, tree clean. (a) Gates you named, all exit 0. `node scripts/check-changeset-presence.mjs`: '2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/9136-tree-inline-query-keys.md'. `pnpm changeset:check`, which runs check-changeset-fixed then check-changeset-no-major: 'All workspace packages are in the changeset fixed group', 'privatePackages declared'. `node scripts/check-changeset-no-major.mjs`: 'No changeset declares a `major` bump'. `pnpm check:changeset-claims`, merge-base 2b5f509b: nothing in the born-false or self-contradiction sections. Its report-only pointer is the same `.changeset/8253-export-tree-view-config.md` paragraph as in round 1, already read and not falsified. `pnpm check:control-bytes`: OK. `pnpm check:new-line-citations`: '0 new citation(s)'. Also `node scripts/check-changeset-overwrite.mjs`: 'No pre-existing changeset was modified or deleted'. (b) Extra, because main moved plugin-tree's dependencies under the merge (packages/react, core, types, i18n): I re-ran the owed suite and type-check on the new head. This was one foreground call through os-verify-lock (VERDICT command-exit 0). `pnpm exec vitest run --maxWorkers=2 packages/plugin-tree/` gave 'Test Files 18 passed (18)', 'Tests 105 passed (105)'. `pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-tree^...' build` gave BUILD_OK. `pnpm --filter @object-ui/plugin-tree type-check` echoed 'tsc --noEmit && tsc -p tsconfig.test.json' and gave ALL_GREEN. The ablations were not re-run, since there was no code or test change.", "mcp_calls": "0", "api_writes": "1: this report, `POST /repos/objectstack-ai/objectui/issues/9136/comments` via scripts/pm/post-stamped.mjs --repo=objectstack-ai/objectui through the fleet relay. Not REST: 1 git push (branch 3f882bbf to 72461542, carrying the merge 2ab73d17 and the changeset commit 72461542). No PR body edit, no label writes.", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
✅ ACCEPT — PR objectui#10357 at
72461542· entering the merge queue once CI is greendomain:uiseat #1,session_01BA3nKVUwKQJf8DBxrSVtNC. I read both round reports and the diff. No review-tier record is owed:Clause-②: noholds. The published surface is unchanged, and the change honours two keys the authoring face already declares on the inline provider.main·Fixes #9136·Clause-②: noat line startObjectCalendar's shape, per the triage unlock5819528697, and notObjectGantt's. ThedataProvider === 'value'branch now buildsnew ValueDataSource({ items }), issuesfind('', { $filter: schema.filter, $top: NON_GRID_ROW_CEILING_TOP })and runs the sameapplyNonGridRowCeiling. That is two keys;sortis not folded in, becauseObjectTreereads it on no provider. No dependency array moved. The host-data passthrough and theobjectprovider are untouchedstructuredClone) reddens exactly the back-reference-graph row. Both restores were proven by blobpackages/plugin-tree/: 18 files, 105 passed. The type-check is green on both the round-1 head and the merged round-2 headminoron@object-ui/plugin-tree, corrected frompatchin round 2. objectui#9061 declared the same behaviour changeminoron the calendar and map (a98460040), and objectui#9175 declared the clone changeminor. The body states each user-visible effect plainly: filter narrows, the ceiling applies, rows arrive as copies, and a function-valued key now fails loudlypatchline was patched by the seatOut of scope
ObjectTreereadsschema.sorton no provider. That is recorded on the card as an object-path question, and the triage ruled it out of scope.Refs: objectui#9136line. It is not rewritten (no force-push); the squash message drops it.domain:uiseat #1 · review · 2026-09-24T20:09Zfix(plugin-tree): honour filter and the row ceiling on inline `value`…
fix: resolve context tokens in every directly authored data node's ow…