Repository navigation
feat(spec)!: retire page-header-subtitle-alias and inline-action-api-params-to-body-extra from the load path at 18 - #23485
Conversation
…params-to-body-extra from the load path at 18 (wip) Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
…Retired; the record-door vehicle moves to a live conversion Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
…ader key with the rename Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
…ve page visibility conversion Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
…geset Claude-Session: https://claude.ai/code/session_01D6F9axfoPzR7t8G1J7Ytzz Co-authored-by: Claude <noreply@anthropic.com>
…tire-page-aliases-at-18
… refuses them, joined in the removal-version pin 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>
…tire-page-aliases-at-18
📓 Docs Drift CheckThis PR changes 1 package(s): ⛔ 2 release-owned page(s) name something this change touched. These are read-only:
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 c0f4e7ae77051838da398ed7dcfda69acf71f7f0 && git checkout c0f4e7ae77051838da398ed7dcfda69acf71f7f0
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin a1285f26db92269642ebb90ab70fe3840dda51cb 6f0fcb21f4efcdfcd6213ab9ad1675341204ffa8 && git checkout -B drift-repro a1285f26db92269642ebb90ab70fe3840dda51cb && git merge --no-ff 6f0fcb21f4efcdfcd6213ab9ad1675341204ffa8
node scripts/docs-audit/affected-docs.mjs --json a1285f26db92269642ebb90ab70fe3840dda51cb
|
Contract reviewServed-tier: Inputs read: card #23421 (body + 3 comments: triage ① Derived judgments
② Semver level
Clause-②: yes (narrowing) — as the changeset declares; the diff's exact arm is ③ Boundary flagsDev flags (report a. File-surface extension ( b. PR body carries no readable c. One wrong sentence in a docblock — d. The new vehicle is itself overdue — e. PR #23418's changeset paragraph and f. Kebab g. Check-runs on the head — 22 completed h. Claim's Implemented-by: VERDICT: PASS Adopted by Generated by Claude Code |
Fixes #23421
Clause-②: yes (narrowing)
What
The two ADR-0087 D2 conversions
page-header-subtitle-alias(page:headerproperties.descriptiontosubtitle) andinline-action-api-params-to-body-extra(an inlinetype: 'api'action's object-formparamstobodyExtra) were declaredtoMajor: 17for protocol 17's one-major window. On the18.0.0-nextline they were still load-active, soos validateand the load path converted silently what the metadata save door (once PR #23418 moves the component-props rule onto it) refuses. This PR retires both from the load path, the way every other retired entry is marked:retiredFromLoadPath: trueandretiredAfter: '17.7.0', the newest published stable release under the18.0.0-next.0label.After this change every door that judges page props answers the same way:
os validate,os build,os lint, and the save door after #23418 all refuse the old spelling, and the refusal names the rename. Stored rows keep healing.applyConversionsToStoredItemreplays the full chain withincludeRetired: true, so does the artifact-ingestion door inside its window, andos migrate metareplays the chain too.Premise check (done before any edit)
toMajor: 17means 18 is N+1. The section "The load-window's second half is now mechanical" namesMetadataConversion.retiredFromLoadPathas the field that implements that retirement.conversions/types.ts:RetiredConversionStateisretiredFromLoadPath: trueplus a requiredretiredAfter.apply.tsskips such an entry unlessincludeRetiredis set.stored.tspinsincludeRetired: true.61b12584f, 45toMajor: 17entries carryretiredFromLoadPath(retiredAfter16.1.0). Among thetoMajor: 18entries, 69 are retired, 7 of them withretiredAfter: '17.7.0'(for exampledeclared-index-unique-scopeandemail-template-category-is-system-removed).Changes
packages/spec/src/conversions/registry.ts: the two entries get the two fields, and their docblocks now record the retirement in place of "Live window; retires at 18".packages/spec/src/ui/component.zod.ts:PageHeaderPropsdescriptionmoves from analiasesrow (a bare "Did you meandescriptiontosubtitle?") to aguidancerow. It is the upgrade prescription in house form: it names@objectstack/spec 18andsubtitle, followed by theos migrate meta --from 16house sentence.packages/spec/src/ui/action.zod.ts: the object-formparamsrefusal keeps itsbodyExtrainstruction. It now also says the loader rewrote that form on an inline page button until@objectstack/spec 18, and it ends in the MIXED two-clauseos migrate meta --from 16sentence. The partial form is used because the conversion only covers the inlineelement:buttoncase.ui/*.zod.ts:shared/retired-key-removal-version.pin.test.tsrequires every entry retired after the newest stable release to be joined to the prescriptions an author meets, and requires each of those prescriptions to name the derived release (18). Neither refusal named a release, so the pin went red on exactly these two ids. The landing spot is the producer of the refusal text, in the same package.conversions/conversions.test.ts: the two entries' rewrite cases run the data-at-rest posture (includeRetired: true). New cases assert that the authoring posture rewrites nothing on bothpage:headerand the kebabpage-header, and on the object-formparams. They also assert the entry fields (toMajor: 17,retiredFromLoadPath: true,retiredAfter: '17.7.0') and that thebodyExtrarefusal is what an author meets. The premise pin onPageHeaderProps(refusesdescription, namessubtitle) stays verbatim.lint/src/validate-component-props.test.ts: the "normalized tier" block asserted the normalized tier says nothing aboutdescription. It now asserts that the normalized tier refuses it ascomponent-props-unknown-key,error, at the exact path, namingsubtitle, and that the raw tier gives the same answer.shared/retired-key-removal-version.pin.test.ts: two JOIN rows.spec/src/stack-conversions-record.test.ts,cli/test/stack-conversion-record-door.test.tsandcli/src/commands/validate-json-strict-exit.e2e.test.tsusedpage-header-subtitle-aliasas their live conversion. Their own docblocks said to re-point them at a live entry when it retired. They now ridepage-component-visibility-to-visibleWhen(visibilitytovisibleWhenon the samepage:headernode,retiresIn: 16), and every assertion is unchanged in substance..changeset/23421-retire-page-aliases-at-18.md:minor, with the BREAKING banner,Clause-②: yes (narrowing), the FROM to TO mapping, and the ADR-0087 disposition. In words, the disposition marker is "adr-0087: not-required (already-registered page-header-subtitle-alias, inline-action-api-params-to-body-extra)". Both conversions are already in the step-17 chain and are the whole mechanical migration, so there is no new D2 conversion and no D3 semantic entry.check-adr-0087-registrationaccepts it.For the seat: one sentence in PR #23418 becomes false
PR #23418's changeset
.changeset/23388-page-component-rules-runtime-door.mdcarries the paragraph that begins "Two live-window ADR-0087 D2 aliases ... are converted atobjectstack validateand at load but not at this door". Once this PR lands, that paragraph is false: neither alias is converted atobjectstack validateor at load any more. This PR does not edit #23418's files. The same goes for the comment block inpackages/lint/src/authoring-rules.ts(thevalidateComponentPropsentry, "normalizedfor a reason worth stating ..."), which still citespage-header-subtitle-aliasas the converted alias that makes the tier matter. That file is in #23418's diff, so it is left for that landing. #23418 is not addressed here.Verification (at
6f0fcb21f, after mergingorigin/mainat3d231ba78)pnpm --filter @objectstack/spec test: 676 files, 20576 tests passed (after the merge).pnpm --filter @objectstack/spec test:repo: 59 files, 1011 tests passed (before the merge, which touched no tree-scoped pin input of this diff).pnpm --filter @objectstack/spec check:generated: all 14 generated artifacts up to date.typecheck:@objectstack/spec,@objectstack/lintand@objectstack/clieach exit 0.@objectstack/lintfull vitest,@objectstack/cli--project unit(287 files, 4307 tests), and the two touched CLI integration and e2e files:test/stack-conversion-record-door.test.ts(21/21) andsrc/commands/validate-json-strict-exit.e2e.test.tsunderOS_TEST_TIERS=nightly(7/7).conversions.test.tshad 5 failing cases andstack-conversions-record.test.tshad 30, all asserting the two conversions ran on the authoring path. The lint tier case and the removal-version pin each went red the same way.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(93 families, the same set before and after the merge). All 93 were run at6f0fcb21fwith exit 0, and the list was reconciled with--ran.Acceptance notes
page-header(kebab): the conversion's walk still lists it, for the data-at-rest replays. Retired, a sourcepage-headernode'sdescriptionis neither converted nor judged, becauseComponentPropsMaphas nopage-headerrow. This is harmless: objectui at the pinned.objectui-shano longer registerspage-header(its components changeset "droppage-headerfrom the opt-in protocol placeholders"), so such a node renders the unknown-component panel whatever its props say.defineStackdoes not run the props gate (that gate runs atos validate/os build/os lintand, after feat(lint)!: the two page component rules run on the runtime publish door (ruling B) #23418, at the save door). This is the same posture every other retired page prop already has (page:headericonandbreadcrumb).examples/,packages/platform-objects,packages/plugins,packages/services). The control grep onpage:headerfinds the canonicalsubtitlein use.Generated by Claude Code