Skip to content

[Decision] ADR-0087: a changeset that retires published runtime exports and carries a FROM → TO block has no honest disposition category: a seventh category (A), a registered D3 entry (B), or a dated reading plus a looser detector (C)? #22915

Closed

Description

@objectstack-fleet

Ruled: 6116351873 · letter A · 2026-10-12T01:53Z

Filed by the domain:services seat 2 (seat post #21118, session_013LbZ9MhPp1iriZEtgJqioA) at the maintainer's request in session chat (「ADR-0087 的分类缺口,开决策卡?」), from the at-tier contract reviews on PR #22875 (6113872462, 6114282872). Filing gate ②: only the maintainer can make this call. Every option either edits ADR-0087 (governed text) or changes what check-adr-0087-registration admits, and #13080's triage placed exactly that class in the decision box. ⛔ Not a claim.

维护者速读

  • 事情: 一个包删掉已发布的运行时导出(函数、常量、插件选项)时,changeset 会给使用者写一段「旧名字 → 改用什么」的迁移列表。ADR-0087 要求每份声明破坏性变更的 changeset 选一个处置分类,现有六类里没有一类能如实对上这种情况。
  • 选项:
    • A: 新增第七类 runtime-export-retired,带可复查的谓词。
    • B: 这类变更改走 registered,每次写一条 D3 迁移条目。不改 ADR、不改门禁。
    • C: 只在 ADR 附录写一句读法,并让检测器不把只涉及代码导出的迁移列表算作处方。
  • 席位推荐 A,退而求其次 B。 请回一个字母:A / B / C。

One-sentence problem

When a package retires published runtime exports and its changeset tells consumers what to call instead (a FROM → TO block), ADR-0087 offers no disposition category that states this honestly. The catch-all no-migration-prescription holds today only because the gate's prescription detector misses list lines that carry no arrow.

Background (measured)

Options × real cost × workload

Option What it does What an author sees Workload
A A seventh category, not-required (runtime-export-retired <package>#<name>[, ...]), with re-runnable predicates. Each named export is reachable from the package's published entry at the merge base and absent at HEAD. None is a metadata surface (not *.zod.ts, not packages/spec/src/contracts/**, not an object definition) and no metadata surface references it at the base. A FROM → TO block is admitted only when its FROM operands are exactly the named exports. A retirement changeset names what it removed and keeps its migration block; the gate verifies the claim. domain:devx, one PR touching docs/adr/** (governed, so a human merge) plus gate predicates and self-tests. Precedent: #13080's sixth category, PR #13596 (+956 / −10).
B No new category. A retirement that carries a FROM → TO block registers an ADR-0087 D3 semantic entry (registered <id>), so os migrate meta and the upgrade guide carry the prescription. One extra entry file per such changeset (about 40 lines); the upgrade guide gains host-code migration lines beside metadata ones. None now; per changeset afterwards. No ADR or gate change.
C A dated reading in ADR-0087's addendum: a FROM → TO block that names only package exports or plugin options is not a migration prescription in ADR-0087's sense. The detector stops counting such lines. Authors keep no-migration-prescription; the gate admits by rule instead of by miss. domain:devx, one PR touching docs/adr/** (human merge) plus a detector change.

⛔ Not offered: the status quo. Keeping the catch-all on a detector miss is the shape D7 was written to retire. The next retirement whose list lines carry an arrow gets refused, and its author is pushed to drop the block or the BREAKING banner: the failure #13080 recorded.

Four axes (from the business side)

Recommendation, fallback, confidence gap

After the ruling

  • A: a domain:devx card implements the category: ADR-0087 addendum, gate predicates, self-tests and the worked example. Governed PR, human merge. Existing changesets are not re-graded; new ones use the category.
  • B: the ruling is recorded on this card, and the next retirement changeset registers a D3 entry. The pending 15205-* changesets stay as they are, since they ship before any rule change takes effect.
  • C: a domain:devx card writes the dated reading and the detector change. Governed PR, human merge.
  • In every case this card closes as its decision record.

os-decision-facets
① 项目长远合理性:A 沿用 D7/#13080 的「点名 + 可复查谓词」;B 让迁移账本混入宿主代码条目,与 D7 推理相反;C 以散文放宽检测器。
② 实际业务拉动:#15205 两个阶段实测撞上;v18 退役批次会再遇到;但 80 份兜底 changeset 里确定只有 1 份属于这一类。
③ 防 AI 犯错:A 逐个核对点名的导出,写错即拒;C 写了就放行;B 只核对条目 id,不核对内容。
④ 创业阶段不扩散:B 零成本,不加门禁复杂度;A 给现有门禁加一类(约千行,有先例);C 改动最小但放宽门禁。

Prior rulings read: D7 (#8299, PR #8456, the runtime-interface-only category); #13080's ruling 5468992520 (the sixth category type-surface-only, maintainer 「同意」 2026-08-30, PR #13596); #17357 (the detector's heading-denial fix); thread: PR #22875's reviews 6113872462 and 6114282872.

Dedupe (MCP search_issues, closed cards included):


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #319 item 1 · letter A · maintainer 「22915 同意」 2026-10-12T01:53Z

    Director seat, summon #37, session_01LqNgdPZB2Jnr5HpGbaqLeB (GitHub os-zhuang; written as objectstack-fleet[bot] via the relay). Batch #319 (two cards, this one first) was presented in chat with this seat's own readings and the recommendation "A, fallback B"; the maintainer answered 「22915 同意」, which takes the recommendation. Freshness gate: the body re-read before this record; the card carried no comment. Thread-read: none.

    Premises re-run on origin/main (7dbb89dc) in this act: the ADR-0087 addendum's closed vocabulary lists exactly six categories, no-migration-prescription "is refused by a body that carries a migration prescription", and runtime-interface-only "inherits the no-migration-prescription refusal"; D7 (:747) names the compiler as the channel and records that the earlier exemption "was held by a detector miss rather than by a positive finding"; PR #22875 merged as 7de0265fc7 with 15205-email-templates-resolve-registry.md carrying a FROM → TO block under no-migration-prescription; 81 pending changesets declare BREAKING and hold no-migration-prescription (the card counted 80 before #22875 landed).

    The ruling

    A: ADR-0087 gains a seventh disposition category for a changeset that retires published runtime exports and carries a FROM → TO block, resting on re-runnable predicates.

    • Spelling: <!-- adr-0087: not-required (runtime-export-retired <package>#<name>[, ...]) <why> -->.
    • Predicates the gate re-verifies on every run: each named export is reachable from the package's published entry at the merge base and absent at HEAD; none is a metadata surface (not *.zod.ts, not packages/spec/src/contracts/**, not an object definition) and no metadata surface references it at the base; a FROM → TO block is admitted only when its FROM operands are exactly the named exports. The category inherits nothing it cannot prove: a body whose FROM operands name anything else keeps the no-migration-prescription refusal.
    • The addendum records the category beside runtime-interface-only and type-surface-only, with the worked example (15205-email-templates-resolve-registry.md) and its measured history, as the two neighbours have.
    • Existing changesets are not re-graded; new retirements use the category.
    • ⛔ Not taken: B (register a D3 metadata-migration entry per such changeset: host-code renames in the ledger os migrate meta and the upgrade guide carry, against D7 / D8's reasoning that the compiler, not the ledger, is the channel for a TypeScript consumer); C (a prose reading that a FROM → TO block naming only package exports is not a prescription, with the detector relaxed to match: the gate would admit by the author's word, the shape D7 was written to retire).

    Why on the first axis

    ADR-0087's vocabulary is closed and every exemption rests on a positive, re-runnable finding; D7 and #13080 added the two neighbouring classes exactly this way. A compiler-carried retirement of published exports is a third such class, and it recurs with ADR-0131's v18 retirements. 自检:只看①选 A;②③④ 是否翻转:否(② 面窄:确定 1 份、疑似 2 份;③ A 逐个核对点名的导出,写错即拒;④ 偏 B,成本差确定,但 B 的代价是迁移账本混入宿主代码条目)。A is more than 3× the cost of B; the first-axis readings are not close (B contradicts D7 / D8), so the letter stands.

    Workload (#22597's rule): domain:devx · 1 PR touching docs/adr/0087-metadata-protocol-upgrade-contract.md (governed, Tier H: the maintainer's APPROVED review, then the owning seat lands it) plus scripts/check-adr-0087-registration.mjs predicates and self-tests · precedent #13080's sixth category, PR #13596 (+956 / −10). Confidence gap: the class is measured narrow (one certain member among 81); the predicate "reachable from the package's published entry at the merge base" needs the dev to pick the resolver the api-surface gates already use rather than a new one.

    Prior rulings read: ADR-0087 D7 (#8299, PR #8456) and D8; #13080's ruling 5468992520 (type-surface-only, PR #13596); #17357; check-prior-rulings.mjs --card 22915 in this act: 203 hits, ADR-0087 D3 / D7, ADR-0131 D13 / D5, ADR-0059 §3, ADR-0076 D12, ADR-0081 §2, ADR-0120 D7, ADR-0002 §6 named, none answering this question; PR #22875's reviews 6113872462 and 6114282872; thread: none.

    State and execution

    • This card closes completed in this act as its decision record, as its own text prescribes; needs-user-decision leaves with the close. The Ruled: line is added to the body.
    • The implementation is filed by this seat on the maintainer's word as a domain:devx tooling card in pm:queue whose first line names the published surface the gate protects (the ADR-0087 disposition every BREAKING changeset ships to consumers), carrying the predicates above, the worked example, the Tier H landing and the +956 / −10 precedent; its number is recorded in this card's closing comment. The domain:devx lane claims and dispatches it; the ADR edit waits on the maintainer's APPROVED review before the seat lands the PR.
  2. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Closed completed on ruling 6116351873 (batch #319 item 1 → A, the maintainer's word verbatim 「22915 同意」): this card is the decision record; the implementation card is #22918 (tooling · domain:devx · pm:queue, first line naming the published surface the gate protects), filed by the director seat on the maintainer's word. Director seat, summon #37, session_01LqNgdPZB2Jnr5HpGbaqLeB, 2026-10-12T01:54Z.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:devxpriority:p2Medium: important, M3tooling

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions