Skip to content

Commit 21476d7

Browse files
claude[bot]claude
andauthored
feat(devx): accept a dotted member path in ADR-0087 type-surface-only references (#15724)
A `type-surface-only` reference was a bare identifier resolved to the FIRST same-named definition in the file. On `packages/client/src/index.ts` that is not a symbol identity: the file declares `get` 14 times and `delete` 10 times, so the members two PRs actually narrowed had no addressable spelling at all, and the gate answered a true sentence about a member the diff never touched. One card's whole category was closed by the reference grammar rather than by a judgement about the claim. The grammar now also accepts a dotted member path, and the READER was widened in the same commit: a dotted reference is resolved STRUCTURALLY through the object-literal nesting it names, walked from the top of the file over the shared comment- and literal-masked projection with offsets preserved, and the member's definition is taken from inside the resolved body. Zero candidates, or more than one, is reported by name and refused -- never guessed at. A line number is never the disambiguator; this file's line numbers were measured to rot within one day. Bare identifiers keep their exact previous behaviour, including the first-same-name reading, which is what every marker written before this means. `runtime-interface-only` refuses a dotted path by name: it reads a top-level type declaration, which has no nesting to walk. ADR-0087's marker grammar and this gate's accepted grammar are pinned to each other, so both example blocks and the predicate-4 prose move in the same commit. Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk Co-authored-by: Claude <noreply@anthropic.com>
1 parent 450e030 commit 21476d7

2 files changed

Lines changed: 430 additions & 14 deletions

File tree

docs/adr/0087-metadata-protocol-upgrade-contract.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,7 @@ gate's log and its `--list` output.
585585
<!-- adr-0087: not-required (no-migration-prescription) <why> -->
586586
<!-- adr-0087: not-required (runtime-interface-only <path>#<Symbol>[, ...]) <why> -->
587587
<!-- adr-0087: not-required (type-surface-only <path>#<Symbol>[, ...]) <why> -->
588+
<!-- adr-0087: not-required (type-surface-only <path>#<a>.<b>.<member>[, ...]) <why> -->
588589
```
589590

590591
**The vocabulary is closed, and every exemption is re-verified on every run** — an
@@ -676,6 +677,7 @@ The vocabulary above gained a sixth answer:
676677

677678
```text
678679
<!-- adr-0087: not-required (type-surface-only <path>#<Symbol>[, ...]) <why> -->
680+
<!-- adr-0087: not-required (type-surface-only <path>#<a>.<b>.<member>[, ...]) <why> -->
679681
```
680682

681683
### The dead end it closes
@@ -748,6 +750,23 @@ checks all four by name (`published`, `no-spec-diff`, `no-metadata-surface-diff`
748750
*both* revs and requires `any` / `unknown` / no annotation at base, and a
749751
concrete type at HEAD.
750752

753+
**The reference is a bare symbol OR a dotted member path.** `<path>#<Symbol>`
754+
resolves a bare name to the **first same-named definition in the file**, and on a
755+
real SDK module that is not a symbol identity: `packages/client/src/index.ts`
756+
declares `get` 14 times and `delete` 10 times, so the members PR #15445 and PR
757+
#15451 actually narrowed had **no addressable spelling at all** — the category
758+
was closed to them by the grammar rather than by any judgement about the claim,
759+
and the gate answered a true sentence about a member the diff never touched
760+
(#15627). A reference may therefore also be written `<path>#<a>.<b>.<member>`:
761+
the object-literal nesting the member sits in, walked **structurally** from the
762+
top of the file over a comment- and literal-masked projection, with the member's
763+
definition taken from inside the resolved body. Bare references keep their exact
764+
previous meaning. ⛔ A line number is never the disambiguator — this file's line
765+
numbers were measured to rot within one day. A dotted path that resolves to
766+
**zero** candidates, or to **more than one**, is reported by name and refused,
767+
never guessed at: a reference that silently landed on the wrong same-named member
768+
would be writable but wrong, which is worse than the refusal it replaces.
769+
751770
### ⭐ Predicate 4 is what makes this a narrowing rather than a hole
752771

753772
This is the **only** category exempt from the `no-migration-prescription` refusal.

0 commit comments

Comments
 (0)