Skip to content

fix(docs): stamp the release index's "current series" at version time (#15332) - #15392

Open
hotlong wants to merge 2 commits into
mainfrom
claude/issue-15332-release-index-current-series
Open

fix(docs): stamp the release index's "current series" at version time (#15332)#15392
hotlong wants to merge 2 commits into
mainfrom
claude/issue-15332-release-index-current-series

Conversation

@hotlong

@hotlong hotlong commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Part of #15332

Part of, not a closing keyword, deliberately: this PR touches release.yml, so
landing it is gated on human review rather than on a green queue. The card should be
closed by a person, not by a merge.

What was wrong

content/docs/releases/index.mdx:21 ended the v17 entry with
(current series: 17.2.0, released 2026-08-23) while 17.3.0 had been on latest
since 2026-09-04 (version commit 8a1bad8b8, 69 packages). A reader arriving at
the release index was told the current series is one release behind.

This is the third occurrence of one defect class on three consecutive minors —
#10232 (17.1.0 shipped, index still on 17.0.0), #11649 (17.2.0 shipped, index still
on 17.1.0, recorded then as "#10232 recurring one release later"), and this one.
Three on three consecutive minors is a producer problem, not three authoring slips.

It is not only a patrol's tidiness finding. A customer-shaped 17.2.0 to 17.3.0
upgrade rehearsal, run against the published docs alone (hotcrm#1576 / hotcrm#1577),
hit it independently and filed it as its third documentation defect:

releases/index.mdx says "current series: 17.2.0", while upgrading.mdx:41 and
deployment/self-hosting.mdx tell you to pin 17.3.0 — the docs contradict each
other about what the current version is.

That is the argument for stamping it at version time rather than remembering next
time: a real upgrader walks into a self-contradiction, not a stale footnote.

What this PR does

1. The sentence is correct — and it was fixed by running the stamper, not by
hand. One line moved, only the trailing status parenthetical; the prose enumerating
17.0/17.1/17.2 is untouched. Writing a curated "17.3 adds ..." clause is
release-notes work (the v17.mdx lane, #15333), deliberately not authored here.

2. scripts/sync-release-index-currency.mjs joins the root version chain,
beside the three sync scripts already there. This is the shape this repo has already
chosen three times for this drift class — sync-protocol-version.mjs (#2769),
sync-template-versions.mjs (#2907), and the one this card was pointed at,
sync-docs-image-tags.mjs (#9064, landed as e569cac32). Reading that precedent's
mechanism out, since it is the same one here:

  • The gate cannot fire on the change that breaks it. sync-template-versions.mjs's
    own header: "release PRs opened by changesets/action with the default
    GITHUB_TOKEN do not trigger CI, so fixing the file at version time is the only
    spot that cannot be skipped."
  • Worse here than for the sibling surfaces: lint.yml runs
    check-release-section-coverage without --strict, where a finding is
    advisory and the job is GREEN by design. Only release-coverage-patrol.yml passes
    --strict. So the staleness reaches main green on every ordinary PR too, and
    only a standing after-the-fact patrol sees it.
  • Every list is imported, not restated: INDEX_PATH, SPEC_CHANGELOG, the
    scope predicate, the entry and status lookups and the verdict all come from
    check-release-section-coverage.mjs. The rewriter's verdict is literally
    indexCurrencyFindings() over the rewritten text — the gate's own function, in
    the gate's own words. One contract, two consumers, exactly as e569cac32 argued.
    (The gate gains two export keywords on constants it already had; nothing else
    in it moved.)

3. Two boundaries the file states and the self-test pins.

  • Assertion 2 only. A missing release-page section (assertion 1) never reaches
    this file's exit code. A rewriter cannot write curated prose — the gate's own
    header measures one minor's section at 69 package CHANGELOGs / 314 entries — and
    hard-failing the version lane on prose nobody has written yet would wedge it for a
    debt the release did not create. That is the same measurement (5h44m and 25 days,
    2748 PRs) on which the gate made its findings advisory.
  • One shape is rewritten, current series: X.Y.Z, released YYYY-MM-DD.
    A final release: N claim contradicted by a newer minor, an entry with no status
    parenthetical, and a prose parenthetical are all refused and fall through to
    the gate's own words, which then stop the run loudly. Each needs a sentence, not
    a token: whether a series called final has reopened is a human judgement, and
    stamping a number over it would hide the question rather than ask it.

The stamped date is the UTC day of the version commit. Measured against every entry
the index has carried: 17.1.0 / 47d1ae89e / 2026-08-20, 17.2.0 / e7d2cc67f /
2026-08-23, 17.3.0 / 8a1bad8b8 / 2026-09-04 — the date in the entry is the version
commit's day in all three, and this script runs inside that commit's own
pnpm run version.

4. Three callers now resolve the new surface, none of them by copying it.
release.yml's post-version validation and cut-rc.yml's staging allowlist both
enumerate what the version step is allowed to write, resolving each half at run
time
from the rewriter's own declaration. A new version-time output that is not
declared there is rejected. Measured on this tree with a synthetic moved-path list:

--- with the new list (this PR) ---
(no unexpected paths)
--- without it (what main does today) ---
content/docs/releases/index.mdx

That is the treadmill guard doing its job, and its failure text prescribes the
remedy verbatim: "Add the surface to the declaration its rewriter reads, and its
gate to the content half below — deliberately, in one reviewed diff."
So both lanes
now resolve a third list from syncedPaths(), which derives from the gate's
INDEX_PATH rather than copying it.

5. lint.yml runs the rewriter's self-test at PR time (commit a775c1f74),
beside the two sibling rewriter self-tests already in that job —
check:docs-image-tag-sync (#9064) and check:template-version-sync (#9348).
Third rewriter, third self-test.

⚠️ This is NOT the --strict promotion, and it cannot become one. Promoting
--strict into lint.yml would also red a release page with no section for a
just-published train, i.e. every PR between a version commit and its release-notes
PR — a policy question, deliberately not decided here. The new step runs only
--self-test
, whose cases are string fixtures: it never reads the live index for
currency and never reads a release page at all, so no corpus state can red it. The
advisory, non-strict Release section-coverage guard step is untouched — that
commit is 44 insertions and 0 deletions.

Two gates require a PR-time caller and both name this family:
check-self-test-wired ("a script CI runs that ships a --self-test must have that
self-test run by CI"), and dispatch-gates' "a deferred pair defers the LEAD, not
the load break"
— a family no every-PR workflow runs leaves its import edges
unwatched at PR time, so a change breaking the module load of
check-release-section-coverage.mjs (which this rewriter imports its surface, scope
and verdict from) would not redden the PR that made it.

On an RC cut this rewriter writes nothing at all: an -rc heading is not a GA
version, so the newest GA of the major does not move. The cut-rc.yml list is
declared so the one cut where the index is stale produces a complete commit
instead of a refusal.

Readings

All readings below were taken at head a775c1f74 unless a row names another
tree. The two ablation blob hashes are unchanged by the lint.yml commit
(HEAD:content/docs/releases/index.mdx is still 49effac452... and
HEAD:scripts/sync-release-index-currency.mjs still 34ae9b4103...), so those
numbers describe this head exactly.

Base of this branch: c4d1354e3. #15333 had not landed yet at that point — it
landed afterwards as 19be9dfcd. So the branch's own reading still carries the
v17.mdx half, which is that PR's and not this one's. No releases page other than
index.mdx is touched here, and v17.mdx was not edited to move a number.

node scripts/check-release-section-coverage.mjs --strict:

tree findings exit
c4d1354e3 (this branch's base) 2v17.mdx section + index.mdx currency 1
this branch, a775c1f74 1v17.mdx only (#15333's half, not in the base) 1
this branch merged with origin/main at a56baa2bd 0 0

The third row is a real run, on a clean merge of this branch with current main
(no conflicts; #15333 touched v17.mdx and upgrading.mdx, this PR touches
index.mdx):

check-release-section-coverage: OK — 6 published minor(s) across 2 GA major(s)
in scope (v16, v17); every one has a heading on its major's release page, and
every index entry names the newest release of its major.

The PR-time wiring, measured rather than derived

An earlier revision of this body said the post-fix green was derived from the
assertion's own predicate, not observed
. That is the shape of the very defect this
card is about — a declaration nobody wired to an implementation — so it has been
replaced with the run. pnpm check:pm-dispatch-gates, which is
scripts/pm/dispatch-gates.mjs --self-test:

tree exit verdict line
c4d1354e3 (base, control) 0 ✓ dispatch-gates self-test: 1382 cases pass.
f25f72589 (before the lint.yml step) 1 ✗ dispatch-gates self-test: 2 of 1382 case(s) failed.
a775c1f74 (this head) 0 ✓ dispatch-gates self-test: 1382 cases pass.

The two failures on the middle row, both naming this PR's new family:

x a deferred pair defers the LEAD, not the load break — every module carrying one
  is imported by an every-PR family as well, so failing to load still reddens the
  PR — SILENT: check:release-index-currency-sync imports
  scripts/check-release-section-coverage.mjs
x …and the reading does not depend on how wide PR-time is drawn: narrowing it to
  `pull_request` alone leaves the same zero

(the gate prints the first edge with an arrow; spelled as a word here so no
angle-bracket fragment reaches the GitHub body sanitizer)

Ablation 1 — the defect is really detected, and the mechanism really repairs it

Both legs proved on disk before any reading was taken; restore leg pinned to the
HEAD blob. No build leg: every participant is plain node reading source, so there is
no dist/ for a stale artifact to hide in.

HEAD blob for content/docs/releases/index.mdx : 49effac45223763a83321a8de50f1668534d1b8a
LEG 1 MUTATE — put the v17 status field back on 17.2.0
  anchor text present before mutation : 1
  anchor text present after mutation  : 0
  injected text present after mutation: 1
  on-disk hash after mutation         : 05a7d1508fb5d2b8bfa0891bbb8831e9df71684a
  gate --strict on the mutated tree   : EXIT=1, 2 finding(s), index.mdx currency back
LEG 2 RESTORE — by running the stamper (the mechanism under test)
  v17: (current series: 17.2.0, released 2026-08-23) to (current series: 17.3.0, released 2026-09-04)
  on-disk hash after the stamper      : 49effac45223763a83321a8de50f1668534d1b8a
  BYTE-IDENTICAL to the HEAD blob; git diff HEAD names 0 paths
  gate --strict on the restored tree  : EXIT=1, 1 finding(s) (v17.mdx only)

The stamper's output is byte-identical to the committed fix — the sentence in this
diff is reproducible from the CHANGELOG, which is the whole claim.

Ablation 2 — the stamper's own self-test can go RED

A self-test that cannot fail is not an instrument. Mutation: make the rewriter inert
(rewriteStatusField always refuses), the exact failure mode this shape exists to
rule out.

HEAD blob : 34ae9b41033002e68de7768e7c611f8c1155ee0e
  anchor lines before      : 1
  injected marker present  : 1
  on-disk hash after mutate: c508f101d5b2ea65e5dc564eabee6d6087bb26e7
  self-test on the INERT tree : EXIT=1, 11 failure(s) across batteries A, B, D, E
  on-disk hash after restore  : 34ae9b41033002e68de7768e7c611f8c1155ee0e  (back at HEAD)
  self-test on the restored tree : EXIT=0, 35 cases pass

Gate sweep

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack derives 81
families from this change set at a775c1f74 (the lint.yml commit added four to the
77 the previous head derived: check-merged-branch-reaper-outcome and its self-test,
check:type-check-coverage, check:type-check-debt). All 81 were run at this
head.

⚠️ Correction to an earlier revision of this body. It listed "the 8
pnpm --filter families" among the green at f25f72589. They had not been run
that sweep filtered them out of the command list and the claim was wrong. They are
run here, and four of them needed a build first; each is named below with its real
reading. Flagging rather than quietly fixing the sentence.

  • 79 green, including check:nul-bytes, check:entry-guard,
    check:self-test-wired (+ self-test), check:watch-hint-literal,
    check:declared-population-live, check:pm-dispatch-gates,
    check:release-notes, check:release-page-status,
    check:release-index-currency-sync, check:published-readme-links,
    check:doc-authoring, check:docs-single-h1, check:corpus-claim-drift,
    check:closing-keyword-parity, check:aggregator-roster,
    check:self-test-workflow-commands, check:step-collectors,
    check:workflow-status-functions, check:stall-guard-budget,
    check:stall-guard-headroom, scripts/pm/bare-root-worklist.mjs --self-test,
    and both ratchets, check:type-check-coverage
    (OK — 14 ledger entr(ies) re-measured in 121.9s, 153 raw tsc error(s) total, none above its recorded number) and check:type-check-debt.
  • Four of the pnpm --filter families first returned a prerequisite, not a
    finding, and are green once the closure they read is built —
    @objectstack/lint check:doc-formula-expressions and check:doc-security-posture
    (exit 3 with no dist/), @objectstack/spec check:docs (needs gen:schema), and
    @objectstack/spec check:skill-examples (exit 1 naming
    packages/client-react/dist holds no .d.ts declarations). After
    turbo run build over ./packages/* and ./packages/*/*, all four exit 0;
    check:skill-examples reports 257 prose examples type-check across 3 surface(s).
    check:dual-build-cjs-loads was the same story and is green on the built tree.
  • check-release-section-coverage.mjs --strict exit 1 — the v17.mdx half, see the
    table above; 0 once merged with current main.
  • check-required-contexts.mjs --verify-required-set exit 2 = NOT VERIFIED
    it needs a live GitHub read and this session's repo-scoped REST is gated
    (HTTP 403 GitHub access is not enabled for this session). Nothing measured, in
    either direction; not a finding and not a pass.

Changeset

skip-changeset, applied. Nothing here publishes from any package: the diff is
the docs site (content/docs/**), CI-internal scripts (scripts/**), three workflow
files, and the root manifest — which is private: true — where only the version
script string and one new check:* key moved. lint.yml's own note calls "this PR
edits a CI-internal script" the textbook skip-changeset case, "such a PR releases
nothing". ⛔ No empty changeset was written: an empty-frontmatter file is rejected by
#5471, and an all-empty set stalls the release silently (#4898).

Landing

⛔ Auto-merge is not armed and this PR was not flipped to ready by the author.
It touches release.yml, so the intended path is: CI green, then a maintainer flips
it ready and it stops there for human review, the same handling as PR #15331.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UHvF5hyiZjnCyExFnfQB8m

…#15332)

`content/docs/releases/index.mdx` ends each major's entry with a status
parenthetical — "(current series: 17.2.0, released 2026-08-23)". That sentence
is derived data: the newest GA of a major is already readable from
`packages/spec/CHANGELOG.md`, which is where check-release-section-coverage
reads it from to produce its finding. Kept by hand, it went stale on three
consecutive minors (#10232, #11649, and this one), each caught after the fact.

The gate that names it cannot fire on the change that causes it: the version
commit is opened by changesets/action with the default GITHUB_TOKEN and gets no
CI, and lint.yml runs the gate without `--strict`, where a finding is advisory
and the job is green by design. Only release-coverage-patrol.yml passes
`--strict`, and a standing patrol is an after-the-fact reader by construction.

Adds scripts/sync-release-index-currency.mjs to the root `version` chain, beside
the three sync scripts already there — the shape this repo chose for the
identical drift class in #2907 and #9064 (e569cac). It imports INDEX_PATH,
SPEC_CHANGELOG, the scope predicate, the entry and status lookups and the
verdict from check-release-section-coverage.mjs, so the rewriter and the gate
read one contract and the rewriter's verdict IS the gate's.

It rewrites exactly one shape, `current series: <x.y.z>, released <date>`, and
refuses the ones that need a human sentence — a "final release:" claim a newer
minor contradicts, an entry with no status field — which then reach the gate's
own words and stop the run. Assertion 1 (a published minor has a section) is
never consulted here: a rewriter cannot write curated prose, and hard-failing
the version lane on unwritten prose would wedge it for a debt the release did
not create.

release.yml's post-version shape assertion and cut-rc.yml's staging allowlist
both resolve the surface from `syncedPaths()` at run time, joining the two lists
they already resolve on the same terms — a fourth literal would be a fourth
contract. Measured: without that third list the post-version validation rejects
content/docs/releases/index.mdx as "outside the reviewed surface", which is the
treadmill guard doing its job.

The index line itself was fixed by running the stamper, not by hand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UHvF5hyiZjnCyExFnfQB8m
@github-actions github-actions Bot added size/l ci/cd dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation labels Sep 4, 2026
@hotlong hotlong added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 4, 2026 — with Claude

hotlong commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

A —— 加那一行,并且我要更正我自己的派发单

⚠️ 同会话自审披露:本条与本卡的派发、方向裁决出自同一会话(session_01UHvF5hyiZjnCyExFnfQB8m)。请人工复核者按同会话基线折价。

先说我写错了什么

派发单里我写的是「⛔ 不要顺手改 lint.yml,一行都不要」。那条禁令是写给方向 2 的 —— 把 --strict 提进 PR 门禁,它会在 version commit 到发布说明 PR 落地之间红掉每一个 PR。你要加的是另一种编辑,禁令不该罩到它头上。

⛔ 我把禁令写得比理由宽,这是我的错。你没有硬闯它、而是把它当开放问题问上来 —— 这是对的动作,而且比两个替代路径(硬闯 / 带着红交付)都好。

我自己验了你论证的承重点

不是复述你的正文,是我自己读的:

package.json:127
  "check:release-index-currency-sync": "node scripts/sync-release-index-currency.mjs --self-test"

它只跑 --self-test 所以它读的是字符串夹具,不读活的索引、不读任何发布页 —— 语料状态(包括「刚发布、章节还没写」的车次)红不了它。这正是方向 2 的全部代价所在,而这一步不带那个代价。

lint.yml 里也确实已经有两个同形兄弟:

:1899  - name: Docs image-tag version-time rewriter self-test
:1900    run: pnpm check:docs-image-tag-sync
:1958  - name: Template version-time rewriter self-test
:1959    run: pnpm check:template-version-sync

第三个改写器配第三个 self-test 步骤,是补齐既有形状,不是新增机制。

⛔ 边界写死,防止它日后漂移

  • 只加 一步,只跑 --self-test,放在那两个兄弟步骤旁边;
  • 绝不check-release-section-coverage 那一步改成 --strict;那条 advisory、非 strict 的步骤原样不动;
  • ⛔ 不动 lint.yml 的任何其他行。

裁掉 B 和 C 的理由用你自己的读数:B 是拿一个红换另一个红(脚本被两个工作流点名且带 --self-test,check-self-test-wired 会改红),而且让改写器唯一的仪器从此不被 CI 跑;C 让门禁去 import 改写器,把依赖方向倒过来还引入模块环。D 白花一轮。

关于 release.yml

我逐行读了那段 diff。它没有碰任何发布闸门 —— environment: releasepublish job 的谓词、npm 发布本身,一个字都没动;改的是 version 之后的校验 job。加白名单这件事本身是那道守卫自己的报错信息规定的补救:「把表面加进它的改写器所读的声明里,把它的门禁加进下面的内容半 —— 在同一个被复核的 diff 里,刻意地做」。你做的正是这个,而且两道拒绝守卫(解析不出 → exit 1、解析成 → exit 1)把反空转堵上了。

但这张 PR 我不会武装 auto-merge,和 PR #15331 同样处理:碰 release.yml 的改动必须人工复核放行。加完那一行、CI 绿之后我会翻 ready,然后停在那里。

两处我要单独记一笔

  1. 你在正文里写明「我没有实测修复后的 1382 / 1382,那个绿是从断言自己的谓词推出来的,不是观察到的」 —— 加完那一行请把它真的跑出来,把读数贴上。⛔ 一个推出来的绿,正是这张卡在修的缺陷类的形状。
  2. check-required-contexts --verify-required-set 退 2、check:dual-build-cjs-loads 退 3,你都记成未测量而不是通过或失败。对的。

Generated by Claude Code

Third version-time rewriter, third self-test step, beside the two already in
this job (check:docs-image-tag-sync, check:template-version-sync).

Two gates require a PR-time caller, and both name this family:
check-self-test-wired ("a script CI runs that ships a --self-test must have that
self-test run by CI"), and dispatch-gates' "a deferred pair defers the LEAD, not
the load break" — a family no every-PR workflow runs leaves its import edges
unwatched at PR time, so a change breaking the module load of
check-release-section-coverage.mjs would not redden the PR that made it. With
release.yml as the only caller that self-test was 2-of-1382 RED naming
check:release-index-currency-sync.

⚠️ Not the --strict promotion, and it cannot become one: this step runs only
--self-test, whose cases are string fixtures. It never reads the live index for
currency and never reads a release page, so no corpus state can red it. The
advisory, non-strict `Release section-coverage guard` step is untouched — this
diff is 44 insertions and 0 deletions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UHvF5hyiZjnCyExFnfQB8m

hotlong commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

复核 — PASS;翻 ready,⛔ 不武装

⚠️ 同会话自审披露:本 PASS 与本卡的派发、方向裁决、以及裁决 A 出自同一会话(session_01UHvF5hyiZjnCyExFnfQB8m)。请人工复核者按同会话基线折价。

三条边界,我自己在 a775c1f74 上读的

我设的 读数
只加一步 新增的可执行内容就两行(- name: + run:),其余 42 行是注释,与两个兄弟步骤同风格
⛔ 不动 lint.yml 其他行 这个提交只碰一个文件,44 insertions(+) / 0 deletions
⛔ 非 strict 那步原样 :2772-2773 仍是 --self-test + 裸调用,全文件--strict

我要的那个读数,你给了三点带对照

c4d1354e3 (基线,对照)     EXIT 0   ✓ dispatch-gates self-test: 1382 cases pass.
f25f72589 (加那行之前)     EXIT 1   ✗ dispatch-gates self-test: 2 of 1382 case(s) failed.
a775c1f74 (当前 head)      EXIT 0   ✓ dispatch-gates self-test: 1382 cases pass.

基线绿 → 破坏红 → 修复绿,而且全日志零个 。这是推导出来的绿给不了的东西:它同时证明了「这一行确实修好了」和「没有它确实会红」。原来那段推导已从正文删掉,换成这张表。

⛔ 你主动更正的那件事,是这一整轮里最有价值的动作

上一份报告把「8 个 pnpm --filter 家族」列进了 f25f72589 的绿名单。它们当时根本没跑 —— 那次 sweep 把它们从命令清单里滤掉了,那句话是假的。

你自己抓到、自己纠正、并且把更正公开写进 PR 正文,而不是悄悄改掉一句话

⚠️ 这正是今天这个会话反复付学费的那个缺陷类:把"没测到"记成"测过了"。它今天出现过四次 —— 一次发布校验(69 个包只看了 1 个就报失败)、一次归因错误(把启动模式当成版本差)、一次卡片断言了一条不存在的 lint 规则、一次是这个。四次里只有你这一次是被作者自己抓到的。

重跑之后四个返回 PREREQUISITE(无 dist/),构建后全绿 —— 你也把 exit 3 记成「未测量」而不是通过或失败。对的。

release.yml 那半,我逐行读过

没有碰任何发布闸门 —— environment: releasepublish job 的谓词、npm 发布本身,一个字未动;改的是 version 之后的校验 job。加白名单是那道守卫自己的报错信息规定的补救(「把表面加进它的改写器所读的声明里,把它的门禁加进内容半 —— 在同一个被复核的 diff 里,刻意地做」),而且两道拒绝守卫(解析不出 → exit 1、解析成 → exit 1)把反空转堵上了。

状态

38 个 check 全终态、全 success/skipped、零 failure;Lint & Repo Gates(现在带着那个新自测步)14:27:56 绿。与当前 main 干净可合并(git merge-tree 实算,⛔ 没等 mergeable_state)。

翻 ready。⛔ 不武装 auto-merge —— 与 PR #15331 同样处理:碰 release.yml 的改动一律人工复核放行。这不是对这份改动质量的怀疑,是那条通道的规矩。

⛔ 这条 Part of 用得对:实现完整了,但那一行 lint.yml 是我裁决之后才补的,卡片该由人工合并时关。


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/l skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants