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
Activity
objectstack-fleet commented on Oct 7, 2026
Claim: PM loop round 7
Session: session_01VF48aw8RPG6wzDnMgp6rtw
Account: os-justin (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-22085-version-lane-major-boundary (new, cut from origin/main 3d9188502e)
Worktree: objectstack-issue-22085
Domain: domain:devx (inherited from #22080, in-flight derivative)
Seat: domain:devx#2
File surface: .github/workflows/release.yml (the version-pr job's Validate the post-version tree step), scripts/sync-release-index-currency.mjs and its battery, and any existing gate script the step newly calls (read-only unless its own battery needs a case).
- ⛔ No edit to
cut-rc.yml. ⛔ No hand edit ofcontent/docs/releases/**. ⛔ No publish, tag orworkflow_dispatchof a release workflow. ⛔ chore: version packages #21988 is not touched. - Stop on a breach and explain it in the report.
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 on
Thread-read: none
Serial constraints cleared: the only open PR touching this surface's neighbourhood is chore: version packages #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-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-line Protocol 17 → 18 section 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.0 counts 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 printed v17: (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 battery Control 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 at released 2026-10-06 (git diff empty), and the GA control train still stamps 17.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/objectstack at 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; battery pnpm check:pm-dispatch-gates exit 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; restored blob == 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's Fixes #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/m on #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 version script 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.0 counts 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\" PR says pnpm run version is 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 commented on 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 预发布模式合并后,第一个预发布版还切不出来,卡在三件事:
- 协议版本 17→18 在哪一步改:推荐先走一个跑全套 CI 的普通 PR;
- v18 发布说明页要不要先写:推荐先写一页短的;
- 预发布期间文档里的版本号跟哪个:推荐跟正式版。
回复一行即可,例如「Q1 B / Q2 A / Q3 B」。
一句话问题: #22084 进入预发布模式后,发版通道第一次切版本会把协议版本从 17 跳到 18。可仓库里的示例应用、两份生成文档、v18 发布说明页和自托管文档的镜像版本都还停在 17。而这次切版本走的是一个不跑 CI 的机器人 PR。所以 18.0.0-next.0 现在切不出来,切出来也会带着不一致出门。需要你定三件事。
背景
- 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 → PR chore(release): enter Changesets pre mode (next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084: 只加.changeset/pre.json和一个major标记,等你合并。 - 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 → 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 不依赖本次裁决,席位复核通过后就落地。 - 实测(dev 报告
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; - 校验一步:退出码 1。
check:spec-changes、check:upgrade-guide、check:release-notes三个门禁红,另有protocol-version.ts未校验; - 对照:同一分支的普通 17.8.0 列车 14 个门禁全绿。
- 完整
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 的大版本。- ADR-0131 §8 表 C8 行:"… both arms and the ledger retired — protocol 18"。ADR-0120 D7:"the 17.x → protocol 18 staging"。
- decision: open v18 now and ship it in stages — release the last 17.x from main first without waiting for #21908's deny (A), skip the last 17.x (B), or keep #22009's order (C)? #22050 裁决
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."- 本技能红线:⛔ 代码 PR 不改
content/docs/releases/(发布说明页归发布侧)。
是否改协议: Q1 的 B 要修改上面那条 lockstep 不变量(预发布模式下的一个窄例外);Q2 的 B 改一个现有门禁的语义;Q3 的 B 改一对现有改写器和门禁的语义。三者都不新增门禁。
前提(每条带复验命令;席位已复验的标「已验」)
- 仓库内 5 个示例包声明
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。 - 协议 18 下
^17被拒(OS_PROTOCOL_INCOMPATIBLE),^18通过;协议 17 下正好相反。来源是 dev 的探针,席位未复验。 - boundary 树上
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)。- 第一次预发布会把 9 处文档镜像/安装版本从
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 在哪一步、由谁来动?
| 选项 | 做什么 | 客户/团队能感知到的后果 |
|---|---|---|
| A. 版本时机械改 | 版本脚本在改协议常量时,顺带重新生成两份文档,并把仓库里的 ^17 改写成 ^18 |
一个约 7.4k 行、不跑 CI 的机器人 PR,同时打开握手翻转和 17→18 迁移转换;示例应用能不能启动,没有人在合并前验证 |
| B. 先走一个普通 PR | 一个跑全套 CI 的 PR 把 PROTOCOL_VERSION 改成 18、重新生成两份文档、把示例/文档片段/fixture 改成 ^18;lockstep 测试加一条窄例外:预发布模式且有待发 major 时,协议大版本可以等于即将发布的大版本 |
翻转在评审过、Dogfood 和 Test Core 都跑过的 diff 里发生;之后切版本时协议常量已是 18,发版通道只剩模板那一半(#22095 已覆盖) |
| D. 协议保持 17 到 C8 | lockstep 在整个预发布期允许协议落后于 spec 大版本,直到 ADR-0131 C8 落地再翻 | 18.0.0-next.N 的握手仍报 17,装了预发布版的人拿不到「这是破坏性版本」的握手信号;特例要维持几个月 |
| C. 先合版本 PR 再手修 | — | 两次合并之间 main 是红的;何况 #21988 已按裁决禁止合并。dev 已否决,席位同意 |
业务含义直译:
- A ≈ 让自动打包机顺手改产品的兼容规则,没人验货就出门。
- B ≈ 兼容规则的变更先走正常评审和质检,打包机只管贴版本号。
- D ≈ 新版本先挂旧的兼容标签,等最后一个阶段再换。
四轴(业务立场):
- ① 项目长远合理性: 两年后的样子应该是:发版通道只渲染版本号,协议大版本的移动永远是一次评审过的 ADR-0087 事件。参照 Kubernetes 的 API 版本、Node 的 N-API 版本:变更都在代码 PR 里完成,发布工具只打标签。B 正是这个形状;A 把规则变更塞进不受 CI 的机器人 PR,和
sync-protocol-version.mjs自己说的教训(fix(spec): PROTOCOL_VERSION 13.0.0 → 14.0.0 — re-lockstep with the released major #2769)方向相反;D 让一个特例长期存在。 - ② 实际业务拉动: 今天就撞上。v18 已开(decision: open v18 now and ship it in stages — release the last 17.x from main first without waiting for #21908's deny (A), skip the last 17.x (B), or keep #22009's order (C)? #22050),spec 车道的 ADR-0120 协议 18 项:D2 conversion(声明索引 unique: true → 'global')+ 裸 true 硬拒 + synonym pin 退役 —— 挂 18 列车,现在勿动工 #5082 正在做
toMajor: 18的转换,它们要在协议 18 下才生效。分诊6038134696的口径是「v18,以及协议 18,从现在起在 main 上开发」。 - ③ 防 AI 犯错: B 让漏改的
^17、过期的生成文档在 PR 上被门禁响亮拒绝;A 让这些错误藏在一个 7k 行、没人跑 CI 的 diff 里;D 让「装的是 18,握手说 17」静默成立。 - ④ 创业阶段不扩散: B 只改一个测试和一个同步条件,不加门禁、不加改写器;A 让版本链多出 3 个输出;D 背一个要维持几个月的特例。
推荐 B,回退 A。
- 自检:只看①选 B;②③④ 是否翻转:否。
- 置信缺口:约 40 个 cli 测试 fixture 声明
^17,在协议 18 下会不会失败没有实测;ADR-0120 协议 18 项:D2 conversion(声明索引 unique: true → 'global')+ 裸 true 硬拒 + synonym pin 退役 —— 挂 18 列车,现在勿动工 #5082 的 17→18 转换在 C8 之前就生效是否安全,也没有实测。这两条由 B 的 PR 实测后才能落地。
Q2. v18 发布说明页要不要在第一次预发布之前就有?
| 选项 | 做什么 | 后果 |
|---|---|---|
| A. 先写页 | 由发布侧(你或总监席,发布页归发布侧所有)写一页短的 v18 落地页:这条线的目的 + 破坏性阶段的规则,并登记进 meta.json |
装 @next 的用户被 CLI 指到 /docs/releases/v18 时有页可看;门禁不变 |
| B. 门禁只认 GA | check:release-notes 只把正式版标题算作已发布的大版本(check-release-section-coverage 已有同样的判定) |
v18 页推到 18.0 GA 再写;整个 next 线期间,CLI 的提示链接会 404 |
- 业务含义: A ≈ 新产品线开张先挂门牌;B ≈ 正式开业前不挂牌,有人按地址找来只看到空地。
- 四轴:
- ①:A 保持「每个对外大版本都有页」的不变量,B 给门禁开一个口子;
- ②:
protocol-version-gap.ts今天就会把装了@next的人指向这一页; - ③:A 门禁不放宽;
- ④:A 只是一页短文档,B 改门禁语义。
- 推荐 A,回退 B。 自检:只看①选 A;②③④ 是否翻转:否。置信缺口:页的内容由发布侧定,席位不起草。
Q3. next 线期间,文档里的镜像/安装版本跟 GA 还是跟预发布?
| 选项 | 做什么 | 后果 |
|---|---|---|
| A. 跟预发布 | 不改,文档版本跟随 packages/cli 的版本 |
整个 next 线期间,自托管和升级文档都写 18.0.0-next.N;照着复制的生产用户会被带到含 ADR-0131 破坏性阶段的预发布线 |
| B. 跟 GA | 预发布模式下 sync-docs-image-tags 和 check-docs-image-tag 改成钉最新 GA(按 CHANGELOG 判定,和现有 GA 判定同法);非预发布模式完全不变 |
文档始终指向默认安装能拿到的版本 |
- 业务含义: A ≈ 店里的价目表写的是试营业菜单;B ≈ 价目表只写正式菜单,试营业另行告知。
- 四轴:
- ①:这对改写器和门禁真正的不变量是「文档版本 = 默认安装拿到的版本」,只有在非预发布模式下它才等于 cli 版本;
- ②:自托管用户会照文档复制版本,17.2 → 17.3 的升级演练就是只看已发布文档跑的;
- ③:门禁仍是相等判断,只是比较对象由计算得出;
- ④:不加门禁,只改一对现有改写器和门禁的语义。
- 推荐 B,回退 A。 自检:只看①选 B;②③④ 是否翻转:否。置信缺口:9 处版本的位置是 dev 的实测,席位未复验。
os-decision-facets
- ① 长远合理性:发版通道只渲染版本号,协议/门禁/文档语义的变化都走评审过的 PR(Q1 B、Q2 A、Q3 B),特例收窄而不是扩散。
- ② 实际业务拉动:v18 今天已开,ADR-0120 协议 18 项:D2 conversion(声明索引 unique: true → 'global')+ 裸 true 硬拒 + synonym pin 退役 —— 挂 18 列车,现在勿动工 #5082 的协议 18 转换在飞,装
@next的用户会立刻碰到握手、发布页链接和文档版本这三处。 - ③ 防 AI 犯错:三处错误都改成在 CI 上响亮失败(示例
^17、过期生成文档、发布页缺失、文档版本漂移),不在无 CI 的机器人 PR 里静默通过。 - ④ 创业阶段不扩散:不新增门禁、不新增版本时改写器;只改一个 lockstep 条件、一对改写器和门禁的判定、写一页短文档。
Prior rulings read: protocol 18|PROTOCOL_VERSION|protocol major|lockstep|releases/v18|docs image tag over the 435 most recently updated issues → 11 hits: on point #22080, #5082 (ADR-0120's protocol-18 items, released for v18 by triage 6038134696), #9591 and #15212 (ADR-0131 C8); the other 7 are incidental (two seat posts, lockstep wording); ADR-0131 §8 C8, ADR-0120 D7; thread: #22050 6037890422, triage 6038134696 on #5082.
推荐:Q1 = B,Q2 = A,Q3 = B。 自检:只看①选 B / A / B;②③④ 是否翻转:否。置信缺口:Q1 的 cli fixture 失败面和转换提前生效的安全性未测;Q3 的 9 处版本位置未复验。
裁后执行
- 不论怎么裁: PR fix(release): judge the major-boundary template stamps on the version-pr lane, and stop prerelease cuts re-dating the last GA #22095 先落地(模板校验 + 发布日期修复)。chore: version packages #21988 继续不合。chore(release): enter Changesets pre mode (
next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084 可以单独合,合并后版本 PR 的刷新会一直红,直到下面几项落地;红只是拒绝,不发布任何东西。 - Q1 = B: 协议常量在
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。 - Q2 = A: 发布页由你或总监席写(席位不碰
content/docs/releases/);席位在本卡记下这件人工动作,等它完成。Q2 = B: 席位立一张 devx 卡改check:release-notes。 - Q3 = B: 席位立一张 devx 卡改
sync-docs-image-tags和check-docs-image-tag。Q3 = A: 不动。 - 回复格式: 一行,例如「Q1 B / Q2 A / Q3 B」,可带附加条件。
objectstack-fleet commented on Oct 7, 2026
ACCEPT (partial landing) — PR #22095 · domain:devx#2 · 2026-10-07T15:38Z
Seat review of PR #22095 against GitHub, at head a4cbcfdb16 on base 3d9188502e. 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 opens Part 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.- ⛔ Not touched:
cut-rc.yml,content/docs/releases/**, the rootversionscript. - Not governed, 195 changed lines.
skip-changesetis correct, because nothing here publishes.
- ⛔ Not touched:
-
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:- create-objectstack's suite;
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.- Battery B4 is inverted, with its reason in the assertion text.
- New battery
Control Hhas 7 cases: next cut, rc cut, a stale-entry positive control, andsyncIndexend to end. The floor goes from 7 to 8. - Ablation: putting the old logic back reds B4 and H's four non-control cases; restored by blob hash.
-
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:
- Boundary train, replayed with the full root
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. - Ordinary 17.8.0 control train: Validate 0, 14/14 green.
- Done-when 1 and 3 are therefore NOT met. Their premise, that existing gates would pass the boundary tree, is falsified by that replay; this is the input to the decision, not a gap in this PR.
- Boundary train, replayed with the full root
-
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:
- The report comment
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.- About 40
packages/clitest fixtures declareengines.protocol: '^17'. They belong to whichever route Q1 takes.
Landing: pr_ready + automerge_enable now. On merge, this card gets a Release: line: the landed half, and the remainder held in needs-user-decision until the ruling. The assignee is cleared in the same act.
objectstack-fleet commented on Oct 7, 2026
os-dev-report
{
"issue": 22085,
"addendum": "patch round: merge origin/main so a new head re-runs Lint and creates the missing required TypeScript Type Check context",
"status": "needs_decision",
"branch": "claude/issue-22085-version-lane-major-boundary",
"pr": "#22095",
"session": "session_01VF48aw8RPG6wzDnMgp6rtw (subagent: the dispatching PM's session)",
"previous_head": "a4cbcfdb16",
"new_head": "877ddea5ef",
"merge": "877ddea5ef = merge commit, parents a4cbcfd (branch) and bafb58b (origin/main: b04a529 #22086 ci.yml/lint.yml, bafb58b #22089 cli). No rebase, no force; the push was a fast-forward a4cbcfd..877ddea. No conflict. main's merge-base delta 3d91885..bafb58b touches neither release.yml nor scripts/sync-release-index-currency.mjs, and both files are byte-identical to a4cbcfd (git diff a4cbcfd HEAD over the two paths is empty). The PR's three-dot diff is still exactly those 2 files.",
"tests": "Run at 877ddea after pnpm install. Exit codes were written to disk before any pipe: node scripts/sync-release-index-currency.mjs --self-test :: exit 0; pnpm check:workflow-step-name-quoting :: exit 0; pnpm check:workflow-status-functions :: exit 0; node scripts/check-self-test-workflow-commands.mjs :: exit 0; node scripts/check-self-test-workflow-commands.mjs --self-test :: exit 0. Verdict lines: OK self-test: 42 cases pass; check-workflow-step-name-quoting: OK (scanned 39 workflow file(s) + 2 composite action file(s), 742 step name(s)); check-workflow-status-functions: OK (scanned 39 workflow file(s), 65 job(s)); check-self-test-workflow-commands: no self-test CI runs prints a line the Actions runner would parse as a workflow command (231 scripts).",
"unchanged": "Q1-Q3 (6040990462) and the ACCEPT (6041309804) are not touched. No other file was edited.",
"mcp_calls": "0",
"api_writes": "1 — this comment (POST /repos//issues/22085/comments via post-stamped). Plus 1 git push (not REST).",
"note": "The first report's relay dispatch fw-20261007T150427Z-017251 never produced a duplicate: as of this round the card carries one os-dev-report (6040836373)."
}
Generated by Claude Code
objectstack-fleet commented on Oct 7, 2026
Box intake (triage): the labels stand (priority:p1 · domain:devx · target:v18). This is the v18 opening's version-lane half, and release-priority. The decision is the seat's 6040990462 (Q1–Q3). It carries the four-facet block and Prior rulings read:, but it has no 「维护者速读」 heading. The seat adds one line of 维护者速读 in business language above Q1, so the director can present it as is. PR #22095 carries the measured half and needs no ruling. ⛔ #21988 stays unmerged until the version lane is ruled and #22084 lands.
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-07T16:17Z. ⛔ Not a claim.
objectstack-fleet commented on Oct 7, 2026
Landed (partial) — PR #22095 → 8a925b3b47 · domain:devx#2 · 2026-10-07T17:58Z
- Merged through the merge queue at 2026-10-07T17:57:37Z. The squash commit
8a925b3b47is onmain. - Verified on
mainby blob identity, both files equal to the PR head877ddea5ef:.github/workflows/release.yml=789eeddda4;scripts/sync-release-index-currency.mjs=28f5ee09dd.
- The queue-time patch round: during GitHub's Actions incident, Lint run
37641661459never created the requiredTypeScript Type Checkaggregate. A merge ofmain(877ddea5ef, addendum6041724501) re-ran it green. Both files were byte-unchanged. - The card stays open (
Part of #22085), inneeds-user-decision.
Release: claim 6039719850 (session_01VF48aw8RPG6wzDnMgp6rtw, os-justin) is released by its own holder at partial landing.
- Landed: Done-when 2 (a prerelease cut no longer re-dates the newest GA; battery H) and 4 (the docs image-tag move, measured in
6040836373). Also the template half of Done-when 1: the blank template's three major-boundary stamps are validated on theversion-prlane instead of refused. - Remainder, and where it goes: the protocol half of Done-when 1, and Done-when 3 (the boundary replay exiting 0). They wait on the maintainer's ruling
6040990462(Q1–Q3) and stay inneeds-user-decision. Once ruled, the execution follows that comment's 裁后执行 section: per the ruling, a spec-lane card (Q1 = B), a release-owned page (Q2 = A), and a devx card (Q3 = B). - The assignee is cleared in this act. ⛔ chore: version packages #21988 stays unmerged.
objectstack-fleet commented on Oct 8, 2026
Ruling: batch #286 item 1 · letters Q1 B · Q2 A · Q3 B · maintainer 「22082 22085 同意」 2026-10-08T00:37Z
Director seat, summon #35, session_01VYToj6PQehTEKNrjGM9akg (GitHub os-zhuang; written as objectstack-fleet[bot] via the relay). Batch #286 was presented in chat with the domain:devx#2 seat's three questions (6040990462) and their options; the maintainer answered 「22082 22085 同意」, which takes every recommendation. Freshness gate: the body and all seven comments (newest 6043742559, the partial landing of PR #22095 at 8a925b3b47, whose Release: line cleared the assignee) were re-read before this record; nothing newer exists. PR #22084 (pre mode plus one major marker) is still open, ready and green, waiting on the maintainer's merge; #21988 is unmerged. Thread-read: 6043742559.
The ruling
- Q1 → B. The protocol major moves in an ordinary pull request that runs the full CI, not in the version pass. That pull request sets
PROTOCOL_VERSIONto 18, regenerates the two generated documents (spec-changes.json, the protocol upgrade guide's 17 → 18 section), rewrites the in-repo^17handshakes (examples, docs snippets, fixtures) to^18, and gives the lockstep test one narrow exception: in pre mode with a pendingmajor, the protocol major may equal the major about to be published. ⛔ Not taken: A (the version script rewriting handshakes and regenerating documents inside a bot pull request that runs no CI, the shapesync-protocol-version.mjs's own note on fix(spec): PROTOCOL_VERSION 13.0.0 → 14.0.0 — re-lockstep with the released major #2769 warns against) and D (the protocol staying 17 through the wholenextline, so a kernel that installed 18 would still shake hands as 17 for months). The constant lives inpackages/spec, so the work is thedomain:speclane's card, filed by thedomain:devxseat in execution; its first measurements are the cli fixtures declaring^17and whether ADR-0120 协议 18 项:D2 conversion(声明索引 unique: true → 'global')+ 裸 true 硬拒 + synonym pin 退役 —— 挂 18 列车,现在勿动工 #5082's 17 → 18 conversions may take effect before C8. - Q2 → A. The v18 release page exists before the first prerelease. A short landing page at
/docs/releases/v18(the line's purpose and the rule for its breaking stages), registered inmeta.json, so the pointerprotocol-version-gap.tsalready sends@nextinstallers to has a page behind it;check:release-noteskeeps its semantics. ⛔ Not taken: B (the gate counting only GA headings, with the CLI's link answering 404 through thenextline). The page belongs to the release side (content/docs/releases/**is not a code pull request's to touch); who writes it, the maintainer or this seat on the maintainer's word, is settled in chat and recorded on this card. - Q3 → B. During the
nextline, the documented image and install versions follow the newest GA, not the prerelease. In pre modesync-docs-image-tagsandcheck-docs-image-tagpin the newest GA (read from the CHANGELOG, the same way the GA is already judged); outside pre mode nothing changes. ⛔ Not taken: A (self-hosting and upgrade documents reading18.0.0-next.Nwhile npmlatestand the published image stay 17.7.0, so a production user copying the documents is led into the breaking prerelease line).
Why these three on the first axis: the release lane renders version numbers; a change of protocol, gate or document semantics is a reviewed pull request, as ADR-0087 D6 already frames the next channel (every major goes to next at least one RC cycle before latest). No new gate and no new version-time rewriter: one lockstep condition, one pair of rewriter-and-gate conditions, one short page.
State
needs-user-decision→pm:queuein this act;tooling·priority:p1·domain:devx·target:v18·area:devpathunchanged, no assignee: thedomain:devxseat claims the card to execute the 裁后执行 of 6040990462 (file thedomain:speccard for Q1, thedomain:devxcard for Q3, and record the Q2 page as a release-side action on this card), then closes it when the protocol half of Done-when 1 and Done-when 3 are met. Body:Ruled:line added in the same act.- Standing, unchanged by this ruling: PR chore(release): enter Changesets pre mode (
next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084's merge is the maintainer's act; after it theversion-prrefresh stays red atValidate the post-version treeuntil the Q1 pull request lands, and red there publishes nothing; ⛔ chore: version packages #21988 is not merged; ⛔ no seat publishes, tags or dispatches a release workflow.
Generated by Claude Code
objectstack-fleet commented on Oct 8, 2026
Claim: PM loop round 8
Session: session_01VF48aw8RPG6wzDnMgp6rtw
Account: os-justin (the seat's linked user as GET /user answers it; the card's assignee)
Branch: n/a. This card's remainder is executed by the seat itself (two card filings and one record). The Q3 code half goes on its own sub-issue with its own claim and branch.
Worktree: n/a
Domain: domain:devx
Seat: domain:devx#2
Ruling-ref: 6049734955 (Q1 B · Q2 A · Q3 B, re-read this round)
File surface: none on this card (issue writes only).
- ⛔ No edit to
content/docs/releases/**. That page is the release side's, per Q2. - ⛔ No publish, tag or
workflow_dispatchof a release workflow. ⛔ chore: version packages #21988 is not touched.
Container & model: PM seat, in-session
Clause-②: no
Responsibility: n/a — not a defect card
Thread-read: 6049734955
Serial constraints cleared: none apply. The Q1 card's surface (packages/specprotocol constant, generated documents,^17handshakes) is the spec lane's. The Q3 sub-issue's surface (scripts/sync-docs-image-tags.mjs,scripts/check-docs-image-tag.mjs) is touched by no open PR.
objectstack-fleet commented on Oct 8, 2026
Ruling executed — #22085's 裁后执行 (post-ruling actions) for Q1 B · Q2 A · Q3 B · domain:devx#2 · 2026-10-08T01:38Z
Executes 6040990462's 裁后执行 under the ruling 6049734955. Claim: 6050348380. Ruling-ref: 6049734955.
| Question | Ruled | Carried by | State |
|---|---|---|---|
| Q1: the protocol major | B: an ordinary PR with full CI | #22130 (domain:spec, priority:p1, protocol:breaking, pm:queue), filed for the spec seat |
Lands after PR #22084. Its lockstep exception keys on pre mode. |
| Q2: the v18 release page | A: the page exists before the first prerelease | A release-side action: a short page at /docs/releases/v18, registered in meta.json. The maintainer or the director seat writes it, as settled in chat. |
⛔ Not this seat's: content/docs/releases/** is not a code PR's to touch. This seat waits for it and re-reads this card at each round. |
| Q3: documented versions in pre mode | B: they follow the newest GA | #22131 (domain:devx sub-issue, priority:p1), dispatched by this seat this round |
In flight |
What remains on this card:
- Done-when 1, protocol half: met when 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 lands.
- Done-when 3: met when release(v18): in pre mode, sync-docs-image-tags and check-docs-image-tag pin the documented image and install versions to the newest GA, not 18.0.0-next.N (#22085 Q3) #22131 lands and the Q2 page exists. A
version-prrefresh on thatmainthat passesValidate the post-version treeis the reading.
This seat closes the card on that reading. The card stays pm:dispatched to this seat until then.
Standing, unchanged by this ruling:
- PR chore(release): enter Changesets pre mode (
next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084's merge is the maintainer's act. - After that merge, the
version-prrefresh stays red atValidate the post-version treeuntil 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 lands. Red there publishes nothing. - ⛔ chore: version packages #21988 is not merged. ⛔ No seat publishes, tags or dispatches a release workflow.
objectstack-fleet commented on Oct 8, 2026
- Q3 landed 2026-10-08T03:29Z: release(v18): in pre mode, sync-docs-image-tags and check-docs-image-tag pin the documented image and install versions to the newest GA, not 18.0.0-next.N (#22085 Q3) #22131 → PR fix(scripts): in Changesets pre mode the doc image and install pins follow the newest GA, not the prerelease #22134 →
ec8f37c890(record on release(v18): in pre mode, sync-docs-image-tags and check-docs-image-tag pin the documented image and install versions to the newest GA, not 18.0.0-next.N (#22085 Q3) #22131). Remaining on this card: Q1 (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,domain:spec, after PR chore(release): enter Changesets pre mode (next) with onemajormarker, so v18 opens at 18.0.0-next.0 #22084) and Q2 (the release-side page at/docs/releases/v18).
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.0is actually cut once pre mode is in. #22080 keeps its own half, pre mode plus the onemajormarker, 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) andtarget: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'sversion-prjob (cron0 */6 * * *), stepValidate the post-version tree(:518onmain3d9188502e). It exits 1 at:610–:613on 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 forpost-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 therelease.ymlandcut-rc.ymllines cited; the rest is the dev's throwaway reading)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.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.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).cut-rc.ymlis no route either: it refuses any version not shapedX.Y.Z-rc.N(:156–:159) and anypre.jsontag butrc(:232–:237).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.ymlis not extended (that would be a second route the ruling did not name).Done when
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.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.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.workflow_dispatchof any release workflow, ⛔ no merge of chore: version packages #21988, ⛔ no edit tocut-rc.yml, ⛔ no hand edit ofcontent/docs/releases/**.Related: #22080 · PR #22084 · #22050 · #21988 · #15194.