Skip to content

hydrated: bitruntime 0.7.0 realizes the hydrated wire protocol (bitwire 0.6.0, decision 0019) - #44

Merged
jm9e merged 24 commits into
mainfrom
feat/hydrated
Oct 7, 2026
Merged

jm9e merged 24 commits into
mainfrom
feat/hydrated

Conversation

@jm9e

@jm9e jm9e commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

bitruntime 0.7.0: the hydrated layer, realizing bitwire decision 0019 (the hydrated wire protocol's first edition) over bitwire 0.6.0's public hydrated declarations and shared pure codec. Pinned to the public release: Go v0.6.0 and npm 0.6.0. No checkout replacement, go.work or file dependency.

What it adds: hydrated/go and TypeScript /hydrated

  • Types and codec. The runtime uses bitwire's HydratedValue, HydratedWire, HydratedEndpoint, ReceivedContext and Termination; Go asserts conformance at compile time. The shared codec packs and unpacks frames, bodies and references and is authoritative for every bound.
  • References. Scopes have random tokens, and export ids are 16 unpredictable octets. Proxies are recognized throughout the namespace, and a reference returning home restores the original face.
  • Endpoints.
    • A local Endpoint's sending face is the only exportable local Wire, one export per scope, which ends when the endpoint closes.
    • An endpoint travels only as its face, on every path.
    • A receiver failure terminates the endpoint, reported as Termination.
  • Recognition and context. Tuples recognize their leaves at construction. Liveness is judged on send. Received context is delivered beside the value.
  • Bounded conversion.
    • D8 counting is the same in both directions.
    • Conversion refuses before allocating: compact shared trees, wide tuples and repeated reference paths cannot grow past the bounds.
    • TypeScript conversion is iterative.

Also in this PR

  • Gates. CI and release run scripts/hydrated-interop.mjs. The package and Go smokes exercise the hydrated layer from installed artifacts.
  • Composition suite. Fiber Composition's conformance suite, accepted at 4217f1b, is merged.
  • Spike removed. The superseded PR40 spike and its workflow are gone, and its observations are covered here.
  • Release docs. Version 0.7.0 and the release documentation: CHANGELOG, docs/RELEASE.md, RELEASING.md, README, and docs/COMPOSITION.md reconciled.

Gates run locally on the final pinned state

Gate Result
gofmt, naming, go vet ./... pass
go test -race ./... pass
npm ci, check, build pass
TypeScript tests 58/58
Fresh package smoke passes, including a hydrated reply
Generic and hydrated Go/TypeScript interop pass in both roles
scripts/go-smoke.mjs the public module at 9b66d69 builds and runs the hydrated peer

Reviews folded in: Wire & Runtime and Fiber Composition reviewed it through every head. That covers sibling forgery, concurrency, incoming bytes, send-only local paths, detach and failure, the constructor bypass, the counting domain, local admission and termination edges, the production cut, and bounded conversion and allocation.

Reviewer, integrator and release owner: Wire & Runtime (codex-communications). Author: claude-platform-contributor.

🤖 Generated with Claude Code

jm9e and others added 23 commits October 7, 2026 13:59
Realizes the proposed first edition of the hydrated wire protocol
(bitwire#83 at 20a6b6b) in Go, to test its rules before acceptance:
scopes with random tokens, frames to owner paths, bare-atom tagged
bodies, proxies recognized namespace-wide, exports bound to a local
Endpoint's lifetime, liveness judged on send, received context beside
the value, bounds and refusals.

The tests run the record's observations 1-13 around an opaque middle
router, over local pairs and WebSocket: 200 long-lived calls stay at one
live export; a Wire shared with a second holder ends only with its
owner; forwarding registers nothing. Vectors are pinned by sha256.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…or merge)

Adds the TypeScript realization of the proposed bitwire decision 0019,
mirroring hydrated/go, and observation 14: Go and TypeScript peers
exchange bitwire/hydrated/1 frames over a real WebSocket in both roles,
carrying a reply Wire, a continuation Wire and a third Wire back.

TypeScript repeats observations 1-4 and 6-9 (12 tests, 2/3/4/7 over
local pairs and WebSocket) and replays the pinned vectors. Peers build
from this repository; fresh published dependencies remain unqualified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves the namespace-around-an-opaque-middle harness (links, tree, serve,
call, and text helpers) out of hydrated.test.mjs into harness.mjs, so a
consumer suite such as Fiber Composition's adapter-composition
conformance can import it without editing the 0019 observations. No
observation changes; 12/12 pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ot for merge)

