Repository navigation
[Decision] Previous-major support after 18.0 GA: correct the published N-1 promise to latest-only (A), an on-demand security line for N-1 (B), or a better-auth-style two-branch model (C)? #25102
Description
Ruled: 6328214336 · letter A · 2026-10-21T22:48Z
Filing gate: ② a decision only the maintainer can make.
- Filed from session
session_01GMBuQthe2LLGteJbhzXhvF, on this request (verbatim): 「我关心的是我们平台是否可以参考类似的规则。立一张决策卡」. - Context: the request followed a reading of how better-auth keeps patching 1.7 while 1.8 is in beta. The better-auth lift that prompted it is deps(plugin-auth): lift the better-auth family from 1.7.3 to 1.7.12 — security fixes published after the 2026-10-01 deferral #25096.
- ⛔ Not a claim.
Acting reader: the maintainer rules. Triage then records the ruling on this card and files the execution named under 裁后执行.
Dedup (MCP search_issues, closed included):
- objectstack: "maintenance branch backport security fixes to previous major version support window N-1 release line" → 8 hits. None is in scope. The nearest are docs(protocol): the Backward Compatibility page says the launch-window minor rule is "in force today", that no major can land, and that the current release is 17.2.0, while main is in pre mode on the v18 major and 17.7.0 has shipped #22964 and docs(releases): the releases index "Versioning policy" says every breaking change ships as a minor and no major can land, while the v18 line ships its breaking changes as a major #22933 (docs regime fixes, closed) and deps(plugin-auth): lift the better-auth family from 1.7.3 to 1.7.12 — security fixes published after the 2026-10-01 deferral #25096 (a dependency lift).
- objectstack: "enter changesets pre mode next tag for v18 major line decision ruling launch window" → 17 hits. The prior rulings are read below.
- cloud: "on-prem ObjectOS EE patch release customers security fix older platform line hotfix" → 0 hits.
Governing text:
content/docs/protocol/backward-compatibility.mdx:153-159(Support Windows);- ADR-0087 D6 (every major goes through the
nextdist-tag for at least one RC cycle beforelatest); - the board rulings on [gate] the v18 development line is not open — ADR-0131 execution cards are blocked on this card #15193 and 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 quoted below.
node scripts/pm/check-prior-rulings.mjs --terms "backport,maintenance line,support window,LTS,release branch,N-1,pre mode" finds 0 ADR decisions on these terms.
维护者速读
你想参考 better-auth 的做法:新大版本在测试时,旧版本继续出补丁;新版本转正后,旧版本再修几周安全问题。
矛盾:
- 10 月 6 日对 17.x 的裁决正好相反:不建维护分支,不建第二条 npm 发布线,cloud 也不钉分支。10 月 7 日又定了不发最后一个 17.x。
- 但公开文档
/docs/protocol/backward-compatibility至今写着:「上一个大版本:只收严重缺陷和安全补丁」。 - 从 8 到 18 的十个大版本里,这个承诺一次都没兑现过。
- 所以无论选哪个字母,这句话都必须改成真话。
三个选项:
- A(推荐):只支持最新大版本,把文档改成真话。
- 文档写明:旧大版本不再收修复,升级走 ADR-0087 的转换层和
migrate meta。 - 一个文档 PR,不加任何流程。
- 文档写明:旧大版本不再收修复,升级走 ADR-0087 的转换层和
- B:平时不开维护线,出高危安全修复时临时开。
- 只在两个条件同时满足时开:出了高危及以上的安全修复,并且新大版本转正不满 4 周。
- 做法:从上个大版本最后一个 tag 切分支,移植修复,用
release-N标签发一个补丁版。 - 要给发版流程加分支触发,并修改 10 月 6 日的两条裁决。better-auth 实际上就是这样运作的。
- C:照搬 better-auth 的完整双分支模型。
- 10 月 6 日已经否决过:main 每天大约 100 个提交,侧分支几天就会烂掉。
推荐 A。回一个字母:A / B / C。
如果你知道有付费的 EE 私有化客户停在 17.x、需要安全补丁,请选 B。
四棱(os-decision-facets)
- ① 项目长远合理性:
- A 把向后兼容放在协议里,而不是靠维护多条代码线。ADR-0087 的转换层和可执行迁移,能让晚了三个大版本的应用一次升到最新。这是 Salesforce 式的模型:所有客户在同一版本上,旧契约由平台转换。
- B 是一个按需开的例外通道,契约增量小,但每次都要人工操作。
- C 增加一条永久分支和四个工作流。
- ② 实际业务拉动:
- 至今没有测到停在 17.x 的 npm 自托管用户。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 的置信缺口一直没补上。
- 唯一可能的拉动是 EE 私有化客户。EE 4.2.0(09-06)跑在 ObjectStack 17.3 上,客户按镜像摘要部署。18.0 转正后,他们拿安全修复只能连带 18 的破坏性迁移一起拿。
- EE 客户数未知。
- ③ 防 AI 犯错:
- 现在文档承诺上一个大版本有补丁,AI 或用户照文档等补丁,会静默落空。A 让文档和行为一致。
- B 和 C 的移植是人工挑提交,漏掉一个安全修复不会有任何报错。
- ④ 创业阶段不扩散:
- A 不增加任何流程。
- B 增加一条按需发版通道,与「不建议再建立一套 npm 发布流程,我运维太麻烦」冲突。
- C 增加一条永久分支和四个工作流。
Prior rulings read:
- terms
backport,maintenance line,support window,lts,release branch,n-1,pre mode→ 0 ADR hits; ADR-0087 D6; - thread: none (this is a new card);
- board rulings: [gate] the v18 development line is not open — ADR-0131 execution cards are blocked on this card #15193
6017499711→6018081901→6018207607, and 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)? #220506037890422.
一句话问题
公开文档承诺「上一个大版本只收严重缺陷和安全补丁」,但旧大版本从来没收到过一个补丁。停在上一个大版本的自托管或 EE 私有化客户,要拿安全修复,只能连同下一个大版本的破坏性迁移一起接受。
我们是像 better-auth 那样继续给上一个版本线出补丁,还是把承诺改成「只支持最新大版本」?
Facts (read at this write, origin/main 1862d8d)
1. The published promise
content/docs/protocol/backward-compatibility.mdx:158 reads: "Previous MAJOR (N-1) | Maintenance | Critical bug fixes and security patches only".
No other page states a support window.
Re-check:
git grep -n -iE "End of Life|security patches only|support window" origin/main -- content skills README.mdThis prints only this page's lines.
2. The rulings it contradicts
All are on #15193, from the triage seat's chat with the maintainer.
6017499711: 「同意分支模型」. This agreed arelease/17.xmaintenance line, for security and release-blocking fixes only.6018081901, amending it the same day: 「不建议再建立一套 npm 发布流程,我运维太麻烦」. The result: no 17.x npm lane.6018207607: 「cloud 也不需要钉分支」. The result: no 17.x maintenance line of any kind.- It also says a branch can be cut later from the recorded pre-v18 commit "if an emergency ever needs one. That is an option, not a plan."
6037890422on 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 ruled B, with no last 17.x: 「我建议直接启动 v18 开发吧」.- It followed the maintainer's cost reading in
6030429903: 「发版本的流程还是挺折腾的,发了还要写 17.8 的说明」.
- It followed the maintainer's cost reading in
3. What npm shows
No version line of @objectstack/spec or @object-ui/core has ever published again after a newer line shipped.
- spec ran majors 8 → 18 between 2026-06-07 and 2026-10-20.
- 17.7.0 (2026-10-06) is the last 17.x.
18.0.0-next.0tonext.5went tonextbetween 10-13 and 10-19.18.0.0went tolateston 10-20.
Re-check:
for p in @objectstack/spec @object-ui/core better-auth; do printf '%s: ' "$p"; curl -s "https://registry.npmjs.org/$p" | jq -r '.time | to_entries[] | select(.key | test("^[0-9]+\\.[0-9]+\\.[0-9]+$")) | "\(.value) \(.key)"' | sort | awk '{split($2,v,"."); print v[1]"."v[2]}' | uniq | sort | uniq -d | tr '\n' ' '; echo; doneThe command prints each version line that published again after a newer line shipped.
- Today it prints nothing for both of ours.
- better-auth is the positive control: it prints
1.4 1.5 1.6 1.7.
4. Why the stable line goes quiet during a prerelease
.github/workflows/release.yml:182-185publishes on push tomainonly.- While
mainis in pre mode, every release is the next major's prerelease. - So between 17.7.0 (10-06) and 18.0.0 (10-20), npm
latestusers received no fix at all.
5. EE, the only measured candidate for a pull
The cloud repo's tags:
| Tag | Date | What it says |
|---|---|---|
ee-v4.1.0 |
08-20 | "first stable on-prem image" |
ee-v4.1.1 |
08-24 | A hotfix, shipped by rolling the framework pin forward to main 502ff8b (#11610), not by a backport. |
ee-v4.2.0 |
09-06 | "moves onto the ObjectStack 17.3 platform line" |
- Customers deploy by digest: see the
release-objectos-ee.ymlheader. - There has been no EE release since 09-06.
- How many licensed EE customers there are is not measured.
Re-check:
git -C cloud ls-remote --tags origin 'ee-v*'
git -C cloud show ee-v4.1.1:.objectstack-sha6. The reference: what better-auth does (read 2026-10-21)
Mechanisms:
mainis stable 1.7.x, published tolatest.nextcarries1.8.0-beta.N, in Changesets pre mode with the tagbeta.auto-retarget.ymlmoves a PR whose changeset isminorormajorfrommaintonext.release.yml:- opens a
main→nextsync PR after every stable release; - publishes a
vX.Y.xbranch under therelease-X.Ydist-tag.
- opens a
promote.ymlexits pre mode and opens anext→mainPR.backport.ymlcherry-picks labelled PRs ontovX.Y.x.
In practice:
release-1.6stopped at 1.6.33 on 09-14, four weeks after 1.7.0 (08-18).v1.6.xtook two more fixes (09-16 and 10-14) that were never published.- The critical GHSA-965c-763c-88jm (all versions below 1.7.7, published 09-30) shipped no 1.6 fix.
- 1.4 and 1.5 ended the same way: 1.4.22 came two weeks after 1.5.0, and 1.5.6 came before 1.6.0.
7. What we already share with better-auth, and what we don't
Shared:
- a lockstep Changesets
fixedgroup: 73 packages against their 22; - majors through a prerelease tag before
latest(ADR-0087 D6). Ours runs onmain, theirs on a branch.
Different:
- To keep breaking changes out of the stable line, we refuse a
majorchangeset outside pre mode (check-changeset-no-major.mjs), where better-auth retargets the PR instead.
Missing:
- a stable line that keeps receiving patches while the next major is in prerelease;
- any line for the previous major after GA.
选项 × 代价 × 工作量
| 选项 | 做什么 | 客户可感知后果 | 工作量 |
|---|---|---|---|
| A | 把文档的 Support Windows 改成「只支持最新大版本;旧大版本不再收修复,升级走 ADR-0087 的转换层与 migrate meta」 |
自托管和 EE 客户读到的是真话:要安全修复就升级,不会再等一个不会来的补丁 | devx 车道 · 1 个文档 PR · 先例 PR #22988(同一页,+18 −16,1 个文件) |
| B | A 的文档改动,加上一条按需的安全线。三个条件同时满足才触发:① 高危及以上的安全修复;② 新大版本转正不满 4 周;③ 有具名用户停在上一个大版本。触发后从上个大版本最后一个 tag 切 release/N.x,移植修复,走同一个 release.yml 用 release-N 标签发补丁版,不打 latest |
上一个大版本的用户在新版转正后 4 周内能拿到高危安全修复,不必马上迁移;4 周后同 A | devx 车道 · 2–3 个 PR(release.yml 的分支触发与标签、移植规则、文档)· 无先例(#21993 在出 PR 前撤销)· 之后每次触发都要你合并、批准、写说明 |
| C | 照搬 better-auth:大版本在长期 next 分支开发,main 只收补丁,加上自动改目标分支、发版后自动同步、转正流程、移植工作流 |
同 B,而且新大版本测试期间旧版本照常收补丁 | devx 车道 · 至少 5 个 PR · 无先例 · 常态成本是 main 每天约 100 个提交下的同步冲突,也就是 6017499711 否决侧分支模型的理由 |
业务含义直译
- A:像 Salesforce。所有客户跑同一个版本,旧契约由平台转换兼容,不维护旧版本。
- B:像保险的宽限期。换代后给老用户几周、只修安全漏洞,到期就停。better-auth 实际就是这样:1.6 在 1.7 发布约 4 周后停更。
- C:像 Node.js 或 GitLab 的长期支持。两条线并行,靠专人或自动化维护。
推荐 + 置信缺口
- 推荐 A。
- 两年后的样子: 平台的兼容承诺写在协议里。晚了几个大版本的应用,靠 ADR-0087 的转换层和迁移链一次升到最新;安全修复只出在最新大版本上。参照 Salesforce 的单一版本加多版本契约模型,而不是维护多条代码线。
- 不取 B: 拉动没有测到,而且与
6018081901、6018207607冲突。B 真正需要的「从 tag 临时切分支」,6018207607已经保留为「一个选项,不是计划」,选 A 不会失去它。 - 不取 C:
6017499711已经因为主干速度否决了长期侧分支,它的成本是常态的。 - 置信缺口: EE 私有化付费客户的数量和所在版本没有测过。如果有客户停在 17.x、需要安全修复,B 的拉动就成立,应该改选 B。
- 只看①选 A;②③④ 是否翻转:否。
裁后执行
- A:
- Triage files one ① docs card for
content/docs/protocol/backward-compatibility.mdx. It replaces the Support Windows table with a latest-only statement and links ADR-0087's conversion layer andobjectstack migrate meta. - It is a docs-only PR (
skip-changeset), the same shape as PR docs(protocol): the backward-compatibility page states the 17.x launch-window rule and the v18 prerelease regime #22988. - The releases index is checked for any contrary sentence in the same PR.
- Triage files one ① docs card for
- B:
- Triage records the amendment of
6018081901and6018207607here, then files the following. - A
domain:devxcard:release.ymlpublishes from arelease/N.xpush under therelease-Ndist-tag, neverlatest;- publishing keeps the existing human approval;
- the trigger conditions are written into the workflow header.
- A backport-rule card, for how a fix reaches the branch.
- The docs card from A, but stating the 4-week, high-or-critical window instead.
- One cloud card naming which framework line each EE version tracks.
- The window length and the severity floor are part of this ruling. The recommended values, if B, are 4 weeks and high or above.
- Triage records the amendment of
- C:
- It needs an ADR first, because the branch model changes the release contract.
- Then an epic with one card per workflow: retarget, sync, promote, backport, and the dual-channel
release.yml.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 21, 2026
Ruling: batch #382 item 5 · letter A · maintainer 「24932 25133 帮我综合分析工作量和风险;25134 25092 25102 同意」 2026-10-21T22:44Z
Director seat, summon #47,
session_01TQvbE2ENCniJr1ffCzbPc6(os-bill, writing through the relay). Presented in this session's chat as batch #382 item 5, from the card's analysis; the director's delta re-checked at this write:content/docs/protocol/backward-compatibility.mdx:153-159still carries the Support Windows table with the N-1 "Maintenance" row; the card's npm re-check prints no re-published line for@objectstack/specwhile the positive controlbetter-authprints1.4 1.5 1.6 1.7;git grep -iE 'support window|backport|maintenance line|\bLTS\b' origin/main -- AGENTS.md docs/adr→ 0 hits on the subject. The cloud repo is not attached to this session, so the EE tags were not re-read. Thread read to its end at this write: no comment on the card.Governing text:content/docs/protocol/backward-compatibility.mdx:153-159; ADR-0087 D6; the board rulings on #15193 (6017499711→6018081901「不建议再建立一套 npm 发布流程,我运维太麻烦」 →6018207607「cloud 也不需要钉分支」) and on #22050 (6037890422).What the ruling binds
objectstack migrate meta. The page links both.6018207607keeps "a branch can be cut from the recorded pre-v18 commit if an emergency ever needs one — an option, not a plan"; A does not retract it.6018081901and6018207607), C (the two-branch model, refused in6017499711for the mainline's commit rate). The confidence gap stays on record: if a paying EE customer is found on 17.x needing a security fix, that is a new card, and B's shape is the one to put to the maintainer then.Effort of the chosen letter:
domain:devx· 1 docs-only PR (skip-changeset) · precedent PR #22988 (+18 / −16, the same page). The same PR checks the releases index for any contrary sentence.State:
needs-user-decision→pm:queue. This card is the execution card (domain:devx, p2,documentation); no second card is filed. Thedomain:devxseat claims and dispatches.Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Claim: PM loop round 39 · the execution half of a p2 decision card the maintainer ruled letter A (ruling
6328214336, 「25134 25092 25102 同意」), routed to this lane's seat by the ruling. Serial dispatch under the maintainer's 「串行派发」.Session:
session_01FM29ZqLTrnPNXxijioZwMpAccount:
os-warren(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-25102-support-windows-latest-onlyWorktree:
objectstack-issue-25102Domain:
domain:devxSeat:
domain:devx#1File surface:
content/docs/protocol/backward-compatibility.mdx: the "Support Windows" section (:153–:159atorigin/mainabc25a3536). The table is replaced by a latest-only statement: the previous major receives no fixes, and an application upgrades through ADR-0087's conversion layer andobjectstack migrate meta. The page links both. Ruling item 2 is kept: the emergency branch from a recorded tag stays "an option, not a plan", and it is not promised.content/docs/releases/index.mdxand its siblings) only if it states a contrary sentence. This is a docs-only PR, so the no-releases-in-a-code-PR rule is not crossed.scripts/docs-audit/handwritten-docs.jsononly ifcheck:docs-audit-scopeasks for it, as generator output.Container & model:
S (one docs section, the precedent PR #22988 is +18 / −16 on the same page),mode:subagent,model: TIER_DEFAULTClause-②: no
Responsibility:
content/docs/protocol/backward-compatibility.mdxpromises the previous major "critical bug fixes and security patches only", which no line has ever received (majors 8 → 18), so a reader waits for a patch that never comes ([Decision] Previous-major support after 18.0 GA: correct the published N-1 promise to latest-only (A), an on-demand security line for N-1 (B), or a better-auth-style two-branch model (C)? #25102, ruled A)|none: the board rulings on [gate] the v18 development line is not open — ADR-0131 execution cards are blocked on this card #15193 (6018081901,6018207607) and 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), which the page never followed|every self-hosted and EE reader on a previous major, and an AI that reads the page as a support contractThread-read: 6328214336 Serial constraints cleared: no open PR touchesbackward-compatibility.mdxor the releases index, and no liveClaim:on apm:dispatched` card names either (read at 2026-10-21T23:38Z). No dev of this session is in flight: spec-shape-gate: red on main for 5 hourly runs since fbb42d900. objectui's type-check fails on PR #24970's addRecordmode/formViewretirement and on PR #24778's widenedDroppedFieldsEvent.reason, and neither is registered #25055 closed 2026-10-21T11:13Z.Generated by Claude Code
objectstack-fleet commentedon Oct 22, 2026
os-dev-report
{
"issue": 25102,
"status": "done",
"branch": "claude/issue-25102-support-windows-latest-only",
"pr": "#25146",
"session": "session_01FM29ZqLTrnPNXxijioZwMp (subagent run; the parent PM seat id, as the dispatch and the claim 6329002310 name it)",
"premise_still_valid": true,
"summary": "Executes ruling 6328214336, letter A. The Support Windows section of backward-compatibility.mdx (:153-:159 at abc25a3) loses its three-row N / N-1 / N-2 table and now states latest-only support. Only the current MAJOR receives fixes, which ship in the next release cut from main, so during a prerelease a fix reaches latest only at the next GA. The previous MAJOR and every older one receive none, and no backport or maintenance release is promised. An older app upgrades through ADR-0087 D2 (load-time conversion of the previous MAJOR's lossless changes) and os migrate meta (D3: --from N down to the protocol-16 floor, --write, --stored --apply); the page links the ADR, the CLI reference and Upgrading. D6 is cited for the next dist-tag, with v18 as the measured instance. The heading text is kept, and the page names no emergency branch, date, window or EE promise. Two sentences the new statement would have contradicted were corrected, each named in the PR body with before and after. The :142 callout no longer gives doctor, diff and the CHANGELOG as the way to upgrade across majors: os migrate meta is named for metadata, and the three tools cover what it does not rewrite; the false "referenced in the migration guides" clause is gone. releases/index.mdx:22 now labels v17 "(final release: 17.7.0)" instead of a second "current series"; every release gate accepts this wording, and the version-time rewriter leaves it alone. Commits carry AGENTS.md's model-free trailer pair, and the PR body carries the session-URL footer. The harness reminder's model-named Co-Authored-By trailer and its alternative PR footer were reported, not imitated.",
"tests": "All readings are at head 062bfaf. Premise re-checks, the card's own, verbatim, at origin/main abc25a3: git grep -n -iE "End of Life|security patches only|support window" origin/main -- content skills README.md -> exit 0, only backward-compatibility.mdx:153, :158 and :159. The npm probe -> @objectstack/spec and @object-ui/core print nothing; better-auth prints 1.4 1.5 1.6 1.7 (positive control). A wider grep (maintenance line, previous major, N-1, LTS, backport, EOL) -> 13 lines, none a support window, so no other page joins the surface. A releases-tree grep -> 14 lines, none promising a previous-major fix; the only contrary statement is the v17 current-series label. Inbound anchors: #support-windows -> exit 1 here and exit 1 in ../objectui at b014f5eea (control leg exit 0). MDX: both pages compile with @mdx-js/mdx 3.1.1 (exit 0); an unclosed-Callout control is refused (exit 1, "Expected a closing tag"). Docs site build under the verify lock: turbo build --filter=@objectstack/docs^... then pnpm --filter @objectstack/docs run build -> VERDICT command-exit 0, "Compiled successfully in 2.2min", 1275/1275 static pages, apps/docs/.next/BUILD_ID present. In the built output, the new lead sentence is in 5 files (including en/docs/protocol/backward-compatibility.html), the removed sentence in 0, and "final release: 17.7.0" in 5. Prerequisite build: turbo build --filter=@objectstack/lint... --filter=@objectstack/client-react... --concurrency=2 -> VERDICT command-exit 0, 37/37 tasks. skip-changeset: 0 of 73 non-private manifests ship content/docs; the removed and added phrases match 0 files under packages/ (dist included); control defineStack matches 989. Control-byte grep on both files -> exit 1 (none). merge-tree against origin/main 4c7dcb4 -> exit 0. No package touched, so no package test or typecheck is owed. No ablation, because no tested behaviour changed.",
"gates": "Local subset: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 062bfaf -> 49 commands, the same list as at 2b3b50b (diff exit 0). All 49 ran, each exit code captured before any pipe: 49 x exit 0. --ran -> exit 0, "49 derived famil(ies) accounted for — 49 run, 0 NOT-MEASURED (a DERIVED zero — all 49 recorded an exit code and none of them is 3)". Verdict lines: check:doc-anchors, 566 links across 424 files resolve; check:docs-redirects OK; check:docs-audit-scope in sync, 206 hand-written docs, no handwritten-docs.json write; check-release-section-coverage OK, plain and --strict; check:release-page-status OK; check:release-notes OK; check:lockstep-package-count 73; check:nul-bytes OK over 11726 files; spec check:docs, 227 in sync; check:skill-examples, 262. A first battery pass on 2b3b50b (also 49 x exit 0) is superseded: the :142 wording changed mid-run, so the union was re-derived and re-run on the final head. NOT MEASURED locally (CI-owned, no local invocation): the 3 workflow-valued families, the Test Core shards, the 4 Type Check lanes, and pnpm lint. PR #25146 check-runs, read once at 00:22Z: Check Changeset success; No other open PR may claim the same issue success; opt-in and auto-label jobs skipped. In progress: Lint (9 lanes), Type Check (4 lanes), Check Documentation Links, Spec property liveness, Governed Surface Queue Guard, The card this PR closes must claim this branch, the single-writer path guard, the Part-of guard, Check PR Size, filter. Test Core, Build Core and Build Docs were not yet listed.",
"mcp_calls": "6, all reads: issue_read get #25102, issue_read get_comments #25102, pull_request_read get #22988, pull_request_read get_diff #22988, pull_request_read get #25146, pull_request_read get_check_runs #25146. No MCP write tool.",
"api_writes": "2 relay strokes, each one POST /repos/objectstack-ai/objectstack/dispatches. (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (draft), POST /repos//issues/25146/assignees [os-warren], POST /repos//issues/25146/labels [skip-changeset, documentation]. Read-back: body 19370 of 19370 bytes identical, assignee os-warren; labels documentation and skip-changeset read back on the PR. (2) This os-dev-report comment -> POST /repos//issues/25102/comments via scripts/pm/post-stamped.mjs. Plus 3 git pushes, which are not REST writes. Every other REST call was a read.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: the public docs page /docs/releases (content/docs/releases/index.mdx:21) states "(current series: 18.0.0, released 2026-10-19)" · evidence: Version Packages commit 06cab48 is dated 2026-10-20T11:47Z, npm time[18.0.0] is 2026-10-20T12:51Z, and releases/v18/18-0.mdx:3 says "published 2026-10-20". Mechanism: 8fbbd50 wrote the status before the cut, and sync-release-index-currency.mjs leaves a current-series field that already names the newest GA "whatever its date", so the version step never stamped it · dedupe words: release index 18.0.0 released date; current series released 2026-10-19; sync-release-index-currency date",
"class: a · reach: the public docs page /docs/releases/v17 (the content/docs/releases/v17/index.mdx status blockquote) states "A plain install now resolves 17.7.0" while npm dist-tags.latest is 18.0.0 · evidence: npm dist-tags show latest 18.0.0; check:release-page-status passes the page because it judges released-ness, not currency · same family as the item above (release-currency prose after the 18.0.0 GA cut), so one card covers both · dedupe words: v17 release status plain install resolves 17.7.0; release page currency after GA",
"carrier: none · noted, not filed — ADR-0087 D6 (every major on next for at least one RC cycle) against npm: majors 8-15 published no prerelease, 16 and 17 used -rc.N on the rc dist-tag, and only 18 used next. The 2026-07-15 addendum still lists the D6 RC discipline as deferred. History with no reach; the page cites D6 and names only v18 (PR Acceptance notes)",
"carrier: none · noted, not filed — prose that paraphrases the old :142 callout ("not yet available"): the comments at packages/cli/src/commands/doctor.ts:2680 and doctor-deprecation-hint-commands.test.ts:18, and docs/qa/platform-checklist/areas/cli.json:1189. The same doctor.ts comment says both of os migrate meta's writes are --out JSON snapshots, which predates --write. Code and QA data outside this PR's surface; nothing reads or compares them (PR Acceptance notes)"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 22, 2026
os-dev-report
{
"issue": 25102,
"status": "done",
"branch": "claude/issue-25102-support-windows-latest-only",
"pr": "#25146",
"session": "session_01FM29ZqLTrnPNXxijioZwMp (subagent run; the parent PM seat id, as the dispatch, the claim 6329002310 and this fix round name it)",
"premise_still_valid": true,
"summary": "Fix round 1: new commit f453405 on top of 062bfaf (no amend, rebase or force-push); it removes the ADR-0087 D6 citation, which the ADR's own as-built addendum lists as deferred. The "Testing a MAJOR" bullet now rests on scripts/check-changeset-no-major.mjs as found at origin/main 459afea (fails a pull request declaring a major bump outside Changesets pre mode at :682, stands aside inside it at :681, with the RC EXEMPTION header at :113-:120). A MAJOR declared in pre mode publishes only prereleases on the pre-mode dist-tag until pre mode exits; v18 used next (18.0.0-next.0 … next.5); install from that tag. The current-MAJOR bullet now says "the pre-mode dist-tag (
nexton the v18 line)". One wording departs from the ruling's letter, and is reported rather than silently chosen: the page avoids "can only be declared in pre mode … never latest". The guard's allow-major label escape hatch (header :122-:124, read live at pr-automation.yml:1063) skips it outside pre mode, so the page uses the indefinite "fails a pull request" form PR #22988 adopted for this same reason, plus the Changesets pre-mode semantics, which always hold. If the seat prefers the absolute wording, the allow-major qualifier would have to go on the page. Nothing enforces the pre tag (cut-rc.yml:235 requires tag rc for its own lane only, and v18 ran next through release.yml), so the page names no future tag. The exact PR-body replacement passages are in pr_body_replacements; nothing else on the page changed.","pr_body_replacements": {
"R1 — replaces the whole table row that starts "| The current MAJOR:"": "| The current MAJOR: bug fixes and security patches ship in the next release cut from
main. While the next MAJOR is in prerelease, every release cut frommainis one of its prereleases on the pre-mode dist-tag (nexton the v18 line), so a fix reacheslatestonly when that MAJOR goes GA. |.github/workflows/release.yml's header:npm publishlives in one job, reachable only from apushtomainand from the repair dispatch, and the repair "cannot mint a version". The card's fact 4 measured the consequence: between 17.7.0 and 18.0.0,latestreceived no fix. The page's own top callout already states the pre-mode half. The tag is written "the pre-mode dist-tag" because nothing fixes it:changeset pre entertakes the tag as an argument, v16 and v17 ran onrcand v18 onnext, and.github/workflows/cut-rc.yml:235requirestag: rcfor its own lane only. |","R2 — replaces the whole table row that starts "| Testing a MAJOR before it reaches
latest:"": "| Testing a MAJOR before it reacheslatest:scripts/check-changeset-no-major.mjsfails a pull request that declares amajorbump outside Changesets pre mode and stands aside inside it, and a MAJOR declared in pre mode publishes only prereleases, on the pre-mode dist-tag, until pre mode exits. The v18 line usednext(18.0.0-next.0…18.0.0-next.5) before 18.0.0. Install from that tag to run your app against a MAJOR before it becomeslatest. |scripts/check-changeset-no-major.mjsatorigin/main459afea1f6:judge()(:678-:683) returnsexemptwhen.changeset/pre.jsonhasmode: 'pre'(:681) andenforceotherwise (:682). Theexemptcase exits 0 (:818-:826), and theenforcecase prints the refusal (:828). The RC EXEMPTION header (:113-:120) states the Changesets semantics: in pre mode "amajorbump only ever produces a … PRE-RELEASE version — nothing final publishes untilchangeset pre exit". npm:18.0.0-next.0(2026-10-13) to18.0.0-next.5(2026-10-19), then18.0.0(2026-10-20). The page says the guard fails "a" pull request, not "any", and it does not say a MAJOR can be declared only in pre mode, because the guard'sallow-majorlabel escape hatch skips it outside pre mode (header:122-:124; the label is read live at.github/workflows/pr-automation.yml:1063). |","R3 — replaces the whole Acceptance-notes bullet that starts "- D6 against what npm shows.", including its three sub-bullets and its closing paragraph": "- ADR-0087 D6 is not cited. D6 reads "Every major is published to the
nextdist-tag at least one RC cycle beforelatest", but the ADR's 2026-07-15 as-built addendum lists "P3 — MCP tools + RC discipline (D6): deferred, evidence-gated", and npm@objectstack/specdoes not follow it:\n - majors 8 to 15 published no prerelease version at all (0 in the registry). That was the pre-launch window, which the same addendum ratifies for 12 to 15.\n - 16 and 17 ran-rc.Nprereleases (16.0.0-rc.0andrc.1;17.0.0-rc.0torc.6), and thercdist-tag still points at17.0.0-rc.6.\n - only 18 ran onnext.\n\n So both prerelease clauses rest onscripts/check-changeset-no-major.mjs, which holds today, and namenextonly as the v18 instance. Nothing found fixes which tag a future pre mode uses, so the page names none. Not filed: it is history, with no reach. Carrier: none.","R4 — replaces the Gates section from its first line ("All readings below are at this branch's head
062bfaf1dd…") through the "- Prerequisite build." bullet; the verdict-line bullets after it stand unchanged (re-measured, same values)": "All readings below are at this branch's headf453405903, againstorigin/mainmerge baseabc25a3536.\n\n- Derivation.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 49 commands: 33 pnpm and 16 direct node; 41 matched by path and 8 declared whole-tree. The change set is 2 paths and 16 changed lines. The list is identical at2b3b50b4da,062bfaf1ddandf453405903(diffexit 0).\n- Ran all 49. Each exit code was captured before any pipe. All 49 exited 0.\n- Reconciliation.--ranprinted: "✓ dispatch-gates --ran: 49 derived famil(ies) accounted for — 49 run, 0 NOT-MEASURED (a DERIVED zero — all 49 recorded an exit code and none of them is 3)."\n- Prerequisite build.pnpm exec turbo run build --filter='@objectstack/lint...' --filter='@objectstack/client-react...' --concurrency=2ran underscripts/pm/os-verify-lock.sh:VERDICT command-exit 0, 37 of 37 tasks. In this round all 37 were cache hits on the same inputs.","R5 — replaces the "- Docs site build." bullet (with its sub-bullets and its closing paragraph) and the "- Merge probe." bullet that follows it": "- Docs site build. Run locally at
062bfaf1ddas the production build that CI'sBuild Docsruns (apps/docs/vercel.jsonbuildCommand), with one declared difference. CI forces turbo (TURBO_FORCE) so the docs task cannot be a replayed cache hit; locally the docs package's ownbuildscript ran directly, outside turbo's cache, after its dependencies built:pnpm exec turbo run build --filter='@objectstack/docs^...' --concurrency=2 && pnpm --filter @objectstack/docs run build, under the verify lock. Results:\n -VERDICT command-exit 0;\n - "✓ Compiled successfully in 2.2min";\n - "✓ Generating static pages using 2 workers (1275/1275)";\n -apps/docs/.next/BUILD_IDpresent.\n\n It was not re-run locally atf453405903. The derivation names it only as CI'sBuild Docsjob, as before, and the fix changed text inside two bullets without changing the MDX shape: both pages compile, and the unclosed-Calloutcontrol is refused. CI'sBuild Docscheck-run onf453405903concludedsuccess.\n- Merge probe.git merge-tree --write-treeagainstorigin/main459afea1f6exits 0 (treee475552dea).mainhas moved two commits since the base, and neither touches either path."},
"tests": "At head f453405. Guard source read at origin/main 459afea: judge() :678-:683 (exempt :681, enforce :682); exempt render exits 0 :818-:826; enforce refusal :828; RC EXEMPTION header :113-:120; allow-major escape hatch header :122-:124 and pr-automation.yml:1063. Pre-tag enforcement search (pre enter, pre.json tag checks across scripts, .github, .changeset and package.json at origin/main): only cut-rc.yml:235 requires tag rc for the cut-rc lane; nothing binds the release.yml lane's tag. grep -c D6 on the page -> 0. MDX: both pages compile with @mdx-js/mdx 3.1.1 (exit 0); the unclosed-Callout control is refused (exit 1). Control-byte grep -> exit 1 (none). merge-tree against origin/main 459afea -> exit 0, tree e475552dea, no main commit since BASE touches either path. Prerequisite build under the lock -> VERDICT command-exit 0, 37/37 tasks (all cached). The docs site build was not re-run locally (MDX shape unchanged); CI Build Docs on f453405 concluded success, and the local build at 062bfaf passed (1275/1275 pages, BUILD_ID present). No package touched: no package test or typecheck owed. No ablation: no tested behaviour changed.",
"gates": "Local at f453405: dispatch-gates --commands --repo objectstack-ai/objectstack -> 49 commands, identical to the previous rounds (diff exit 0). All 49 ran, each exit code captured before any pipe: 49 x exit 0. --ran -> exit 0, "49 derived famil(ies) accounted for — 49 run, 0 NOT-MEASURED (a DERIVED zero — all 49 recorded an exit code and none of them is 3)". Verdicts: check:doc-anchors, 566 links across 424 files resolve; check:docs-audit-scope in sync, 206 hand-written docs; check-release-section-coverage OK; check:release-page-status OK; check:lockstep-package-count 73; check:nul-bytes OK over 11726 files. PR check-runs on f453405, read once: 40 total, 30 success, 8 skipped, 2 in_progress, 0 failure. Successes include Lint & Repo Gates, TypeScript Type Check, Governed Surface Queue Guard, Build Docs, Check Documentation Links, every Lint and Type Check lane, and Test Core 3/6 to 6/6. Test Core 1/6 and 2/6 are in_progress; Build Core is skipped.",
"mcp_calls": "This round: 0. Run total: 6, all reads (issue_read get and get_comments #25102; pull_request_read get and get_diff #22988; get and get_check_runs #25146). No MCP write tool, ever.",
"api_writes": "This round: 1 relay stroke, POST /repos/objectstack-ai/objectstack/dispatches -> POST /repos//issues/25102/comments (this os-dev-report, via scripts/pm/post-stamped.mjs), plus 1 git push (062bfaf..f453405, fast-forward, not REST). Run total: 3 relay strokes (pr_create with its assignee and label legs; two os-dev-report comments) and 4 git pushes. No PR body PATCH, no review request, no ready flip.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: the public docs page /docs/releases (content/docs/releases/index.mdx:21) states "(current series: 18.0.0, released 2026-10-19)" · evidence: Version Packages commit 06cab48 is dated 2026-10-20T11:47Z, npm time[18.0.0] is 2026-10-20T12:51Z, and releases/v18/18-0.mdx:3 says "published 2026-10-20". Mechanism: 8fbbd50 wrote the status before the cut, and sync-release-index-currency.mjs leaves a current-series field that already names the newest GA "whatever its date" · dedupe words: release index 18.0.0 released date; current series released 2026-10-19; sync-release-index-currency date",
"class: a · reach: the public docs page /docs/releases/v17 (the content/docs/releases/v17/index.mdx status blockquote) states "A plain install now resolves 17.7.0" while npm dist-tags.latest is 18.0.0 · evidence: npm dist-tags show latest 18.0.0; check:release-page-status passes the page because it judges released-ness, not currency · same family as the item above, so one card covers both · dedupe words: v17 release status plain install resolves 17.7.0; release page currency after GA",
"carrier: none · noted, not filed — ADR-0087 D6 against npm (majors 8-15 no prerelease; 16-17 on rc; only 18 on next) and the addendum's "deferred" status. The page no longer cites D6 (R3 above)",
"carrier: none · noted, not filed — prose paraphrasing the old :142 callout ("not yet available"): doctor.ts:2680, doctor-deprecation-hint-commands.test.ts:18 and platform-checklist cli.json:1189. The same doctor.ts comment says both of os migrate meta's writes are --out JSON snapshots, which predates --write"
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 22, 2026
Landed ·
domain:devxseat 1 ·session_01FM29ZqLTrnPNXxijioZwMp· 2026-10-22T01:05Zf35b4e18fe(ACCEPT6329925392; not governed;Fixes #25102)origin/main, by contentcontent/docs/protocol/backward-compatibility.mdx(77e82e8141) andcontent/docs/releases/index.mdx(74aa5bfa23) are byte-identical to the headf453405903State change: PR #25146 closed this card through
Fixes #25102(completed).pm:dispatchedcomes off in this act.On
main, ruling6328214336letter A is executed:/docs/protocol/backward-compatibility's Support Windows section states latest-only support. Only the current MAJOR receives fixes, and the previous MAJOR and every older one receive none, with no backport or maintenance release promised. An older app upgrades through ADR-0087's conversion layer (D2) andos migrate meta(D3). Its prerelease clauses rest onscripts/check-changeset-no-major.mjs, not on D6, which the ADR lists as deferred.The dev's out-of-scope release-currency pair is #25148 (p3).
Generated by Claude Code