Skip to content

js/deltic: recognize deltic values by protocol brands, not class identity - #56

Merged
lann merged 2 commits into
mainfrom
implement-48
Aug 17, 2026
Merged

js/deltic: recognize deltic values by protocol brands, not class identity#56
lann merged 2 commits into
mainfrom
implement-48

Conversation

@lannbot

@lannbot lannbot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Implements #48: the three sites that recognized deltic values by class identity now use the @deltic/protocol recognition predicates (brand symbols in the Symbol.for registry), which the pinned release (0.1.0-pre.g50778a1) already re-exports from @deltic/runtime/embedder — no pin bump.

The migration

  • js/deltic/websocket.ts sendViaStream error wrap: instanceof WitErrorisWitError. This was the real exposure: in a multi-copy graph, a WitError minted by a different runtime copy failed instanceof and was flattened to { tag: "other", val: String(error) } instead of passing its structured payload through.
  • js/deltic/websocket.ts collectByteStream: instanceof StreamhasBrand(stream, STREAM). Milder than the issue implies: deltic's Stream is async-iterable, so a foreign-copy handle previously fell into the for await fallback 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.ts error display: instanceof WitErrorisWitError.

WitError stays imported for construction (witError(), the SendViaStreamError wrap); 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 under instanceof short of loading two real runtime copies. Both fail against the pre-migration code (verified by mutation). The literal /1 keys 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. The exam-deltic gate 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.md unchanged
  • just exam-deltic — pin gate green
  • deno check of examples/deltic-demo/run.ts under the driver config (not covered by any existing gate)

Fixes #48

lann added 2 commits August 17, 2026 17:28
…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
@lannbot

lannbot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Resolved the conflicts by merging main: everything re-applied under the A10 rename (isWitErrorisComponentException, payloads {tag, val}{kind, value}) and the caret-honest 0.1.0 pin regime — the narrowed MODULE-IDENTITY comments now carry main's resolved-version/caret wording.

One fact worth recording: the A10 rename did not change the brand vocabulary — COMPONENT_EXCEPTION is still Symbol.for("deltic.witError/1") at protocol 0.2.0 — so the hand-rolled-brand tests' literal keys are unchanged, and the test comment now notes that key spellings are stable across upstream renames.

Gates re-run post-merge: deltic-module-check 14/14, conformance-ct 4 targets / 220 results / 0 failing (matrix.md unchanged), exam-deltic (now reporting the resolved 0.1.0), and deno check of the demo runner.

@lann
lann merged commit ad42983 into main Aug 17, 2026
2 checks passed
@lann
lann deleted the implement-48 branch August 17, 2026 22:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consider migrating class-identity checks to deltic A8 recognition predicates

2 participants