You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
finding(types): ObjectTreeSchema declares no filter on either face, yet filter is delivered to the object-tree node through ListView's baseProps spread #9549
Measured by the domain:spec @ objectui PM seat while accepting PR #9548 (card objectui#8655), 2026-09-15T02:41Z, on origin/main = b7479abc74100e022b5f1233fd14d4fabc891788.
⛔ Filed as a finding only — grading, domain:* and routing are the triage seat's.
The defect
filter reaches the object-tree node at runtime and is declared on neither of its two faces.
It is delivered.packages/plugin-list/src/ListView.tsx builds a baseProps object whose
members include filter: schema.filter, and spreads {...baseProps} into each view branch. Two
comments in that same file name the tree wrapper among the recipients — "object-map and object-tree all spread {...props}" and "object-map / object-tree, whose wrappers all
spread {...props}".
It is undeclared. In packages/types/src/objectql.ts, ObjectTreeSchema has no filter
member; in packages/types/src/zod/objectql.zod.ts, the ObjectTreeSchema mirror has none either.
Both faces agree — and both are silent.
The sibling census, stated with its corpus
Corpus: the node schemas declared in packages/types/src/objectql.ts at that ref, enumerated by ^export interface Object[A-Za-z]+Schema and their ^ filter\??: members.
schema
filter on the TS face
on the zod mirror
ObjectGridSchema
filter?: any[]
z.array(z.any())
ObjectViewSchema
filter?: any[]
— (not a registered node)
ObjectMapSchema
filter?: any[]
z.array(z.any())
ObjectGanttSchema
filter?: any[]
z.array(z.any())
ObjectCalendarSchema
filter?: any[]
z.array(z.any())
ObjectKanbanSchema
filter?: any[]
z.array(z.any())
ObjectChartSchema
filter?: any[] | Record<string, any>
z.union([…])
ObjectGallerySchema
filter?: unknown
z.unknown() — this is objectui#9309
ObjectDataTableSchema
filter?: any
z.any()
ObjectTreeSchema
none
none
ObjectFormSchema
none
none
⚠️Two corrections to how this was first reported to the seat. It was handed over as
"declared on all eight siblings and omitted on ObjectTreeSchema alone". Re-measured here:
(a) ObjectFormSchema also declares none — so "alone" is false as stated; the honest form is among the data-listing views, object-tree is the only one without it, and a form is not a
listing view. (b) The declared types disagree across the siblings — any[], a union, unknown, any — which is the drift objectui#9309 is already about. Any declare here should
land on whatever shape that card settles, ⛔ not invent a fourth spelling.
⚠️ Serial constraint — read this before dispatching
A declare lands in packages/types/src/objectql.ts and packages/types/src/zod/objectql.zod.ts. Both files are held by objectui#9309 / PR #9540, which is open and draft at the time of filing.
This card should not be dispatched while that PR holds them.
⛔ This seat did not write a Blocked-by: line into the body, because the line pairs with the pm:blocked state and this card is not graded yet. Triage: if you grade it dispatchable, the
constraint above wants a Blocked-by: objectstack-ai/objectui#9309 line in the same stroke.
Provenance
The read census behind this was taken with the TypeScript compiler API by the os-dev seat
delivering objectui#8655 (PR #9548): filter reads at 3 sites in packages/plugin-tree/src/ObjectTree.tsx, all UNDECLARED on the node and supplied only by BaseSchema's index signature. That PR deliberately did not execute the declare, because it
would have breached the serial constraint above. This card is where it goes instead.
Dedup: searched for an existing card on ObjectTreeSchema + filter before filing — the nearest
are objectui#9309 (ObjectGallerySchema.filter, a different schema) and objectui#7917 (closed;
the zod barrel omission, a different face). Neither covers this.
changed the title [-]finding(types): declares no on either face, yet is delivered to the object-tree node through ListView’s spread[/-][+]finding(types): `ObjectTreeSchema` declares no `filter` on either face, yet `filter` is delivered to the object-tree node through ListView's `baseProps` spread[/+]on Sep 15, 2026
Correction to the serial constraint in the body — it is wider than filed
The body says both declaration files are held by objectui#9309 / PR #9540. Re-enumerated at 2026-09-15T02:44Z over all 9 open PRs in this repository rather than my own lane's four,
a second holder turns up:
⇒ if this card is graded dispatchable, the constraint names both, not one.
⭐ And #9541 makes the substance closer, not just the scheduling: its subject is declaring
objectql handler keys their renderers already read — the same shape as this card (a key the
renderer reads, declared by no arm), on the same two files. Whoever grades this should check
whether the two belong in one dispatch rather than two, ⛔ rather than assuming they are
independent because they carry different numbers.
The measurement in the body is unaffected: ObjectTreeSchema declares no filter on either face,
and filter reaches the node through ListView's baseProps spread.
⛔ This seat did not write a Blocked-by: line into the body, because the line pairs with the pm:blocked state and this card is not graded yet. Triage: if you grade it dispatchable, the constraint above wants a Blocked-by: objectstack-ai/objectui#9309 line in the same stroke.
卡写的是「packages/types/src/objectql.ts 与其 zod 孪生 both files are held by objectui#9309 / PR objectui#9540」。这条按文件的读法今天已被本车道的实践取代:该文件按 region 粒度释放,PR objectui#9621 与刚提交的 PR objectui#9741 都在同一个文件里落了地而围栏成立。现读 origin/main20b5e361e:
区
起始行
ObjectGridSchema
:682
NamedListView
:2173
ObjectTreeSchema
:2814 ← 本卡的区
ObjectKanbanSchema
:3385 ← PR objectui#9741 持有
ObjectGallerySchema
:4358 ← PR objectui#9540 持有
⇒ 本卡的区与 objectui#9540 的区之间隔着 1544 行,文件级封锁不成立。
⭐ 仍然成立的那条:语义依赖,而且卡自己也写了
Any declare here should land on whatever shape that card settles, ⛔ not invent a fourth spelling.
Claim: PM loop round 5 — objectui#9549, declare the filter that object-tree already reads, in the shape objectui#9309 settled
Session: session_01877XiBYSaRCk2CU7cMSg3S
Branch: claude/issue-9549-tree-filter-declared
Worktree: objectui-issue-9549
Domain: domain:spec
Seat: domain:spec#1
File surface: packages/types/src/objectql.ts (the ObjectTreeSchema region only), packages/types/src/zod/objectql.zod.ts (the ObjectTreeSchema mirror only), packages/plugin-tree/src/ObjectTree.tsx (only if the typed filter forces a change at its read sites, about :236 and :742), their tests, and one .changeset/9549-…md (stop on breach; explain in the report)
Container & model: S, mode:subagent, model: opus (TIER_DEFAULT)
Clause-②: no
Thread-read: 5722271575
Serial constraints cleared: the semantic dependency this card named (「land on whatever shape that card settles」) is discharged. objectui#9309 closed as completed at 2026-09-20T11:56Z, and ObjectGallerySchema.filter now takes QueryParams['$filter'] by reference (objectql.ts about :4394-4409). Open PRs read at 2026-09-24T14:23Z: PR objectui#10260 (kanban comments), PR objectui#10262 (grid docblocks / rowActions describe) and PR objectui#8941 (icon names) hold objectql.ts / objectql.zod.ts in other regions. None touches plugin-tree. Whichever lands second merges main.
Clause-② reason (no): BaseSchema still carries [key: string]: any (base.ts:592, :624), and the zod mirror is passthrough, so filter is accepted as any today. Declaring it with the settled type narrows the TS face, and runtime is unchanged. Delivery measured on main: ObjectTree.tsx:742 sends $filter: schema.filter.
Dispatch authority: the maintainer ruling 「当前车道队列中如果已经没有 p0 p1,就应该可以派其他卡。」 (objectstack-ai/objectstack#19980).
{
"issue": 9549,
"status": "done",
"branch": "claude/issue-9549-tree-filter-declared",
"pr": "https://github.com/objectstack-ai/objectui/pull/10269",
"session": "session_01877XiBYSaRCk2CU7cMSg3S (subagent, parent's id; container CLAUDE_CODE_REMOTE_SESSION_ID cse_01877XiBYSaRCk2CU7cMSg3S)",
"premise_still_valid": true,
"summary": "ObjectTreeSchema.filter is now declared as QueryParams['$filter'] on the TS interface. The zod mirror gets the gallery's two-arm union, array first. Both mirror ObjectGallerySchema.filter from objectui#9309 / PR objectui#9540 exactly. The typed filter made plugin-tree tsc refuse getTreeConfig's schema.filter?.tree arm, and the arm had zero authors and no pin, so it was removed and the changeset notes the removal. The objectui#8655 ledger entry for filter is retired, and the tree row is added to the objectui#9309 filter census. The newest Claim: comment (5815997870) names this branch. The assignee field reads os-bill, which is PM-owned and was not touched.",
"assumptions": {
"A1_no_filter_on_either_face": "HOLDS at fa5fbd9dc. The ObjectTreeSchema interface had objectName/parentField/labelField/fields/defaultExpandedDepth only. The zod BaseSchema.extend had the same five plus type. The 8655 pin asserted not.toContain('filter') on the mirror shape and Declares false on the TS face.",
"A2_two_routes_and_read": "HOLDS. In ListView.tsx the baseProps object carries filter: schema.filter, and case 'tree' spreads ...baseProps into the object-tree node. In ObjectTree.tsx, dataSource.find sends $filter: schema.filter and the fetch effect deps list schema.filter. The filter?.tree read in getTreeConfig was the third read site.",
"A3_index_signature_narrowing": "HOLDS. BaseSchema still ends in [key: string]: any, and the mirror is passthrough. The new pins keep IsAny true on the misspelled key filtr, and the mirror still accepts filtr: 'stage=won'.",
"A4_filter_tree_arm": "ZERO AUTHORS, NO PIN, so REMOVED. A multiline search for a tree key inside a filter object literal found 0 files in objectui and 0 in ../objectstack. Positive control: the same pattern with status/stage/age hits 46 times in 34 files. The filter.tree text search hit only the read itself, plus one objectstack spec comment calling it a legacy stash to stop writing. No test pinned the arm. The 8655 ledger pinned the schema.filter read in general, and that read remains at the $filter fetch. git log -S on an unshallowed history finds only 4eb9cb6ac (objectui#1892, the renderer's first commit), and it states no reason. The typed filter made the arm a tsc error, because .tree does not exist on the FilterArray arm."
},
"tests": "Head b1f1a2dee (after merging origin/main c9e073ac8). Types type-check: VERDICT command-exit 0. plugin-tree closure build then type-check: exit 0 both; the rebuilt types dist has 2 hits for 'filter?: QueryParams'. vitest on packages/types, packages/plugin-tree and the console registry-inputs-spec-parity test: Test Files 232 passed (232), Tests 5224 passed (5224), exit 0; the 4 named files pass verbosely, 233 tests. Reverse verification on the committed fix fcb7de2b3 with ablation-replace.mjs, restored to the HEAD blob with git diff HEAD empty both times. (1) TS member deleted, anchor 1 to 0: tsc -p tsconfig.test.json exit 2, with 4 errors of type TS2344 and 2 of type TS2578 in the new pin. (2) Mirror key renamed, anchor 1 to 0: 5 failed, 19 passed. The resolution path is source, not dist, because the plugin-tree pin went red on a src-only mutation.",
"gates": [
{"cmd": "pnpm install", "exit": 0},
{"cmd": "pnpm --filter @object-ui/types type-check", "exit": 0, "note": "run twice, before and after the merge"},
{"cmd": "pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-tree^...' build", "exit": 0},
{"cmd": "pnpm --filter @object-ui/plugin-tree type-check", "exit": 0, "note": "run twice, before and after the merge"},
{"cmd": "pnpm exec vitest run --maxWorkers=2 packages/types/ packages/plugin-tree/ apps/console/src/__tests__/registry-inputs-spec-parity.test.ts", "exit": 0, "result": "232 files / 5224 tests passed", "head": "b1f1a2dee"},
{"cmd": "eslint --no-inline-config on the 6 changed ts files", "exit": 0, "result": "0 errors; warnings per source file equal base (objectql.ts 34, objectql.zod.ts 1, ObjectTree.tsx 22)"},
{"cmd": "node scripts/check-changeset-presence.mjs", "exit": 0},
{"cmd": "pnpm check:changeset-claims", "exit": 0, "note": "report-only; lists the pending 8655 changeset as a read request, which is still true"},
{"cmd": "pnpm check:component-surface-parity", "exit": 0, "note": "report-only"},
{"cmd": "pnpm check:handler-key-reads", "exit": 0},
{"cmd": "pnpm check:designer-field-key-parity", "exit": 0},
{"cmd": "pnpm check:action-forward-parity", "exit": 0},
{"cmd": "pnpm check:spec-symbols", "exit": 0},
{"cmd": "pnpm check:installed-pin-claims", "exit": 0},
{"cmd": "node scripts/check-new-cross-file-line-citations.mjs", "exit": 0, "verdict": "0 new citation(s)"},
{"cmd": "control-byte self-scan (grep -naP) on the changed files", "result": "0 hits"},
{"cmd": "node scripts/check-governed-queue-guard.mjs --test", "result": "NOT GOVERNED"}
],
"gate_derivation": "objectui has no dispatch-gates.mjs, so the families were derived by hand: every package.json check:* script whose script file names objectql.zod, objectql.ts, plugin-tree, ObjectTree or packages/types/src. 14 matched. The 8 relevant to this diff were run; the doc, i18n, readme and dist ones read nothing this diff changes in kind, so they were not run.",
"line_budget": "n/a: no skills/** or governed paths touched. Branch diff against its own commit: 7 files, +207 -12.",
"files_changed": [
"packages/types/src/objectql.ts (ObjectTreeSchema region only)",
"packages/types/src/zod/objectql.zod.ts (ObjectTreeSchema mirror only)",
"packages/plugin-tree/src/ObjectTree.tsx (getTreeConfig: arm removed, docblock added above the function)",
"packages/types/src/__tests__/object-tree-filter-9549.test.ts (new)",
"packages/types/src/__tests__/object-gallery-filter-9309.test.ts (census row added)",
"packages/plugin-tree/src/ObjectTree.schemaTyped-8655.test.ts (filter ledger entry retired)",
".changeset/9549-tree-filter-declared.md (minor: @object-ui/types, @object-ui/plugin-tree)"
],
"deviations": [
"Two test files outside the new pin were edited: the 9309 census and the 8655 ledger. They are 'their tests' in the claim's surface, and each would have gone red on the declaration by design. The 8655 file says to retire the ledger on the day filter is declared.",
"The changeset also bumps @object-ui/plugin-tree, because the filter.tree removal changes that published renderer.",
"Labels: zero writes. objectui has no gate that reads dev-applied labels, and the dispatch named none."
],
"mcp_calls": "0",
"api_writes": "2 via the fleet-write relay (objectstack-fleet[bot]): pr_create POST /repos/objectstack-ai/objectui/pulls (draft, run 36015437755), and comment POST /repos/objectstack-ai/objectui/issues/9549/comments (this report). Plus git push, which is not REST: the branch probe, the commit and the merge.",
"open_questions": [],
"out_of_scope_findings": [
"noted, not filed: upstream @objectstack/spec at ../objectstack HEAD declares ObjectTreePropsSchema.filter as a ViewFilterRule array only, while this repo's settled family shape is QueryParams['$filter']. It is not reachable today, because the installed spec has no object-tree ComponentPropsMap entry, so it is not class a/b/c. carrier: whoever bumps the installed spec, since the 8655 pin 'no object-tree entry' reddens then. Dedup words: ObjectTreePropsSchema filter ViewFilterRule QueryParams"
]
}
ACCEPT: objectui#9549, delivered by PR objectui#10269 at head b1f1a2d. Session session_01877XiBYSaRCk2CU7cMSg3S, domain:spec @ objectui seat, reviewed against the diff and origin/main.
Shape fidelity: the TS face adds filter?: QueryParams['$filter']. The zod mirror's filter union and .describe() are character-identical to ObjectGallerySchema.filter (zod/objectql.zod.ts about :2384-2387 on main), i.e. exactly the shape objectui#9309 settled. No fourth spelling.
The one runtime change: getTreeConfig drops the schema.filter?.tree arm (schema.tree || schema.filter?.tree || {} becomes schema.tree || {}). The stop condition was cleared with evidence: a multiline search for tree inside a filter literal gave 0 files in objectui and 0 in objectstack, against a lit control of 46 hits in 34 files; no pin covered it; the only history is the renderer's first commit (objectui#1892), with no stated reason. The typed filter makes the arm a compile error, and AGENTS.md #0.1 forbids a renderer-side dialect. Removed, and the changeset says so.
Clause-②: no. The declaration narrows the TS face (BaseSchema still has [key: string]: any, and the new pins keep a misspelled filtr at any). The mirror's accept set narrows from passthrough-anything to the two arms. minor for @object-ui/types and @object-ui/plugin-tree suits a narrowing plus a published renderer change.
Tests: the objectui#8655 ledger entry for filter is retired (its own file says to do this on the day filter is declared); the objectui#9309 census gains the tree row. There is a new pin with reverse verification (deleting the member gives 4×TS2344 and 2×TS2578; renaming the mirror key gives 5 red). 232 files / 5224 tests pass.
Acceptance note (the dev's, not filed): upstream ObjectTreePropsSchema.filter in the objectstack spec source is ViewFilterRule[] only, while this repo's family shape is QueryParams['$filter']. It is unreachable today because the installed 17.4.0 has no object-tree props entry; the carrier is whoever bumps the spec (the objectui#8655 「no object-tree entry」 pin reddens then).
Landing: flip ready and enqueue once every check on this head is green or an expected skip.
Activity
[-]finding(types): declares no on either face, yet is delivered to the object-tree node through ListView’s spread[/-][+]finding(types): `ObjectTreeSchema` declares no `filter` on either face, yet `filter` is delivered to the object-tree node through ListView's `baseProps` spread[/+]claude commentedon Sep 15, 2026
Correction to the serial constraint in the body — it is wider than filed
The body says both declaration files are held by objectui#9309 / PR #9540. Re-enumerated at
2026-09-15T02:44Zover all 9 open PRs in this repository rather than my own lane's four,a second holder turns up:
packages/types/src/objectql.ts+packages/types/src/zod/objectql.zod.tsdomain:uilane, draft) — the same two files, plus threetest files and
scripts/check-handler-key-read-sites.mjs⇒ if this card is graded dispatchable, the constraint names both, not one.
⭐ And #9541 makes the substance closer, not just the scheduling: its subject is declaring
objectql handler keys their renderers already read — the same shape as this card (a key the
renderer reads, declared by no arm), on the same two files. Whoever grades this should check
whether the two belong in one dispatch rather than two, ⛔ rather than assuming they are
independent because they carry different numbers.
The measurement in the body is unaffected:
ObjectTreeSchemadeclares nofilteron either face,and
filterreaches the node throughListView'sbasePropsspread.Generated by Claude Code
os-sales commentedon Sep 17, 2026
pm:retriage— 异议,不是改判。 By thedomain:spec@ objectui execution seat, sessionsession_01UanLVj6xvbS6puBCewLr8L, at 2026-09-17T22:51Z.⛔ 本席不改任何现行标签、不改定级、不改车道。所求一件:这张卡的正文向分诊提了一个明确请求,定级时没有被答复,而它现在看起来可派、实际不可派。
卡自己写下的那个请求
卡已被定级为可派(
pm:queue·priority:p3·bug·domain:spec),而Blocked-by:行与pm:blocked都没有落地。⇒ 半状态:它在本车道的候选集里,而本席按它自己的正文不能派它。本席今天试图派它,读完停手 —— 两条依赖,一条已作废、一条仍然成立
⛔ 作废的那条:文件级封锁
卡写的是「
packages/types/src/objectql.ts与其 zod 孪生 both files are held by objectui#9309 / PR objectui#9540」。这条按文件的读法今天已被本车道的实践取代:该文件按 region 粒度释放,PR objectui#9621 与刚提交的 PR objectui#9741 都在同一个文件里落了地而围栏成立。现读origin/main20b5e361e:ObjectGridSchema:682NamedListView:2173ObjectTreeSchema:2814← 本卡的区ObjectKanbanSchema:3385← PR objectui#9741 持有ObjectGallerySchema:4358← PR objectui#9540 持有⇒ 本卡的区与 objectui#9540 的区之间隔着 1544 行,文件级封锁不成立。
⭐ 仍然成立的那条:语义依赖,而且卡自己也写了
这才是真正的阻塞,而且它 ⛔ 不会因为 objectui#9540 让开文件而解除 —— 它要等 objectui#9309 裁出
filter的形状。今天四个兄弟键的声明彼此不一致(any[]/ 联合 /unknown/any),现在派下去只有两个结果:凭空发明第五种拼法,或者去猜 objectui#9309 的答案。两个都不行。所求(三选一,⛔ 本席不替分诊选)
pm:blocked+ 正文补Blocked-by: objectstack-ai/objectui#9309—— 这正是卡自己请求的那一笔,解锁扫描会在 objectui#9309 关闭时把它放回。本席认为这一条最贴合事实。pm:queue,但把范围改成「只测量、不声明」 —— 即 objectui#9711 / objectui#9729 那个形状:钉住投递路径(ListView.tsx的baseProps扩散确实到达object-tree)与两面皆无声明的事实,⛔ 不碰任何已发布面。这样它今天就可派,且不预判 objectui#9309。⛔ 本席已经在做的事
pm:blocked、不自行写Blocked-by:行、不改定级 —— 这些是分诊的笔。按细则,
pm:retriage与现行pm:*并存,⛔ 不摘原标;答复后由分诊席同笔摘标。⭐ 顺带一条对分诊有用的读数,⛔ 不是本卡的内容:本席今天在本车道连续两次把「在飞文件面」表读短了,两次漏的都是长期开着的 draft PR(objectui#9540、objectui#8941),而不是本轮的分支。串行表按「本轮推的分支」枚举是不够的。
Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
Claim: PM loop round 5 — objectui#9549, declare the
filterthatobject-treealready reads, in the shape objectui#9309 settledSession:
session_01877XiBYSaRCk2CU7cMSg3SBranch:
claude/issue-9549-tree-filter-declaredWorktree:
objectui-issue-9549Domain:
domain:specSeat:
domain:spec#1File surface:
packages/types/src/objectql.ts(theObjectTreeSchemaregion only),packages/types/src/zod/objectql.zod.ts(theObjectTreeSchemamirror only),packages/plugin-tree/src/ObjectTree.tsx(only if the typedfilterforces a change at its read sites, about:236and:742), their tests, and one.changeset/9549-…md(stop on breach; explain in the report)Container & model:
S,mode:subagent,model: opus(TIER_DEFAULT)Clause-②: no
Thread-read: 5722271575
Serial constraints cleared: the semantic dependency this card named (「land on whatever shape that card settles」) is discharged. objectui#9309 closed as completed at 2026-09-20T11:56Z, and
ObjectGallerySchema.filternow takesQueryParams['$filter']by reference (objectql.tsabout:4394-4409). Open PRs read at 2026-09-24T14:23Z: PR objectui#10260 (kanban comments), PR objectui#10262 (grid docblocks /rowActionsdescribe) and PR objectui#8941 (icon names) holdobjectql.ts/objectql.zod.tsin other regions. None touchesplugin-tree. Whichever lands second mergesmain.Clause-② reason (
no):BaseSchemastill carries[key: string]: any(base.ts:592,:624), and the zod mirror is passthrough, sofilteris accepted asanytoday. Declaring it with the settled type narrows the TS face, and runtime is unchanged. Delivery measured onmain:ObjectTree.tsx:742sends$filter: schema.filter.Dispatch authority: the maintainer ruling 「当前车道队列中如果已经没有 p0 p1,就应该可以派其他卡。」 (objectstack-ai/objectstack#19980).
objectstack-fleet commentedon Sep 24, 2026
os-dev-report
{ "issue": 9549, "status": "done", "branch": "claude/issue-9549-tree-filter-declared", "pr": "https://github.com/objectstack-ai/objectui/pull/10269", "session": "session_01877XiBYSaRCk2CU7cMSg3S (subagent, parent's id; container CLAUDE_CODE_REMOTE_SESSION_ID cse_01877XiBYSaRCk2CU7cMSg3S)", "premise_still_valid": true, "summary": "ObjectTreeSchema.filter is now declared as QueryParams['$filter'] on the TS interface. The zod mirror gets the gallery's two-arm union, array first. Both mirror ObjectGallerySchema.filter from objectui#9309 / PR objectui#9540 exactly. The typed filter made plugin-tree tsc refuse getTreeConfig's schema.filter?.tree arm, and the arm had zero authors and no pin, so it was removed and the changeset notes the removal. The objectui#8655 ledger entry for filter is retired, and the tree row is added to the objectui#9309 filter census. The newest Claim: comment (5815997870) names this branch. The assignee field reads os-bill, which is PM-owned and was not touched.", "assumptions": { "A1_no_filter_on_either_face": "HOLDS at fa5fbd9dc. The ObjectTreeSchema interface had objectName/parentField/labelField/fields/defaultExpandedDepth only. The zod BaseSchema.extend had the same five plus type. The 8655 pin asserted not.toContain('filter') on the mirror shape and Declares false on the TS face.", "A2_two_routes_and_read": "HOLDS. In ListView.tsx the baseProps object carries filter: schema.filter, and case 'tree' spreads ...baseProps into the object-tree node. In ObjectTree.tsx, dataSource.find sends $filter: schema.filter and the fetch effect deps list schema.filter. The filter?.tree read in getTreeConfig was the third read site.", "A3_index_signature_narrowing": "HOLDS. BaseSchema still ends in [key: string]: any, and the mirror is passthrough. The new pins keep IsAny true on the misspelled key filtr, and the mirror still accepts filtr: 'stage=won'.", "A4_filter_tree_arm": "ZERO AUTHORS, NO PIN, so REMOVED. A multiline search for a tree key inside a filter object literal found 0 files in objectui and 0 in ../objectstack. Positive control: the same pattern with status/stage/age hits 46 times in 34 files. The filter.tree text search hit only the read itself, plus one objectstack spec comment calling it a legacy stash to stop writing. No test pinned the arm. The 8655 ledger pinned the schema.filter read in general, and that read remains at the $filter fetch. git log -S on an unshallowed history finds only 4eb9cb6ac (objectui#1892, the renderer's first commit), and it states no reason. The typed filter made the arm a tsc error, because .tree does not exist on the FilterArray arm." }, "tests": "Head b1f1a2dee (after merging origin/main c9e073ac8). Types type-check: VERDICT command-exit 0. plugin-tree closure build then type-check: exit 0 both; the rebuilt types dist has 2 hits for 'filter?: QueryParams'. vitest on packages/types, packages/plugin-tree and the console registry-inputs-spec-parity test: Test Files 232 passed (232), Tests 5224 passed (5224), exit 0; the 4 named files pass verbosely, 233 tests. Reverse verification on the committed fix fcb7de2b3 with ablation-replace.mjs, restored to the HEAD blob with git diff HEAD empty both times. (1) TS member deleted, anchor 1 to 0: tsc -p tsconfig.test.json exit 2, with 4 errors of type TS2344 and 2 of type TS2578 in the new pin. (2) Mirror key renamed, anchor 1 to 0: 5 failed, 19 passed. The resolution path is source, not dist, because the plugin-tree pin went red on a src-only mutation.", "gates": [ {"cmd": "pnpm install", "exit": 0}, {"cmd": "pnpm --filter @object-ui/types type-check", "exit": 0, "note": "run twice, before and after the merge"}, {"cmd": "pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-tree^...' build", "exit": 0}, {"cmd": "pnpm --filter @object-ui/plugin-tree type-check", "exit": 0, "note": "run twice, before and after the merge"}, {"cmd": "pnpm exec vitest run --maxWorkers=2 packages/types/ packages/plugin-tree/ apps/console/src/__tests__/registry-inputs-spec-parity.test.ts", "exit": 0, "result": "232 files / 5224 tests passed", "head": "b1f1a2dee"}, {"cmd": "eslint --no-inline-config on the 6 changed ts files", "exit": 0, "result": "0 errors; warnings per source file equal base (objectql.ts 34, objectql.zod.ts 1, ObjectTree.tsx 22)"}, {"cmd": "node scripts/check-changeset-presence.mjs", "exit": 0}, {"cmd": "pnpm check:changeset-claims", "exit": 0, "note": "report-only; lists the pending 8655 changeset as a read request, which is still true"}, {"cmd": "pnpm check:component-surface-parity", "exit": 0, "note": "report-only"}, {"cmd": "pnpm check:handler-key-reads", "exit": 0}, {"cmd": "pnpm check:designer-field-key-parity", "exit": 0}, {"cmd": "pnpm check:action-forward-parity", "exit": 0}, {"cmd": "pnpm check:spec-symbols", "exit": 0}, {"cmd": "pnpm check:installed-pin-claims", "exit": 0}, {"cmd": "node scripts/check-new-cross-file-line-citations.mjs", "exit": 0, "verdict": "0 new citation(s)"}, {"cmd": "control-byte self-scan (grep -naP) on the changed files", "result": "0 hits"}, {"cmd": "node scripts/check-governed-queue-guard.mjs --test", "result": "NOT GOVERNED"} ], "gate_derivation": "objectui has no dispatch-gates.mjs, so the families were derived by hand: every package.json check:* script whose script file names objectql.zod, objectql.ts, plugin-tree, ObjectTree or packages/types/src. 14 matched. The 8 relevant to this diff were run; the doc, i18n, readme and dist ones read nothing this diff changes in kind, so they were not run.", "line_budget": "n/a: no skills/** or governed paths touched. Branch diff against its own commit: 7 files, +207 -12.", "files_changed": [ "packages/types/src/objectql.ts (ObjectTreeSchema region only)", "packages/types/src/zod/objectql.zod.ts (ObjectTreeSchema mirror only)", "packages/plugin-tree/src/ObjectTree.tsx (getTreeConfig: arm removed, docblock added above the function)", "packages/types/src/__tests__/object-tree-filter-9549.test.ts (new)", "packages/types/src/__tests__/object-gallery-filter-9309.test.ts (census row added)", "packages/plugin-tree/src/ObjectTree.schemaTyped-8655.test.ts (filter ledger entry retired)", ".changeset/9549-tree-filter-declared.md (minor: @object-ui/types, @object-ui/plugin-tree)" ], "deviations": [ "Two test files outside the new pin were edited: the 9309 census and the 8655 ledger. They are 'their tests' in the claim's surface, and each would have gone red on the declaration by design. The 8655 file says to retire the ledger on the day filter is declared.", "The changeset also bumps @object-ui/plugin-tree, because the filter.tree removal changes that published renderer.", "Labels: zero writes. objectui has no gate that reads dev-applied labels, and the dispatch named none." ], "mcp_calls": "0", "api_writes": "2 via the fleet-write relay (objectstack-fleet[bot]): pr_create POST /repos/objectstack-ai/objectui/pulls (draft, run 36015437755), and comment POST /repos/objectstack-ai/objectui/issues/9549/comments (this report). Plus git push, which is not REST: the branch probe, the commit and the merge.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: upstream @objectstack/spec at ../objectstack HEAD declares ObjectTreePropsSchema.filter as a ViewFilterRule array only, while this repo's settled family shape is QueryParams['$filter']. It is not reachable today, because the installed spec has no object-tree ComponentPropsMap entry, so it is not class a/b/c. carrier: whoever bumps the installed spec, since the 8655 pin 'no object-tree entry' reddens then. Dedup words: ObjectTreePropsSchema filter ViewFilterRule QueryParams" ] }Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
ACCEPT: objectui#9549, delivered by PR objectui#10269 at head
b1f1a2d. Sessionsession_01877XiBYSaRCk2CU7cMSg3S,domain:spec@ objectui seat, reviewed against the diff andorigin/main.filter?: QueryParams['$filter']. The zod mirror'sfilterunion and.describe()are character-identical toObjectGallerySchema.filter(zod/objectql.zod.tsabout:2384-2387onmain), i.e. exactly the shape objectui#9309 settled. No fourth spelling.getTreeConfigdrops theschema.filter?.treearm (schema.tree || schema.filter?.tree || {}becomesschema.tree || {}). The stop condition was cleared with evidence: a multiline search fortreeinside afilterliteral gave 0 files in objectui and 0 in objectstack, against a lit control of 46 hits in 34 files; no pin covered it; the only history is the renderer's first commit (objectui#1892), with no stated reason. The typedfiltermakes the arm a compile error, and AGENTS.md #0.1 forbids a renderer-side dialect. Removed, and the changeset says so.no. The declaration narrows the TS face (BaseSchemastill has[key: string]: any, and the new pins keep a misspelledfiltratany). The mirror's accept set narrows from passthrough-anything to the two arms.minorfor@object-ui/typesand@object-ui/plugin-treesuits a narrowing plus a published renderer change.filteris retired (its own file says to do this on the dayfilteris declared); the objectui#9309 census gains the tree row. There is a new pin with reverse verification (deleting the member gives 4×TS2344 and 2×TS2578; renaming the mirror key gives 5 red). 232 files / 5224 tests pass.ObjectTreePropsSchema.filterin the objectstack spec source isViewFilterRule[]only, while this repo's family shape isQueryParams['$filter']. It is unreachable today because the installed 17.4.0 has noobject-treeprops entry; the carrier is whoever bumps the spec (the objectui#8655 「no object-tree entry」 pin reddens then).Landing: flip ready and enqueue once every check on this head is green or an expected skip.
Generated by Claude Code
feat(types,plugin-tree): declare ObjectTreeSchema.filter in the settl…