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
[finding] bare element:filter / element:form nodes still validate clean, and retired component types are offered as typo suggestions — the node-level refusal #14159 built could close both #15110
Filed by the os-dev developer subagent for #14159 (session session_0174WZTU6XcFcS7g2kykC53i, branch claude/issue-14159-user-profile-not-placeable) as an out-of-scope observation — not fixed there (the ruling's scope is the one member user:profile; every other member of both lists is untouched). Unassigned; triage's to grade.
Observation
#14159 (ruling B) adds RETIRED_PAGE_COMPONENT_TYPES (packages/spec/src/ui/page.zod.ts): a retired page-component TYPE is refused by NAME at the parse — the enum's error map, a check on PageComponentSchema.type, and the kept ComponentPropsMap row all carry one prescription. That closes, for user:profile, the gap the two earlier element-grain retirements recorded in their own docblocks as structural:
packages/spec/src/ui/component.zod.ts (ElementFilterPropsSchema, ElementFormPropsSchema): "A bare node with empty properties parses clean (the open type union accepts any string, so a node-level refusal is not expressible here)".
Retired types are offered as "Did you mean" suggestions.KNOWN_COMPONENT_TYPE_CANDIDATES (component-type-vocabulary.ts) is derived from the enum + every ComponentPropsMap row, so element:filter, element:form — and, after Ruling needed: does user:profile get a renderer, or become explicitly not author-placeable? — the one #12183 sibling that ruling never covered (gates objectui#7135) #14159, user:profile — are candidates findClosestMatches can propose for a typo inside a reserved namespace (e.g. element:fitler gets Rename element:fitler → element:filter, a rename INTO a retired element). The vocabulary's docblock also describes the row-superset as "exactly" the measured string-arm registrations plus the two tombstoned elements; user:profile now joins that set, so the sentence is one member short.
Not urgency: nothing in examples/** or packages/** authors a bare element:filter / element:form node (grep at 29db3cd2).
Suggested shape, if ruled
Add both names to RETIRED_PAGE_COMPONENT_TYPES with their existing prescriptions (the node-level check and the enum error map pick them up with no further wiring); have KNOWN_COMPONENT_TYPE_CANDIDATES exclude RETIRED_PAGE_COMPONENT_TYPES keys so a typo is never renamed into a retired type; flip the two docblocks' "not expressible here" sentences. Pins mirror component.test.ts's #14159 describe. PALETTE_EXCLUSIONS in objectui stays as is either way.
Refs: #14159 (the ruling and the mechanism) · #12183 (the four-sibling ruling) · #9220 / #9249 (the two element-grain retirements) · #12950 (the component-type-unknown rule and its vocabulary).
Filed by the
os-devdeveloper subagent for #14159 (sessionsession_0174WZTU6XcFcS7g2kykC53i, branchclaude/issue-14159-user-profile-not-placeable) as an out-of-scope observation — not fixed there (the ruling's scope is the one memberuser:profile; every other member of both lists is untouched). Unassigned; triage's to grade.Observation
#14159 (ruling B) adds
RETIRED_PAGE_COMPONENT_TYPES(packages/spec/src/ui/page.zod.ts): a retired page-component TYPE is refused by NAME at the parse — the enum's error map, a check onPageComponentSchema.type, and the keptComponentPropsMaprow all carry one prescription. That closes, foruser:profile, the gap the two earlier element-grain retirements recorded in their own docblocks as structural:packages/spec/src/ui/component.zod.ts(ElementFilterPropsSchema,ElementFormPropsSchema): "A bare node with emptypropertiesparses clean (the opentypeunion accepts any string, so a node-level refusal is not expressible here)".packages/spec/src/conversions/registry.ts(element-filter-removed) and the ADR-0049 candidate:element:filterdeclarestargetVariable(and possibly the whole element) with no renderer or reader in any repo #9220 / ADR-0049 candidate:element:formdeclares a full form contract with no renderer registration found in objectstack/objectui #9249 changelog entries say the same: the bareelement:filter/element:formnode "stays inert as it always was".Two consequences remain measurable on
origin/main(read at29db3cd2; re-derived on the #14159 branch at4c392c5d):A bare
element:filter/element:formnode still validates clean at every door.PageComponentSchema.safeParse({ type: 'element:filter' })succeeds;os validate/os build/os lintaccept it (thecomponent-type-unknownrule treats aComponentPropsMaprow as known, and the SDUI 组件 props 没有解析闸门:PageComponent.properties是开放 record,ComponentPropsMap的 29 个站点从不被 parse(#4001 批 17 的 no gate 判定) #5068 props gate has nothing to judge on an empty bag). The user-visible consequence is the one Console rendersnav:menu/global:search/global:notifications/app:launcheras "Component Placeholder" — four spec-declared PageComponentType members with no renderer #12183 and Ruling needed: doesuser:profileget a renderer, or become explicitly not author-placeable? — the one #12183 sibling that ruling never covered (gates objectui#7135) #14159 were filed about: the console draws the placeholder / unknown-type panel in front of an end user. The mechanism to refuse the node by name now exists; adding the two members toRETIRED_PAGE_COMPONENT_TYPES(with their own prescriptions — both already have aDelete the componentstory and a live replacement) is a contract decision (Clause ②: accept-set narrowing), so it is recorded here rather than done as a rider.Retired types are offered as "Did you mean" suggestions.
KNOWN_COMPONENT_TYPE_CANDIDATES(component-type-vocabulary.ts) is derived from the enum + everyComponentPropsMaprow, soelement:filter,element:form— and, after Ruling needed: doesuser:profileget a renderer, or become explicitly not author-placeable? — the one #12183 sibling that ruling never covered (gates objectui#7135) #14159,user:profile— are candidatesfindClosestMatchescan propose for a typo inside a reserved namespace (e.g.element:fitlergetsRename element:fitler → element:filter, a rename INTO a retired element). The vocabulary's docblock also describes the row-superset as "exactly" the measured string-arm registrations plus the two tombstoned elements;user:profilenow joins that set, so the sentence is one member short.What is NOT claimed
user:profileget a renderer, or become explicitly not author-placeable? — the one #12183 sibling that ruling never covered (gates objectui#7135) #14159 answered foruser:profile, and it is a ruling, not a reading. The prescription text for each (list surfaces own filtering; the object-boundobject-formblock) already exists in theirretiredKeytombstones.examples/**orpackages/**authors a bareelement:filter/element:formnode (grep at29db3cd2).Suggested shape, if ruled
Add both names to
RETIRED_PAGE_COMPONENT_TYPESwith their existing prescriptions (the node-level check and the enum error map pick them up with no further wiring); haveKNOWN_COMPONENT_TYPE_CANDIDATESexcludeRETIRED_PAGE_COMPONENT_TYPESkeys so a typo is never renamed into a retired type; flip the two docblocks' "not expressible here" sentences. Pins mirrorcomponent.test.ts's #14159 describe.PALETTE_EXCLUSIONSin objectui stays as is either way.Refs: #14159 (the ruling and the mechanism) · #12183 (the four-sibling ruling) · #9220 / #9249 (the two element-grain retirements) · #12950 (the
component-type-unknownrule and its vocabulary).Generated by Claude Code
Generated by Claude Code