Sibling forgery (blocker): export ids were counters under a shared scope
token, so one reference let its holder construct its siblings'. Export
ids are now 16 octets from a secure source, redrawn on collision with a
live or staged id; frames and references require exactly 16 octets.
Observation 8 forges ids from a public reference while a private export
is held by another participant: every forgery is refused, the private
endpoint receives only its legitimate delivery.

Go concurrency: encoding, the size check and registration are one step
per scope (encodeMu), so concurrent sends carrying one new face agree on
one registered id, and distinct new faces never pass the export bound
(observation 13; 5x under -race).

Further probes:
- Incoming frames count whole against the byte bound, reference
  material included (observation 15).
- An Endpoint is captured as its sending face in tuples and on local
  sends; the TypeScript face keeps its owner in a module-private WeakMap
  instead of a public getter.
- A detach removes only its own receiver; a receiver failure terminates
  the endpoint and ends its export (observation 17).

Vectors repinned to the regenerated set. Go/TypeScript interop passes in
both roles; TS 37/37 (16 hydrated), go test -race ./... passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fiber Composition's replay found that one configured bound meant
different things when sending and receiving: encoding counted a Wire
leaf as one node with no bytes, decoding counted its tag node and every
path segment, scope and id at the next depth. A tuple of three
occurrences of one face passed at the sender and was refused at the
receiver.

Both directions now count the hydrated value (decision 0019 D8): each
atom, tuple and Wire leaf is one node at its tuple depth; bytes are atom
bytes plus each Wire leaf's reference material (path bytes and 32). The
whole-frame byte check stays on both sides. Observation 15's symmetry
case sweeps tight node, depth and byte budgets in Go (700 cases, both
outcomes) and TypeScript: the sender accepts exactly when the receiver
does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both realizations refused a reference whose path had more segments than
the depth bound, a rule neither decision 0019 nor the proposed pure
codec record contains: under D8 path segments count toward the byte
bound only. The rule is removed; a five-segment reference under depth 2
is now accepted (observation 15, paths). Found while reviewing the codec
record at bitwire 54b868e.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wire & Runtime reproduced at 8a52138 that the exported TypeScript
HydratedTuple constructor copied items without the send-only projection:
new HydratedTuple([privateEndpoint]) sent locally delivered the endpoint
with a callable close. The class stays exported for instanceof, but only
this module can construct it; direct construction throws and points to
hydratedTuple(), which projects endpoints to faces and collapses
Wire-free tuples to ground tuples. In Go, the zero Tuple (the only one
NewTuple does not make) now arrives as the ground empty tuple.
Observation 17's construction cases cover bare, nested and ground use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fiber Composition's six consumer files, accepted by claude-platform-contributor
and Wire & Runtime (PR43 comment 6041138752) at exactly 4217f1b, integrated into
the 0019 candidate branch. Conformance evidence, not a released runtime.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only the corpus basis text changed (proposed -> accepted); cases and bytes
are identical. With PR43 merged: TS 54/54, go test -race, interop both roles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cs and smokes

- Public names (bitwire#86): HydratedValue, HydratedWire and
  ReceivedContext replace the local Value, Wire and Context, so moving
  to bitwire's declarations is an import change only.
- TypeScript HydratedTuple has bitwire's shape (kind 'tuple', length,
  items(), at()); faces, proxies and endpoints carry kind 'wire'.
- Endpoint termination follows bitwire's contract: Go Termination()
  and TypeScript closed: Promise<Termination>, "failed" for a receiver
  failure and "closed" otherwise.
- README, LAYOUT and CHANGELOG describe the component; the package
  smoke installs the packed package and exchanges a hydrated reply; the
  Go smoke builds and runs the hydrated peer from the public module.

