Repository navigation
release(v18): the version-pr lane refuses the major boundary at Validate the post-version tree, so #21988 never refreshes into 18.0.0-next.0 — wire the lane's major-only gates in, and stop prerelease cuts re-dating the last GA #22085
Description
Ruled: 6049734955 · letters Q1 B · Q2 A · Q3 B · 2026-10-08T00:41Z
This card carries the version-lane half of #22080's opening: the route by which 18.0.0-next.0 is actually cut once pre mode is in. #22080 keeps its own half, pre mode plus the one major marker, as PR #22084. Its After-it-lands line ("changesets/action refreshes #21988 into the prerelease version PR") is what this card makes true.
Filed by PM seat domain:devx#2 (session_01VF48aw8RPG6wzDnMgp6rtw) as an in-flight derivative of #22080. Per the execution duties, it inherits #22080's domain (domain:devx), priority (p1) and target:v18, and this seat dispatches it directly. ⛔ Not a claim; the claim follows.
Filing gate: ① a measured defect with a named producer. reach: named producer: release.yml's version-pr job (cron 0 */6 * * *), step Validate the post-version tree (:518 on main 3d9188502e). It exits 1 at :610–:613 on the first refresh after #22084 merges.
Reader: this seat's next dispatch, now.
Dedupe: the 435 most recently updated issues (state=all, REST page loop, PRs excluded), titles and bodies grepped for post-version tree|MAJOR_ONLY|major boundary|version-pr|18\.0\.0-next|release-index-currency|cut-rc. That gives 5 hits: #22080, #9139, #22050, #21993 and #21772. None wires the lane for the boundary. Dedupe words: version-pr major boundary; Validate the post-version tree; MAJOR_ONLY unvalidated; release index currency prerelease date.
What was measured (PR #22084's dev, report 6039596838. The seat re-read the release.yml and cut-rc.yml lines cited; the rest is the dev's throwaway reading)
- In a throwaway worktree at chore(release): enter Changesets pre mode (
next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084's head52f7a509c6, never committed, the full rootversionscript exits 0 and puts all 69fixedmembers at18.0.0-next.0. The script ischangeset version,sync-protocol-version,sync-template-versions,sync-docs-image-tagsandsync-release-index-currency. - Replaying the step's shape assertion on that tree finds 0 unexpected paths, but MAJOR_ONLY is non-empty:
packages/spec/src/kernel/protocol-version.ts,'17.0.0'→'18.0.0';packages/create-objectstack/src/templates/blank/objectstack.config.ts,objectstack.manifest.jsonandpackage.json.- The step prints
this version pass crossed a MAJOR boundary and wrote the surfaces above, which this lane has no gate for … Wire them in before letting this refresh through.and exits 1 (:610–:613). - The changesets/action step that would refresh chore: version packages (next) #21988 does not run.
cut-rc.ymlis no route either: it refuses any version not shapedX.Y.Z-rc.N(:156–:159) and anypre.jsontag butrc(:232–:237).- Same throwaway:
scripts/sync-release-index-currency.mjsrewrote the v17 entry incontent/docs/releases/index.mdxfromreleased 2026-10-06toreleased 2026-10-07, the cut's date. 17.7.0's version commit4e4e881427is dated 2026-10-06. In pre mode the newest GA does not move, so every prerelease cut would re-date the last GA.
The route (the seat's call, not re-rulable here)
#22050's ruling 6037890422, verbatim: "Once the opening lands, changesets/action turns it into the prerelease version PR." So the version PR is the ruled route, and this card wires it. ⛔ cut-rc.yml is not extended (that would be a second route the ruling did not name).
Done when
- A version pass that crosses the major boundary passes
Validate the post-version tree. The step now validates each MAJOR_ONLY surface instead of refusing it: the protocol-version lockstep and the blank template's render, using gates the lane or the repo already has. The refusal stays for any major-only path still unvalidated. sync-release-index-currencydoes not re-date the newest GA entry on a prerelease cut. This is pinned in its own battery.- Pin, in the PR body: the full root
versionscript plus the step's replayed assertion, on a throwaway tree carrying chore(release): enter Changesets pre mode (next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084'spre.jsonandmajorchangeset (or onmainonce chore(release): enter Changesets pre mode (next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084 merges). It exits 0 at18.0.0-next.0, and the release index's v17 date is unchanged. - Measured and reported, not edited: on the first prerelease,
sync-docs-image-tagsmoves the docs image pins (docker/README.md,content/docs/deployment/self-hosting.mdx,content/docs/upgrading.mdx) from17.7.0to18.0.0-next.0while npmlateststays 17.7.0. If keeping them on the GA during thenextline needs a choice, it goes in the report'sopen_questions. - ⛔ No publish, no tag, no
workflow_dispatchof any release workflow, ⛔ no merge of chore: version packages (next) #21988, ⛔ no edit tocut-rc.yml, ⛔ no hand edit ofcontent/docs/releases/**.
Activity
objectstack-fleet commentedon Oct 7, 2026
Claim: PM loop round 7
Session:
session_01VF48aw8RPG6wzDnMgp6rtwAccount:
os-justin(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-22085-version-lane-major-boundary(new, cut fromorigin/main3d9188502e)Worktree:
objectstack-issue-22085Domain:
domain:devx(inherited from #22080, in-flight derivative)Seat:
domain:devx#2File surface:
.github/workflows/release.yml(theversion-prjob'sValidate the post-version treestep),scripts/sync-release-index-currency.mjsand its battery, and any existing gate script the step newly calls (read-only unless its own battery needs a case).cut-rc.yml. ⛔ No hand edit ofcontent/docs/releases/**. ⛔ No publish, tag orworkflow_dispatchof a release workflow. ⛔ chore: version packages (next) #21988 is not touched.Container & model:
M,mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate; default tier; release-lane judgment)Clause-②: no
Responsibility:
release.yml's ownversion-prrefusal (this repo's release lane) | none:cut-rc.ymlrefusesnext, so no other lane cuts it | the maintainer's v18 prerelease cuts, from chore(release): enter Changesets pre mode (next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084's merge onThread-read: none
Serial constraints cleared: the only open PR touching this surface's neighbourhood is chore: version packages (next) #21988 (the Version Packages PR;
content/docs/releases/index.mdx), which is ⛔ not merged by ruling and not edited here. PR chore(release): enter Changesets pre mode (next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084 (release(v18): enter Changesets pre mode on main (changeset pre enter next) with onemajormarker, so the first v18 prerelease is 18.0.0-next.0 — the opening ruled B on #22050 #22080, this seat) touches.changeset/only; this card's pin replays on a throwaway tree that carries chore(release): enter Changesets pre mode (next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084's two files. ci: Lint's three Type Check jobs, the Test Core shards, dogfood and Temporal each rebuild the workspace (3.5–5.8 min per job, ~25–30 job-min per CI+Lint pair) — extend #21186's turbo remote cache to them #22077 (this seat) holdslint.ymlandci.yml; ci(lint)/pm: the PM dispatch-gates self-test (7.6–13.1 min, one step) is Lint & Repo Gates' critical path on PR and merge_group runs; its family read-set selects it on most PRs — tier the battery or narrow the read-set #22076 (this seat) holdsscripts/ci/select-gate-families.sh; no shared file.os-justin commentedon Oct 7, 2026
os-dev-report
{
"issue": 22085,
"status": "needs_decision",
"branch": "claude/issue-22085-version-lane-major-boundary",
"pr": "#22095",
"session": "session_01VF48aw8RPG6wzDnMgp6rtw (subagent: the dispatching PM's session; the relay derived the same id from CLAUDE_CODE_REMOTE_SESSION_ID)",
"premise_still_valid": false,
"summary": "Partly falsified; draft PR #22095 (head a4cbcfd, base main 3d91885,
Part of #22085,Clause-②: no) carries the half that holds. MAJOR_ONLY from my own replay (this branch + PR #22084's two files, never committed; and main's own step on #22084's head 52f7a50 as baseline, exit 1 naming all 4): packages/spec/src/kernel/protocol-version.ts (17.0.0 → 18.0.0) and blank template objectstack.config.ts, objectstack.manifest.json, package.json; 0 unexpected paths (236 moved before the fix, 235 after: the release index no longer moves). Per-surface gates, all existing, no build, measured on the boundary tree: template stamps →pnpm --filter create-objectstack test(renders the blank template from an npm-packed copy and ratchets all three stamps against create-objectstack's new major; 16 files, 249 tests, green, 23 s; negative control: specVersion set back to ^17.0.0 → template-consistency exit 1, 2 failed, restored by hash) +check:template-manifests(green, 2 s); protocol-version.ts → protocol-version.test.ts as ONE file (green, 5 s wall; Zone 2 #2's 'whole spec suite only' is false, so the 5m26s suite cost does not apply and was not re-measured) + check:spec-changes and check:upgrade-guide (2-3 s each), both RED on the boundary tree (green on the pre-version control): the version pass moves PROTOCOL_VERSION and regenerates neither (regeneration moves spec-changes.json by 6342 lines and adds a 1024-lineProtocol 17 → 18section to docs/protocol-upgrade-guide.md). Beyond those gates, the handshake: probed with the post-version constant, checkProtocolCompat gives^17→ incompatible OS_PROTOCOL_INCOMPATIBLE and^18→ ok (pre-version control: the reverse). examples/app-crm, app-showcase, app-todo and app-multi-package's two packages declare^17, and runtime/app-plugin.ts:421 asserts it at app load. No gate this lane can afford boots them. So the step now validates the template half instead of refusing it, runs the protocol half's three gates, and KEEPS the refusal for protocol-version.ts (Done-when 1's last clause), collected rather than exited on so one run names everything. A second boundary-only red the card did not foresee: the existing content gate check:release-notes exits 1 because## 18.0.0-next.0counts as a shipped 18.x and content/docs/releases/v18 does not exist. Result: Done-when 1 and 3 are NOT met; the boundary replay still exits 1 (3 red gates + 1 unvalidated), and that is correct, not a wiring gap. The three decisions are in open_questions. Release-index re-date: reproduced twice (the version script on 52f7a50 printedv17: (current series: 17.7.0, released 2026-10-06) → (… released 2026-10-07)). Cause confirmed: rewriteStatusField re-stamped the date on a field already naming the newest GA, and battery B case 4 pinned that. Fix: a same-version field is refused (the gate judges the version only; the date is the release date of the version the run moves the field to). B4 inverted, new batteryControl H: a prerelease cut never re-dates the newest GA(7 cases: next cut, rc cut, positive control, syncIndex end to end), floor 7 → 8. After the fix, the boundary replay leaves the v17 entry atreleased 2026-10-06(git diff empty), and the GA control train still stamps17.8.0, released 2026-10-07. Docs image tags, measured and not edited: the first prerelease moves 9 pins 17.7.0 → 18.0.0-next.0 (docker/README.md 3 image tags + 1 build-arg; content/docs/deployment/self-hosting.mdx 3 image tags + 1 npm pin; content/docs/upgrading.mdx 1 image tag). npm view dist-tags for @objectstack/cli, @objectstack/spec and create-objectstack: latest 17.7.0, rc 17.0.0-rc.6, no next. The ghcr latest tag does not move for a prerelease (docker-publish.yml:83). Throwaway pin exit codes: boundary train: Render (full root version script) 0, 69/69 fixed members at 18.0.0-next.0, pre.json unchanged; shape pass; Validate 1; Restore 0. Ordinary 17.8.0 control train (this branch, no opening files): Render 0, Validate 0 with all 14 gates green (44 s held), Restore 0.","tests": "All exit codes written to disk before any pipe. Derived (
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat a4cbcfd, final head, no push after): 50 commands, all exit 0, incl. check:release-index-currency-sync, check:workflow-status-functions, check:workflow-step-name-quoting, check:pnpm-filter-targets, check:self-test-workflow-commands, check:nul-bytes; batterypnpm check:pm-dispatch-gatesexit 0,✓ dispatch-gates self-test: 1976 cases pass.in 997.8 s.--ran:Run reconciliation — 50 derived, 50 run, 0 NOT-MEASURED, 0 UNRUN.node scripts/sync-release-index-currency.mjs --self-test: exit 0,OK self-test: 42 cases pass. Ablation (fix committed first at c3bfb5c, via scripts/ablation-replace.mjs, trap restore): putting the pre-fix logic back (const rewritten = …; return rewritten === field ? null : rewritten;) → exit 1,5 failure(s)= B4 + H's next/rc/date/syncIndex cases, H's 3 controls stay green; restoredblob == HEAD (28f5ee09dd5f) and git diff HEAD is empty. A first, cruder ablation that only deleted the guard line also reddened B1-3 and C; that mutation was too strong and is not the reading. Workflow replays (steps extracted from this branch's release.yml with a YAML parser, run verbatim): boundary Render 0 / Validate 1 (green 11: 8 existing content gates + create-objectstack suite + check:template-manifests + protocol-version.test.ts; red: check:release-notes, check:spec-changes, check:upgrade-guide; unvalidated protocol-version.ts) / Restore 0; ordinary train Render 0 / Validate 0 (14 green,Post-version tree validated.) / Restore 0. Lock runs (os-verify-lock, slot issue-22085-dev): protocol-version.test.ts VERDICT command-exit 0 (3 tests, 5 s); 3 PROTOCOL-reading spec tests (protocol-version, migrations, spec-changes-surface-scope) VERDICT 0 (179 tests); create-objectstack suite VERDICT 0 (249 tests); boundary Validate VERDICT 1 (held 56 s, waited 8m08s); control Validate VERDICT 0 (held 44 s). NOT MEASURED: the whole @objectstack/spec suite on the boundary tree (reason: no longer the lockstep's only gate, and the step does not call it); the cli/runtime/dogfood suites under protocol 18 (reason: the handshake probe already shows the refusal, and those suites need builds); whether v17's release page predated 17.0.0-rc.0 (reason: shallow clone). CI on #22095 at report time: 33 check runs, 10 success, 11 skipped, 12 in_progress, 0 failed; not waited on.","gates": {
"derived_commands": 50,
"run": 50,
"exit_nonzero": 0,
"reconciliation": "50 derived, 50 run, 0 NOT-MEASURED, 0 UNRUN",
"battery": "pnpm check:pm-dispatch-gates :: exit 0 (1976 cases, 997.8 s)",
"card_pins": {
"root version script on boundary tree": "exit 0, 69/69 at 18.0.0-next.0",
"Validate the post-version tree, boundary tree": "exit 1 (check:release-notes, check:spec-changes, check:upgrade-guide red; protocol-version.ts unvalidated)",
"Validate the post-version tree, 17.8.0 control tree": "exit 0 (14/14 green)",
"release index v17 date on boundary tree": "unchanged, released 2026-10-06"
},
"ci_at_report": "in_progress"
},
"line_budget": "195 changed lines (+162 / -33) over 2 files, under the 5000 human-merge threshold; no skills/** or governed surface touched",
"files_changed": [
".github/workflows/release.yml",
"scripts/sync-release-index-currency.mjs"
],
"deviations": [
"PR body opens
Part of #22085, not the dispatch'sFixes #22085. Done-when 1 and 3 are not met (the protocol half and check:release-notes need decisions), so a merge must not close the card. The definition rules: Part of when a merge should not close the card.","Done-when 1 ('a version pass that crosses the major boundary passes') and 3 ('exits 0') are not delivered. Their premise, that existing gates would pass the boundary tree, is false as measured. No new gate was invented and nothing outside the claimed file surface was edited (root version script, cut-rc.yml, content/docs/releases/** untouched).",
"The template gates and the protocol gates run on EVERY refresh, not only at a boundary, so they cannot go dormant between majors. Cost on the ordinary train: the whole Validate step held 44 s (header previously priced the content half at 7 s); the header now says so.",
"Commit trailers are the AGENTS.md model-free pair (Claude-Session + Co-authored-by: Claude) rather than the harness reminder's model-named Co-Authored-By. The PR body footer is the AGENTS.md session-URL form rather than the harness reminder's form.",
"Label
size/mon #22095 was set by the repo's size labeler, not by this run.","One throwaway-only local commit (5f1f464f14, carrying #22084's two files onto this branch) was made in a detached throwaway worktree so the Render step's clean-tree assertion would hold. It was never pushed and is unreferenced."
],
"mcp_calls": "0",
"api_writes": "3 — each one relay stroke (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): pr_create = POST /repos/objectstack-ai/objectstack/pulls (#22095, draft, 9384 bytes sent = stored); label-write = POST /repos//issues/22095/labels (skip-changeset) + POST /issues/22095/assignees (os-justin), one dispatch, read back MATCHES; post-stamped = POST /repos//issues/22085/comments (this report). Plus 4 git pushes (not REST).",
"rest_writes": "3 — same as api_writes",
"open_questions": [
{
"question": "Q1. How does the protocol major move at the v18 opening? Measured on the boundary tree: moving PROTOCOL_VERSION 17 → 18 at version time stales check:spec-changes and check:upgrade-guide (both in the required TypeScript Type Check job), and makes the handshake refuse the in-repo
engines.protocol: '^17'declarations: examples/app-crm, app-showcase, app-todo, app-multi-package core and orders, plus 3 docs snippets and about 40 cli test fixtures (their verdicts are not measured). The version PR runs no CI, so none of this is judged where it lands.","options": [
"A. Version-time: the root
versionscript also runs gen:spec-changes and gen:upgrade-guide when sync-protocol-version moves the constant, and a version-time restamp moves in-repo engines.protocol. The step's protocol refusal is lifted once those are green and stamped. Cost: the version chain grows by 2 generated outputs (about 7.4k lines in the bot PR) and 1 new rewriter. The shape allowlist and cut-rc.yml's allowlist gain paths. The handshake flip and the 17 → 18 conversion hop activate in a PR no CI runs.","B. Ordinary PR first: one CI-judged PR moves PROTOCOL_VERSION to 18.0.0, regenerates both artifacts, and restamps examples, docs snippets and fixtures to ^18, before #21988 refreshes. protocol-version.test.ts and sync-protocol-version.mjs are amended so that, while pre.json is in pre mode with a pending major, the protocol major may equal the major that release computes. At 18.0.0-next.0 sync-protocol-version then finds 18 already, protocol-version.ts never moves on the lane, and MAJOR_ONLY is template-only, which #22095 already validates.",
"C. Leave the lane refusing and hand-fix main after a version PR merges. Rejected: main goes red between the two merges, and #21988 is not mergeable by ruling anyway."
],
"recommendation": "B. Business need: measured, the flip refuses 4 in-repo apps and activates a migration hop and a 1024-line upgrade section. Those are runtime behaviour changes whose judges (Dogfood Regression Gate, Test Core) run only on an ordinary PR. Long-term: it keeps the version lane a renderer of package versions. A protocol major is an ADR-0087 event with generated docs, not a stamp, and A is one more turn of the rewriter treadmill the step's own header names. AI-error axis: B puts the flip in a reviewed, CI-judged diff where a stale artifact or a missed stamp fails loudly; A ships it inside a bot PR with a 7k-line generated diff no CI reads. Startup focus: B adds no gate and no version-time rewriter (it amends one test and one sync predicate); A grows the version chain by three outputs. The lockstep amendment is a contract change: the maintainer's call."
},
{
"question": "Q2. check:release-notes, already in the step, exits 1 at the boundary:
## 18.0.0-next.0counts as a shipped 18.x, so it requires content/docs/releases/v18.mdx (or v18/index.mdx) plus its meta.json entry. That tree is release-owned and this run did not write it.","options": [
"A. A docs-only PR by the maintainer or release seat writes the v18 landing page (the line's purpose and the breaking-stage policy) and lists it in meta.json, before the first prerelease refresh.",
"B. check:release-notes counts GA headings only (the gaVersions predicate check-release-section-coverage already uses), so the v18 page is due at 18.0 GA."
],
"recommendation": "A. Business need: the page has a runtime reader on the prerelease line. packages/cli/src/utils/protocol-version-gap.ts points an app whose engines.protocol excludes the installed spec at /docs/releases/v18, relying on check-release-notes for 'never 404s'. Installing @next makes that fire. Long-term: B would let that advisory link 404 for the whole next line. AI-error axis: A keeps the gate strict and the advisory honest. Startup focus: A is one short release-owned page, with no gate change; B is a gate-semantics change whose cost is that 404."
},
{
"question": "Q3. Should the docs image pins stay on the newest GA during the next line? Measured: the first prerelease moves 9 pins in docker/README.md, deployment/self-hosting.mdx and upgrading.mdx to 18.0.0-next.0, while npm latest (cli, spec, create-objectstack) and the ghcr latest tag stay 17.7.0.",
"options": [
"A. Leave it: docs follow packages/cli's version, so self-hosting and upgrading docs on main name 18.0.0-next.N for the whole line.",
"B. In pre mode, sync-docs-image-tags and check-docs-image-tag pin the newest GA (read from the CHANGELOG the way gaVersions does) instead of packages/cli's version. Outside pre mode, nothing changes."
],
"recommendation": "B. Business need: self-hosters and upgraders copy these pins (the 17.2 → 17.3 upgrade rehearsal ran against the published docs alone), and a prerelease pin sends production users onto a line carrying ADR-0131's breaking stages. Long-term: the invariant the pair encodes is 'docs pin = what a default install resolves', which equals packages/cli's version only outside pre mode. AI-error axis: the gate stays an equality, against a computed value. Startup focus: no new gate, just a semantic change in an existing rewriter and gate pair. A costs nothing now but ships prerelease pins on main for months."
}
],
"out_of_scope_findings": [
"carrier: none (承接者:无) · noted, not filed — release.yml's comment above
Create or update the \"chore: version packages\" PRsayspnpm run versionis FOUR rewriters; it is five since sync-release-index-currency joined. In #22095's Acceptance notes.","carrier: none (承接者:无) · noted, not filed — cut-rc.yml's 'On an RC cut this rewriter writes NOTHING' was false for the date before #22095 (an rc cut on a later day re-dated the entry), and is true after it. cut-rc.yml is not edited, by the card.",
"carrier: the Q1 decision's PR · noted — about 40 packages/cli test fixtures and 3 docs snippets declare engines.protocol '^17'. Whether those tests fail under protocol 18 is not measured; they belong to whichever route Q1 takes."
],
"cleanup": "throwaway worktree objectstack-issue-22085-replay: version output discarded by the workflow's own Restore step (porcelain empty), node_modules removed and worktree removed without --force after this report; fetched ref refs/os22085/pr22084 deleted; task worktree /home/user/objectstack-issue-22085 clean and fully pushed, node_modules + worktree removed after this report posts; no server started; the one detached battery process (PID recorded) exited 0 before the report."
}
Generated by Claude Code
objectstack-fleet commentedon Oct 7, 2026
待裁:v18 第一个预发布版
18.0.0-next.0怎么切出来(三个子问题,一次裁清)席位
domain:devx#2·session_01VF48aw8RPG6wzDnMgp6rtw· 2026-10-07T15:22Z。⛔ 不是认领,也不是派发。本卡转入needs-user-decision。席位仍持有 PR #22095(Part of #22085,只落已实测成立的那一半)直到合并,届时另写Release:行。维护者速读
v18 预发布模式合并后,第一个预发布版还切不出来,卡在三件事:
回复一行即可,例如「Q1 B / Q2 A / Q3 B」。
一句话问题: #22084 进入预发布模式后,发版通道第一次切版本会把协议版本从 17 跳到 18。可仓库里的示例应用、两份生成文档、v18 发布说明页和自托管文档的镜像版本都还停在 17。而这次切版本走的是一个不跑 CI 的机器人 PR。所以 18.0.0-next.0 现在切不出来,切出来也会带着不一致出门。需要你定三件事。
背景
changeset pre enter next) with onemajormarker, so the first v18 prerelease is 18.0.0-next.0 — the opening ruled B on #22050 #22080 → PR chore(release): enter Changesets pre mode (next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084: 只加.changeset/pre.json和一个major标记,等你合并。Validate the post-version tree, so #21988 never refreshes into 18.0.0-next.0 — wire the lane's major-only gates in, and stop prerelease cuts re-dating the last GA #22085 → PR fix(release): judge the major-boundary template stamps on the version-pr lane, and stop prerelease cuts re-dating the last GA #22095: 把模板那一半接进发版通道的校验(创建脚手架的测试套件 + 模板清单检查,都是现有门禁),并修好预发布切版时把 17.7.0 发布日期改成当天的问题。协议版本那一半仍然拒绝,原因如下。这个 PR 不依赖本次裁决,席位复核通过后就落地。6040836373,boundary 树 =3d9188502e+ chore(release): enter Changesets pre mode (next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084 两个文件):version脚本:退出码 0,69 个包都到18.0.0-next.0;check:spec-changes、check:upgrade-guide、check:release-notes三个门禁红,另有protocol-version.ts未校验;Governing text
packages/spec/src/kernel/protocol-version.test.ts:18-26:"The protocol major MUST equal the published @objectstack/spec major, so the handshake a package declares (engines.protocol: '^N') matches the version it actually installed."scripts/sync-protocol-version.mjs:3-11:版本 PR 不触发 CI(fix(spec): PROTOCOL_VERSION 13.0.0 → 14.0.0 — re-lockstep with the released major #2769),所以协议常量在版本时机械地跟随 spec 的大版本。6037890422:"Once the opening lands, changesets/action turns it into the prerelease version PR."release.yml的Validate the post-version tree原拒绝文案:"Wire them in before letting this refresh through."content/docs/releases/(发布说明页归发布侧)。是否改协议: Q1 的 B 要修改上面那条 lockstep 不变量(预发布模式下的一个窄例外);Q2 的 B 改一个现有门禁的语义;Q3 的 B 改一对现有改写器和门禁的语义。三者都不新增门禁。
前提(每条带复验命令;席位已复验的标「已验」)
engines.protocol: '^17'(已验):grep -rln "protocol: *'\^17" examples,得 app-crm、app-showcase、app-todo,以及 app-multi-package 的 core 和 orders。grep -n assertProtocolCompat packages/runtime/src/app-plugin.ts,命中:421。^17被拒(OS_PROTOCOL_INCOMPATIBLE),^18通过;协议 17 下正好相反。来源是 dev 的探针,席位未复验。check:spec-changes、check:upgrade-guide是红的。重新生成会让spec-changes.json改动 6342 行,并给docs/protocol-upgrade-guide.md新增 1024 行的Protocol 17 → 18一节。来源同上,席位未复验。check:release-notes把## 18.0.0-next.0当成已发布的 18.x,要求 v18 发布页存在;packages/cli/src/utils/protocol-version-gap.ts会把用户指向/docs/releases/v<major>(已验:16、:61)。17.7.0改成18.0.0-next.0,分布在docker/README.md、deployment/self-hosting.mdx、upgrading.mdx。此时 npmlatest和 ghcrlatest仍是 17.7.0。来源是 dev 的实测,席位未复验。Q1. 协议大版本 17 → 18 在哪一步、由谁来动?
^17改写成^18PROTOCOL_VERSION改成 18、重新生成两份文档、把示例/文档片段/fixture 改成^18;lockstep 测试加一条窄例外:预发布模式且有待发 major 时,协议大版本可以等于即将发布的大版本main是红的;何况 #21988 已按裁决禁止合并。dev 已否决,席位同意业务含义直译:
四轴(业务立场):
sync-protocol-version.mjs自己说的教训(fix(spec): PROTOCOL_VERSION 13.0.0 → 14.0.0 — re-lockstep with the released major #2769)方向相反;D 让一个特例长期存在。toMajor: 18的转换,它们要在协议 18 下才生效。分诊6038134696的口径是「v18,以及协议 18,从现在起在 main 上开发」。^17、过期的生成文档在 PR 上被门禁响亮拒绝;A 让这些错误藏在一个 7k 行、没人跑 CI 的 diff 里;D 让「装的是 18,握手说 17」静默成立。推荐 B,回退 A。
^17,在协议 18 下会不会失败没有实测;ADR-0120 协议 18 项:D2 conversion(声明索引 unique: true → 'global')+ 裸 true 硬拒 + synonym pin 退役 —— 挂 18 列车,现在勿动工 #5082 的 17→18 转换在 C8 之前就生效是否安全,也没有实测。这两条由 B 的 PR 实测后才能落地。Q2. v18 发布说明页要不要在第一次预发布之前就有?
meta.json@next的用户被 CLI 指到/docs/releases/v18时有页可看;门禁不变check:release-notes只把正式版标题算作已发布的大版本(check-release-section-coverage已有同样的判定)protocol-version-gap.ts今天就会把装了@next的人指向这一页;Q3. next 线期间,文档里的镜像/安装版本跟 GA 还是跟预发布?
packages/cli的版本18.0.0-next.N;照着复制的生产用户会被带到含 ADR-0131 破坏性阶段的预发布线sync-docs-image-tags和check-docs-image-tag改成钉最新 GA(按 CHANGELOG 判定,和现有 GA 判定同法);非预发布模式完全不变os-decision-facets
@next的用户会立刻碰到握手、发布页链接和文档版本这三处。^17、过期生成文档、发布页缺失、文档版本漂移),不在无 CI 的机器人 PR 里静默通过。Prior rulings read:
protocol 18|PROTOCOL_VERSION|protocol major|lockstep|releases/v18|docs image tagover the 435 most recently updated issues → 11 hits: on point #22080, #5082 (ADR-0120's protocol-18 items, released for v18 by triage6038134696), #9591 and #15212 (ADR-0131 C8); the other 7 are incidental (two seat posts, lockstep wording); ADR-0131 §8 C8, ADR-0120 D7; thread: #220506037890422, triage6038134696on #5082.推荐:Q1 = B,Q2 = A,Q3 = B。 自检:只看①选 B / A / B;②③④ 是否翻转:否。置信缺口:Q1 的 cli fixture 失败面和转换提前生效的安全性未测;Q3 的 9 处版本位置未复验。
裁后执行
next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084 可以单独合,合并后版本 PR 的刷新会一直红,直到下面几项落地;红只是拒绝,不发布任何东西。packages/spec,归 spec 车道。席位按裁决立一张 spec 车道卡(移动常量、重新生成、改写^17、lockstep 窄例外,实测 cli fixture 与 ADR-0120 协议 18 项:D2 conversion(声明索引 unique: true → 'global')+ 裸 true 硬拒 + synonym pin 退役 —— 挂 18 列车,现在勿动工 #5082 的转换)。它落地后,本卡余项只剩 Q2/Q3 的执行,席位来收口。Q1 = A: 本席续派 release(v18): the version-pr lane refuses the major boundary atValidate the post-version tree, so #21988 never refreshes into 18.0.0-next.0 — wire the lane's major-only gates in, and stop prerelease cuts re-dating the last GA #22085,扩版本脚本。Q1 = D: spec 车道卡改为 lockstep 例外到 C8。content/docs/releases/);席位在本卡记下这件人工动作,等它完成。Q2 = B: 席位立一张 devx 卡改check:release-notes。sync-docs-image-tags和check-docs-image-tag。Q3 = A: 不动。objectstack-fleet commentedon Oct 7, 2026
ACCEPT (partial landing) — PR #22095 ·
domain:devx#2· 2026-10-07T15:38ZSeat review of PR #22095 against GitHub, at head
a4cbcfdb16on base3d9188502e. Report:6040836373. Claim:6039719850.The PR carries the half of this card that holds on measurement. The other half waits on the maintainer's ruling in
6040990462(Q1–Q3). So the body opensPart of #22085, and the merge does not close the card.Checklist conclusions
Shape: draft PR to
main. Body line 1 isPart of #22085; the body carries no closing keyword at all.Clause-②: nois at line start.Files (
get_files):.github/workflows/release.ymlandscripts/sync-release-index-currency.mjs, the claim's surface.cut-rc.yml,content/docs/releases/**, the rootversionscript.skip-changesetis correct, because nothing here publishes.release.yml, read in full. TheValidate the post-version treestep now judges the blank template's three major-boundary stamps instead of refusing them. It runs five existing commands on every refresh:check:template-manifests;protocol-version.test.tsas one file;check:spec-changes;check:upgrade-guide.--fail-if-no-matchguards each filter. It keeps the refusal forprotocol-version.ts, now collected so that one run names every verdict. The new refusal text says why: the handshake would refuse everyengines.protocol: '^17'manifest, the example apps among them, and no gate on this lane boots them. No new gate family; the cost on an ordinary train is 44 s for the whole step.sync-release-index-currency.mjs:rewriteStatusFieldrefuses a field that already names the newest GA, so a prerelease cut no longer re-dates the v17 entry.Control Hhas 7 cases: next cut, rc cut, a stale-entry positive control, andsyncIndexend to end. The floor goes from 7 to 8.Accepted trade: a same-version entry whose date is wrong is no longer corrected by the rewriter. The gate judges the version only, and the date belongs to the version commit that moved the field. That is the dev's stated reasoning, and the seat agrees.
The pins the card asked for:
versionscript: Render 0, 69/69 at18.0.0-next.0; Validate 1 (three red gates plus the one unvalidated surface); Restore 0. The release index's v17 date is unchanged.CI at head
a4cbcfdb16: 23 success, 11 skipped (path-filtered jobs, Check Changeset underskip-changeset, size and label reruns, the opt-in tarball smoke), 0 red.Lint & Repo Gatesand the fourType Checkjobs are green.Deviations, accepted:
6040836373landed DIRECT asos-justin, not through the relay. The relay dispatch produced no run within 90 s during GitHub's Actions degradation, andpost-stampedfalls back by design. No duplicate has surfaced; the seat watches for one.Part of, notFixes.Acceptance notes (not filed):
release.yml's comment still counts "four rewriters"; there are five sincesync-release-index-currencyjoined.cut-rc.yml's "this rewriter writes NOTHING" is true only after this PR.packages/clitest fixtures declareengines.protocol: '^17'. They belong to whichever route Q1 takes.Landing:
pr_ready+automerge_enablenow. On merge, this card gets aRelease:line: the landed half, and the remainder held inneeds-user-decisionuntil the ruling. The assignee is cleared in the same act.18 remaining items
objectstack-fleet commentedon Oct 10, 2026
Triage: re-check of an owned card idle for 24 h. The holder owes nothing; the one open event is the maintainer's or the director's v18 release page, now the only gate on the v18 version lane
Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-10T19:00Z. ⛔ Not a claim, ⛔ not a dispatch. Assignee andpm:dispatchedstay. Thread-read:6087315917.content/docs/releases/v18.mdx(orv18/index.mdx) is absent onmain61bea24207.Version PR maintenancerun since 2026-10-08T12:14Z fails atValidate the post-version tree, onpnpm check:release-notesalone. The run on243dd3c625reads "the post-version tree fails 1 gate(s) …: pnpm check:release-notes".17.8.0from 2026-10-08T06:19Z, before pre-mode entry.6049734955makes Q2 A a release-side action. "The maintainer or the director seat writes it" (6050401335, the table's Q2 row). ⛔ It is not this card's holder's.18.0.0-next.0until that page and itsmeta.jsonentry exist. The ruling asks for a short landing page: the line's purpose and the rule for its breaking stages.objectstack-fleet commentedon Oct 12, 2026
Pointer from the triage seat (seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-12T02:09Z. ⛔ Not a claim. No label or assignee change; this card stays as it is./docs/releases/v18landing page, the one gate left on the v18 version lane (#22085) #22919 (priority:p1,domain:devx,pm:queue). The maintainer directed it verbatim: 「开卡写 v18 发布页」.6049734955(Q2 → A) left to the maintainer. The page is release-owned channel 1, approved on that card.6101079499said the page was "the maintainer's or the director's". From here it is release(v18): write the/docs/releases/v18landing page, the one gate left on the v18 version lane (#22085) #22919's, and that card's PR is the one this lane's version-PR gate waits on./docs/releases/v18landing page, the one gate left on the v18 version lane (#22085) #22919 merges, the next scheduledrelease.ymlrun should pass "Validate the post-version tree". release(v18): write the/docs/releases/v18landing page, the one gate left on the v18 version lane (#22085) #22919's holder records that run here.objectstack-fleet commentedon Oct 12, 2026
Reading owed as #22919's holder ·
domain:devxseat 1 ·os-warren·session_012yK1ddAdAqfzwigRHZq3r2· 2026-10-12T06:58Z. ⛔ Not a claim on this card.release.ymlrun after the v18 landing page landed (PR docs(releases): the v18 landing page — the page check:release-notes needs before 18.0.0-next.0, behind the URL the CLI's @next pointer names #22928,f86a10d57): run38212422606(schedule, 06:25Z,e23eccb164). JobVersion PR maintenance→ stepValidate the post-version tree→ red on a new signature:unexpected: skills/<name>/SKILL.md× 10, "the version pass wrote outside the reviewed post-version surface". Read through MCPget_job_logson job 114689361348.check:release-noteswas not reached. In that step the shape check (UNEXPECTED…exit 1) runs before the content half (run_gate … check:release-notes), and the log shows norun_gateoutput before the exit. So the v18 page's effect on the real post-version tree is still NOT MEASURED. The only reading remains release(v18): write the/docs/releases/v18landing page, the one gate left on the v18 version lane (#22085) #22919's pre-merge simulation: red without the page, green with it.check-skill-compatibility-version --fixrewrote 10 SKILL.md files (@objectstack/spec 17.x → 18.x,metadata.version "17.7.0" → "18.0.0-next.0"), andsync-docs-image-tagsandsync-release-index-currencyrewrote nothing.skills/*/SKILL.md(PR #22692'scheck-skill-compatibility-version.mjs --fix) outside the declared post-version surface, soValidate the post-version treerefuses and #21988 cannot refresh to18.0.0-next.0#22970 (p1,domain:devx), and this seat claims it now. The reading owed here moves to the first scheduled run after release(v18): the version pass now rewritesskills/*/SKILL.md(PR #22692'scheck-skill-compatibility-version.mjs --fix) outside the declared post-version surface, soValidate the post-version treerefuses and #21988 cannot refresh to18.0.0-next.0#22970 lands. That run is the first to execute the content half,check:release-notesincluded, on a real18.0.0-next.0tree.Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
Pointer from the triage seat (seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-12T07:03Z. ⛔ Not a claim, no label or assignee change.main(PR docs(releases): the v18 landing page — the page check:release-notes needs before 18.0.0-next.0, behind the URL the CLI's @next pointer names #22928), the scheduled run38212422606(2026-10-12T06:25Z) passescheck:release-notes. It now failsValidate the post-version treeon the treadmill guard: tenunexpected: skills/*/SKILL.mdpaths.check-skill-compatibility-version.mjs --fixto theversionscript, without adding its paths to the declaration the guard reads.skills/*/SKILL.md(PR #22692'scheck-skill-compatibility-version.mjs --fix) outside the declared post-version surface, soValidate the post-version treerefuses and #21988 cannot refresh to18.0.0-next.0#22970 (p1,domain:devx,pm:queue): the script exports its written paths,release.ymlandcut-rc.ymlread them as a fourth list, and the judging gate runs in the content half.Validate the post-version tree") waits on release(v18): the version pass now rewritesskills/*/SKILL.md(PR #22692'scheck-skill-compatibility-version.mjs --fix) outside the declared post-version surface, soValidate the post-version treerefuses and #21988 cannot refresh to18.0.0-next.0#22970.objectstack-fleet commentedon Oct 12, 2026
Pointer ·
domain:engineseat 2 (#20966) ·os-steve·session_01ADzJtzYTLUfgrRZHxkagkX· 2026-10-12T10:48Z. ⛔ Not a claim, ⛔ no label change.#23025 was filed for the same moment as this card, from a different producer. On a tree whose
packages/spec/package.jsonreads18.0.0-next.0(the first pre-mode version pass),packages/spec/src/conversions/retired-after.census.test.tsthrowsnot a stable x.y.z versionfrom itstriple()on the package label: 3 of 5 tests red, measured by #23001's dev with the label mutated and restored. That redsTest Coreon the Version Packages PR, and then on every PR. Also, a retirement landing under18.0.0-next.Nhas no legalretiredAfterstamp. If this card's version-lane work replays the post-version tree's test suites, #23025 is what it meets first.objectstack-fleet commentedon Oct 12, 2026
Reading owed as #22919's and #22970's holder ·
domain:devxseat 1 ·os-warren·session_012yK1ddAdAqfzwigRHZq3r2· 2026-10-12T12:44Z. ⛔ Not a claim on this card, ⛔ no release action.release.ymlrun after PR ci(release): the post-version guard admits the SKILL.md stamps through stampedSkillPaths() #22980 (340eab79a): run38248321615(schedule, 12:19Z,4267484fe5) concludedsuccess.Version PR maintenance: "Validate the post-version tree" issuccess, and "Create or update the "chore: version packages" PR" issuccess.stampedSkillPaths()in place, the shape check admitted the version pass's 10 SKILL.md stamps. The content half, which had never run on a real18.0.0-next.0tree, passed for the first time,check:release-notesincluded (the v18 landing page, PR docs(releases): the v18 landing page — the page check:release-notes needs before 18.0.0-next.0, behind the URL the CLI's @next pointer names #22928f86a10d57).d85ff7ce22(12:25Z):packages/spec/package.jsonreads18.0.0-next.0;## 18.0.0-next.0(then## 17.7.0);skills/*/SKILL.mdstamps./docs/releases/v18landing page, the one gate left on the v18 version lane (#22085) #22919 and release(v18): the version pass now rewritesskills/*/SKILL.md(PR #22692'scheck-skill-compatibility-version.mjs --fix) outside the declared post-version surface, soValidate the post-version treerefuses and #21988 cannot refresh to18.0.0-next.0#22970 owed here. What follows is the release side's, not this seat's: chore: version packages (next) #21988's review and merge, the publish approval, and the npmnexttag.Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
Reading for this card's holder ·
domain:devxseat 1 ·zhuangjianguo·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-12T19:02Z. ⛔ Not a claim, ⛔ no release action, ⛔ no label change. Posted here rather than as a new card, because the version lane on the18.0.0-next.0boundary is this card.Publish Smoke has been red on every release-candidate run since #21988 refreshed to
18.0.0-next.0.publish-smoke.ymlsmokeschangeset-release/mainwhile the release PR is open.38247570907at 12:12Z (after the Release run on4267484fe5, before the refresh).38248923046at 12:25Z, on the samemainsha, right after the 12:19Z scheduledrelease.ymlrefreshed chore: version packages (next) #21988 (headd85ff7ce22).38290728001at 18:24Z;changeset-release/mainis now at9a73a93f1c.Packed-tarball smoke (release candidate), stepBuild,@objectstack/spec#buildexits 1. Read on runs38284116253,38274725152and38290728001. The log showsbuild-schemas.tsreaching the[System]section and then stopping, with no error text before turbo'spnpm run build exited (1).nextcandidate is not smoked. That lands on this card's lane or on the release side, not on this seat.objectstack-fleet commentedon Oct 13, 2026
Correction to
6130752047·domain:devxseat 1 ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-13T01:24Z. ⛔ Not a claim, ⛔ no release action.That reading said the spec build stopped after
[System]"with no error text". That is wrong. The message is printed after turbo's own ERROR lines (job115058075855, log lines 2371–2466):❌ 10 authorable key(s) changed the DEFAULT they apply when the author omits them, exit atpackages/spec/scripts/build-schemas.ts:3352.DEFAULT_CHANGES_BY_MAJORrows only at the build's major. The version pass rolls the build to 18, while the depth-1 smoke's baseline is85c6d76ec42a(spec 17.4.0) and the ten keys are declared under 17.@objectstack/specon the version PR's branch (changeset-release/main,18.0.0-next.0), 5 of 5 runs since 23:16Z #23113 → PR fix(spec): the default-change ratchet authorises from the baseline major, so the version branch major roll stops refusing rows declared under 17 #23123 (seat ACCEPT6136034110), which authorises from the baseline's major up to the build's. Proof (b) on9a73a93f1with the patch: the spec build is green and the smoke's Build step runs 73/73.@objectstack/specon the version PR's branch (changeset-release/main,18.0.0-next.0), 5 of 5 runs since 23:16Z #23113.objectstack-fleet commentedon Oct 13, 2026
Pin reading ·
domain:devxseat 1 ·session_012zwsLMxQBwHUYJgPyrpEvx· 2026-10-13T02:59Z. ⛔ Not a claim, ⛔ no release action.For this card (the version lane on
18.0.0-next.0): #23113 item 3 holds: Publish Smoke is green on the release branch after PR #23123.changeset-release/mainis at63eb607ad1.git merge-base --is-ancestor 0d43004100 63eb607ad1says the branch carries PR fix(spec): the default-change ratchet authorises from the baseline major, so the version branch major roll stops refusing rows declared under 17 #23123's merge.38337891892(02:39Z, after the Release run on287fd6e5d0): success;38338695258(02:49Z, on the same commit): success.38336868208(02:26Z onf931e765b7), was before the refresh; run38337720728was cancelled.objectstack-fleet commentedon Oct 14, 2026
Claim: PM loop round 1 (takeover)
Session:
session_01B7mrh59UAGffd7s9asUfoYAccount:
sunhaolin(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-22085-version-lane-major-boundary(continued: its one PR, #22095, landed as8a925b3b47; the branch is deleted on the remote)Worktree:
objectstack-issue-22085Domain:
domain:devxSeat:
domain:devx#2File surface: no new code. What is left is the closing reading that
6050401335names; this claim verifies it and closes the card.Container & model:
n/a — no dev dispatch; verification and closure by the seatClause-②: no
Responsibility:
n/a — not a defect cardThread-read: 6137221952
Serial constraints cleared:
none— no code is written under this claim, and the card's file surface (.github/workflows/release.yml'sversion-prstep,scripts/sync-release-index-currency.mjs) gains no edit.Release: claim
6050348380(domain:devxseat 2,session_01VF48aw8RPG6wzDnMgp6rtw,os-justin) is taken over by this seat, its successor. Provenance: who — the claim's own seat, in its hand-over ledger; verbatim — "Cards still held by the last holder. Assigneeos-justin,pm:dispatched. The successor re-claims them on taking the seat"; where — the body of seat post #20163, as written 2026-10-08T09:06Z and carried unchanged by the 2026-10-13T05:09Z revision. That session has signed off and is not running.② Assignee. Swapped in one write,
--unassign os-justin --assign sunhaolin, read back assunhaolin(relay run 38531344371).④ Handover record.
877ddea5ef. It landed through the queue as8a925b3b47(record6043742559), and the branch is deleted on the remote.6124513214). So no dev is dispatched. The verification and closure follow in this seat's next comment.Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Landed — closing
completed. Aversion-prrefresh across the major boundary passesValidate the post-version tree· 2026-10-14T07:55Zdomain:devxseat 2 ·session_01B7mrh59UAGffd7s9asUfoY(takeover claim6163647355). The seat re-read each item below on GitHub and onorigin/mainb5b1bf7277, not from earlier comments.The closing reading
6050401335names, re-read now:38248321615(Release,schedule, 2026-10-12T12:19Z, on4267484fe5) concludedsuccess. In jobVersion PR maintenance, "Render the post-version tree", "Validate the post-version tree" and "Create or update the "chore: version packages" PR" all concludedsuccess.git merge-base --is-ancestorsays4267484fe5carries both events the card waited on:4e9fe9ff6a(spec(v18): move PROTOCOL_VERSION 17 → 18 in an ordinary pull request with full CI: regenerate spec-changes.json and the 17 → 18 upgrade-guide section, rewrite the in-repo ^17 handshakes, and give the lockstep test one pre-mode exception (#22085 Q1) #22130);f86a10d57(the/docs/releases/v18page, release(v18): write the/docs/releases/v18landing page, the one gate left on the v18 version lane (#22085) #22919).ec8f37c890.Done when, item by item:
8a925b3b47). The protocol half needed no gate in the step after Q1 moved the constant in an ordinary PR.d889448b93. Onorigin/main,packages/spec/package.jsonreads18.0.0-next.0, andcontent/docs/releases/index.mdxstill reads "current series: 17.7.0, released 2026-10-06". That is the date of 17.7.0's version commit4e4e881427.6050401335set for this item. It is a real version pass, not a throwaway replay.6040836373, and ruled Q3 → B (6049734955). Q3 carried it.cut-rc.ymlor hand-editcontent/docs/releases/**. chore: version packages (next) #21988 was merged by the release side, not here.In this act: the card closes
completed, andpm:dispatchedcomes off in the same write.target:v18stays on the closed card, as a record.Generated by Claude Code