Found while implementing #12866 (ADR-0006 D2, SDK half). Filed unassigned.
What happens
check-adr-0087-registration.mjs's runtime-interface-only predicate (step 4 — "NO metadata surface REFERENCES it") counts a symbol that appears only inside a JSDoc prose comment of a metadata surface as a reference it cannot resolve, and refuses the disposition.
Reproduced on cae0e248c:
runtime-interface-only packages/client/src/index.ts#ObjectStackClient cannot be verified:
packages/spec/src/api/contract.zod.ts (a Zod schema) mentions `ObjectStackClient` while
neither declaring nor importing it:
* `success`, which is what `ObjectStackClient.unwrapResponse` keys on and what
Unresolvable, so refused rather than assumed unrelated (#4690).
The "reference" is packages/spec/src/api/contract.zod.ts line 164 — a sentence inside the BaseResponseSchema docblock explaining what unwrapResponse keys on. It is prose. ObjectStackClient is not imported there, is not in any schema, and objectstack migrate meta has nothing to reach through it. Steps 1, 2 and 3 of the predicate all pass.
Why it matters
The refusal pushes an author toward not-required (no-migration-prescription), which for a changeset carrying a real before/after migration table is a self-contradiction — exactly the detector-miss anti-pattern the gate's own header records as #8299 and exists to close. So the blind spot converts an honest, nearly-verified disposition into pressure to claim a dishonest one.
It is currently the only .zod.ts in the repo that mentions ObjectStackClient (measured: git grep -ln ObjectStackClient -- '*.zod.ts' returns exactly that file), so the blast radius today is small — but the shape is general: any metadata surface whose docblock names a runtime type blocks that type's exemption.
Suggested direction (not a decision)
Strip comments before the step-4 scan, or treat a match that occurs only inside a comment as not-a-reference and say so in the refusal text. Both keep #4690's "refuse rather than assume unrelated" stance for real code references. The gate has a --self-test; a case for "named only in a docblock" belongs with it.
Evidence
- Gate:
scripts/check-adr-0087-registration.mjs, the runtime-interface-only block (~line 1671 onwards) - The blocking mention:
packages/spec/src/api/contract.zod.ts:164 - The changeset that hit it:
.changeset/adr0006-d2-client-environments-namespace.md on branch claude/issue-12866-adr0006-d2-sdk-environments
Generated by Claude Code
Found while implementing #12866 (ADR-0006 D2, SDK half). Filed unassigned.
What happens
check-adr-0087-registration.mjs'sruntime-interface-onlypredicate (step 4 — "NO metadata surface REFERENCES it") counts a symbol that appears only inside a JSDoc prose comment of a metadata surface as a reference it cannot resolve, and refuses the disposition.Reproduced on
cae0e248c:The "reference" is
packages/spec/src/api/contract.zod.tsline 164 — a sentence inside theBaseResponseSchemadocblock explaining whatunwrapResponsekeys on. It is prose.ObjectStackClientis not imported there, is not in any schema, andobjectstack migrate metahas nothing to reach through it. Steps 1, 2 and 3 of the predicate all pass.Why it matters
The refusal pushes an author toward
not-required (no-migration-prescription), which for a changeset carrying a real before/after migration table is a self-contradiction — exactly the detector-miss anti-pattern the gate's own header records as #8299 and exists to close. So the blind spot converts an honest, nearly-verified disposition into pressure to claim a dishonest one.It is currently the only
.zod.tsin the repo that mentionsObjectStackClient(measured:git grep -ln ObjectStackClient -- '*.zod.ts'returns exactly that file), so the blast radius today is small — but the shape is general: any metadata surface whose docblock names a runtime type blocks that type's exemption.Suggested direction (not a decision)
Strip comments before the step-4 scan, or treat a match that occurs only inside a comment as not-a-reference and say so in the refusal text. Both keep #4690's "refuse rather than assume unrelated" stance for real code references. The gate has a
--self-test; a case for "named only in a docblock" belongs with it.Evidence
scripts/check-adr-0087-registration.mjs, theruntime-interface-onlyblock (~line 1671 onwards)packages/spec/src/api/contract.zod.ts:164.changeset/adr0006-d2-client-environments-namespace.mdon branchclaude/issue-12866-adr0006-d2-sdk-environmentsGenerated by Claude Code