Skip to content

docs(adr-0087): amend D8 predicate 4 and D9 predicate 1 for ui packages - #26455

Merged
os-zhuang merged 1 commit into
mainfrom
claude/project-thread-rcgxug
Oct 27, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/project-thread-rcgxug

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread

Part of #26220 (PR 1 of 2 for parts 3 and 4: the ADR wording. PR 2, the gate code, follows once this lands).

Clause-②: no
Metadata-protocol: none

Governed (Tier H): docs/adr/**. This PR stays a draft and is not queued or armed until a GOVERNED_APPROVERS account approves it.

维护者速读(草稿)

改了什么: 只改了 ADR-0087 一个文件,加了两条修订说明,状态行也记了一笔。

  • D8 谓词 4 加一个窄分支:接口除了 any 索引签名变成非 any(unknown 也算)以外,继承和所有成员逐字不变,就算收窄。
  • D9 谓词 1 的入口映射:除了 src/index.ts,也认 src/index.tsx。两个都有就判为歧义拒绝,都没有照旧拒绝。

为什么改: 有两个 ui PR 走真实处置被门禁拒。#26293 把 [key: string]: any 改成 unknown,原文只认“整体是 any”。#26365(plugin-ai 退役)卡在入口映射上:38 个发布的 ui 包里有 21 个入口是 src/index.tsx。两处都只影响 TS 消费者,账本不是正确渠道。这是你在决策卡上选的方案 A。

风险与代价(含回滚): 谓词 4 是 type-surface-only 豁免的唯一保险。新分支要求除索引签名外逐字相同,所以 #6048(删成员)的形状照样被拒,自测里的回归钉继续断言这一点。入口映射只按源文件名判断,不读构建配置。本 PR 只改文字;门禁代码在 PR 2,带电池行和消融。回滚:revert 本 PR;PR 2 落地后要一起 revert。

席位意见: 同意合入(ui 席 1)。两条修订都只放宽到实测挡住的那一类,没有顺手扩大。D8 的新分支只放行「声明成员完全不变、只有 any 索引签名收窄」这一种情况;#6048 那种丢成员的情况照旧被拒,回归钉还在。D9 只多认 src/index.tsx 一个入口,两个入口同时存在时按有歧义拒绝。被挡的是 #26293(#25918)和 #26365(#25921 plugin-ai 下线);PR 2 把检查脚本和测试补上后,会拿这两个 PR 证明 exit 0。

你要做的: 读两条修订说明(D8 谓词 4 下、D9 不可映射段落下),同意就批准本 PR。批准后由席位入队,然后开 PR 2。

What changes

docs/adr/0087-metadata-protocol-upgrade-contract.md only (+63 / −1):

  • Status line: one **Amended** (2026-10-27, #26220 …) entry pointing at the two notes.
  • D8, under predicate 4: amendment note "predicate 4 reads an any INDEX SIGNATURE". For a bare reference naming an exported interface, or a type alias whose right-hand side is an object type literal, predicate 4 also holds when (1) at base the member surface has at least one index signature typed any, (2) at HEAD at least one of them carries a non-any value type, with unknown counted as narrowed there only, and (3) heritage, type parameters and every member are otherwise identical, compared member by member on the masked, normalised surface. The note states why this is not a weakening: the feat(runtime)!: 退役 ctx.user 的 roles 别名,positions 成为唯一拼法 (#6011) #6048 shape (a member removed) fails condition 3 and keeps the founding-case refusal, and dotted member paths are untouched.
  • D9, under the unmappable-entry paragraph: amendment note "the source entry may be src/index.tsx". The declaration entry (dist/index.d.ts or its twins) maps to the package's one source entry, src/index.ts or src/index.tsx. Both present is refused as ambiguous, neither present is refused as before, and the build tool is never consulted.

Measured (main 83e9d718)

  • 38 published ui/ packages (46 manifests, 8 private). 21 have src/index.tsx, and all 21 name ./dist/index.d.ts as their types entry; their builds are vite-plugin-dts with insertTypesEntry: true.
  • No workspace package has both src/index.ts and src/index.tsx.
  • @objectstack/client-react (one of D9's four measured unmappables) builds with tsup src/index.tsx, the same shape.
  • fix(types,components)!: renderer props index signatures map to unknown, not any #26293's operand at its merge base: { schema: TSchema; [key: string]: any; } → HEAD { schema: TSchema; [key: string]: unknown; } (gate output at e349c832, predicate 4 refusal).

Gates

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derives 24 commands at 2494b54b (base 83e9d718). All 24 exit 0, including node scripts/check-adr-0087-registration.mjs --base origin/main and --self-test, node scripts/check-adr-links.mjs, node scripts/check-adr-symbol-anchors.mjs, pnpm check:adr-anchors, pnpm check:doc-authoring and pnpm check:pm-governed-merges. pnpm --filter @objectstack/lint run check:doc-formula-expressions first exited 3 (prerequisite: @objectstack/formula and @objectstack/lint dist not built); after pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint it exits 0. --ran: 24 derived, 24 run, 0 NOT-MEASURED, 0 UNRUN. No package or script is touched, so there is no build closure and no changeset (skip-changeset).

Acceptance notes


🤖 Generated with Claude Code

https://claude.ai/code/session_01Am8eYNReiNP66D2JihPS1q

D8: predicate 4 also holds when an exported interface's only change is
an `any` index signature moving to a non-`any` value type (`unknown`
counts as narrowed there); heritage and every other member must be
identical, so the #6048 member-removal shape stays refused.

D9: the declaration entry maps to the package's one source entry,
`src/index.ts` or `src/index.tsx` (vite-plugin-dts in ui/, tsup in
client-react); both present is refused as ambiguous.

Maintainer decision A on #26220 (claim amendment 6433464805).

Claude-Session: https://claude.ai/code/session_01Am8eYNReiNP66D2JihPS1q
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 27, 2026
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s 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.

3 participants