Repository navigation
feat(lint)!: the two page component rules run on the runtime publish door (ruling B) - #23418
Conversation
… the runtime publish door for page writes Ruling of record 6161173492 (letter B): both page component rules cross to the Studio/REST/MCP save door with runtimeTypes ['page']; the #4716 stored-row discipline the entries cited is replaced by that ruling. Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
…the D3 texts that said a stored page still saves, and the changeset Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
📓 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:
What this run could not see
Coarse fallback — 142 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 c7a44fe9ce8cb2dab65098a6c186e1ece6dd9459 && git checkout c7a44fe9ce8cb2dab65098a6c186e1ece6dd9459
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 394f65e891f0ac6c6be708fb807740d5cb446520 3301d5f2f1545c2bcc0e566254c0b0597ab85941 && git checkout -B drift-repro 394f65e891f0ac6c6be708fb807740d5cb446520 && git merge --no-ff 3301d5f2f1545c2bcc0e566254c0b0597ab85941
node scripts/docs-audit/affected-docs.mjs --json 394f65e891f0ac6c6be708fb807740d5cb446520
|
Contract reviewServed-tier: Inputs read: card #23388 (body + 5 comments: delta 6160833647, ruling of record 6161173492 letter B, triage 6161267305, claim 6161640267, os-dev report 6163297010); PR #23418 body, 35-file list, net diff Check-runs on the head (their conclusions are the gate verdicts). Success: Auto Label · Check Documentation Links · Check PR Size · Dogfood Regression Gate · Flag docs affected by code changes · Governed Surface Queue Guard · Lint · CI, release & engine gates · Lint · PM dispatch-gates · Lint · scoped · query-options erasure · Lint · scoped · slot lookup & corpus · Lint · scoped · tooling self-tests · No other open PR may claim the same issue · No other open PR may claim the same single-writer path · Part-of PR must not also close its card · Spec property liveness · The card this PR closes must claim this branch · Type Check · source gates · filter. Failure: Check Changeset — the DELIBERATE CORRECTION class ( ① Derived judgments
② Semver level
Clause-②: no — an accept-set narrowing on a published door; the PR body, the changeset, the claim and triage all say ③ Boundary flags
Implemented-by: VERDICT: PASS Adopted by Generated by Claude Code |
Confirmation requested: two pending release notes corrected (DELIBERATE CORRECTION) ·
|
| note | sentence before | sentence after | what in this PR makes "before" false |
|---|---|---|---|
.changeset/23147-component-props-every-finding-refused.md |
"The runtime publish door (the Studio, REST /meta, MCP) does not run this rule, so a page saved there is not refused for any of these." |
(deleted) | validateComponentProps moves to surfaces: CLI_AND_RUNTIME, runtimeTypes: ['page'] |
.changeset/23103-page-action-row-on-success-and-executor.md |
"A stored page still saves and loads." | "A stored page still loads; the metadata save door runs the same gate, so the next save of a page carrying a refused row is refused with the same text." | the same line |
维护者速读
- 改了什么: 页面组件的两条校验规则(属性、类型)从只在 CLI 跑,改为在保存门(Studio / REST / MCP)也跑。顺带改了两条尚未发布的 release note 里因此变假的一句。
- 为什么改: 您对 [Decision] Pages saved through Studio, REST or MCP skip the component-props rule that
os validaterefuses: cross it to the runtime door, and on what evidence #23388 的裁决 B(「如果页面有问题,不是应该修改了再保存吗?」)。 - 风险与代价(含回滚): 已存储页面照常加载;只有带问题的页面下次保存会被拒并给出修法。回滚 = revert 本 PR。
- 席位意见: 两处改句都只说本 PR 让其成真的内容,建议确认。
- 你要做的(一个动作): 在本 PR 回一句「确认两条 changeset 改句」;CI 其余检查全绿后,席位入队。
Generated by Claude Code
…ge-rules-runtime-door
… door; the normalized-tier comment and the changeset say so Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Supersedes the record on Check-runs on this head — all completed, nothing in progress. Success: Auto Label · Build Core · Build Docs · Check Documentation Links · Check PR Size · Dogfood Regression Gate · Flag docs affected by code changes · Governed Surface Queue Guard · Lint & Repo Gates · Lint · CI, release & engine gates · Lint · ESLint · Lint · PM dispatch-gates · Lint · docs & code guards · Lint · repo & tooling gates · Lint · scoped · query-options erasure · Lint · scoped · slot lookup & corpus · Lint · scoped · tooling self-tests · No other open PR may claim the same issue · No other open PR may claim the same single-writer path · Part-of PR must not also close its card · Spec property liveness · Test Core · Test Core (1/6)–(6/6) · The card this PR closes must claim this branch · Type Check · consumer gates · Type Check · debt ledger · Type Check · source gates · Type Check · workspace · TypeScript Type Check · filter. Skipped (not applicable): Console Pin Gate, Dogfood Regression Gate shards, Dogfood Verify CLI, Packed-tarball smoke, Temporal Conformance. Failure: Check Changeset — its annotations on this head name exactly ① Derived judgmentsCarried forward from the
The delta
② Semver levelUnchanged from the previous head and still matching the diff. Clause-②: no — an accept-set narrowing on a published door; the PR body, the changeset, the claim, triage and the p1 regrade all say ③ Boundary flags
Implemented-by: VERDICT: PASS Adopted by Generated by Claude Code |
Maintainer confirmation: the two pending release notes corrected (DELIBERATE CORRECTION) · recorded by
|
Fixes #23388
Clause-②: no (narrowing)
Ruling of record
6161173492(letter B), quoting the maintainer: 「23388 B 是不是最简单?」「23388 如果页面有问题,不是应该修改了再保存吗?」What changes
packages/lint/src/authoring-rules.ts:validateComponentPropsandvalidateComponentTypesgo fromsurfaces: CLI_ONLYtoCLI_AND_RUNTIME, withruntimeTypes: ['page'](ruling items 1 and 2). Both entry comments drop the [P2] 运行时授权门扩到 object 写入 + 全量 runtime-safe 规则快照(#4463 P1 之后) #4716 stored-row false-refusal discipline and the two pendingsurfaceReasons, and cite this ruling as the ruling of record (item 3). ThevalidatePrintPageBlocksentry comment said "the false-refusal budgetvalidateComponentTypesis held on"; it now says that budget was replaced by this ruling. The rules' own code andComponentPropsMapare not touched.RUNTIME_OBJECT_ADVISORY_VOLUME) describe the [P2] 运行时授权门扩到 object 写入 + 全量 runtime-safe 规则快照(#4463 P1 之后) #4716 split of the OBJECT rules, not these two page rules. They are still true and are not rewritten. No other header line in the file names these two rules.pagealready maps topagesinTYPE_TO_STACK_KEY. The runtime gate judges a finding located on the written item against the baseline without the item, so the next save of a stored page with a finding is that save's own finding. The read and boot path runs no authoring rule.packages/metadata-protocol/src/protocol.runtime-authoring-gate.test.tsand run through the realsaveMetaItem/publishMetaItem/loadMetaFromDb/getMetaItem:page:headercarriestitelis refused with422 INVALID_METADATA, rulecomponent-props-unknown-keyatpages[0].regions[0].components[0].properties.titel. The message carries`titel` → `title`and the hint carriesRemove `titel`. Nothing is stored. The draft-to-active promotion of the same page is refused the same way.page:headris refused with422, rulecomponent-type-unknown, hint exactlyRename `page:headr` → `page:header`.acme:pipeline_board, a type outside the reserved namespaces.loadMetaFromDbreturnsloaded: 1, errors: 0, invalid: 0and registers the page;getMetaItemserves the stored body; the next save of the same body is refused with both rule ids and the stored row is unchanged; the fixed page then saves. This mirrors the precedent sentence at18.page-default-record-page-one-per-object-refused.ts:42..changeset/23388-page-component-rules-runtime-door.md.@objectstack/lintgetsminorwith the BREAKING banner, and@objectstack/specgetspatch(text only). It carries the ruling's sentence verbatim and the ADR-0087 dispositionnot-required (already-registered …), listing the same D3 ids the 23147 changeset names. The card's step ① (a stored-row listing) is not built.Overlap with #23357 (ruling item 6, for the seat)
Once this lands, #23357's narrow judge (the retired page data binding, in
packages/lint/src/validate-component-props.ts/packages/metadata-protocol/src/protocol.ts) overlaps the general rule at the save door. One operation has two implementations, and the governed side wins. I did not touch it, because seat 1 holds those files. The same seat should fix one sentence while it is in those files:validate-component-props.ts:111-116("The runtime publish door … does not run this rule") becomes false with this PR.File surface beyond the claim, and why
Ruling item 3 limits the rewrite to
authoring-rules.ts. My change also made the texts below false, and os-dev requires a published text that a change makes false to be fixed in that same change, so I corrected them here:packages/lint/src/validate-print-page-blocks.tsandpackages/lint/src/validate-component-types.tsheaders: comment-only. Each named the props/types rules' pending stored-row budget orsurfaceReason.packages/spec/src/migrations/entries/semantic/18.ui-*,18.element-data-source-and-object-block-filter-rule-array.ts, andpackages/spec/src/migrations/registry.ts.template: these are shipped upgrade-guide andos migrate metatext. Each said "a stored page still saves and loads, because a page component'spropertiesis not parsed on the metadata save or load path", or for one entry "a re-save through the metadata API is not refused there". After this PR, the next save of such a page is refused by the component-props gate at the save door. Each now says the page still loads and that its next save meets the component-props gate at the metadata save door. Code comments that said "a stored page is never refused" now say "never refused at load". Text only: no key, schema or conversion changes. No committed generated artifact moves (registry.tsis gitignored, andcheck:spec-changes/check:upgrade-guideare green).operation: 'update'andonSuccessparses, whileActionSchemarefuses the same shape — the rows typeoperationasz.unknown()and never carried the rule #23332 holds that file: the doc comment on theobject-gridexport-options row atpackages/spec/src/ui/component.zod.ts:5991-5994("a stored page still saves and loads"). It is a comment, not runtime text.Deliberate correction of pending changesets
(Seat update at head
3301d5f2f:18.0.0-next.1was cut onmain(0c52e4307), which moved both notes into.changeset/pre/; they are retained for the GA18.0.0note thatchangeset pre exitassembles, so the correction still applies there. The shipped18.0.0-next.1CHANGELOG is history and is not edited. Paths below are the current ones.)check:empty-changesetis red by design: this PR changes two pending changesets it did not add, and those sentences became false because of this PR's diff. I added no label. The seat decides at review, against the head sha..changeset/pre/23147-component-props-every-finding-refused.md/meta, MCP) does not run this rule, so a page saved there is not refused for any of these.defineStackand the stack schema keep the openpropertiesbag as written. …"defineStackand the stack schema keep the openpropertiesbag as written. …"packages/lint/src/authoring-rules.ts, thevalidateComponentPropsentry,- surfaces: CLI_ONLY,becomes+ surfaces: CLI_AND_RUNTIME,/+ runtimeTypes: ['page'],..changeset/pre/23103-page-action-row-on-success-and-executor.mdcomponent-props-invalidfinding (an error, like every finding of that gate). A stored page still saves and loads."component-props-invalidfinding (an error, like every finding of that gate). A stored page still loads; the metadata save door runs the same gate, so the next save of a page carrying a refused row is refused with the same text."validateComponentPropsline inauthoring-rules.ts.The gate's exact failing output (
node scripts/check-empty-changeset.mjs --base origin/main, exit 1, atba20e780e):It ends with one
::error file=…annotation for each of the two files: "… exists on the merge base and was not added by this PR … DELIBERATE CORRECTION -- your change may have made this PENDING release note false, and you rewrote it in the same stroke. Remedy: do NOT restore it -- say so on the PR and get it confirmed …"Acceptance notes
3301d5f2f: closed. PR feat(spec)!: retire page-header-subtitle-alias and inline-action-api-params-to-body-extra from the load path at 18 #23485 (finding(spec): two live-window page-property aliases (page:headerdescription, an inlineapiaction's objectparams) are converted atos validateand at load but not at the metadata save door, which now runs the component-props rule (PR #23418) #23421,8693110c4) retired both conversions from the load path at 18, so both spellings are refused with the rename at every door and the save door andos validateagree. The measurement below describes the state before that landing.)normalizedtier, after ADR-0087 D2 conversions. The save door judges the body as sent. I ran both rules over every conversion fixture with apagesstack (31 of 136 conversions), raw against normalized:page-header-subtitle-alias(page:headerdescription, 5 raw-only findings) andinline-action-api-params-to-body-extra(an inline api action's objectparams, 3 raw-only).toMajor: 17, so their window runs out at 18 (retiresIn = toMajor + 1), but neither isretiredFromLoadPathyet. Until that happens, a save spelling them is refused with the canonical key (for example, "Did you meandescription→subtitle?"), whileos validateconverts them.Verification (head
ba20e780e)pnpm --filter @objectstack/lint test: 138 files, 6699 tests passed.typecheckpassed.pnpm --filter @objectstack/metadata-protocol test: 235 files passed, 3 skipped; 28368 tests passed, 19 skipped.typecheckpassed.@objectstack/objectql(default-record-page-save-door,protocol-meta) 113 passed;@objectstack/rest(meta-alternate-door-read-gates,meta-history-diff-authoring-door,meta-plural-i18n,rest) 667 passed;@objectstack/runtime(domains/meta-list-projection-parity) 739 passed.@objectstack/spec:vitest --project localoversrc/migrations,src/conversionsandsrc/stack-conversions-record.test.ts, 763 passed;test:repo, 59 files, 1011 tests passed.scripts/ablation-replace.mjs(anchor 1 → 0, blob changed), then a lint rebuild andablation-dist-preflight(marker present in 4 built files).validateComponentPropsback onCLI_ONLY: (a), the draft promotion and (b) go red; (c) and the control stay green.validateComponentTypesback onCLI_ONLY: (c) and (b) go red, and (a) goes red too (itsrulesRunassertion names both rules).git checkout HEAD, hash equal to the HEAD blob, rebuild, both markers--absent, and the 5 pins pass.dispatch-gates --ran): 89 derived; 85 run, 4 NOT MEASURED, 0 unrun.check-empty-changeset(by design, above).check-plugin-teardown-shape --self-test: shallow clone, so the pinned control commit is unreachable.check:dual-build-cjs-loads: needs a whole-repo build.check:type-check-debt: its re-measure build was OOM-killed (137) on the shared box.check:query-options-erasure: the whole-repo eslint ratchet was killed by a 240 s timeout.Generated by Claude Code