Uh oh!
There was an error while loading. Please reload this page.
feat(types,mobile)!: retire the MobileComponentConfig published type - #7526
Conversation
`MobileComponentConfig` published a four-key mobile component-schema
extension (`responsive`, `gestures`, `pullToRefresh`, `infiniteScroll`)
that nothing read. Re-measured on current main: four code mentions
repo-wide (declaration, one doc cross-reference, two barrel re-exports),
no mount point, no reader, zero authors in the example apps or the
objectstack sibling checkout.
Removed outright rather than tombstoned with `?: never`: the whole
interface goes, so there is no surviving object to hang a never-key on,
and no documentation ever taught it. Same zero-pull, no-successor shape
as MobileOverrides (objectui#4919).
The dangling `{@link MobileComponentConfig}` cross-reference on
MobileResponsiveConfig is rewritten rather than left pointing at a
removed name; that type and GestureConfig become zero-consumer published
types as a result, recorded as objectui#7519 rather than widened here.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EMrWaQw3XS5DxTHxp4yRyC✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-project-manager
commented
Sep 3, 2026
受托契约复核:FAIL(窄口径) —— 一处需改,其余全部独立复现
转录档位核验(维护者 2026-08-27 裁),采信前先做:该复核者转录 73 个 assistant 轮次,73 个全部 stamped 按同一裁定,派发席只可逐字采信或整份作废,⛔ 不得改写、删节或润色。以下是复核者原文。 ⛔ 简报中未包含本席的任何判断,这是刻意的 —— 独立复核的意义是重新推导,不是确认。 裁断:FAIL(窄口径——只有一处需要改,其余全部复现)被击穿的一点:PR 把 一、我独立复现的读数(命令 + 数字)基线:GitHub 报 base 攻击点 1:计数
PR 列的四处行号(626 / 50 / 283 / 68)逐字命中。注意分类脆弱: 攻击点 3:"唯一消费者"
③ 边界标记
攻击点 2:外部消费者探针scratchpad 独立目录,
N 在 before 腿就报错,证明 before 腿的 exit 0 是"真解析到名字"而不是仪器把整包解析成 ① 派生判断
② semver
验证联合
二、复现不了 / 与 PR 不符的读数
三、试过但没击穿的角度
四、要 PASS 需改什么
复核用的两个工作树保留在 派发席处置FAIL ⇒ 补丁轮,⛔ 不放行。PR 保持 draft + ⭐ 这个击穿点是本轮最值得记的一条,因为它是注释机制层面的:
补丁轮的三条要求按复核原文执行(第 3 条为建议,不阻塞)。补完重新提交复核。 Generated by Claude Code |
…tted .d.ts Contract-review patch round. The retirement note left by the previous commit is a `//` line comment, which TypeScript's declaration emit strips; the rewritten JSDoc on MobileResponsiveConfig pointed at it with "see the RETIRED note below" and also said "widened into that PR". Both survive into the PUBLISHED packages/types/dist/mobile.d.ts, where neither resolves -- measured on the PR head: the pointer string occurs once in the emitted file and its target zero times. The JSDoc now carries only references an external reader of the .d.ts can resolve (objectstack#4115, objectui#5942, PR objectui#7526, objectui#7519, and a repo-relative test path), and it no longer names the retired symbol at all -- which also restores the property the precedent PR reported, that the retired name occurs zero times anywhere in the emitted declarations rather than only in the two index.d.ts barrels. Also drops "for objectui's mobile component overrides" from the same block: it named the concept retired by objectui#4919, so it was stale twice over. Changeset gains a warning that TS2724's "Did you mean 'ComponentConfig'?" is a lexical near-match, not a migration target -- ComponentConfig is the renderer registration record. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EMrWaQw3XS5DxTHxp4yRyC
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-project-manager
commented
Sep 3, 2026
受托契约复核 第二轮:PASS(head |
读数(packages/types/dist/mobile.d.ts 除非注明) | 旧 head c0eb3eb2f | 新 head 37f82c558 |
|---|---|---|
grep -c 'see the RETIRED note below' | 1 | 0 |
grep -c 'RETIRED' | 1(即那句悬空) | 0 |
grep -c 'that PR' | 1 | 0 |
grep -c 'mobile component overrides' | 1 | 0 |
grep -rn MobileComponentConfig packages/{types,mobile}/dist --include='*.d.ts' | 1(mobile.d.ts:42) | 0 |
grep -rho MobileComponentConfig packages/*/dist(39 个 dist) | — | 0 |
对照点亮(同一轮):MobileResponsiveConfig -w 3、GestureConfig -w 6、BaseSchema -w 44 个文件。被指向的注释在已发布文件里为 0,指向它的句子也为 0——悬空消失是因为指针被删,不是目标被发布。名字在全部已发布 .d.ts 里归零,#5941 那条"退休名不漏进 dist"的性质被恢复。
二、补丁有没有开新口子
新 JSDoc 的每个引用,用 emitted 文件逐个数:objectstack#4115 = 6、objectui#5942 = 1、objectui#7526 = 1、objectui#7519 = 1、page-nav-misc-spec-parity.test.ts = 4——与 PR 正文报的五个数逐字相同。"the spec name-ownership tripwire named next" 指向同一 JSDoc 块内下一段 "Tripwire: …",在 emitted 块里自洽。SpecResponsiveConfig 确是 packages/types/src/index.ts:1343 的导出。文件里剩余的 "below" 两处(:114、:202)都是补丁前就有的,且各自的目标(PWAConfig 邻接段、{@link SpecGestureConfig})都在同一 emitted 文件内。整个文件 "above" = 0。
"整 dist 口径"是否真整:PR 给的三条命令我原样跑了,packages/{types,mobile}/dist 与 packages/*/dist(39 个 dist 全在)都是 0;PR 说 "MobileResponsiveConfig still occurs 3 times across packages/*/dist",我测 3。口径是整的。
非阻塞第三条做没做对:
- feat(types,mobile)!: retire the MobileOverrides type and its mount point (#4919) #5941 措辞:正文改为 "states the discriminator … merged with zero reviews (opened 02:37, self-merged 02:51), so it 'established' nothing procedurally … rests on objectui#4919's recorded maintainer ruling"——与我第一轮
get_reviews=[]、时间戳、finding(types):MobileOverrides.navigation发布了三值导航词表,全仓零读点 —— 与 #3985 同族的另一处「声明即全部」 #4919 裁定链的读数一致,做对了。 - changeset 新段 "Do not follow the compiler's suggestion":声称
ComponentConfig是 "{ type: string; component: T }, extendingComponentMeta"。git show 37f82c558:packages/types/src/base.ts第 757 行:export interface ComponentConfig<T = any> extends ComponentMeta { type: string; component: T; }——逐字属实。"import from@object-ui/mobilegets a plain TS2305 with no suggestion" 与我的探针 A2 一致。做了,且做对。
裸数字是否仍在转发:正文新增了一整段"That count depends on where you cut, so here is the cut",明写 3 / 4 / 5 三种切法并说 "the bare number should not be forwarded without the cut";之后的小结句仍写 "four code mentions",但在同一节、紧跟切法定义之后。changeset 第 15 行 "exactly four code mentions repo-wide — its own declaration, one doc-comment cross-reference, and the two barrel re-exports",枚举本身就是切法。可接受,不构成新问题。
changeset 作为会进 CHANGELOG.md(在 files 里随 tarball 发布)的文本:扫 "below / above / this PR / that PR / see the / RETIRED note",只命中 "See skills/objectui/guides/mobile.md",是仓库路径引用而非相对指针。引用计数 objectui#4919 3、#5942 1、#7519 1,均为可解析编号。
回归:消费者探针五项与上一轮 after 腿完全一致(A TS2724、A2 TS2305、C 0、N TS2305、D TS2307);四个 changeset 门禁 exit 0(presence 仍是 "3 source file(s) of 2 released package(s) … 1 changeset(s)");两包 type-check exit 0;三个改动文件 eslint exit 0;控制字节 0 命中;pnpm exec vitest run packages/types/ packages/mobile/99 / 1651 passed。
三、check:readme-exports 是否真绿
- 仪器对照:只建 2 包时
node scripts/check-readme-exports.mjs→ exit 1,"population COLLAPSED … 757 export symbol(s) read from 3 of 40 … 34 unbuilt"。这就是第一轮 NOT MEASURED 的状态,我复现了。 - 全量:
pnpm exec turbo run build --filter='./packages/*'(readme-exports.yml第 92 行的原命令)→ 39 个 dist;再跑门禁 → exit 0,判定行 "421 of them self-imports judged (421 real, 0 wrong-path, 0 fabricated); 3310 export symbol(s) read from 37 of 40 tracked package(s) (0 unbuilt, 3 declare no types)"——与 PR 报的四个数逐字相同。 - 绿得对不对:
--list里packages/types/README.md8 条、packages/mobile/README.md5 条自引用全判real,没有一条是MobileComponentConfig——门禁存在的目的正是抓"README 教了一个被删的导出",这里它有完整种群且没抓到东西,是真读数。 - 口径标注:turbo 报 "39 cached, 39 total",2 秒完成——其余 37 包的 dist 是按输入哈希从缓存恢复的,两个受审包是我从零编译的。独立旁证:CI 在新 head(commit 16:58:45Z,check 起跑 17:02:32Z)的
README Export Checksuccess,该 workflow 先pnpm install再全量turbo run build再跑门禁,是从零构建的种群。升级成立。
四、试过但没击穿的角度
- 新 JSDoc 逐引用计数 / 块内 next 指向 / 文件级 below-above 扫描 /
SpecResponsiveConfig导出存在性。 - 整 dist 口径(2 包与 39 包)+ 三个点亮对照。
- changeset 里的相对指针 / 事实主张(
ComponentConfig形状、TS2724 文本、TS2305 无建议)。 - turbo 缓存是否可能掩盖新 head 的 dist——两包本机从零编译且 mtime 晚于 checkout;恢复后的读数与恢复前一致。
- 补丁是否触碰代码——只有注释与 changeset;type-check / vitest / 门禁 / CI 32 项全绿。
五、留给 docket 的非阻塞观察(不影响裁断)
- emitted JSDoc 里的 "Tripwire:
__tests__/page-nav-misc-spec-parity.test.ts" 指向的文件不在 tarball(files: dist, README.md, CHANGELOG.md, LICENSE)。这是该文件四处 JSDoc 共用的既有写法,补丁前就在,不是本轮引入。 - 新开头句 "for the mobile renderer's box layout"——"mobile renderer" 是同一块第 11 行早已在用的说法,但目前没有渲染器读这个类型;一致但略有张力,属 finding(types): retiring
MobileComponentConfigleavesMobileResponsiveConfigandGestureConfigas zero-consumer published types #7519 的题。
派发席处置:放行
PASS ⇒ 剥双载体 needs:contract-review(PR 与卡片)、ready、auto-merge。
⭐ 本轮最值得留下的一条,是实现者选了指令没给的第三条路:单子给了「重写 JSDoc」与「若保留退休名字在散文里就声明口径差异」两个选项,它让新 JSDoc 完全不提MobileComponentConfig —— 于是退休名字在全部 39 个 dist 里归零,恢复了 #5941 的口径而不是偏离它,⇒ 连声明都不必了。复核者用「悬空消失是因为指针被删,不是目标被发布」一句点破了这个区别。
非阻塞观察两条已记,其中第 2 条归 #7519。
Generated by Claude Code
Uh oh!
There was an error while loading. Please reload this page.
Fixes#5942
Retires
MobileComponentConfigvia the ADR-0049 enforce-or-remove route, following theMobileOverridesretirement pattern (objectui#4919, PR objectui#5941) that triage named. This narrows a published surface, so the PR is a draft carryingneeds:contract-reviewand is for the docket to clear, not for me to land.The card is dated 2026-08-24. Every premise was re-measured against
origin/mainata27d153c2before anything was deleted, and all of them hold.Patch round: what contract review caught, and the fix
Review returned FAIL (narrow) on
c0eb3eb2fand it was right. The defect was in this PR's own doc edit, on the very surface it claims to protect.The retirement note is a
//line comment, which TypeScript's declaration emit strips. The rewritten JSDoc onMobileResponsiveConfigpointed at it with "see the RETIRED note below", and JSDoc is emitted. So in the publishedpackages/types/dist/mobile.d.tsthe pointer survived and its target did not — one dangling reference traded for another, this time on the published surface. The same paragraph said "widened into that PR", which no external reader of a.d.tscan resolve. Reproduced independently before fixing, on the review tree atc0eb3eb2f:Why I did not catch it myself, stated plainly: my after-leg dist measurement checked only the two
index.d.tsbarrels and reported "0/0". objectui#5941, the precedent I was copying, measured all ofpackages/*/dist. Having changed the comment mechanism — moving explanation into a live type's JSDoc — I silently lost the property that caliber was protecting. Narrowing a measurement without declaring it moves the evidence away from where the defect is.The fix (
37f82c558) rewrites the JSDoc so every reference resolves for someone reading only the.d.ts—objectstack#4115,objectui#5942, PRobjectui#7526,objectui#7519, and a repo-relative test path, each verified present in the emitted file — and it no longer names the retired symbol at all. That is deliberately not a declared divergence from objectui#5941: dropping the name restores that PR's property exactly, so the retired name now occurs zero times across every emitted declaration rather than only in the barrels. It also drops "for objectui's mobile component overrides" from the same block, which named the concept objectui#4919 retired and so was stale twice over.Two separate measurements, because "no reader in the repo" and "not published" are different facts
The card says "four mentions, all barrels/self-references". That phrasing is consistent with the type being on the published surface, and it is — measured, not inferred.
Table 1 — in-repo readers: zero
Read-shape probes over the whole tree, all file types. Every zero is paired with a control lit in the same run, because a probe whose query shape is wrong returns zero too.
MobileComponentConfig: SComponentSchema= 11S[]ComponentSchema[]= 1<SRecord= 815extends SBaseSchema= 159implements Sas SRecord= 1053| SSchemaNode= 103& S*Schema= 2keyof/typeof Skeyof= 342export interface SSibling
objectstackcheckout, case-insensitive, all file types: 0 hits, withComponentSchemalit at 255 hits in the same run.Bare-word counting would have been wrong here, which is exactly why the table is shaped this way.
MobileComponentConfighas seven bare-word occurrences today, not four: objectui#4919's own retirement note and its pending changeset both name the type in prose.That count depends on where you cut, so here is the cut. Three occurrences are load-bearing code — the declaration and the two barrel re-exports. A fourth is a JSDoc cross-reference, which is code-adjacent in a way that turned out to matter: declaration emit publishes it, which is exactly how this PR's first round went wrong. A fifth lives in a
//line comment insidemobile.tsand is stripped from emit, so by the same test it is prose. The card's "four" is the first four under that cut; "5 mentions in.tsfiles" and "3 real code references" are the same tree measured differently, and the bare number should not be forwarded without the cut. Under every cut, the number of reads is zero:Members are
responsive,gestures,pullToRefresh,infiniteScroll—mobileOverridesremoved by objectui#5941, as the card predicted. Premise intact on every axis: zero mount points, zero readers, four code mentions.Table 2 — published-surface reachability: it IS published, from two packages
packages/typesbarrelsrc/index.ts:626, insideexport type { ... } from './mobile.js'— the package ROOT barrel, one hoppackages/mobilebarrelsrc/index.ts:68, insideexport type { ... } from '@object-ui/types'— root barrel, one hop@object-ui/typesexportsmap"." -> ./dist/index.d.ts; package is not private, version 17.6.0@object-ui/mobileexportsmap"." -> ./dist/index.d.ts; not private, 17.6.0packages/types/dist/index.d.tspackages/mobile/dist/index.d.tsThe
./mobilesubpath is not in the exports map and there is no wildcard subpath, sopackages/types/dist/mobile.d.tsis not directly importable — but the root barrel re-exports the name, so it reaches consumers anyway. That is the distinction that matters: reachability is a property of the barrel chain plus the exports map, not of the declaring file.Conclusion: Clause-2 yes. This is a breaking narrowing of a published surface, and the card's own description matches what is on disk.
The loud-signal requirement, measured with a real consumer on both legs
A removal from
src/proves nothing about what consumers see, so an external consumer was compiled against the built.d.tsthrough the realexportsmap (its own directory, its ownnode_modulessymlinks,moduleResolution: bundler), on both sides of the change.import type { MobileComponentConfig } from '@object-ui/types''"@object-ui/types"' has no exported member named 'MobileComponentConfig'. Did you mean 'ComponentConfig'?@object-ui/mobile(the second barrel)Module '"@object-ui/mobile"' has no exported member 'MobileComponentConfig'.MobileResponsiveConfig, a still-live export from the same file and the same barrelsRow A/A2 before the change is the card's defect reproduced exactly: the dead type imports cleanly from both published packages and type-checks. The control is what makes the after column mean something — if the probe had been misconfigured, A would have "failed" for a reason indistinguishable from success.
Ablation discipline, both legs: the mutation was confirmed on disk by anchored counts in both directions (deleted-text anchor
export interface MobileComponentConfig0 to 1, injected-text anchorRETIRED (objectui#59421 to 0), each leg was rebuilt, and the mutation was confirmed to have reacheddistbefore any reading was taken (types/dist/index.d.tsandmobile/dist/index.d.tsat 1/1 on the before leg, 0/0 on the after leg). The whole script ran under a restore trap using absolute paths. Restore was proven by observed state, not by an exit code:git diff HEADempty,git status --porcelainempty, and all three files byte-exact against their HEAD blob hashes, then rebuilt back to zero.The consumer probe was re-run unchanged at the patched head
37f82c558and returns the same two diagnostics, since the patch round touches doc comments only and moves no exported name.dist evidence at the whole-dist caliber
This is the measurement the first round narrowed and review restored. Rebuilt at
37f82c558, the two commands review named plus the widest form:The three strings review flagged are gone from the emitted file:
see the RETIRED note below1 to 0,widened into that PR1 to 0,mobile component overrides0. Controls in the same run, so a zero is a reading and not a broken instrument:MobileResponsiveConfigstill occurs 3 times acrosspackages/*/dist, and every reference the new JSDoc makes is present in the emittedmobile.d.ts—objectstack#4115(6),objectui#5942(1),objectui#7526(1),objectui#7519(1),page-nav-misc-spec-parity.test.ts(4).Which retirement branch, and the precedent it copies
Branch (a): one-stage removal, source retirement note, no
?: never. This PR completes the card; there is no stage 2.Copied from objectui#5941 (
MobileOverrides), which states the discriminator on this exact file. Stated honestly, because review checked: objectui#5941 was merged with zero reviews (opened 02:37, self-merged 02:51), so it "established" nothing procedurally. What carries authority is the outcome shape it implements, which does rest on objectui#4919's recorded maintainer ruling, plus the retirements it tabulates (AccordionItem.icon,ToggleGroupItem.icon,confirm,hoverable/striped) — each independently checkable in source. The discriminator stands on that evidence, not on the precedent PR's review status:?: nevertombstone exists to steer authors to a named live replacement key, or to keep loud a key the docs actively taught as working;Neither tombstone reason applies, and one of them is structurally impossible here:
MobileOverrideswas a type reached through a key (mobileOverrides?:) on a surviving interface, so aneverkey had somewhere to live.MobileComponentConfighas no mount point at all — the whole interface goes, and there is no surviving object to hang aneverkey on. Keeping the interface with all four members retypedneverwould publish a carcass nothing could reach, which is the declare-without-enforce shape the route exists to close.On the docs half: no published documentation ever described this type.
skills/objectui/guides/mobile.mdteaches the React hooks (useGesture,usePullToRefresh,ResponsiveContainer,useBreakpoint) and never namesMobileComponentConfigor its keys as a metadata surface; zero occurrences in any.md/.mdxin the repo outside objectui#5941's own changeset prose.No ledger verdict is demanded, checked rather than assumed. The ADR-0087 /
retiredKey()registry path governs metadata-spec keys with a Zod twin;packages/types/src/zod/has nomobile.zod.ts, so the loud-parse-rejection half has nothing to attach to.zod/tombstone.zod.tsis the ADR-0049 helper for schema keys and names nothing here.internal/retired-field-keys.tsis a FIELD-key registry for the designer strip sites; a type name is not a field key. objectui has no liveness-ledger machinery. Triage's stop-and-report conditions were therefore all checked and none fired.What changed
Three source files and one changeset — the same footprint as objectui#5941.
packages/types/src/mobile.ts— the declaration replaced by the RETIRED note (the tombstone), carrying the measurement, the discriminator, the fact that no behaviour is retired, and the reopen condition.packages/types/src/mobile.ts— the{@link MobileComponentConfig}cross-reference inMobileResponsiveConfig's doc comment rewritten. It would otherwise dangle at a removed name, and the sentence it made ("It is consumed only byMobileComponentConfig") would be false.packages/types/src/index.ts— barrel re-export removed.packages/mobile/src/index.ts— barrel re-export removed..changeset/5942-retire-mobile-component-config.md—minorfor both packages.The changeset opens with "Removes a published export." and carries an explicit
## Upgradingsection rather than leaving the break implicit. Its guidance, verbatim:minornotmajor, per AGENTS.md 版本号策略, which reservesmajorfor following@objectstackacross a major — the same classification objectui#5941 used for an identically breaking type removal.check-changeset-no-majorconfirms it.Consequence worth the docket's attention, deliberately not widened into this PR
MobileComponentConfigwas the sole consumer of two other published types declared in the same file:After this change both are zero-consumer published types, one level down the same lineage. Visible in the dist controls:
MobileResponsiveConfig4 hits to 3,GestureConfig7 hits to 6 — each losing exactly its mount point and nothing else.Filed for triage as objectui#7519 rather than widened here, for the same reason objectui#5941 filed this card instead of widening:
MobileResponsiveConfigcarries a spec name-ownership tripwire that outlives the type, and retire-vs-implement is a product call. Their live siblings on the same file —GestureType,GestureContext,ResponsiveValue— are genuinely read byuseGesture.ts,useSpecGesture.ts,breakpoints.tsanduseResponsive.ts, and are untouched.Verification
Verification union re-ran in full against the final commit,
37f82c558, with a clean tree; the figures below are that run, not the first round's. Exit codes captured before any pipe; results quoted from each gate's own verdict line.pnpm --filter @object-ui/types --filter @object-ui/mobile build— exit 0;dist completeness: 118 emitted files verified(types) and51(mobile)pnpm --filter @object-ui/types --filter @object-ui/mobile type-check— exit 0; both script names echoed (type-checkis hyphenated in this repo), so not a zero-match silent passpnpm exec vitest run packages/types/ packages/mobile/ --maxWorkers=2—Test Files 99 passed (99),Tests 1651 passed (1651). 99 = 95 types + 4 mobile counted on disk, so the filter matched these packages and nothing elsepnpm --filter @object-ui/types --filter @object-ui/mobile lint— exit 0; 180 files linted (159 + 21), 0 errors, 285 warnings all pre-existing in tests/examples. All three changed files: 0 errors, 0 warningscheck:control-bytes— OK, 6195 tracked text files scanned; plus a manual control-byte scan of the four changed filescheck-changeset-presence—3 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)check-changeset-no-major/check-changeset-fixed/check-changeset-overwrite— exit 0check:published-dist—No published package's build output carries tooling material(this one builds all 43 packages first, 6m50s, which is why the run below is worth having)check:readme-exports— now green on a FULL population, which the first round could not achieve:421 of 421 self-imports judged real, 0 fabricated, 0 wrong-path,3310 export symbol(s) read from 37 of 40 tracked package(s),0 unbuilt. In round one this gate exited 1 withthe population COLLAPSED -- this run proves nothingbecause only 3 of 40 packages were built in that worktree; that was a prerequisite failure, not a verdict, and it is now resolved rather than argued around. Removing an export from two barrels is exactly the change this gate exists to catch, so it should be a real reading and now ischeck:spec-symbols,check:doc-types,check:self-import,check:phantom-deps— all exit 0One honest note on scope:
eslint .(this repo's real lint command and its real granularity —lintis a per-package turbo task), the file counts are eslint's own--format jsonoutput, and type-aware linting is not configured ineslint.config.js(noproject, noprojectService, norecommendedTypeChecked), so this diff cannot move the verdict of any file it did not touch. The repo-wide farm is CI's run.Scope
Three source files and one changeset. No
content/docs/releases/edit. No gate ceiling raised, no test skipped or disabled. Left as a draft withneeds:contract-reviewfor the docket.🤖 Generated with Claude Code
https://claude.ai/code/session_01EMrWaQw3XS5DxTHxp4yRyC
Generated by Claude Code