Repository navigation
spec(release): prepare successor plan at cut time - #7445
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
## Exact decision needed Whether a change that makes a released component meet its accessibility target, and in doing so replaces documented interaction or accessibility behavior, is a breaking change. ## Existing authority searched - `spec:AST-017`: - FR3 puts documented interaction and accessibility behavior inside the compatibility promise. - FR5 says a proposal that intentionally replaces the documented contract is not a fix. - FR32–FR34 classify a correction with a released victim as `[breaking]`, held for a planned minor or shipped behind an opt-in in a patch. - Together these send every accessibility conformance fix that changes documented behavior to the next minor. - `spec:AST-020`: owns the accessibility targets (WCAG 2.2 A/AA in FR1; APG pattern adoption in FR15). It says nothing about release classification. - `spec:AST-009`: owns real-AT evidence. Not about classification. - Overlapping open work: #7444 and #7445 also edit AST-017, in unrelated sections (codemod evidence, successor plan). - Prompting change: #7515 replaces DropdownMenu's 0.7.0 Tab behavior to meet the APG Dialog pattern. ## Decision `spec:AST-017/DEC-20`, decided by @cixzhang on 2026-10-14: accessibility behavior fixes are not breaking. Her words that day: - 08:18 PT: "Accessibility behavior fixes are not breaking" - 08:20 PT: "Yeah go ahead and amend ast017" - 08:33 PT: "Yeah accessibility fixes are patches" - 08:34 PT: "Accessibility fixes should always be internal" and "I don't think it should ever change app layer code" - 08:34:58 PT: "Adding a new prop is not breaking either though" The rule: - **FR53 (new):** a change whose purpose is to make a released component meet its accessibility target is `[fix]` and patch-eligible, with no deprecation or coexistence path, even when it replaces documented roles, accessible names, states and properties, focus movement or keyboard behavior. The target is: - a WCAG 2.2 Level A or AA success criterion, - the required parts of an APG pattern the component adopts under AST-020 FR15, or - a current accessibility requirement in its record. - **No app-layer code change:** existing props, types, exports, tokens and documented usage keep working unchanged. - It may add optional public surface, such as a new optional prop. That is not breaking, and the addition is admitted under AST-017's existing rules for public additions. - It never removes, renames, or narrows existing surface. - A change that would make apps edit code is redesigned so the component absorbs it, or it is classified under FR1. - **Release note:** the Changeset names the old and new behavior and the accessibility target, so a documented behavior change gets a release-note line. - **How additive surface is admitted:** spec and API review, and its patch-or-minor handling, are left to the existing AST-017 rules. - **FR3, FR5, FR25, FR32, FR33** point to FR53. FR33 names the accessibility target as the authority for such a fix. - **Review routing:** the record's `review-applicability` block lists FR53 and DEC-20 under compatibility. - **Verification:** an FR53 row with all four cells. **IDs:** main ends at FR51 and DEC-18. Open AST-017 changes claim FR52 (#7444) and DEC-19 (#7444 and #7445 both). This change takes **FR53** and **DEC-20**; no open change claims either. The gap at FR52 is fine (AST-029 already has one). ## Rejected alternatives - Classifying accessibility corrections as breaking whenever a released caller observes the old behavior. That delays every conformance fix to a minor and keeps the harm in place meanwhile. ## Claim scope and non-goals - Governs release classification of accessibility conformance changes only. - Does not decide what any component's accessible behavior is. That stays with AST-020 and the component records. - Does not change visual-only classification (DEC-17), emergency correction (FR35), or the patch/minor gate for other breaking changes. ## Evidence and implementation relationship No implementation. #7515 is the first change classified under this rule. ## Writing rubric results - R1 narration: none. FR53 and DEC-20 state the rule in the present tense. The "replaces" wording describes the class of change the rule covers, not this PR's history. - R2 research in the record: none. - R3 evidence naming a change: none. The FR53 verification row names review and the component record's evidence. - R4 rejected alternatives over one line or outside a decision: one, one line, inside DEC-20. - R5 pull request or issue references remaining: none in the record. - R6 ruled open questions still listing options: none. Open questions stay "None." ## Scope - [x] This PR contains specification records only. - [x] It records observable behavior and preserves equivalent internal implementations. - [x] Any named internal mechanism is intentionally public, names its dependent caller/system, and explains why an equivalent implementation would not satisfy the contract. - [x] Verification states the evidence layer and failure signal without prescribing CI job/workflow topology. - [x] It records one intentional durable decision, not a rescue for a separable tagalong. - [x] The canonical knowledge owner, affected current claims, and overlapping open work are named; any ownership collision is resolved or called out for human decision. - [x] Adjacent API, visual, accessibility, composition, and implementation facts remain outside scope unless this exact decision depends on them. - [x] Public text and artifacts contain no internal Meta context. ## Validation - `pnpm check:knowledge`: aligned - Prettier: applied - `git diff --check`: clean
Main took DEC-20 (accessibility fixes, FR53) and #7444 keeps DEC-19, so the cut-time successor-plan decision becomes DEC-21 in its heading, reference, and review-applicability entry.
|
/approve-spec 525d2d5 |
PR Analysis ReportView Storybook for this PR · View Sandbox for this PR
Generated by PR Enrichment workflow | View current CI run |
There was a problem hiding this comment.
This spec-only change looks ready to merge: the record's owner has approved this exact head, knowledge validation passes, and the amended FR51 stays consistent with merge-back preservation (FR50) and the canary ordering boundary (FR46). One optional fix: the FR51 verification row lists the pre-advanced main plan state but names only merge-back as what must not lower or duplicate a newer plan, and its equality state no longer has a matching failure expectation. Any further commit will need a fresh /approve-spec, and the open draft #7545 also adds a DEC-21 to this record, so whichever lands second will need to renumber.
[Automated review]
| | FR49 | Malformed and inconsistent declaration fixtures | disagreeing group versions, canary identifier, release version unlike the cut manifest, already-released version, skipped version, no stable tag | An untrustworthy or mismatched declaration is released | | ||
| | FR50 | Three-way squash merge-back fixtures bound to the immutable tag, branch head, and plan digest | exact branch outputs, frozen deletion, branch-only marker exclusion, post-cut Changeset/manifest edit, newer main declaration, merge conflict, regenerated output | Merge-back differs from release bytes, lands lifecycle files, consumes post-cut work, overwrites a newer main declaration or unrelated field, or chooses a version | | ||
| | FR51 | Separate next-plan manifest/pin/lockfile/compatibility-asset fixtures plus canary routing assertions | default patch successor, explicitly named minor, pre-advanced main plan, unrelated main work during equality | Equality publishes a canary, the default skips a patch, pending Changesets choose a minor, exact pins or compatibility assets split, or merge-back requires a duplicate bump for an existing newer plan | | ||
| | FR51 | Cut-time successor-plan preparation plus manifest/pin/lockfile/compatibility-asset and lifecycle fixtures | default patch successor, explicitly named minor, no-publication abort, immutable tag before merge-back, pre-advanced main plan, unrelated main work during equality | The plan merges before the cut version is non-reusable, survives an unpublished terminal cut, skips the default patch, derives a minor from pending Changesets, splits pins/assets, or merge-back lowers or duplicates an existing newer plan | |
There was a problem hiding this comment.
Optional: this row lists pre-advanced main plan, but its only matching failure is "merge-back lowers or duplicates an existing newer plan", while FR51 now gives that duty to the prepared change ("the prepared change closes or refreshes instead of duplicating or lowering it"). unrelated main work during equality also lost its expectation when "Equality publishes a canary" was dropped (FR46's row still covers canary equality).
A minimal fix: end the failure cell with "…, or the prepared plan or merge-back lowers or duplicates an existing newer plan", and either drop the equality state or pair it with "unrelated main work waits for the plan".
## Exact decision needed Release generation intentionally moves staged codemods from `transforms/next/` into an immutable version folder. Repository tests and validators that read transform source can become path-coupled to either side of that move. The decision is whether evidence must follow one transform identity through both lifecycle locations instead of treating promotion as deletion. ## Existing authority searched - `spec:AST-017` FR47 and FR50 own release-branch version generation, promoted codemods as exact release output, and merge-back of those bytes. - `spec:AST-040` owns what codemods may modify in consumer files; it does not own repository source location or release promotion. - `scripts/promote-codemod-next.mjs` moves staged modules, tests, and the manifest into `v<declared-version>/`, reseeds `next/`, and updates the registry. - #7408 made one source-level guard tolerate the `next/` and `v0.7.0/` locations. No current rule generalizes that requirement. AST-017 is the canonical owner because this is release-output identity, not a consumer-file modification rule. ## Decision A staged codemod and its promoted release copy are one transform at two lifecycle locations. Any checked-in test, validator, documentation generator, or other repository evidence that reads transform source identifies the transform independently of its folder and resolves the lifecycle-appropriate staged or promoted location. Evidence fails when the transform is missing, when multiple candidates make its identity ambiguous, or when promotion no longer exposes the same transform identity and declared entry set. Promotion does not retain a duplicate under `next/` merely to keep a source path stable. This rule changes no consumer migration contract and does not prescribe one resolver implementation. It requires the same source-owned proof to remain active before and after expected promotion. ## Rejected alternatives - **Keep a duplicate under `next/`:** creates two writable owners and lets the copies drift. - **Hardcode only the staged path:** turns expected release generation into a test failure or silently dropped evidence. - **Hardcode one immutable version forever:** cannot validate the staged state before that release and does not generalize to another transform. - **Copy transform declarations into the test:** replaces source evidence with a parallel hand-maintained list. ## Claim scope and non-goals This is a specification-only proposal. It does not change codemod promotion, edit #7408, add a source resolver, alter consumer migration semantics, or modify release artifacts. ## Implementation relationship A later implementation can use explicit lifecycle candidates, manifests, a shared resolver, or another equivalent mechanism. It must fail missing/ambiguous identity, prove the evidence runs on both sides of promotion, and preserve one source transform. That implementation remains a separate atomic change. ## Writing rubric results R1 narration: none in the record; the new requirement and decision describe the present lifecycle contract. R2 research: none in the record; the `0.7.0` incident and implementation inspection stay in this pull-request description. R3 evidence: FR52 verification names staged/promoted/missing/ambiguous states rather than a pull request or workflow. R4 rejected alternatives: DEC-19 keeps one bounded `Rejected:` paragraph inside the decision. R5 change references: none added to the record. R6 open questions: none; the proposal states one exact decision for owner approval. ## Scope - [x] The canonical owner and affected current claims are named. - [x] One release-evidence identity decision changes. - [x] Implementation and consumer behavior remain outside scope. - [x] Public text contains no private or internal operational context. ## Validation - `pnpm check:knowledge` - `pnpm check:repo` - Prettier - `git diff --check` - Merged main: `main` took FR53 and DEC-20; this record keeps FR52 and DEC-19 (#7445 renumbered its decision to DEC-21). The requirement and decision text are unchanged. - Owner decision: the spec owner approved this record change on 2026-10-14 ("Merge the specs", 19:31 PT; "Can you resolve the not merging specs", 19:33 PT), so its decision records `cixzhang`, 2026-10-14, as decider.
# Conflicts: # docs/specs/AST-017/spec.md
|
/approve-spec 7d3683a |
There was a problem hiding this comment.
Changes requested for one small inconsistency: the record's owner has approved this head, and the amended FR51 fits FR46's canary boundary and FR50's merge-back preservation, but its new close rule is stated two ways. FR51 and DEC-21 close the prepared plan only for a terminal cut with no immutable public identity, while the Current-state impact sentence and the FR51 verification row close it for any unpublished terminal cut, so the two disagree for a cut that was tagged but never published. Please use one condition in all four places (for example, "a terminal cut with neither an immutable tag nor stable package publication"), and consider also naming the prepared plan in the FR51 row's failure for a pre-advanced main plan. The fix will need a fresh /approve-spec, and the open draft #7545 also adds a DEC-21, so whichever lands second will need to renumber.
[Automated review]
| post-cut consumption, or plan changes. Release tooling prepares the separate successor | ||
| plan at cut time—patch by default, minor only when Cindy names it—and holds it until the | ||
| cut version becomes non-reusable. It may then land before or after merge-back without | ||
| holding unrelated main work; an unpublished terminal cut closes it unmerged. |
There was a problem hiding this comment.
This closes the plan for any unpublished terminal cut, but FR51 (lines 665–666) and DEC-21 close it only for a terminal cut with no immutable public identity, and FR51 lets the plan merge as soon as an immutable tag exists. For a cut that is tagged but never published the two rules disagree, and closing the plan there would leave main declaring an already-tagged version that FR49 refuses to release.
Suggested wording: "…; a terminal cut with neither an immutable tag nor stable package publication closes it unmerged."
| | FR49 | Malformed and inconsistent declaration fixtures | disagreeing group versions, canary identifier, release version unlike the cut manifest, already-released version, skipped version, no stable tag | An untrustworthy or mismatched declaration is released | | ||
| | FR50 | Three-way squash merge-back fixtures bound to the immutable tag, branch head, and plan digest | exact branch outputs, frozen deletion, branch-only marker exclusion, post-cut Changeset/manifest edit, newer main declaration, merge conflict, regenerated output | Merge-back differs from release bytes, lands lifecycle files, consumes post-cut work, overwrites a newer main declaration or unrelated field, or chooses a version | | ||
| | FR51 | Separate next-plan manifest/pin/lockfile/compatibility-asset fixtures plus canary routing assertions | default patch successor, explicitly named minor, pre-advanced main plan, unrelated main work during equality | Equality publishes a canary, the default skips a patch, pending Changesets choose a minor, exact pins or compatibility assets split, or merge-back requires a duplicate bump for an existing newer plan | | ||
| | FR51 | Cut-time successor-plan preparation plus manifest/pin/lockfile/compatibility-asset and lifecycle fixtures | default patch successor, explicitly named minor, no-publication abort, immutable tag before merge-back, pre-advanced main plan, unrelated main work during equality | The plan merges before the cut version is non-reusable, survives an unpublished terminal cut, skips the default patch, derives a minor from pending Changesets, splits pins/assets, or merge-back lowers or duplicates an existing newer plan | |
There was a problem hiding this comment.
Same mismatch here: the no-publication abort state and the "survives an unpublished terminal cut" failure would require closing a tagged-but-unpublished plan that FR51 lets merge. Suggested: the state "abort before any tag or publication" and the failure "survives a terminal cut with neither an immutable tag nor stable publication".
Optionally, the pre-advanced main plan failure could also name the prepared plan ("…, or the prepared plan or merge-back lowers or duplicates an existing newer plan"), since FR51 now gives that duty to the prepared change.
…-21, impact, and verification
268a94e to
6eaab96
Compare
|
/approve-spec 6eaab96 |
There was a problem hiding this comment.
This spec-only change looks ready to merge: its owner has approved this exact revision, knowledge validation and the pull request's checks pass, and the close rule for the prepared plan now reads the same in FR51, DEC-21, the Current-state impact and the FR51 verification row. One optional fix remains: the FR51 verification row's unrelated main work during equality state has no matching failure, so either add one (for example, “unrelated main work waits for the plan”) or drop the state. Any further commit needs a fresh /approve-spec, and the open draft #7545 also adds a DEC-21 to this record, so whichever lands second will need to renumber.
[Automated review]
| | FR48 | Category and classification admission under each declared tier | patch release with `[breaking]`, patch release with a deprecation, minor release with `[breaking]` | Incompatible work passes in a patch release, or a deprecation is refused in one | | ||
| | FR49 | Malformed and inconsistent declaration fixtures | disagreeing group versions, canary identifier, release version unlike the cut manifest, already-released version, skipped version, no stable tag | An untrustworthy or mismatched declaration is released | | ||
| | FR50 | Three-way squash merge-back fixtures bound to the immutable tag, branch head, and plan digest | exact branch outputs, frozen deletion, branch-only marker exclusion, post-cut Changeset/manifest edit, newer main declaration, merge conflict, regenerated output | Merge-back differs from release bytes, lands lifecycle files, consumes post-cut work, overwrites a newer main declaration or unrelated field, or chooses a version | | ||
| | FR51 | Cut-time successor-plan preparation plus manifest/pin/lockfile/compatibility-asset and lifecycle fixtures | default patch successor, explicitly named minor, abort before any tag or publication, immutable tag before merge-back, pre-advanced main plan, unrelated main work during equality | The plan merges before the cut version is non-reusable, survives a terminal cut with neither an immutable tag nor stable publication, skips the default patch, derives a minor from pending Changesets, splits pins/assets, or the prepared plan or merge-back lowers or duplicates an existing newer plan | |
There was a problem hiding this comment.
Optional: unrelated main work during equality no longer has a matching failure in this row, since “Equality publishes a canary” moved out (the FR46–FR47 row still covers canary equality). Either add “unrelated main work waits for the plan” to the failure cell, or drop the state.
Exact decision needed
The release cut already knows the deterministic patch successor and every version-coupled file, but AST-017 currently waits until after merge-back to prepare the next-plan pull request. The decision is whether the cut prepares that separate change immediately while withholding merge authority until the cut version is non-reusable.
Existing authority searched
spec:AST-017FR46–FR51 and DEC-15 own main's declared plan, release-branch identity, merge-back preservation, and the separate successor plan.scripts/release/active-release.mjsalready validates the patch successor, an explicitly named minor successor, and the complete fixed-package/pin/lockfile/compatibility-asset set.AST-017 is the canonical owner. This PR changes no release code and grants no release or minor-cut authority.
Decision
A successful cut prepares one separate successor-plan pull request from current main. It changes every fixed-group package version, every generated exact internal pin, the lockfile, and version-stamped compatibility assets together.
The default is the cut version's patch successor. A minor successor appears only when the release owner explicitly names that minor; pending
[breaking]Changesets never choose it.The prepared change cannot merge until an immutable tag or stable package publication makes the cut version non-reusable. It may then land through normal gates before or after exact release merge-back, which preserves an already-landed newer declaration. A terminal cut with no immutable public identity closes the prepared change unmerged. A pre-existing newer owner plan closes or refreshes the prepared change rather than being lowered or duplicated.
Rejected alternatives
Claim scope and non-goals
This is a specification-only proposal. It does not implement automation, merge a successor plan, change canary publication, alter merge-back bytes, authorize a minor, change the daily release schedule, or modify a failed/active release lifecycle.
Implementation relationship
A later implementation would prepare the PR at the cut, hold merge until public identity is non-reusable, close it on a clean unpublished abort, and reuse the existing next-plan and merge-back validators. The implementation remains separate and requires its own normal review.
Writing rubric results
R1 narration: none in the record; the amendment states lifecycle behavior in present tense.
R2 research: none in the record; current implementation facts stay in this pull-request description.
R3 evidence: FR51 verification names cut, abort, immutable-identity, and merge-order states rather than a pull request or workflow.
R4 rejected alternatives: DEC-21 keeps one bounded
Rejected:paragraph inside the decision.R5 change references: none added to the record.
R6 open questions: none; the proposal states one exact decision for owner approval.
Scope
Validation
pnpm check:knowledgepnpm check:repoPrettier
git diff --checkRenumbered after merging main:
maintook DEC-20 (accessibility fixes, FR53) and spec(release): make codemod evidence tolerate promotion #7444 keeps DEC-19, so this decision is DEC-21 in its heading, reference line, and review-applicability entry. Its text is unchanged.Owner decision: the spec owner approved this record change on 2026-10-14 ("Merge the specs", 19:31 PT; "Can you resolve the not merging specs", 19:33 PT), so its decision records
cixzhang, 2026-10-14, as decider.