Uh oh!
There was an error while loading. Please reload this page.
feat(spec): retire the element:filter element at element grain (#9220, ADR-0049) - #9250
Conversation
… ADR-0049) No renderer or reader for element:filter exists in any repo (objectui registers none; Studio's palette lists it as a no-renderer exclusion; the 2026-06 audit recorded it rendering 'Unknown component type'). All six authorable keys are retiredKey() tombstones; the ComponentPropsMap row stays so the #5068 props gate keeps refusing loudly; the PageComponentType enum entry is removed (de-advertisement — the open string arm makes it parse-neutral). D2 conversion element-filter-removed (protocol 18) strips the keys from old sources; the #9198 conversion's negative-control fixture moves to an open-union custom type (pre-registered flip). Pin tests, regenerated baselines/docs, minor changeset per the post-17.0.0 launch-window convention. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fs18A2DdXLVN2h8PaaFBcP
#9220) The package's own component-field-specs-liveness gate (#6629) refuses entries naming retired keys; the element-grain tombstones turned it red with the exact prescription to drop the entry. Patch changeset for @objectstack/lint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fs18A2DdXLVN2h8PaaFBcP
…ment-filter-adr0049
…al clear) Merge of origin/main (2abb66b) into the #9220 branch; regenerated gen:schema + gen:docs + gen:openapi from the merged tree per scripts/pm/os-regen-merge.sh step 4. Survival asserted: step-18 block, six ElementFilterProps retired-keys entries, element-filter-removed conversion, fixture control, and the reference pages under the merged (#9239) generator. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fs18A2DdXLVN2h8PaaFBcP
📓 Docs Drift CheckThis PR changes 2 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 113 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop):
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#9220
Verdict first (measurement-first card — recorded on the issue before any removal work)
DEAD at element grain. Full table in the measurement comment. Summary: at objectstack
2f65b1b42and objectui5ffcc14(read-only sweep), no renderer or behavior reader ofelement:filterexists anywhere — objectui's only hits are a stale comment (renderers/basic/elements.tsx:18) and aPALETTE_EXCLUSIONSentry, i.e. Studio deliberately does NOT offer the element and records "no renderer" as the reason, answering the dispatch's palette question in the inverse direction. The 2026-06 page-liveness audit (docs/audits/2026-06-pageschema-property-liveness.md) had already recorded it rendering "Unknown component type". Cloud was not reachable from this session: the cloud half of the verdict relies on the card's recorded sweep (taken at objectui372d9f9b4) and the triage 04:44Z re-verification, not on a fresh reading.What this PR does (the #9198 / PR #9221 precedent, one grain wider)
object,fields,targetVariable,layout,showSearch,aria) onElementFilterPropsSchemaviaretiredKey(), each carrying the element-grain prescription (delete the component; list surfaces own filtering via a view'suserFilters/ the list toolbar's filter builder;os migrate meta --from 17).ComponentPropsMaprow deliberately STAYS — the SDUI 组件 props 没有解析闸门:PageComponent.properties是开放 record,ComponentPropsMap的 29 个站点从不被 parse(#4001 批 17 的 no gate 判定) #5068 props gate dispatches on it; deleting the row would demote the type to an unregistered custom string the gate deliberately skips, turning a loud retirement back into a silent no-op. A node-level refusal is not expressible:PageComponentSchema.typeis an open union (enum ∪ string), so a bare node still parses — inert, as it always was.element:filterremoved fromPageComponentType(page.zod.ts) — parse-neutral by the open-union argument above, but stops advertising the element in docs, TS vocabulary and palette derivations. Surface widening declared in the claim amendment.18.ui__ElementFilterProps__*), folded bygen:migration-registry; D2 conversionelement-filter-removed(protocol 18,retiredFromLoadPath), wired into the step-18 chain appended after the feat(spec): retire inerttargetVariableonelement:text_input/element:record_picker(ADR-0049) #9221 entries (their block untouched).targetVariableonelement:text_input/element:record_picker— a declarative hint with zero readers in any repo and no liveness-ledger entry #9198 conversion's fixture usedelement:filter.targetVariableas its untouched control; it now uses an open-unioncustom:legacy_inputnode — same load-bearing assertion (the strip dispatches on the component TYPE, not the key name), one hop further out.component.test.ts): the former accept shapes are now refusal pins asserting the prescription substance (.toThrow(/…removed…element is retired…/s), the feat(spec): retire inerttargetVariableonelement:text_input/element:record_picker(ADR-0049) #9221 pattern); the bare migrated node parses clean and materializes nothing; a node-level-parse pin documents where the refusal does NOT live. Note: the dispatch's ADR-0112code+statusclause cannot apply to a zod parse surface (no error envelope exists there) — message-substance assertions per the feat(spec): retire inerttargetVariableonelement:text_input/element:record_picker(ADR-0049) #9221 precedent are the honest equivalent, and the prescription string is itself the contract here.packages/lint): the'element:filter': { props: ['fields'] }COMPONENT_FIELD_SPECSentry is dropped — forced by the lint package's owncomponent-field-specs-livenessgate (validate-page-field-bindings的element:record_picker条目仍列着 #5775 已退役的displayField/searchFields#6629), which turned red on the tombstones with the exact prescription to drop it.@objectstack/lintpatch changeset included.authorable-surface/ui.json+authorable-defaults/ui.json([RETIRED] rows), regenerated references (component.mdx,page.mdx), hand-authoredcontent/docs/ui/pages.mdxlisting,format-type.test.tsenum pin.spec-changes.json/ upgrade guide are correctly untouched — they render released majors only (protocol 17), same as feat(spec): retire inerttargetVariableonelement:text_input/element:record_picker(ADR-0049) #9221.content/docs/releases/untouched.@objectstack/specminor (post-17.0.0 launch-window convention, the feat(spec): retire inerttargetVariableonelement:text_input/element:record_picker(ADR-0049) #9221 precedent) with FROM → TO and the adr-0087 marker;@objectstack/lintpatch.Verification (all at final head
bd4495c0dunless noted)pnpm --filter @objectstack/spec test: 407 files / 10848 tests passed ata75d602d6;git diff a75d602d6..bd4495c0d -- packages/specis empty, so the result stands for this head byte-identically.pnpm --filter @objectstack/lint test: 2065 passed (was 2064 passed / 1 failed before the residue drop — that red run is the gate demanding the lint edit).element:filternegative control turnedconversions.test.tsred exactly as predicted — the new conversion strips the control toproperties: {}, failing the fixture-equality assertion — proving the flip was load-bearing; restored and green (164/164).turbo run buildfull workspace closure: 70/70.turbo run typecheck --filter='...@objectstack/spec'(spec + downstream consumers, prefix filter): 125/125 — the tombstones'nevertyping swept every authoring site clean.check:generated: all 13 artifacts up to date. Light union all PASS: merge-driver, spec-parsed-alias, type-source-resolution, objectui-changeset, quick-reference-counts, role-word, adr-0087-registration, changeset-no-major, cross-package-test-inputs, empty-changeset, dev-prereqs, docs-audit affected-docs, nul-bytes, query-options-erasure, engine-double-contract, where-matcher, type-check-coverage, variant-docs, empty-state, skill-examples.check:type-check-debt --re-measure: 33 entries, no surplus.Cross-repo follow-ups (for the PM to file; objectui deliberately not edited)
PALETTE_EXCLUSIONS['element:filter']entry (block-types.ts:156) when the spec pin moves (its block-config test derives coverage fromPageComponentType), and fix the staleelements.tsx:18comment that still nameselement:filter(itselement:formhalf is ADR-0049 candidate:element:formdeclares a full form contract with no renderer registration found in objectstack/objectui #9249's question).Out-of-scope finding filed unassigned: #9249 (
element:formdeclares a full form contract; same no-renderer shape measured during this card's sweep — needs its own verdict measurement). #6590'selement:filterhalf is mooted by this retirement; itselement:formhalf stands.Generated by Claude Code