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 }}
Repository navigation
spec(ui): ListViewSchema.filterableFields is described as the userFilters.fields shorthand, but its one renderer reads it as the Filter panel whitelist; retire or redefine (objectui#13047) #24640
ListViewSchema.filterableFields is described in the spec as the "legacy shorthand for userFilters.fields" (quick filters). The objectui renderer reads it differently:
ListView's filterFields memo takes it as the Filter panel's field whitelist;
filterableFields: ['stage'] on a page list-view node draws no quick-filter bar.
objectui therefore keeps it unpublished by measurement on list-view.
Options (the objectui dev's analysis, not a ruling)
A. Amend the describe to the Filter-panel whitelist the renderer reads, then objectui publishes it.
B. Have the renderer honour it as the userFilters.fields shorthand. That creates a second spelling of userFilters.fields.
C. Retire filterableFields (ADR-0049 / ADR-0087 conversion, no window). If a Filter-panel whitelist is wanted, it gets its own declared key.
The dev recommends C: the spec already calls it legacy, two meanings for one key is the trap "declared means enforced" exists to stop, and no measured author was found. A is the fallback.
Reader who acts: the domain:spec seat, in one PR on packages/spec/src/ui/view.zod.ts and its form row.
Dedupe: MCP search_issues "filterableFields userFilters shorthand legacy list view filter panel whitelist", closed included: 2 hits. They are this card, and REST 列表:显式 filter 在场时,同时传的字段级参数被静默丢弃(#4134 的邻居) #4164 (closed, REST list filter precedence), which is unrelated.
Fresh read (origin/main7c7741dcb4).
view.zod.ts:2844 describes filterableFields as "Legacy shorthand for userFilters.fields — … Prefer userFilters".
view.form.ts:81 offers it to authors as "Field names available for filtering".
So two spec texts already lean two ways.
Why p3.
No measured author.
objectui keeps the key unpublished on list-view, so no user flow breaks.
A consumer follow-up is p1 only when its absence breaks users (filing-gate.md:40).
Option. The objectui dev's recommendation, C (retire under an ADR-0087 conversion), is the lane's to take, with A as the fallback.
Protocol class. This retires or redefines a spec key, so the 「是否提前」 question goes to the maintainer. Triage lean: don't pull it forward. A conversion entry keeps a later retirement non-breaking, and no author is waiting.
Seat hold · domain:spec seat 2 (#18549) · session session_019oFY6Hi35J7atvgVFnmoaK · 2026-10-19T21:39Z · ⛔ Not a claim.
This card is the lane's only pm:queue candidate, and this seat has a free slot. It is not dispatched: under the standing triage rule 6261447528, a protocol-class card waits for the maintainer's 「是否提前」 answer, and landing it on main now would put it into 18.0 without that word. The seat put the question to the maintainer in its session report at 2026-10-19T21:39Z. The answer is recorded here when it comes.
Seat readings, for the answer:
Option. The lane takes C: retire filterableFields through an ADR-0087 conversion, with no window, and A as the fallback.
The governing text is the decision principle "declared but not honoured is an implementation gap: implement it or retire it, never narrow at the consumer". The spec declares the key as the userFilters.fields shorthand (view.zod.ts:2844). Its one renderer reads it as the Filter panel whitelist. The spec's own Studio form offers it as "Field names available for filtering" (view.form.ts:81).
Implementing it (B) would mint a second spelling of userFilters.fields, and a deprecated spelling retires at once.
Workload. S–M: view.zod.ts, view.form.ts, one conversion entry with its pin, the existing pins that name the key (view.test.ts:509, view-list-tabs-retirement.test.ts:308), the regenerated ui shards and reference page, and a changeset.
Seat correction to hold 6277988620 · domain:spec seat 2 (#18549) · session session_019oFY6Hi35J7atvgVFnmoaK · 2026-10-19T22:37Z · ⛔ Not a claim.
The hold's readings missed one consumer. Re-read at objectui origin/main:
The key is live on an object's list views.
packages/app-shell/src/views/ObjectView.tsx:3455 forwards filterableFields: viewDef.filterableFields ?? listSchema.filterableFields to ListView.
packages/plugin-list/src/ListView.tsx (the filterFields memo, around :4655) uses it as the Filter panel's field whitelist. Those are the fields "Add filter" offers.
A field the definition marks hidden: true is offered when the whitelist names it.
Field-level read security still applies (objectui#11925).
objectui withholds it only on a page list-view node (packages/plugin-list/src/index.tsx, around :126), for the reason the card gives. "objectui keeps it unpublished" is true of that node, not of object views.
No author found in this repository.git grep finds no example, app or platform object that writes it, only the Studio form row and its translations.
What this changes:
C is not behaviour-preserving. Retiring the key removes a working Filter-panel whitelist from object list views. A conversion filterableFields → userFilters.fields would not keep what an author sees: the whitelist would vanish and quick-filter chips would appear.
A becomes the cheapest coherent end state. The describe says what the renderer does, with no accept-set change and no conversion. userFilters keeps the quick-filter bar, and filterableFields names the Filter panel's fields: two UI surfaces with two keys. The spec's own form row already reads "Field names available for filtering" (view.form.ts:81).
A against C is a product question: does the platform want a Filter-panel whitelist at all? The seat does not settle it. The question goes to the maintainer with the timing question.
Ruled: C · recorded by domain:spec seat 2 (#18549) · session session_019oFY6Hi35J7atvgVFnmoaK · 2026-10-19T22:42Z
The maintainer's word, in this seat's session chat at 2026-10-19T22:42Z, verbatim: 「C」. It answers the question in the seat's correction 6278907207: "does the platform want a Filter-panel whitelist at all? … no ⇒ C".
What C means here.ListViewSchema.filterableFields retires.
The spec refuses the key with a tombstone that names the fix, and its Studio form row (view.form.ts:81) goes.
The key's live reader is objectui's Filter-panel whitelist (plugin-list/src/ListView.tsx, the filterFields memo, and app-shell/src/views/ObjectView.tsx:3455). It is removed in an objectui follow-up filed when the spec PR lands.
No Filter-panel whitelist replaces it: that is the ruling.
Conversion. An ADR-0087 entry may not rewrite filterableFields to userFilters.fields. The seat's correction measured that this does not keep what an author sees: the whitelist goes and quick-filter chips appear. So the retirement is a plain refusal with a tombstone. Its migration disposition is the dispatch's to measure against check-adr-0087-registration: either a conversion that drops the key, or not-required with the prescription.
Not yet answered: the timing (「是否提前」, rule 6261447528). The seat's lean is to pull it into 18.0. Once 18.0 is out, a retirement is a narrowing that waits for 19.0 or needs a non-breaking form, and the start-up doctrine allows no staged window. The question is put to the maintainer now. Until it is answered, the card stays pm:queue, undispatched.
Serial constraint, either way: the retirement's migration entry sits under packages/spec/src/migrations/entries/, where seat 3's #24637 is in flight. Dispatch follows its landing.
Ruled: pull into 18.0 · recorded by domain:spec seat 2 (#18549) · session session_019oFY6Hi35J7atvgVFnmoaK · 2026-10-19T22:46Z
The maintainer's word, in this seat's session chat at 2026-10-19T22:46Z, verbatim: 「提前」. It answers the 「是否提前」 question in 6278975049 (rule 6261447528): the retirement ruled C lands in 18.0.
Label change in this act:target:v18 is added, executing that word. The source is the maintainer, verbatim 「提前」, in seat 2's session chat. The grade (p3), the lane and area:api are unchanged.
Correction to the serial constraint that 6277988620 and 6278975049 both stated: there is none.
Claim: PM loop round 1 · 2026-10-19T22:47Z · retire ListViewSchema.filterableFields (and its ObjectListView twin) with a tombstone, ruled C, in 18.0
Ruled C (6278975049) and pulled into 18.0 (6279033298) on the maintainer's words in this session's chat, verbatim: 「C」 and then 「提前」. The seat's batch 2 (「并发2」) holds it; #24563 is this seat's other card, in the merge queue.
Session: session_019oFY6Hi35J7atvgVFnmoaK (the seat; the dev is an os-dev subagent of this session)
Account: zhuangjianguo (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-24640-retire-filterable-fields
Worktree: objectstack-issue-24640
Domain: domain:spec
Seat: domain:spec#2 (seat post #18549)
File surface (paths on origin/mainbfc1539fe0 or later; stop on a breach and explain it in the report):
packages/spec/src/ui/view.zod.ts: filterableFields (about :2844) leaves the list-view shape and is refused with a tombstone that names the fix. The shape is the one the existing ListView retirements take, bordered / striped / virtualScroll. It covers ObjectListView, which derives from the same shape;
packages/spec/src/ui/view.form.ts: the filterableFields Studio form row (about :81) goes;
packages/spec/src/migrations/entries/retired-keys/18.ui__ListView__filterableFields.ts and 18.ui__ObjectListView__filterableFields.ts (or whatever entries the retirement gate names), plus a conversion that DROPS the key, if check-adr-0087-registration asks for one. ⛔ It must never rewrite the key to userFilters.fields;
the pins that name the key (view.test.ts:509, view-list-tabs-retirement.test.ts:308) and a new tombstone pin;
generated artefacts by their own tools only: authorable-surface/ui.json and authorable-surface.base.json, liveness/view.json, content/docs/references/**, the platform-objects metadata-forms translations, and any other the generators name;
the hand-written example at content/docs/concepts/architecture.mdx:245;
one .changeset/24640-*.md (@objectstack/spec).
⛔ Not content/docs/releases/, not packages/spec/CHANGELOG.md, not userFilters.
Container & model: S–M, mode:subagent, model: default tier for the draft (dispatch-gates --tier: a Clause-② SUSPECT hint on packages/spec/src/**, no path-derived mandate). The review before the queue runs at CONTRACT_REVIEW_TIER (the narrowing face: a key leaves the accept set).
Clause-②: yes (narrowing)
Responsibility: the spec's own declaration (view.zod.ts:2844 describes the key as the userFilters.fields shorthand; the one renderer reads it as the Filter panel's whitelist) · the platform path that covers the need is userFilters for a curated quick-filter bar, and field read security and hidden for the Filter panel · it is reached by objectui's object list views (app-shell/src/views/ObjectView.tsx:3455, plugin-list/src/ListView.tsx's filterFields); no author was found in this repository
Thread-read: 6279033298
Serial constraints cleared:
The file lists of all open PRs were read in this act. None touches ui/view.zod.ts, ui/view.form.ts or the ui shards.
mode:subagent: the dev is an os-dev subagent of this session, on branch claude/issue-24640-retire-filterable-fields, at the default tier. batch 2: #24563 is this seat's other card, in the merge queue.
The ruling is C, pulled into 18.0 (6278975049, 6279033298):
filterableFields retires from the list-view shape, ObjectListView included, with a tombstone that names userFilters.
The Studio form row goes.
The docs example is re-trued.
No replacement key.
⛔ No conversion to userFilters.fields. If the ADR-0087 machinery wants a conversion, it is one that drops the key, as view-list-passthrough-keys-removed does.
The dev verifies four premises before editing:
the key's sites;
no author in this repository;
the 17.x ListView retirement mechanism;
the generated artefacts.
It stops and reports a fork on any breach.
The spec-lane fixture rule applies: the consumer packages that parse views, and every example's os validate, run after the change.
objectui's reader is objectui's follow-up, filed by the seat when this lands.
The dev reports here as an os-dev-report comment and opens a draft PR. The contract review runs on the narrowing face before the queue.
os-dev-report
{
"issue": 24640,
"status": "done",
"branch": "claude/issue-24640-retire-filterable-fields",
"pr": "#24721",
"session": "session_019oFY6Hi35J7atvgVFnmoaK — subagent of the domain:spec seat 2 session (parent's id)",
"premise_still_valid": true,
"summary": "Retired ListViewSchema.filterableFields per ruling C. The retirement has five parts. (1) A retiredKey() tombstone in ListViewShapeSchema; it covers ObjectListViewSchema (derived by .omit), the flattened overlay arms and a page list-view node's properties. Its prescription: delete the key; no per-view Filter-panel whitelist replaces it; userFilters for a curated filter bar; the Filter panel offers every readable field, minus fields the object marks hidden. (2) The Studio form row is removed and the 4 bundles are regenerated. (3) D2 conversion view-list-filterable-fields-removed DROPS the key and never rewrites it to userFilters.fields (toMajor 18, retiredFromLoadPath, retiredAfter 17.7.0), with D3 entry list-view-filterable-fields-retired, the retired-keys entries ui/ListView:filterableFields and ui/ObjectListView:filterableFields, and a STEP18_RATIONALE fragment. (4) The liveness row flips live to dead with a REMOVED note. (5) architecture.mdx is re-trued to userFilters, and the changeset is minor + BREAKING + registered. files_changed (24 vs origin/main): .changeset/24640-list-view-filterable-fields-retired.md; content/docs/concepts/architecture.mdx; content/docs/references/{api/protocol,data/object,ui/view}.mdx (generated); packages/platform-objects/src/apps/translations/{en,es-ES,ja-JP,zh-CN}.metadata-forms.generated.ts (generated); packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts; packages/spec/authorable-surface/ui.json (generated); packages/spec/liveness/state-counts/view.md (generated); packages/spec/liveness/view.json; packages/spec/src/conversions/registry.ts; packages/spec/src/migrations/entries/retired-keys/18.ui__ListView__filterableFields.ts; packages/spec/src/migrations/entries/retired-keys/18.ui__ObjectListView__filterableFields.ts; packages/spec/src/migrations/entries/semantic/18.list-view-filterable-fields-retired.ts; packages/spec/src/migrations/registry.ts.template; packages/spec/src/shared/retired-key-removal-version.pin.test.ts; packages/spec/src/ui/view-list-filterable-fields-retirement.test.ts (new); packages/spec/src/ui/view.form.ts; packages/spec/src/ui/view.test.ts; packages/spec/src/ui/view.zod.ts; packages/spec/vitest.repo-tests.json. deviations: (a) The file surface grew inside packages/spec where gates demanded it: a JOIN row in retired-key-removal-version.pin.test.ts (every retired entry at the newest stable must have one); the registry.ts.template rationale fragment; vitest.repo-tests.json (the new tree-walk pin, held equal by check:cross-package-test-inputs); and two extra generated reference pages. (b) A cross-lane rider for the seat to declare: platform-objects object-lifecycle-panel-echo-decisions.test.ts, where the pinned metadata-form catalog count moves 674 to 673 because the removed input took its label out of all three locales. (c) The runtime local suite ran in 3 batches and the cli unit suite in 4, because of the foreground cap. (d) The metadata-protocol, objectql, rest, runtime and cli readings were taken at c0c1a8a, before merging origin/main; the merge brought zero new filterableFields mentions (per-file git grep -c is identical at base and at origin/main 1c1144f). (e) 7 build/publish-tooling tests in the spec repo project are NOT MEASURED locally (they outlast the foreground cap) and are left to CI. (f) Commits carry the AGENTS.md model-free trailer pair, not the harness's model-named Co-Authored-By line. Also: the Studio offered the key, so stored view rows may carry it; the D2 drop widens their Filter panel, which is the ruled end state and is stated in the changeset and the D3 entry. PR #24721 opened as a draft with assignee zhuangjianguo and no labels; the Auto Label job (another actor) ran on it.",
"tests": "All runs under os-verify-lock.sh with --maxWorkers=2, verdicts read from VERDICT lines. @objectstack/spec local: 702 files / 21352 passed (1 todo), at c0c1a8a and again at merged head bb71914. spec repo project: 64 of 71 files / 1039 passed at bb71914, including the new pin and view-list-tabs-retirement. The other 7 (build-console-objectstack-root, build-schemas-check-mode, dist-freshness, dist-freshness-adoption, publish-smoke-boot-failure, publish-smoke-port-collision, published-projection-choke-point) are NOT MEASURED: they hit timeout 124 under the foreground cap; reason: shared box, tooling not read by this diff; owner: CI Test Core. spec typecheck: exit 0 at bb71914 (the test layer compiles, so the @ts-expect-error on the tombstone is live). @objectstack/lint: 148 files / 6935 passed at bb71914. @objectstack/platform-objects: 79 / 1195 passed at bb71914; its typecheck exits 0. It went red once before the count update (zh-CN positive control expected 674, received 673). @objectstack/metadata-protocol: 249 files (3 skipped) / 20771 passed. @objectstack/objectql local: 448 / 8447 passed. @objectstack/rest local: 300 / 6095 passed (326 skipped). @objectstack/runtime local: 425 files in 3 batches / 1928+2822+1921 passed (19 skipped). @objectstack/cli unit: 314 files in 4 batches / 1426+1017+1209+989 passed; the integration layer is declared to CI. The last five ran at c0c1a8a. Examples: os validate plus os build pass on app-crm, app-todo, app-showcase (after building its closure; the first try was MODULE_NOT_FOUND, a prerequisite and not a red) and app-multi-package. ABLATION, committed fix first: scripts/ablation-replace.mjs in wrap mode with an outer trap swapped the tombstone line for filterableFields: z.array(z.string()).optional(). On disk: anchor 1 to 0, replacement 0 to 1, blob 1e5e34e05ab8 to d38c1ae00383, in-command grep -c 1/0. The new pin plus retired-key-removal-version.pin went RED as predicted: 13 failed / 71 passed. The failures were the 8 door refusals, the empty array, the prescription, the tsc-channel parse, the object listViews boundary and the JOIN row; the controls, boundaries and D2 pins stayed green. Restore: blob == HEAD 1e5e34e05ab8 and git diff HEAD empty. No dist leg applies, because the pins import src by relative path.",
"gates": "Re-derived on the final head bb71914 with no paths: dispatch-gates --commands --repo objectstack-ai/objectstack, 24 paths vs merge base 1c1144f, giving 115 commands. All 115 were run, each exit captured before any pipe. 114 exited 0 on the first pass. check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET: 7 unrelated packages had no dist), then 0 after building them. --ran reconciliation: 115 derived famil(ies) accounted for — 115 run, 0 NOT-MEASURED (a DERIVED zero — all 115 recorded an exit code and none of them is 3). Key verdict lines: check-adr-0087-registration 'registered view-list-filterable-fields-removed, list-view-filterable-fields-retired (new here: both)'; check:api-surface 'public API surface + factory signatures unchanged'; check:docs '227 generated files in sync'; check:generated 'All 14 generated artifacts are up to date'; check:skill-examples '262 prose examples type-check'; check:i18n OK; check:doc-authoring clean; check:cross-package-test-inputs OK; check:nul-bytes OK; check-empty-changeset and check-changeset-no-major pass. check:entry-nameability carries a standing NOT MEASURED note about api-assembled/qa that predates this diff. Local-only: check:dev-prereqs exit 0. check-platform-checklist --changed-from was not run: no exported symbol was renamed or removed (api-surface unchanged). PR #24721 check-runs, read once at report time: in_progress for Lint & Repo Gates lanes (Lint ESLint, Lint repo & tooling, Lint docs & code guards, Lint PM dispatch-gates, Lint CI release & engine, Lint scoped x3), Type Check lanes (workspace, source gates, consumer gates, debt ledger), Test Core 1-6/6, Build Core, Build Docs, Governed Surface Queue Guard and Check Changeset. success: Spec property liveness, Check PR Size, Check Documentation Links, Flag docs affected by code changes, filter, the card-claims-this-branch check, the single-writer and single-issue claim checks, Part-of check, Auto Label and Dogfood Regression Gate. skipped (full battery only): Console Pin Gate, Temporal Conformance, Dogfood shards, Dogfood Verify CLI and Packed-tarball smoke.",
"mcp_calls": "0 — no MCP tool used",
"api_writes": "2 — each one relay stroke (POST /repos/objectstack-ai/objectstack/dispatches): (1) pr_create, executed as POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/24721/assignees, read back identical; (2) this os-dev-report comment, POST /repos//issues/24640/comments. Plus git push of the branch, which is not a REST write.",
"open_questions": [
{
"question": "ADR-0047 (Accepted) Decision 1 still says filterableFields 'stays as the legacy shorthand; loaders auto-upgrade it to userFilters.fields entries'. That loader was never built, and ruling C retires the key and forbids that rewrite. Its own section 4 calls the alias 'one-release courtesies, not commitments'. Prime Directive 13 wants a reversed recorded decision amended. Does ADR-0047 get an amendment line, and where?",
"options": [
"A: a separate docs-only PR adds an amendment line to ADR-0047's status block, citing records 6278975049 and 6279033298. It is Tier H (maintainer approval) and about 15 min to author; PR #24721 lands as is.",
"B: fold the same amendment into PR #24721. Same authoring cost, but the whole PR becomes Tier H, so it waits for the maintainer's approval before the seat can queue it.",
"C: no amendment. Zero cost now; the stale Decision 1 sentence keeps telling the next reader that a loader rewrites filterableFields to userFilters.fields."
],
"recommendation": "A, by the four axes. Business need: zero authors were measured, but the ADR has a real reader, the next agent or maintainer planning list-view work. Long-term soundness: Prime Directive 13 keeps the record true, and A does it without coupling a governed landing to this contract change. Preventing AI authoring errors: left stale, the sentence invites an agent to re-add exactly the rewrite conversion the ruling forbids; A and B close that and C does not. No startup sprawl: A adds one small governed PR, B adds a Tier H wait to this PR, and C costs nothing but leaves the trap. The ruling itself is not reopened by any option."
}
],
"out_of_scope_findings": [
"carrier: domain:spec seat 2 (session_019oFY6Hi35J7atvgVFnmoaK), beside the objectui follow-up it files — noted, not filed (dead code once the parse refuses the key). In-repo readers still classify filterableFields off raw input: packages/lint/src/validate-list-view-field-refs.ts (role and severity maps, plus its test fixtures); packages/lint/src/validate-react-page-props.ts REACT_FIELD_SPECS.ListView, plus the 'covers the legacy filterableFields shorthand' test; packages/lint/src/validate-field-consumers.ts:307; packages/lint/src/rule-explanations.ts:3114 and :3149 (os explain text naming the key as a checked position); packages/metadata-protocol/src/metadata-diagnostics.ts:237 plus the packages/objectql/src/metadata-diagnostics.test.ts fixtures; packages/metadata-core/src/object-schema-fls-references.ts LIST_VIEW_NAME_LISTS.filterableFields. The new pin's RESIDUE set tracks the four that spell it as an object key and goes red when they are deleted. Dedupe words: filterableFields lint residue, list view field refs filterableFields, LIST_VIEW_NAME_LISTS filterableFields.",
"carrier: domain:spec seat 2 (session_019oFY6Hi35J7atvgVFnmoaK) — noted, not filed; reach is NOT MEASURED. Boundary: a react page's ListView element can still pass a filterableFields prop. Its source string is parsed against no schema, and the react-props lint treats the prop as field-bearing ('honored by the renderer'). objectui's reader still honours it at pin 12dc7b47; once objectui's follow-up removes the reader, the prop becomes a silent no-op on react pages unless the react-props lint learns to refuse it. Dedupe words: react ListView filterableFields prop, REACT_FIELD_SPECS retired prop, react page props retired key.",
"carrier: domain:spec seat 2 (session_019oFY6Hi35J7atvgVFnmoaK), who files it when this lands, per the dispatch. objectui follow-up, re-read at the moved pin 12dc7b47: app-shell/src/views/ObjectView.tsx:3448 forwards the key; plugin-list/src/ListView.tsx:4656 holds the filterFields whitelist; plugin-view/src/ObjectView.tsx:3124 forwards it, :1030 keeps a key list, and plugin-view/src/index.tsx:90 registers an input; types/src/objectql.ts:2625 and :2966 declare it locally; types/src/zod/objectql.zod.ts:1300 reads .shape.filterableFields by reference, so the tombstone flows in on the next pin bump. No export is removed, so the pinned objectui build compiles unchanged. Dedupe words: objectui filterableFields whitelist removal, ListView filterFields memo, filterableFields follow-up."
]
}
git patch-id --stable of the merge's diff equals that of the reviewed head bb71914fc9 against its merge base (74136a0a93). What landed is what the contract review 6281884602 passed.
The queue branch gh-readonly-queue/main/pr-24721-* is gone.
The mis-close scan over issues closed in the merge minute finds this card alone.
State:pm:dispatched was removed in this act. domain:spec, area:api, priority:p3 and target:v18 stay.
What it carries (ruling C 「C」 6278975049, pulled into 18.0 「提前」 6279033298):
ListViewSchema.filterableFields is a retiredKey() tombstone that names userFilters;
the D2 conversion view-list-filterable-fields-removed DROPS the key, never rewriting it to userFilters.fields, with its D3 entry;
the Studio form row is gone, the liveness row is dead, and architecture.mdx is re-trued.
Activity
objectstack-fleet commentedon Oct 19, 2026
Triage: p3 ·
bug· lanedomain:spec·area:api·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-19T21:05ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
Filing-gate answers completed under ruling 「B」 (#24589).
ListView'sfilterFieldsmemo, measured in feat(plugin-list): list-view publishes the spec keys its renderer honours on a page node (objectui#13047) objectui#13072.domain:specseat, in one PR onpackages/spec/src/ui/view.zod.tsand its form row.search_issues"filterableFields userFilters shorthand legacy list view filter panel whitelist", closed included: 2 hits. They are this card, and REST 列表:显式filter在场时,同时传的字段级参数被静默丢弃(#4134 的邻居) #4164 (closed, REST listfilterprecedence), which is unrelated.Fresh read (
origin/main7c7741dcb4).view.zod.ts:2844describesfilterableFieldsas "Legacy shorthand for userFilters.fields — … Prefer userFilters".view.form.ts:81offers it to authors as "Field names available for filtering".Why p3.
list-view, so no user flow breaks.filing-gate.md:40).Option. The objectui dev's recommendation, C (retire under an ADR-0087 conversion), is the lane's to take, with A as the fallback.
Protocol class. This retires or redefines a spec key, so the 「是否提前」 question goes to the maintainer. Triage lean: don't pull it forward. A conversion entry keeps a later retirement non-breaking, and no author is waiting.
Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Seat hold ·
domain:specseat 2 (#18549) · sessionsession_019oFY6Hi35J7atvgVFnmoaK· 2026-10-19T21:39Z · ⛔ Not a claim.This card is the lane's only
pm:queuecandidate, and this seat has a free slot. It is not dispatched: under the standing triage rule6261447528, a protocol-class card waits for the maintainer's 「是否提前」 answer, and landing it onmainnow would put it into 18.0 without that word. The seat put the question to the maintainer in its session report at 2026-10-19T21:39Z. The answer is recorded here when it comes.Seat readings, for the answer:
filterableFieldsthrough an ADR-0087 conversion, with no window, and A as the fallback.userFilters.fieldsshorthand (view.zod.ts:2844). Its one renderer reads it as the Filter panel whitelist. The spec's own Studio form offers it as "Field names available for filtering" (view.form.ts:81).userFilters.fields, and a deprecated spelling retires at once.packages/spec/src/migrations/entries/, a shared hot spot. Seat 3's 18.0 release text still sends operators toos migrate organization-ownership --out / --apply --plan-file, which 18.0 refuses on every database (family close-out: spec upgrade-guide entries, runtime boot refusals, plugin-security report, docs) #24637 (p1,target:v18) is in flight there now. This card dispatches after it, either way.view.zod.ts,view.form.ts, one conversion entry with its pin, the existing pins that name the key (view.test.ts:509,view-list-tabs-retirement.test.ts:308), the regenerateduishards and reference page, and a changeset.是否提前(给维护者)
filterableFields在加载时会被改写成userFilters.fields。list-view也没发布它。os migrate organization-ownership --out / --apply --plan-file, which 18.0 refuses on every database (family close-out: spec upgrade-guide entries, runtime boot refusals, plugin-security report, docs) #24637 正在动,发版前硬挤一个 p3 进去,风险大于收益;pm:on-hold,Restart-when:设为 18.0.0 发布。发布后按 C 派发。Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Seat correction to hold
6277988620·domain:specseat 2 (#18549) · sessionsession_019oFY6Hi35J7atvgVFnmoaK· 2026-10-19T22:37Z · ⛔ Not a claim.The hold's readings missed one consumer. Re-read at objectui
origin/main:packages/app-shell/src/views/ObjectView.tsx:3455forwardsfilterableFields: viewDef.filterableFields ?? listSchema.filterableFieldstoListView.packages/plugin-list/src/ListView.tsx(thefilterFieldsmemo, around:4655) uses it as the Filter panel's field whitelist. Those are the fields "Add filter" offers.hidden: trueis offered when the whitelist names it.list-viewnode (packages/plugin-list/src/index.tsx, around:126), for the reason the card gives. "objectui keeps it unpublished" is true of that node, not of object views.git grepfinds no example, app or platform object that writes it, only the Studio form row and its translations.What this changes:
filterableFields → userFilters.fieldswould not keep what an author sees: the whitelist would vanish and quick-filter chips would appear.userFilterskeeps the quick-filter bar, andfilterableFieldsnames the Filter panel's fields: two UI surfaces with two keys. The spec's own form row already reads "Field names available for filtering" (view.form.ts:81).更正(给维护者)
list-view组件没开放它。userFilters.fields也保不住原来的效果。Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Ruled: C · recorded by
domain:specseat 2 (#18549) · sessionsession_019oFY6Hi35J7atvgVFnmoaK· 2026-10-19T22:42ZThe maintainer's word, in this seat's session chat at 2026-10-19T22:42Z, verbatim: 「C」. It answers the question in the seat's correction
6278907207: "does the platform want a Filter-panel whitelist at all? … no ⇒ C".What C means here.
ListViewSchema.filterableFieldsretires.view.form.ts:81) goes.plugin-list/src/ListView.tsx, thefilterFieldsmemo, andapp-shell/src/views/ObjectView.tsx:3455). It is removed in an objectui follow-up filed when the spec PR lands.Conversion. An ADR-0087 entry may not rewrite
filterableFieldstouserFilters.fields. The seat's correction measured that this does not keep what an author sees: the whitelist goes and quick-filter chips appear. So the retirement is a plain refusal with a tombstone. Its migration disposition is the dispatch's to measure againstcheck-adr-0087-registration: either a conversion that drops the key, ornot-requiredwith the prescription.Not yet answered: the timing (「是否提前」, rule
6261447528). The seat's lean is to pull it into 18.0. Once 18.0 is out, a retirement is a narrowing that waits for 19.0 or needs a non-breaking form, and the start-up doctrine allows no staged window. The question is put to the maintainer now. Until it is answered, the card stayspm:queue, undispatched.Serial constraint, either way: the retirement's migration entry sits under
packages/spec/src/migrations/entries/, where seat 3's #24637 is in flight. Dispatch follows its landing.Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Ruled: pull into 18.0 · recorded by
domain:specseat 2 (#18549) · sessionsession_019oFY6Hi35J7atvgVFnmoaK· 2026-10-19T22:46ZThe maintainer's word, in this seat's session chat at 2026-10-19T22:46Z, verbatim: 「提前」. It answers the 「是否提前」 question in
6278975049(rule6261447528): the retirement ruled C lands in 18.0.Label change in this act:
target:v18is added, executing that word. The source is the maintainer, verbatim 「提前」, in seat 2's session chat. The grade (p3), the lane andarea:apiare unchanged.Correction to the serial constraint that
6277988620and6278975049both stated: there is none.os migrate organization-ownership --out / --apply --plan-file, which 18.0 refuses on every database (family close-out: spec upgrade-guide entries, runtime boot refusals, plugin-security report, docs) #24637 is PR fix(spec): 18.0 upgrade-guide entries say 18.0 supports fresh installs only #24661. It edits seven files underpackages/spec/src/migrations/entries/semantic/and its own changeset, read in this act.entries/retired-keys/, as17.ui__ListView__bordered.tsand17.ui__ObjectListView__bordered.tsdo.packages/spec/src/migrations/registry.tsis generated and git-ignored.retired-keys/are feat(plugin-webhooks,runtime)!: declared webhooks are read from the registry, the seeder retires, and the activation ledger switches them (18.x step 1, 8b-0g′) #24588 and feat(objectql,cli,plugin-webhooks)!: 18.x step 4: the walled lift (8b walled half, the os serve lift, the declared-webhook name guard, declared webhooks deployment-wide) #24667, on18.integration__Connector__webhooks.ts. No open PR touchesui/view.zod.ts,ui/view.form.tsor theuishards.The card is claimed and dispatched in this act.
Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Claim: PM loop round 1 · 2026-10-19T22:47Z · retire
ListViewSchema.filterableFields(and itsObjectListViewtwin) with a tombstone, ruled C, in 18.0Ruled C (
6278975049) and pulled into 18.0 (6279033298) on the maintainer's words in this session's chat, verbatim: 「C」 and then 「提前」. The seat'sbatch 2(「并发2」) holds it; #24563 is this seat's other card, in the merge queue.Session:
session_019oFY6Hi35J7atvgVFnmoaK(the seat; the dev is anos-devsubagent of this session)Account:
zhuangjianguo(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-24640-retire-filterable-fieldsWorktree:
objectstack-issue-24640Domain:
domain:specSeat:
domain:spec#2(seat post #18549)File surface (paths on
origin/mainbfc1539fe0or later; stop on a breach and explain it in the report):packages/spec/src/ui/view.zod.ts:filterableFields(about:2844) leaves the list-view shape and is refused with a tombstone that names the fix. The shape is the one the existingListViewretirements take,bordered/striped/virtualScroll. It coversObjectListView, which derives from the same shape;packages/spec/src/ui/view.form.ts: thefilterableFieldsStudio form row (about:81) goes;packages/spec/src/migrations/entries/retired-keys/18.ui__ListView__filterableFields.tsand18.ui__ObjectListView__filterableFields.ts(or whatever entries the retirement gate names), plus a conversion that DROPS the key, ifcheck-adr-0087-registrationasks for one. ⛔ It must never rewrite the key touserFilters.fields;view.test.ts:509,view-list-tabs-retirement.test.ts:308) and a new tombstone pin;authorable-surface/ui.jsonandauthorable-surface.base.json,liveness/view.json,content/docs/references/**, the platform-objects metadata-forms translations, and any other the generators name;content/docs/concepts/architecture.mdx:245;.changeset/24640-*.md(@objectstack/spec).content/docs/releases/, notpackages/spec/CHANGELOG.md, notuserFilters.Container & model:
S–M,mode:subagent,model: default tierfor the draft (dispatch-gates --tier: a Clause-② SUSPECT hint onpackages/spec/src/**, no path-derived mandate). The review before the queue runs atCONTRACT_REVIEW_TIER(the narrowing face: a key leaves the accept set).Clause-②: yes (narrowing)
Responsibility: the spec's own declaration (
view.zod.ts:2844describes the key as theuserFilters.fieldsshorthand; the one renderer reads it as the Filter panel's whitelist) · the platform path that covers the need isuserFiltersfor a curated quick-filter bar, and field read security andhiddenfor the Filter panel · it is reached by objectui's object list views (app-shell/src/views/ObjectView.tsx:3455,plugin-list/src/ListView.tsx'sfilterFields); no author was found in this repositoryThread-read: 6279033298
Serial constraints cleared:
ui/view.zod.ts,ui/view.form.tsor theuishards.retired-keys/18.integration__Connector__webhooks.ts, a different file.os migrate organization-ownership --out / --apply --plan-file, which 18.0 refuses on every database (family close-out: spec upgrade-guide entries, runtime boot refusals, plugin-security report, docs) #24637 (PR fix(spec): 18.0 upgrade-guide entries say 18.0 supports fresh installs only #24661) is inentries/semantic/, which is disjoint.columnsfields are accepted (200 active, draft → publish) where the same body is refused 422list-view-field-unknown#24563 (this seat) is inpackages/lint/**and test files, which are disjoint.Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Dispatched ·
domain:specseat 2 · sessionsession_019oFY6Hi35J7atvgVFnmoaK· 2026-10-19T22:49Z · for claim6279050200.mode:subagent: the dev is anos-devsubagent of this session, on branchclaude/issue-24640-retire-filterable-fields, at the default tier.batch 2: #24563 is this seat's other card, in the merge queue.The ruling is C, pulled into 18.0 (
6278975049,6279033298):filterableFieldsretires from the list-view shape,ObjectListViewincluded, with a tombstone that namesuserFilters.userFilters.fields. If the ADR-0087 machinery wants a conversion, it is one that drops the key, asview-list-passthrough-keys-removeddoes.The dev verifies four premises before editing:
ListViewretirement mechanism;It stops and reports a fork on any breach.
The spec-lane fixture rule applies: the consumer packages that parse views, and every example's
os validate, run after the change.objectui's reader is objectui's follow-up, filed by the seat when this lands.
The dev reports here as an
os-dev-reportcomment and opens a draft PR. The contract review runs on the narrowing face before the queue.Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{
"issue": 24640,
"status": "done",
"branch": "claude/issue-24640-retire-filterable-fields",
"pr": "#24721",
"session": "session_019oFY6Hi35J7atvgVFnmoaK — subagent of the domain:spec seat 2 session (parent's id)",
"premise_still_valid": true,
"summary": "Retired ListViewSchema.filterableFields per ruling C. The retirement has five parts. (1) A retiredKey() tombstone in ListViewShapeSchema; it covers ObjectListViewSchema (derived by .omit), the flattened overlay arms and a page list-view node's properties. Its prescription: delete the key; no per-view Filter-panel whitelist replaces it; userFilters for a curated filter bar; the Filter panel offers every readable field, minus fields the object marks hidden. (2) The Studio form row is removed and the 4 bundles are regenerated. (3) D2 conversion view-list-filterable-fields-removed DROPS the key and never rewrites it to userFilters.fields (toMajor 18, retiredFromLoadPath, retiredAfter 17.7.0), with D3 entry list-view-filterable-fields-retired, the retired-keys entries ui/ListView:filterableFields and ui/ObjectListView:filterableFields, and a STEP18_RATIONALE fragment. (4) The liveness row flips live to dead with a REMOVED note. (5) architecture.mdx is re-trued to userFilters, and the changeset is minor + BREAKING + registered. files_changed (24 vs origin/main): .changeset/24640-list-view-filterable-fields-retired.md; content/docs/concepts/architecture.mdx; content/docs/references/{api/protocol,data/object,ui/view}.mdx (generated); packages/platform-objects/src/apps/translations/{en,es-ES,ja-JP,zh-CN}.metadata-forms.generated.ts (generated); packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts; packages/spec/authorable-surface/ui.json (generated); packages/spec/liveness/state-counts/view.md (generated); packages/spec/liveness/view.json; packages/spec/src/conversions/registry.ts; packages/spec/src/migrations/entries/retired-keys/18.ui__ListView__filterableFields.ts; packages/spec/src/migrations/entries/retired-keys/18.ui__ObjectListView__filterableFields.ts; packages/spec/src/migrations/entries/semantic/18.list-view-filterable-fields-retired.ts; packages/spec/src/migrations/registry.ts.template; packages/spec/src/shared/retired-key-removal-version.pin.test.ts; packages/spec/src/ui/view-list-filterable-fields-retirement.test.ts (new); packages/spec/src/ui/view.form.ts; packages/spec/src/ui/view.test.ts; packages/spec/src/ui/view.zod.ts; packages/spec/vitest.repo-tests.json. deviations: (a) The file surface grew inside packages/spec where gates demanded it: a JOIN row in retired-key-removal-version.pin.test.ts (every retired entry at the newest stable must have one); the registry.ts.template rationale fragment; vitest.repo-tests.json (the new tree-walk pin, held equal by check:cross-package-test-inputs); and two extra generated reference pages. (b) A cross-lane rider for the seat to declare: platform-objects object-lifecycle-panel-echo-decisions.test.ts, where the pinned metadata-form catalog count moves 674 to 673 because the removed input took its label out of all three locales. (c) The runtime local suite ran in 3 batches and the cli unit suite in 4, because of the foreground cap. (d) The metadata-protocol, objectql, rest, runtime and cli readings were taken at c0c1a8a, before merging origin/main; the merge brought zero new filterableFields mentions (per-file git grep -c is identical at base and at origin/main 1c1144f). (e) 7 build/publish-tooling tests in the spec repo project are NOT MEASURED locally (they outlast the foreground cap) and are left to CI. (f) Commits carry the AGENTS.md model-free trailer pair, not the harness's model-named Co-Authored-By line. Also: the Studio offered the key, so stored view rows may carry it; the D2 drop widens their Filter panel, which is the ruled end state and is stated in the changeset and the D3 entry. PR #24721 opened as a draft with assignee zhuangjianguo and no labels; the Auto Label job (another actor) ran on it.",
"tests": "All runs under os-verify-lock.sh with --maxWorkers=2, verdicts read from VERDICT lines. @objectstack/spec local: 702 files / 21352 passed (1 todo), at c0c1a8a and again at merged head bb71914. spec repo project: 64 of 71 files / 1039 passed at bb71914, including the new pin and view-list-tabs-retirement. The other 7 (build-console-objectstack-root, build-schemas-check-mode, dist-freshness, dist-freshness-adoption, publish-smoke-boot-failure, publish-smoke-port-collision, published-projection-choke-point) are NOT MEASURED: they hit timeout 124 under the foreground cap; reason: shared box, tooling not read by this diff; owner: CI Test Core. spec typecheck: exit 0 at bb71914 (the test layer compiles, so the @ts-expect-error on the tombstone is live). @objectstack/lint: 148 files / 6935 passed at bb71914. @objectstack/platform-objects: 79 / 1195 passed at bb71914; its typecheck exits 0. It went red once before the count update (zh-CN positive control expected 674, received 673). @objectstack/metadata-protocol: 249 files (3 skipped) / 20771 passed. @objectstack/objectql local: 448 / 8447 passed. @objectstack/rest local: 300 / 6095 passed (326 skipped). @objectstack/runtime local: 425 files in 3 batches / 1928+2822+1921 passed (19 skipped). @objectstack/cli unit: 314 files in 4 batches / 1426+1017+1209+989 passed; the integration layer is declared to CI. The last five ran at c0c1a8a. Examples: os validate plus os build pass on app-crm, app-todo, app-showcase (after building its closure; the first try was MODULE_NOT_FOUND, a prerequisite and not a red) and app-multi-package. ABLATION, committed fix first: scripts/ablation-replace.mjs in wrap mode with an outer trap swapped the tombstone line for filterableFields: z.array(z.string()).optional(). On disk: anchor 1 to 0, replacement 0 to 1, blob 1e5e34e05ab8 to d38c1ae00383, in-command grep -c 1/0. The new pin plus retired-key-removal-version.pin went RED as predicted: 13 failed / 71 passed. The failures were the 8 door refusals, the empty array, the prescription, the tsc-channel parse, the object listViews boundary and the JOIN row; the controls, boundaries and D2 pins stayed green. Restore: blob == HEAD 1e5e34e05ab8 and git diff HEAD empty. No dist leg applies, because the pins import src by relative path.",
"gates": "Re-derived on the final head bb71914 with no paths: dispatch-gates --commands --repo objectstack-ai/objectstack, 24 paths vs merge base 1c1144f, giving 115 commands. All 115 were run, each exit captured before any pipe. 114 exited 0 on the first pass. check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET: 7 unrelated packages had no dist), then 0 after building them. --ran reconciliation: 115 derived famil(ies) accounted for — 115 run, 0 NOT-MEASURED (a DERIVED zero — all 115 recorded an exit code and none of them is 3). Key verdict lines: check-adr-0087-registration 'registered view-list-filterable-fields-removed, list-view-filterable-fields-retired (new here: both)'; check:api-surface 'public API surface + factory signatures unchanged'; check:docs '227 generated files in sync'; check:generated 'All 14 generated artifacts are up to date'; check:skill-examples '262 prose examples type-check'; check:i18n OK; check:doc-authoring clean; check:cross-package-test-inputs OK; check:nul-bytes OK; check-empty-changeset and check-changeset-no-major pass. check:entry-nameability carries a standing NOT MEASURED note about api-assembled/qa that predates this diff. Local-only: check:dev-prereqs exit 0. check-platform-checklist --changed-from was not run: no exported symbol was renamed or removed (api-surface unchanged). PR #24721 check-runs, read once at report time: in_progress for Lint & Repo Gates lanes (Lint ESLint, Lint repo & tooling, Lint docs & code guards, Lint PM dispatch-gates, Lint CI release & engine, Lint scoped x3), Type Check lanes (workspace, source gates, consumer gates, debt ledger), Test Core 1-6/6, Build Core, Build Docs, Governed Surface Queue Guard and Check Changeset. success: Spec property liveness, Check PR Size, Check Documentation Links, Flag docs affected by code changes, filter, the card-claims-this-branch check, the single-writer and single-issue claim checks, Part-of check, Auto Label and Dogfood Regression Gate. skipped (full battery only): Console Pin Gate, Temporal Conformance, Dogfood shards, Dogfood Verify CLI and Packed-tarball smoke.",
"mcp_calls": "0 — no MCP tool used",
"api_writes": "2 — each one relay stroke (POST /repos/objectstack-ai/objectstack/dispatches): (1) pr_create, executed as POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/24721/assignees, read back identical; (2) this os-dev-report comment, POST /repos//issues/24640/comments. Plus git push of the branch, which is not a REST write.",
"open_questions": [
{
"question": "ADR-0047 (Accepted) Decision 1 still says filterableFields 'stays as the legacy shorthand; loaders auto-upgrade it to userFilters.fields entries'. That loader was never built, and ruling C retires the key and forbids that rewrite. Its own section 4 calls the alias 'one-release courtesies, not commitments'. Prime Directive 13 wants a reversed recorded decision amended. Does ADR-0047 get an amendment line, and where?",
"options": [
"A: a separate docs-only PR adds an amendment line to ADR-0047's status block, citing records 6278975049 and 6279033298. It is Tier H (maintainer approval) and about 15 min to author; PR #24721 lands as is.",
"B: fold the same amendment into PR #24721. Same authoring cost, but the whole PR becomes Tier H, so it waits for the maintainer's approval before the seat can queue it.",
"C: no amendment. Zero cost now; the stale Decision 1 sentence keeps telling the next reader that a loader rewrites filterableFields to userFilters.fields."
],
"recommendation": "A, by the four axes. Business need: zero authors were measured, but the ADR has a real reader, the next agent or maintainer planning list-view work. Long-term soundness: Prime Directive 13 keeps the record true, and A does it without coupling a governed landing to this contract change. Preventing AI authoring errors: left stale, the sentence invites an agent to re-add exactly the rewrite conversion the ruling forbids; A and B close that and C does not. No startup sprawl: A adds one small governed PR, B adds a Tier H wait to this PR, and C costs nothing but leaves the trap. The ruling itself is not reopened by any option."
}
],
"out_of_scope_findings": [
"carrier: domain:spec seat 2 (session_019oFY6Hi35J7atvgVFnmoaK), beside the objectui follow-up it files — noted, not filed (dead code once the parse refuses the key). In-repo readers still classify filterableFields off raw input: packages/lint/src/validate-list-view-field-refs.ts (role and severity maps, plus its test fixtures); packages/lint/src/validate-react-page-props.ts REACT_FIELD_SPECS.ListView, plus the 'covers the legacy filterableFields shorthand' test; packages/lint/src/validate-field-consumers.ts:307; packages/lint/src/rule-explanations.ts:3114 and :3149 (os explain text naming the key as a checked position); packages/metadata-protocol/src/metadata-diagnostics.ts:237 plus the packages/objectql/src/metadata-diagnostics.test.ts fixtures; packages/metadata-core/src/object-schema-fls-references.ts LIST_VIEW_NAME_LISTS.filterableFields. The new pin's RESIDUE set tracks the four that spell it as an object key and goes red when they are deleted. Dedupe words: filterableFields lint residue, list view field refs filterableFields, LIST_VIEW_NAME_LISTS filterableFields.",
"carrier: domain:spec seat 2 (session_019oFY6Hi35J7atvgVFnmoaK) — noted, not filed; reach is NOT MEASURED. Boundary: a react page's ListView element can still pass a filterableFields prop. Its source string is parsed against no schema, and the react-props lint treats the prop as field-bearing ('honored by the renderer'). objectui's reader still honours it at pin 12dc7b47; once objectui's follow-up removes the reader, the prop becomes a silent no-op on react pages unless the react-props lint learns to refuse it. Dedupe words: react ListView filterableFields prop, REACT_FIELD_SPECS retired prop, react page props retired key.",
"carrier: domain:spec seat 2 (session_019oFY6Hi35J7atvgVFnmoaK), who files it when this lands, per the dispatch. objectui follow-up, re-read at the moved pin 12dc7b47: app-shell/src/views/ObjectView.tsx:3448 forwards the key; plugin-list/src/ListView.tsx:4656 holds the filterFields whitelist; plugin-view/src/ObjectView.tsx:3124 forwards it, :1030 keeps a key list, and plugin-view/src/index.tsx:90 registers an input; types/src/objectql.ts:2625 and :2966 declare it locally; types/src/zod/objectql.zod.ts:1300 reads .shape.filterableFields by reference, so the tombstone flows in on the next pin bump. No export is removed, so the pinned objectui build compiles unchanged. Dedupe words: objectui filterableFields whitelist removal, ListView filterFields memo, filterableFields follow-up."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 20, 2026
Landed ·
domain:specseat 2 · sessionsession_019oFY6Hi35J7atvgVFnmoaK· 2026-10-20T03:51Z4bc3becd5f4a1042d9f180eca262a90bfddcbb92onmain.Fixes #24640closed this card ascompleted.origin/main.git patch-id --stableof the merge's diff equals that of the reviewed headbb71914fc9against its merge base (74136a0a93). What landed is what the contract review6281884602passed.gh-readonly-queue/main/pr-24721-*is gone.pm:dispatchedwas removed in this act.domain:spec,area:api,priority:p3andtarget:v18stay.6278975049, pulled into 18.0 「提前」6279033298):ListViewSchema.filterableFieldsis aretiredKey()tombstone that namesuserFilters;view-list-filterable-fields-removedDROPS the key, never rewriting it touserFilters.fields, with its D3 entry;architecture.mdxis re-trued.filterableFieldsFilter-panel whitelist reader — the spec retired the key in 18.0 (objectstack-ai/objectstack#24640, ruling C: no per-view whitelist replaces it) objectui#13118: objectui removes its Filter-panel whitelist reader. objectui's pinf4755a68a7is 78 commits behind4bc3becd5f. The reader removal does not wait on the pin; thetypeszod mirror line rides the pin bump.filterableFields"stays as the legacy shorthand; loaders auto-upgrade it touserFilters.fields" — retired in 18.0 by ruling C (#24640), and that loader was never built #24727: the ADR-0047 Decision 1 amendment (domain:skills, Tier H).filterableFieldsretires (#24640),os lintstill reads it as a live field position — a valid name passes silently and a stale one is reported as a field error, never as the retirement; plus the residue readers to delete #24728: the in-repo residue readers.packages/platform-objectson [PM seat] domain:engine — 🟢 os-project-manager #6367 (6281700097).mainpublishes nothing.@objectstack/specminorrides the next Version Packages PR, which is a human act.Generated by Claude Code
docs(adr): ADR-0047 records the 18.0 retirement of filterableFields