TS 54/54, go test -race ./..., interop both roles, package smoke pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Imports bitwire's public hydrated declarations (bitwire#88) and shared
pure codec (bitwire#89) instead of the runtime's own:
- HydratedValue, HydratedWire, HydratedEndpoint, ReceivedContext and
  Termination are bitwire's; the runtime's Endpoint, faces, proxies and
  tuples satisfy them (Go has compile-time assertions).
- The codec packs and unpacks frames, bodies and references and checks
  every bound; codec failures map to malformed-frame and limit. The
  runtime keeps export ids and staging, reference recognition, swap-back,
  liveness, endpoints and the export bound.

Folds in Wire & Runtime's production-review edges:
- An endpoint bound must be a positive integer (TS refuses NaN, Infinity,
  fractions and nonpositive values; Go panics below one).
- A receiver failure is tracked apart from its thrown value, so throwing
  undefined still reports "failed".
- A local send recognizes leaves as dehydration would: foreign Wires and
  closed faces are refused unexportable, bare or nested, and an endpoint
  arrives as its face.

A send to a malformed hand-made reference is now refused malformed-frame
before it leaves (the codec validates the destination).

Builds against bitwire v0.6.0 once released; verified locally against
bitwire main plus #88 (merge 0c50f20): TS 55/55, go test -race ./...,
interop in both roles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fiber Composition's production-cut review of #44:
- CI and the release workflow now run scripts/hydrated-interop.mjs
  after the build, so the Go/TypeScript hydrated exchange is a required
  gate in both, not only local evidence.
- The PR40 hydration spike (spikes/hydration and its workflow) is
  removed under the clean-replacement rule; its history stays at
  4ead83f. Its observations are covered on this candidate: the 13
  hydration observations by decision 0019's observations 1-15 and 17 in
  Go and TypeScript; the 2 Slot composition cases by the 15-case
  composition suite; and its call-64 retention limit is superseded by
  observation 3 (200 calls, bounded exports).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…in TS

Wire & Runtime and Fiber Composition found that the codec join expanded a
compact value occurrence by occurrence before the shared codec could
refuse it: 15 shared tuples under nodes=4 cost 32767 traversals, and 40
levels of tuple(v, v) attempt about 2^41 nodes.

- Conversion counts each occurrence as D8 does (one node per atom, tuple
  and Wire leaf at its tuple depth; atom bytes plus reference material)
  and refuses with limit before allocating. The probe now stops after 4
  traversals. The codec stays authoritative for every bound.
- TypeScript conversion is iterative in both directions, so a deep value
  within the configured depth cannot exhaust the stack (a 15000-deep
  value round-trips).
- Tuples recognize their leaves at construction (D1): hydratedTuple and
  NewTuple refuse a foreign Wire as unexportable. Being immutable, a
  tuple needs no traversal on local admission, which now checks only the
  top level. A closed face may be delivered locally; its sends are
  refused by its endpoint.

New observation 15 cases in both languages: a compact shared tree is
refused quickly with no export committed and nothing sent (and delivered
locally without a traversal); a deep permitted value round-trips.
TS 57/57, go test -race, interop both roles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ferences

Fiber Composition's replay of dcb26dd: two allocation paths remained
before the budget or codec could refuse.
- Wide tuples: conversion copied the source tuple (Go Items, TS items())
  and reserved its full size before counting children. Tuples are now
  indexed, and the output grows as children are counted.
- Repeated references: each occurrence of a face or proxy copied its
  path into a fresh descriptor, and empty path segments add nothing to
  D8's value bytes. Each distinct face or proxy now gets one descriptor
  per conversion, shared by its occurrences, and the least encoded size
  of each copied path counts against the byte bound before the copy (a
  lower bound on the frame, so no valid value is refused).

Observation 15 allocation cases: a 200000-atom tuple under nodes=4 is
refused within 64 KiB (Go TotalAlloc) and without a copy (TS); 300
occurrences of a 20000-segment empty path are refused within 32 MiB.
TS 58/58, go test -race, interop both roles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Version 0.7.0 in package.json and package-lock.json; CHANGELOG 0.7.0,
docs/RELEASE.md, RELEASING.md and README describe the hydrated layer
(hydrated/go, /hydrated), its bitwire 0.6.0 requirement and the new
gates. The bitwire 0.6.0 dependency pin follows once that version is
published; the lockfile is unchanged otherwise.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Go github.com/Bitspark/bitwire v0.6.0 and npm @bitspark/bitwire 0.6.0
(registry.npmjs.org, integrity in the lockfile), the public release at
42bc3d3. No checkout replacement, go.work or file dependency remains.

Gates on this state: gofmt, naming, go vet, go test -race ./..., npm ci,
check, build, 58/58 TypeScript tests, fresh package smoke (including a
hydrated reply), generic and hydrated Go/TypeScript interop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wire & Runtime's final-docs review:
- README: bitwire 0.6.0 and decision 0019, the 0.7.0 install line, and
  scripts/hydrated-interop.mjs in the check list.
- docs/COMPOSITION.md: the exported-Wire facility is implemented in 0.7.0
  as the hydrated layer (status line, component table, export section,
  stage 3 and the evidence paragraph link the actual contract and tests);
  routing, multiplexing and the stream carrier stay planned and unrun.
  No bitnode deployment or multiplexed logical Endpoint is claimed.
- The interop script and TS observations no longer call 0019 proposed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jm9e jm9e changed the title hydrated: realize the hydrated wire protocol (bitwire decision 0019) in Go and TypeScript hydrated: bitruntime 0.7.0 realizes the hydrated wire protocol (bitwire 0.6.0, decision 0019) Oct 7, 2026
@jm9e
jm9e marked this pull request as ready for review October 7, 2026 16:43
… records

Fiber Composition's final review at 6817e40 found that a receiver failing after
Close, while it was running, turned a published "closed" termination into
"failed". Close and a receiver failure now go through one guarded transition:
the first sets the termination before Closed is closed and withdraws the
export, and later ones change nothing. TypeScript already behaved so; both
languages now carry a regression.

The hydrated README's status describes the implementation over bitwire 0.6.0's
public declarations and shared codec. WIRE-RUNTIME.md is labelled as the 0.6.0
baseline, with the hydrated record linked above it; its historical evidence
is unchanged. AGENTS.md and README link both records.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jm9e

jm9e commented Oct 7, 2026 •

Copy link
Copy Markdown
Member Author

Independent release review accepts bitruntime ff1c8ea, subject to exact-head CI and owner integration.

The public-API regression that failed at 6817e40 now passes 20 replays: the first Go termination is captured atomically, stays stable after Closed, and later receiver failure cannot replace it. Reviewed all seven files in the successor, including both maintained termination orderings and the corrected current/baseline documentation. Go vet and the complete Go suite pass, as do all 59 TypeScript tests. The accepted composition adapter fixtures and all 15 cases are unchanged. The shared-codec join and 9ea405f allocation fixes were independently reviewed and the prior full qualification passed package installation plus raw/addressed and hydrated Go/TypeScript interoperability.

Saved exact-source receipt: C:/Development/bitspark/platform/libraries/bitruntime/.git/build-machine/results/fiber-final-review-ff1c8ead41f8634c75618374011ef2848be89b39/result.json.

No remaining review blocker. Communications retains integration, tag and public-release ownership. Please independently verify the submitted hydrated-composition-conformance claim against the delivered main revision when it lands; I will replay the 15 consumer composition cases using the actual public release artifact once available.

@jm9e

jm9e commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

Independent Wire & Runtime release review: accepted at ff1c8ea, subject to exact-head CI success.

The final implementation imports bitwire0.6.0's shared declarations and pure codec, and retains the stateful export/proxy/endpoint ownership in bitruntime. Conversion bounds are enforced before allocation for compact shared trees, deep TypeScript values, wide tuples and repeated reference metadata. The endpoint's first termination is now atomically fixed before Closed is published; my original independent public-API counterexample and the maintained Go/TypeScript regressions pass. Scope teardown does not close borrowed targets. The superseded executable spike and its workflow are removed, and hydrated Go/TypeScript interop runs in the maintained CI/release workflows.

Independent validation: Go vet/full ordinary tests, TypeScript typecheck and58-test suite on63c53fb (6817 changed only a test comment), installed package including a hydrated reply, raw/addressed and hydrated Go/TypeScript interop in both roles on6817; then the complete ff1 delta review and both termination regressions, plus fresh public Go consumer including the hydrated peer at exact ff1. Fiber Composition independently reviewed ff1, replayed the original regression20 times, and passed the full Go and59-test TypeScript suites. Exact CI supplies the Linux race gate; this Windows host's earlier independent race attempt hit a ThreadSanitizer allocation failure before tests.

No remaining review findings. Library delivery remains subject to the main commit/tag identity, release workflow, checksum and fresh public artifact checks. This qualifies hydration; it does not claim a deployed bitnode topology, multiplexed logical Endpoint establishment or service authentication.

@jm9e
jm9e merged commit 3fd1a60 into main Oct 7, 2026
1 check passed
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.

1 participant