Repository navigation
feat(lint)!: component-props-invalid refuses a retired page-component prop as an error at os validate, os build and os lint - #23140
Conversation
… prop as an error A value verdict raised by a retiredKey() tombstone (invalid_type expecting never, directly or as the one arm of a collapsed union that judged keys) is now severity error, so os validate, os build and os lint refuse it with the tombstone's prescription. Every other finding of the rule stays a warning. validateComponentProps becomes a gating rule in the authoring registry. The warning-period inventory the gate header named as the upgrade's acceptance baseline measured 0 retired-key findings and 0 other findings over the example apps, the shipped pages and the scaffold template. Claude-Session: https://claude.ai/code/session_012uFegdfR6K6uqvLzt7XsdZ Co-authored-by: Claude <noreply@anthropic.com>
…doors that refuse them The record-picker reconciliation's shared docblock said the loader rejects a tombstoned key loudly, and the object-grid defaultFilters entry said an author is refused at the parse. The load path keeps the open properties bag as written; the refusal is the component-props gate's, at os validate, os build and os lint. Both sentences now say so. Comment-only; nothing in @objectstack/spec's published files changes. Adds the @objectstack/lint changeset for the retired-key error upgrade. Claude-Session: https://claude.ai/code/session_012uFegdfR6K6uqvLzt7XsdZ Co-authored-by: Claude <noreply@anthropic.com>
…that authors it The component-props gate's new union-arm pin authors publicPicker on an object-form field to prove a tombstone inside a union arm is refused as an error. Excluded with its reason, as the breadcrumb and detail-sortField absence pins already exclude the same file. Claude-Session: https://claude.ai/code/session_012uFegdfR6K6uqvLzt7XsdZ Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 6 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 2 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 141 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 6e2cd4e2d5d79aef349154d5059207a79b4bfab0 && git checkout 6e2cd4e2d5d79aef349154d5059207a79b4bfab0
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin dc93781c1947b53cff50a550ad551e462a464594 20c00221c6ff0a2a41e1d94f9396f69dd831fb23 && git checkout -B drift-repro dc93781c1947b53cff50a550ad551e462a464594 && git merge --no-ff 20c00221c6ff0a2a41e1d94f9396f69dd831fb23
node scripts/docs-audit/affected-docs.mjs --json dc93781c1947b53cff50a550ad551e462a464594
|
Contract reviewServed-tier: Inputs: card #23026 (body and all five comments, the ① Derived judgments
② Semver level
③ Boundary flags
Why FAIL, and what lifts it. The narrowing, its severity, its doors, the changeset and the marker are right in every respect I could derive, and no shipped sentence is false. The head fails on the contract path leg alone: the diff falsifies Implemented-by: VERDICT: FAIL |
…r as the head enforces it The contract-tier review of the retired-key error upgrade found two conversion docblocks this change made false: page-header-breadcrumb-removed and object-master-detail-form-detail-sort-field-removed said the tombstone refuses the key "advisory, via the props lint". Both now say os validate, os build and os lint refuse it as an error, the load path keeping the open properties bag. The sweep of registry.ts and migrations/entries for the same class found three pre-existing false sentences, folded in under the seat's amendment: element-text-variant-heading-levels said an author is refused at parse (a retired enum value is an advisory finding); page-tabs-type-to-tab-style said the tombstone refuses at load (the load path does not parse the props bag); time-default-utc-suffix-dropped said refused at parse for an element:button inline action (an advisory finding there). The breadcrumb retired-key note keeps its residue argument and now says the lint was advisory in every release that shipped the default. Comment-only. Claude-Session: https://claude.ai/code/session_012uFegdfR6K6uqvLzt7XsdZ Co-authored-by: Claude <noreply@anthropic.com>
…nt-props gate's tier as the head enforces it validating-metadata.mdx listed "SDUI component props" only in the Advisory row of the one-gate, four-doors table. A retired (tombstoned) prop is now an error at os validate, os build and os lint, so it gets its own gating row (not on the runtime publish door: the rule is CLI-only), and the advisory row keeps every other props finding. layout-dsl.mdx said the authoring rules reject a misspelled prop. A misspelled prop is a component-props-unknown-key warning; a retired prop is refused as an error. Pre-existing, folded in under the seat's amendment. Docs only. Claude-Session: https://claude.ai/code/session_012uFegdfR6K6uqvLzt7XsdZ Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Inputs: card #23026 (body and all nine comments: triage, the claim, the seat pointer, three How far the head moved. Two commits since ① Derived judgments
② Semver levelCarried by reference from 6137697373 ② — the changeset did not move. Re-confirmed on this head: ③ Boundary flags
Why FAIL, and what lifts it. Everything the earlier record failed on is fixed and true, every sentence the two patch rounds edited is true against the code on this head, the patches changed nothing but comment and docs text, and ① and ② of 6137697373 hold unchanged. The head fails on one point of the same class: the diff turns the Implemented-by: VERDICT: FAIL |
…-props gate's tier as the head enforces it The contract-tier review of the retired-key error upgrade found the docblock above the breadcrumb tombstone still saying the row is parsed only by the advisory props lint; component.zod.ts ships in the tarball. It is dated the way its retired-keys twin was: the props lint was advisory in every release that shipped the default, and the residue argument is kept whole. The rest of the file's tier sentences, read on the head: the #5068 header said the gate is warning-level and that the page rewrites stood before the error upgrade, and the #7751 section said findings on its rows are advisory, still gated on the inventory. Both now record the upgrade for the retired-key class and that every other finding stays a warning. Three test comments of the same class (the breadcrumb and detail-sortField retirement pins, the flat-binding retirement test) now say the props lint refuses those tombstones as an error. Comment-only; no schema, guidance string or describe text changed. Claude-Session: https://claude.ai/code/session_012uFegdfR6K6uqvLzt7XsdZ Co-authored-by: Claude <noreply@anthropic.com>
… a tombstoned key say it refuses it as an error validate-page-field-bindings said the #5068 props gate is advisory about the tombstoned displayField / searchFields; it refuses them as an error at os validate, os build and os lint and stays advisory for every other finding. The registries-differ argument is unchanged. The breadcrumb and detail-sortField absence pins' EXCLUDED comments said the props-lint pin asserts the advisory warning; it asserts the refusal, an error. Comment-only. Closes the class the contract-tier review named. Claude-Session: https://claude.ai/code/session_012uFegdfR6K6uqvLzt7XsdZ Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Inputs: card #23026 (body and all thirteen comments: triage, the claim, the seat pointer, five How far the head moved. Two commits since ① Derived judgments
② Semver levelCarried by reference from 6137697373 ② and 6138451028 ② — the changeset did not move (no ③ Boundary flags
Why PASS. The sentence the last record failed on is dated and true; every sentence the two comment-only commits edited is true against the code on this head, the ruling quotation is byte-identical to Implemented-by: VERDICT: PASS |
Fixes #23026
Clause-②: no (narrowing:
os validatestops accepting a retired page-component prop; triage's grade6123043175reads the same)What this does
The component-props gate's error upgrade, the step its own header recorded ("the warning-period inventory is the acceptance baseline for the error upgrade, and the upgrade is its own step once the inventory is empty"), scoped to the class triage named: a retired key.
component-props-invalidnow files aretiredKey()tombstone's verdict aserror.os validate,os buildandos lintrefuse the stack, and the message carries the tombstone's own prescription.warning. That covers other value refusals (including the two closed-set refusals that just landed: a url action'stargetscheme from PR feat(spec)!: a type:'url' action's target declares its closed scheme set — http(s)://, mailto: and in-app paths — at both url-action doors #23076, and arecord:detailssectioncountfrom PR feat(spec): a record:details section heading can show how many values a multi-value field holds (sections[].count and the {{ count }} hole) #23080), retired enum values, undeclared keys and the missingdataSource.objectbinding.validateComponentPropsbecomestier: 'gating'inauthoring-rules.ts, which the wiring guard requires of any rule that emitserror. It already ran on all three commands.Measured before acting
Inventory (H2), at
21c86444e, before the change:component-props-*findingexamples/app-crm,app-todo,app-multi-package,app-showcaseos validate --jsonplatform-objectssys-organization, sys-position, sys-user;plugin-approvalssys-approval-request;qa/downstream-contractwelcomepackages/apps/*(account, setup, studio), thecreate-objectstackblank template, CLI generatorsRe-measured on the merged head
f88009a41: the same zeros. The page instrument was checked against a positive control (one fixture page with a retired key, an invalid value and an unknown key), which it counted 1 / 1 / 1. Class (b) is therefore 0, and that is the next step's baseline. Whether (b) should also move is an open question in the report, not part of this diff.How a retired key is told apart (H1). It is read off the issue, never off its text. A
retiredKey()isz.never(...).optional(), which raisesinvalid_typewithexpected: 'never'. The spec's privateisRetiredKeyIssueinflow-node-config-refusals.tsuses the same discriminator. A schema-graph walk ofComponentPropsMapfinds 50 never-nodes:user:profile,ai:chat_window;retiredComponentProps, the same issue shape with the element's prescription), refused the same way;object-form/object-master-detail-formsections[].fields[], the object arm'spublicPicker). There zod collapses the arm failures into oneinvalid_union, so the classifier applies the existing one-arm rule ofunrecognizedKeysFromUnionArm: exactly one arm raised tombstone issues and nothing else. A mixed arm stays a warning, and that is pinned.Retired enum values (
enumWithRetiredValues) raise an enum issue, notinvalid_type/never, so they are not swept in. Theelement:textvariant migration text that calls that finding advisory therefore stays true.Both doors on one fixture (H4). The fixture was a
defineStackapp withobject-gridproperties.defaultFilters:21c86444e)os validatecomponent-props-invalidwarningos buildos lintNo door still passes. The runtime publish door (Studio / REST
/meta/ MCP) does not run this rule (surfaces: CLI_ONLY), so a page saved there is not refused. That is written into the rule header, the registry sentences and the changeset, and nothing claims otherwise.Registry text (H3).
packages/spec/src/conversions/registry.ts:object-grid-default-filters-removeddocblock said "refused at the parse with the prescription".The load path keeps the open
propertiesbag as written (PageComponent.propertiesisz.record). Both sentences now nameos validate,os buildandos lint(the component-props gate). This is a comment-only edit. On this head the first round stopped at these two sentences; the patch round below corrects six more. It publishes nothing:@objectstack/spec'sfilesshipsdistplussrc/**/*.zod.ts, and on a built dist the old sentences have 0 hits while a string literal from the same entry hits (positive control).Tests
packages/lint/src/validate-component-props.test.tschanges:breadcrumb, detailsortField,displayField, and the wiring pin fromadvisorytogating.targetrefusal and the feat(spec): a record:details section heading can show how many values a multi-value field holds (sections[].count and the {{ count }} hole) #23080 sectioncountrefusal both stay warnings;runAuthoringRules('validate')pipeline carries the error.packages/spec/src/ui/form-field-public-picker-retirement.test.tsgains one exclusion: the props-lint pin authorspublicPickerto prove the union-arm refusal, exactly as thebreadcrumband detail-sortFieldabsence pins already exclude that same file.f88009a41, all under the shared verify lock:@objectstack/lint: 137 files / 6624 tests passed;typecheck(tsc plus the test layer undertsconfig.test.json) passed, debt ledger unchanged;@objectstack/cliunit layer for validate / build / author-time: 5 files / 61 tests passed (build-warning-truncation-notice,generate-scaffold-validates,validate-build-gate-parity,validate-per-package-authoring-seam,src/utils/author-time-rules). The integration layer is declared to CI, since no spawn entry was touched;@objectstack/spec: the 20 test files that readconversions/registry.tspassed (1060 tests);typecheckpassed;check:generatedreports all 14 artifacts current against a freshly built dist;os validatereruns are in the inventory table. No example metadata changed, so no example package owes its own suite.HEADand proved the blob equal toHEAD, withgit diff HEADempty:Gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon the final headf88009a41derived 88 commands. 87 ran, each exited 0, with exit codes captured before any pipe.--ranreconciles as "88 derived, 87 run, 1 NOT-MEASURED, 0 UNRUN".check:type-check-debt. Reason: a whole-workspace build plus--re-measure; CI owns it (dispatch instruction).check:dual-build-cjs-loadsfirst refused with PREREQUISITE NOT MET (8 unrelated packages had no dist). After building them it passed.origin/mainmoved 4 commits pastf88009a41while the union ran. One family input changed in that range (scripts/engine-double-contract.pinned.json); CI's merge ref reads it.Changeset
.changeset/23026-retired-component-prop-refused.md:@objectstack/lint: majoron the v18 pre line,Clause-②: no (narrowing), FROM → TO table, and the ADR-0087 dispositionalready-registered. It names the 20 ledger ids that retired the refused keys.check:adr-0087-registrationandcheck-changeset-no-majorjudged it green. The clause-② level axis is PR-scoped and CI reads it.Patch round: the registry sentences the first head left false
The contract-tier review FAILed
f88009a41(record 6137697373 on this PR): tworegistry.tsdocblocks still called the props gate "advisory" for keys this PR refuses as anerror. The seat amended the claim's file surface (6137721990 on #23026) to every comment sentence inconversions/registry.tsandmigrations/entries/**that states what the component-props gate does with a tombstoned key or a retired value and is false on the head. Commitf1905ac90is comment-only: 2 files, 6 sentences. No code, test, changeset or other file changed.Made false by this PR, corrected:
registry.ts:10621-10625(page-header-breadcrumb-removed)PageHeaderPropsrefuses it for a live author (advisory, via the props lint:PageComponentSchema.propertiesis an open bag)."PageHeaderPropsrefuses it for a live author:os validate,os buildandos lintrefuse it as anerrorwith the prescription (the component-props gate,@objectstack/lint; the load path keeps the openpropertiesbag as written)."registry.ts:13565-13569(object-master-detail-form-detail-sort-field-removed)PageComponentSchema.propertiesis an open bag)."os validate,os buildandos lintrefuse it as anerrorwith the prescription (the component-props gate,@objectstack/lint; the load path keeps the openpropertiesbag as written)."False before this PR, folded in under the seat's amendment 6137721990. Each is the same defect class as the card, a mechanical sentence edit, unclaimed elsewhere, and in the same gate family.
registry.ts:8333-8340(element-text-variant-heading-levels; the review cited it as:8327-8328). This is pre-existing.retiredFromLoadPath: an author is refused at parse with the prescription rather than silently rewritten; stored rows replay it ..."retiredFromLoadPath: an author is not silently rewritten —os validate,os buildandos lintreport an old spelling as an advisorycomponent-props-invalidfinding carrying the prescription (the component-props gate,@objectstack/lint: a retired enum value is a value verdict, a warning; the load path keeps the openpropertiesbag as written); stored rows replay it ..."registry.ts:5836-5839(page-tabs-type-to-tab-style). This is pre-existing and was found by the sweep.tsc) and at load (the parse), whatever the walk reached."tsc) and atos validate/os build/os lint, where the component-props gate refuses it as anerror(the load path keeps the openpropertiesbag as written), whatever the walk reached."registry.ts:8032-8037(time-default-utc-suffix-dropped). This is pre-existing and was found by the sweep; only theelement:buttonposition was false.os migrate metareplay it."element:button's inline action, which sits in the openpropertiesbag the load path keeps as written, where the refusal is an advisorycomponent-props-invalidfinding atos validate/os build/os lint(the component-props gate,@objectstack/lint) — and data at rest andos migrate metareplay it."migrations/entries/retired-keys/18.ui__PageHeaderProps__breadcrumb.ts:16-19. The residue argument is kept whole; only the present-tense "advisory", false on this head, is dated.breadcrumb: true..."breadcrumb: true..."Measured on the head, not argued. The built rule at
f1905ac90gives:page:tabstypeerrorpage:headerbreadcrumberrordetails[].sortFielderrorelement:textvariant: 'heading'warning(enum issue, prescription carried)element:buttoninline-actiontimeparamdefaultValue: '09:00:00Z'warning(acustomissue ataction.params.0.defaultValue)record:chatterposition: 'sidebar'warningobject-formlayout: 'grid'warningThe sweep read 21
registry.tssites and everymigrations/entries/**hit of the props-gate vocabulary. The rest are true as written; the per-site list with evidence is in theos-dev-reporton #23026.Gates on
f1905ac90. The derivation gives 89 commands: the 88 off88009a41pluscheck:spec-changes, which themigrations/entriesedit adds. 19 ran, each exit 0:check-spec-docblock-symbol-anchors, both halves;check-issue-citations, both spellings;check:docs,check:spec-changes,check:upgrade-guide,check:liveness,check:authorable-surface;check:doc-authoring,check:nul-bytes;check-drift-comment;check-affected-docs;check:pm-prior-rulings,check:cross-package-test-inputs.check:generatedalso ran: all 14 artifacts are current against a freshly built dist. The spec tests that readregistry.ts(11 files insrc/conversions, the migrate-sentence class pin, and 20 more) passed: 32 files, 1520 tests.--ranreconciles as "89 derived, 19 run, 70 NOT-MEASURED, 0 UNRUN". The 69 other lines are carried fromf88009a41, where each exited 0, because the patch adds comment text only.check:type-check-debtstays NOT MEASURED by dispatch.Patch round 2: the docs that state the gate's tier
The seat found a published page that states the tier this PR changes (amendment 6138049056 on #23026), plus a sibling sentence in the same class. Commit
175a546b8is docs-only: two files undercontent/docs/, with no code, test, changeset orpackages/**change.content/docs/deployment/validating-metadata.mdx:473and:488, the "one gate, four doors" table. Made false by this PR.os validate,os buildandos lint, with no runtime publish tick.ComponentPropsMaptombstones (retiredKey()), refused with its prescription (lint/spec: a retired page-component prop (object-grid defaultFilters) passes os validate with only a warning, while the conversion registry says the loader refuses it — the props gate's error upgrade has no carrier since its blockers closed #23026)", ticked onos validate,os buildandos lint, with no runtime publish tick. The advisory row now reads "SDUI component props (every finding but a retired prop)".content/docs/protocol/objectui/layout-dsl.mdx:741-745, the callout under thecustom.*example. Pre-existing, folded in under 6138049056.ComponentPropsMapand reject a misspelled prop; acustom.*type has no entry there, so its props are validated only by whatever registered the component."os validate,os build,os lint) dispatchComponentPropsMap: a misspelled prop is reported as a warning, and a retired prop is refused as an error, with its prescription. Acustom.*type has no entry there, so its props are validated only by whatever registered the component."Measured on the built rule at this head:
page:headertitel)warningcomponent-props-unknown-keyobject-griddefaultFilters,page:headerbreadcrumberrorcomponent-props-invalidlimit, or a missingdataSource.objectwarningcomponent-props-invalidcustom.*nodeThe registry entry reads
tier: gating, commandsbuild,lintandvalidate, and surfacesclionly, so the runtime publish column stays empty.Sweep of
content/docs/**:releases/is excluded as release-owned, andreferences/as generated from spec.describe()text, which this PR does not change. The two pages above are the only sentences that state the props gate's tier. The other hits concern other rules, or schemas the load path parses:ai/tools,automation/approvals,automation/flows,data-modeling/field-types;:357;:219,:411,:449,:626,:754;ui/views.mdx:453;searchFieldsmentions.The per-site list is in the
os-dev-reporton #23026.Gates on
175a546b8. The derivation gives 109 commands: the 89 off1905ac90plus 20 that thecontent/docspaths add. 32 ran, each exit 0:check:doc-security-posture,check:skill-examples,check:corpus-claim-drift,check:doc-anchors,check:docs-audit-scope,check:docs-redirects,check:docs-single-h1,check:docs-spec-enumerations,check:published-readme-links,check:react-page-adapter-contract,check:skill-identifier-liveness,check:vendor-version-stamps;check:doc-authoring,check-affected-docs,check-drift-comment,check:docs,check:docs-transcript-drift;check:nul-bytes,check:cross-package-test-inputs,check:pm-prior-rulings.check:skill-examplesfirst refused with PREREQUISITE NOT MET (@objectstack/client-reactwas unbuilt); after building it, it exited 0. "Check Documentation Links" is lychee in CI and has no local form in this container: NOT MEASURED. These edits add no link.--ranreconciles as "109 derived, 32 run, 77 NOT-MEASURED, 0 UNRUN": 8 lines carried fromf1905ac90, 68 fromf88009a41, andcheck:type-check-debtby dispatch. Each carry holds because this round changes twocontent/docspages and no input of those families.Patch round 3: the shipped docblocks in
component.zod.tsThe contract-tier review FAILed
175a546b8(record 6138451028) on one shipped sentence: the docblock above thebreadcrumbtombstone still called the props lint "advisory", andcomponent.zod.tsships in the tarball (src/**/*.zod.ts). The seat amended the surface (6138461923) to that file's comments plus four non-shipped sites. Commit6280ca3b0is comment-only: 4 files, +24/-15. The diff guard counts 0 non-comment lines. No schema,retiredKey()guidance string or.describe()text changed; those belong to #23145's claim.component.zod.ts:654-658, the docblock abovebreadcrumb. Made false by this PR; dated the way its retired-keys twin was, with the residue argument kept whole.component.zod.ts:284-303, the SDUI 组件 props 没有解析闸门:PageComponent.properties是开放 record,ComponentPropsMap的 29 个站点从不被 parse(#4001 批 17 的 no gate 判定) #5068 header. Made false by this PR.page:card.visible→ the component-levelvisibleWhen, showcase 的 project-detail 页在page:tabs上授权items[].key,renderer 读的是items[].value—— 两个 tab 的稳定 URL token 从未生效 #5776's tabkey→value), not a declaration in this file."retiredKey()tombstone's verdict is anerroratos validate/os build/os lint. Every other finding of the gate stays a warning (lint: the rest of the component-props gate's recorded plan — everycomponent-props-invalidclass andcomponent-props-unknown-keygo toerror, after an external-corpus inventory #23147 carries the rest)."component.zod.ts:4849-4854, the A typo'd key inside a page component'spropertiesis accepted in silence — the props bag is a passthrough record and the SDUI props gate has no schema to dispatch forobject-*blocks #7751 object-* section. The review read it as true for its subject. My probe refutes that: these rows carry tombstones (object-griddefaultSortandnavigation.view,object-kanbanquickAdd), and each is anerroron this head. The maintainer ruling quotation is kept verbatim.PageComponent.properties是开放 record,ComponentPropsMap的 29 个站点从不被 parse(#4001 批 17 的 no gate 判定) #5068 inventory (the ruling: ...)."PageComponent.properties是开放 record,ComponentPropsMap的 29 个站点从不被 parse(#4001 批 17 的 no gate 判定) #5068 inventory (the ruling: ...). Once that inventory measured empty, lint/spec: a retired page-component prop (object-grid defaultFilters) passes os validate with only a warning, while the conversion registry says the loader refuses it — the props gate's error upgrade has no carrier since its blockers closed #23026 made one class anerror— aretiredKey()tombstone's verdict, such as a retired key these rows carry; every other finding on them stays advisory (lint: the rest of the component-props gate's recorded plan — everycomponent-props-invalidclass andcomponent-props-unknown-keygo toerror, after an external-corpus inventory #23147 carries the rest)."ui/page-header-breadcrumb-retirement.test.ts:19-21and 5.ui/master-detail-detail-sort-field-retirement.test.ts:22-24. Not shipped.erroratos validate/os build/os lint— and never by the page parse: an existing page is never hard-refused at load."ui/element-flat-binding-retirement.test.ts:201-202. Not shipped.propertiesbag is the props lint's to judge (advisory), not the page parse's."propertiesbag is the props lint's to judge (a retired flat key is anerroratos validate/os build/os lint), not the page parse's."Kept as written, with evidence:
conversions/walk.ts:371is read in context. Its story ispage:headerdescription, which is not a tombstone; the strict row'sunrecognized_keysmakes it acomponent-props-unknown-keywarning, which the probe confirms at a nested site. So "advisory" is true there.component.zod.ts:5686(exportOptions, "advisory"): a bare array and apdfformat are both warnings, per the probe.component.zod.ts:3376and:3429(the props gate "refusing every authored key" ofelement:filter/element:form): those keys are tombstones, now errors.Still false after this round. Not edited, because the round's single push was spent before a wider grep found them:
packages/lint/src/validate-page-field-bindings.ts:233-234: "the SDUI 组件 props 没有解析闸门:PageComponent.properties是开放 record,ComponentPropsMap的 29 个站点从不被 parse(#4001 批 17 的 no gate 判定) #5068 props gate reports the key ... That gate is advisory and CLI-only". The keys are the tombstoneddisplayField/searchFields, now errors.ui/page-header-breadcrumb-retirement.test.ts:356-357andui/master-detail-detail-sort-field-retirement.test.ts:447-448: "The props-lint pin authors the key to assert the advisory warning". Those pins now assert an error.All three are non-shipped comments. One three-sentence comment commit closes the class.
Measured on the head. The built rule at
6280ca3b0gives:page:headerbreadcrumberrorobject-griddefaultSortandnavigation.view,object-kanbanquickAdderrorobject-gridpagination.pageSizeof the wrong type, the unknown keyfilterswarningexportOptionsrefusalswarningpage:headerdescriptionwarningcomponent-props-unknown-keyelement:repeaterproperties.objecterrorelement:filterkeyerrorGates on
6280ca3b0. The derivation gives the same 109 commands as175a546b8. 17 ran, each exit 0:check:docs;check-spec-docblock-symbol-anchors, both halves;check:spec-changes,check:liveness,check:authorable-surface,check:api-surface,check:exported-any;check:nul-bytes, comment-mask adoption (both halves),check:doc-authoring,check:cross-package-test-inputs.check:generatedreports all 14 artifacts current after a real spec build from this head. Tests: the three touched spec files passed (96 tests), andvalidate-component-props.test.tspassed (75 tests).--ranreconciles as "109 derived, 17 run, 92 NOT-MEASURED, 0 UNRUN": 24 lines carried from175a546b8, 1 fromf1905ac90, 66 fromf88009a41, andcheck:type-check-debtby dispatch. Each carry holds because this round changes comment text only.Patch round 4: the last three comments of the class
Round 3's widened grep found three more false comments after that round's push. The seat amended the surface to cover them (6138732286 on #23026). Commit
20c00221cis comment-only: 3 files, +9/-7. The diff guard counts 0 non-comment lines. None of the three ships.packages/lint/src/validate-page-field-bindings.ts:232-239, about the tombstoneddisplayField/searchFields. The registries-differ argument is kept: the gate neither precedes nor suppresses this rule.PageComponent.properties是开放 record,ComponentPropsMap的 29 个站点从不被 parse(#4001 批 17 的 no gate 判定) #5068 props gate reports the key with its rename/delete prescription. That gate is advisory and CLI-only and lives in a different registry (authoring-rules) from this suite, so it neither precedes nor suppresses this rule — ..."PageComponent.properties是开放 record,ComponentPropsMap的 29 个站点从不被 parse(#4001 批 17 的 no gate 判定) #5068 props gate refuses the key as anerroratos validate/os build/os lint, with its rename/delete prescription (it stays advisory for every other finding). That gate is CLI-only and lives in a different registry (authoring-rules) from this suite, so it neither precedes nor suppresses this rule — ..."ui/page-header-breadcrumb-retirement.test.ts:356-357and 3.ui/master-detail-detail-sort-field-retirement.test.ts:447-448, the absence pins'EXCLUDEDcomments.os validate/os build/os lint."error) an author meets atos validate/os build/os lint."The class is closed. The class grep on
20c00221coverpackages/spec/srcandpackages/lint/srccombined round 3's patterns with the widened ones ("advisory warning", "gate is advisory"), plus the advisory-adjective and props-gate-with-tier-word sweeps. It returns no false hit. Every remaining hit falls into one of these groups:component.zod.ts:284-303,:656,:4849-4854, the retired-keys comment, and this PR's own lint text;walk.ts:371(adescriptionunknown-key warning),component.zod.ts:5686(exportOptionsvalue verdicts), and theregistry.ts.templatetyped-member strings;The per-hit list is in the
os-dev-reporton #23026.Gates on
20c00221c. The derivation gives the same 109 commands. 10 ran, each exit 0: comment-mask adoption and issue citations (both halves of each),check:doc-authoring, closing-keyword parity (both halves),check:nul-bytes, lintcheck:doc-formula-expressions,check:cross-package-test-inputs. Tests under the verify lock: the two touched spec files passed (40 tests), andvalidate-page-field-bindings.test.tspassed (38 tests).--ranreconciles as "109 derived, 10 run, 99 NOT-MEASURED, 0 UNRUN": 8 lines carried from6280ca3b0, 24 from175a546b8, 1 fromf1905ac90, 65 fromf88009a41, andcheck:type-check-debtby dispatch. Each carry holds because this round changes three comments only.Acceptance notes
File surface vs the claim. Paths outside the claim's original list, each since added by a seat amendment:
packages/lint/src/authoring-rules.ts: thetierflip that the wiring guard requires for any rule emittingerror, plus its comment;packages/spec/src/conversions/registry.ts: the two H3 sentences, which the dispatch pre-authorized, and the patch round's five docblock sentences (amendment 6137721990); pluspackages/spec/src/migrations/entries/retired-keys/18.ui__PageHeaderProps__breadcrumb.ts, one comment;packages/spec/src/ui/form-field-public-picker-retirement.test.ts: the one exclusion above.content/docs/deployment/validating-metadata.mdxandcontent/docs/protocol/objectui/layout-dsl.mdx: patch round 2 (amendment 6138049056).packages/spec/src/ui/component.zod.ts(comments only) and three spec test files' comments: patch round 3 (amendment 6138461923).packages/lint/src/validate-page-field-bindings.ts, one comment: patch round 4 (amendment 6138732286).No example or template needed a fix (inventory 0). No CLI test pinned the old warning.
Two sibling absence pins (
page-header-breadcrumb-retirement.test.ts,master-detail-detail-sort-field-retirement.test.ts) described this lint test file as asserting "the advisory warning"; patch round 4 corrected bothEXCLUDEDcomments to say it asserts the refusal, anerror.validateComponentPropskeepssurfaceReason: RUNTIME_NEEDS_FULL_SNAPSHOT("reads a stack-wide collection the per-write snapshot does not carry"). The rule is page-local, so that reason looks inaccurate, but I did not measure a page write's snapshot. Whether the gating rule should cross to the runtime door is its own rollout decision, with a false-refusal budget over stored tenant pages. Carrier: none.Generated by Claude Code