js/deltic: recognize deltic values by protocol brands, not class identity - #56
Conversation
…tity
Migrate the three class-identity recognition sites to the pinned deltic
release's @deltic/protocol predicates, already re-exported from
@deltic/runtime/embedder at the current pin:
- websocket.ts sendViaStream error wrap: instanceof WitError -> isWitError,
so a WitError minted by another runtime copy passes its structured
payload through instead of being flattened to { tag: "other" }.
- websocket.ts collectByteStream: instanceof Stream -> hasBrand(STREAM),
so a foreign-copy stream handle dispatches to the batched-read branch
(previously it fell through to the async-iterable fallback).
- examples/deltic-demo/run.ts error display: instanceof WitError ->
isWitError.
WitError stays imported for construction; recognition alone migrates.
Two unit tests hand-roll branded values from the Symbol.for registry keys
and fail against the instanceof code, proving recognition no longer
depends on module identity.
The MODULE-IDENTITY comments narrow to the pin gate's remaining
rationale: one runtime/translator plan-format pairing per graph, refusal
of cross-copy stateful handles, and the single-version review surface.
Fixes #48
…ion, {kind, value}) and the caret-honest release pins
|
Resolved the conflicts by merging main: everything re-applied under the A10 rename ( One fact worth recording: the A10 rename did not change the brand vocabulary — Gates re-run post-merge: |
Implements #48: the three sites that recognized deltic values by class identity now use the
@deltic/protocolrecognition predicates (brand symbols in theSymbol.forregistry), which the pinned release (0.1.0-pre.g50778a1) already re-exports from@deltic/runtime/embedder— no pin bump.The migration
js/deltic/websocket.tssendViaStreamerror wrap:instanceof WitError→isWitError. This was the real exposure: in a multi-copy graph, aWitErrorminted by a different runtime copy failedinstanceofand was flattened to{ tag: "other", val: String(error) }instead of passing its structured payload through.js/deltic/websocket.tscollectByteStream:instanceof Stream→hasBrand(stream, STREAM). Milder than the issue implies: deltic'sStreamis async-iterable, so a foreign-copy handle previously fell into thefor awaitfallback and was still consumed correctly — misrecognition cost the batched-read fast path, not correctness. Now it dispatches to the intended branch.examples/deltic-demo/run.tserror display:instanceof WitError→isWitError.WitErrorstays imported for construction (witError(), theSendViaStreamErrorwrap); only recognition migrates.Tests
Two new unit tests hand-roll branded values from nothing but the literal registry keys (
deltic.witError/1,deltic.stream/1) — per the protocol contract a hand-rolled brand carrier is a legal value from any copy, so the tests prove recognition without class identity, which was untestable underinstanceofshort of loading two real runtime copies. Both fail against the pre-migration code (verified by mutation). The literal/1keys are deliberate: an upstream brand-generation bump fails here and forces the recognition sites to be revisited.MODULE-IDENTITY comments
As the issue anticipated, the pin-discipline comments (
deno.json×2, READMEs ×2,AGENTS.md,run.ts,worker-entry.ts,deltic-carrier.ts, demo header) narrow to the gate's remaining rationale: one runtime/translator plan-format pairing per graph, the runtime's refusal of cross-copy stateful handles, and the single-version review surface. Theexam-delticgate itself is unchanged.One nit surfaced while implementing: the issue cites amendment A8; the pinned sources label the brand vocabulary A9 (renumbered upstream), so the comments cite the contract section by name instead of by amendment number.
Gates
just deltic-module-check— 14/14 (incl. the 2 new tests)just conformance-ct— 4 targets, 220 results, 0 failing;matrix.mdunchangedjust exam-deltic— pin gate greendeno checkofexamples/deltic-demo/run.tsunder the driver config (not covered by any existing gate)Fixes #48