Skip to content

[finding] three runtime domains still reach the protocol service through an untyped handle — the shape that fixes them is now written and proven next door #15238

Description

@os-litant

Found while implementing #13598 (PR #15215), which narrowed packages/runtime/src/domains/packages.ts from twelve untyped deps.resolveService(context, 'protocol') handles to one. Filed rather than folded in: #13598's dispatch scoped its file surface to packages.ts and named domains/meta.ts explicitly as "same family, a different file, and NOT in scope by default".

Measured on 34a1740a (PR #15215's head), after that change lands

Instrument, per non-test file under packages/runtime/src:

grep -c "resolveService([^,]*, 'protocol'"   and   grep -c "protocol as any\|protocol: any"
file resolveService(…, 'protocol') sites any casts on the handle
domains/meta.ts 9 4
domains/mcp.ts 1 1
domains/ui.ts 1 0
domains/packages.ts (after #13598) 1 0

The packages.ts row is the control: it is the same instrument on the file that was just fixed, and its single remaining site is the one inside the narrowing helper. Without that row the other three counts say nothing about whether the pattern is repairable.

ui.ts is the cheapest of the three and shows the shape plainly: the handle is untyped, so protocol.getUiView({ object: objectName, type }) compiles against nothing even though getUiView and GetUiViewRequest are both declared on the spec's MetadataProtocol. mcp.ts already declares type McpMergedMetadataRead = Pick(MetadataProtocol, 'getMetaItems') for its merged-read seam but resolves its second handle (domains/mcp.ts:609) as a bare any.

Why it may be worth a card

  • Same seam, same reason: 'protocol' is deliberately unmapped in ServiceSlotContracts, so resolveService answers any for that name and nothing downstream compiles against a contract.
  • The consumer-side fix now EXISTS in-tree and is proven: PackagesDomainProtocol plus a one-line resolveProtocol helper in domains/packages.ts, with a pin (packages-protocol-handle-typing.test.ts) whose @ts-expect-error directives go unused — TS2578 — if the seam regresses. A follow-up is a template application, not a design question.
  • ⛔ The runtime feature-detection probes must survive any such change, for the documented reason: a host may occupy the slot with a partial object. Every member of the handle type is optional precisely so the type agrees with the probes instead of replacing them.
  • ⛔ Not a packages/spec change. Mapping 'protocol' in ServiceSlotContracts would assert that a filled slot IS a MetadataProtocol, whose members are mostly required — which is what the probes exist to deny — and it would have to answer for the verbs no contract declares.

Observation-grade: no behavioural defect measured, declared-vs-served unaffected. meta.ts in particular builds its literals field by field and has its own pins, so the win there is narrower than it was in packages.ts; sizing and priority are triage's call.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions