Repository navigation
Evaluate native HTTP/WebSockets end to end #20
Copy link
Copy link
Closed
Labels
ready-for-agentSpecified and ready for agent implementationSpecified and ready for agent implementation
Description
Parent
Native Bun APIs: measure and selectively migrate runtime boundaries (#18)
What to build
A supported decision for the main environment server's HTTP/WebSocket boundary. Adopt native Bun transport only if it fixes the qualifying problem or provides the measured benefit while users retain authenticated RPC, responsive Browser streams, remote connections, and a working installed archive. Otherwise record why the existing transport remains the right choice.
Ticket-definition review completed on 2026-10-08: Claude Opus 5.5 agrees this ticket is ready for agent implementation with no remaining blockers. Separate review thread. The completed-work review below remains required after execution.
Acceptance criteria
- Read the parent and baseline ticket. Refresh the baseline if the pin, application, dependency graph, or measured build changed. Declare this boundary's workload and claimed benefit before prototyping; the parent's attribution gate must pass first.
- If attribution is insufficient, parity is impossible, or evidence is inconclusive, record a retained/inconclusive decision and land no production changes, including composition refactors. A retained result is successful completion.
- For an eligible candidate, keep Bun-only imports in fork-owned modules reached from production entry composition. Inject HTTP layers at existing construction sites. Replace only existing Browser Node socket/handshake reads with a scoped capability for pending outbound bytes, immediate termination, and uncompressed upgrade/send; keep route control flow unchanged. Fork-owned Node-test and Bun-production implementations provide that capability without runtime selection. Replace only the auth client-address source read with the portable Effect request address while keeping current normalization; no new auth service is needed. Any local adapter port stays narrow and shares one Effect context.
- Compose a server-only native layer/port while retaining the existing HTTP platform, file-response implementation, HTTP body compression, and ETag generation. Do not adopt the reference aggregate Bun layer's pathname-based file responses or new compression algorithms as a side effect. Native file-operation changes belong to Evaluate native file operations #21.
- Prove current-build routing, authenticated RPC, OAuth/MCP endpoints, cookies/CORS, streaming bodies, failed/refused upgrades, reconnection/cancellation, and graceful shutdown. Prove session client-address metadata is preserved in persisted sessions and its displayed/CLI form using portable request metadata. Late writes to dead/closed sockets must not terminate the server. Hosted/local clients and local/remote/relay/tunnel interfaces retain their contracts at existing transport seams; no live cloud/relay account is required. Loopback callback servers and outbound HTTP clients remain outside the candidate.
- Through the new transport, reuse existing HTTP/file tests to prove static, media, attachment, and Browser download content, invalid/nonregular paths, validated identity-change behavior, range/HEAD, cache/ETag, Content-Encoding/wire behavior, and descriptor closure on client abort. Prove retained raw Node-readable bodies keep lazy opening, no descriptor open for HEAD, client-driven backpressure, abort destruction/close, Content-Length, and 206 framing, including compressed raw bodies. A narrow raw-body-to-web-stream conversion inside transport response mapping is allowed if needed; adopting a native file platform to bypass failed parity is not. When native transport is accepted, this proof is required before Evaluate native file operations #21 begins.
- Prove Browser viewers have bounded queued bytes and unacknowledged frames, immediate slow-viewer cleanup, and correct send/drop/backpressure/drain handling. JPEG frames stay uncompressed; extension-negotiation internals are not the contract. Browser limits do not tighten RPC socket limits.
- Measure representative RPC wire bytes and server CPU, preserving compression benefits. Dedicated per-socket compression is allowed; a transport passing functional tests but materially worsening wire traffic does not pass.
- Reuse Bun-run contract fixtures and the disposable source/actual-archive harness. Native-adapter evidence covers macOS arm64, Linux x64, and Linux arm64. Permitted container/emulation evidence is identified and never used for performance claims; missing parity evidence prevents acceptance. Real-client/browser verification follows AGENTS.md and applicable consent; no new browser authorization is implied by ticket creation.
- Apply the parent's adoption/regression method: qualifying incompatibility fix or at least 5% end-to-end benefit exceeding baseline range; two independent alternating batches, at least five launches per variant/build per batch, at least 60 seconds idle, separate RSS/footprint/heap metrics, and no failing regression gate. Source and archive pass separately; neither can be averaged away. One-batch-only regression or unresolved noise prevents adoption; at most one repeat.
- Pass the parent's baseline/candidate upstream-import rehearsal. Native implementation remains fork-owned; shared substitutions are limited to existing construction/entry sites and the specifically identified transport consumers above. The fixed input/rehearsal covers every changed shared file, including consumers: include the full recorded import ranges needed to cover their most recent upstream edits, rather than selecting only the bootstrap's last edit. Consumer substitutions must introduce no additional conflicts outside construction/entry sites; only construction/entry conflicts may need the parent's mechanical preservation-rule repair. Broader conflicts or recurring manual procedures require retaining the candidate. Record a real fixed input and conflicts/repairs; a no-op merge is not evidence.
- On acceptance, ship one chosen production backend, remove comparison variants, and update only durable runtime/sync guidance. Honor the parent's single-user runtime-break permission, unchanged wire/auth/durable formats, safe upgrades, web/server scope, and existing CI. Put results/artifact links on this ticket, not research files in the repository.
- Have the completed decision and any implementation/evidence verified by Claude Opus 5.5 in a fresh separate T3 thread; record its link and resolve blocking findings before completion.
Blocked by
- Baseline and profile native Bun opportunities (#19) — baseline workloads, measurements, and attribution eligibility.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
ready-for-agentSpecified and ready for agent implementationSpecified and ready for agent implementation
Activity
Igloczek commentedon Oct 8, 2026
Program progress: execution started (2026-10-08)
perMessageDeflateis never negotiated through thewscompatibility path (matched controls: Bun 494,592 vs Node 4,206 received bytes). See the Baseline and profile native Bun opportunities #19 results comment.native-bun/http-websockets, the bottom layer, based onorigin/main=d5cee2d8fa, in orchestration worktreet3-325d51f7. The layer is omitted if the decision is retained or inconclusive.native-bun-20-exec-r1(Codex GPT-6.1-Sol, high reasoning).Status: evaluating
Igloczek commentedon Oct 8, 2026
#20 outcome: retained (no production changes; stack layer omitted, no PR)
Decision: keep the current Effect Node HTTP /
ws-compatibility transport on Bun 1.4.2.Bun.servealways strips a handler-suppliedContent-Lengthon streamed bodies. Every stream form becomes chunked: Node-readable, Web,type:"direct", bytes, async-iterable, 206 ranges and raw gzip. Only bodies fully buffered before the first write keep their length. The cause isRequestContext.rsdo_write_headersplus the stream sink at tagbun-v1.4.2. The ticket requires Content-Length and 206 framing for retained raw bodies, including compressed ones. Buffering whole files, reopening validated files by pathname, adopting native file responses, and upgrading the pin are all out of scope.Bun.file(fd).slice(a, b)on a held descriptor returns 206 withContent-Lengthset to the full file size while sending only the slice. Only pathname-opened files frame correctly. Evaluate native file operations #21 also depends on this.Still unresolved (stated explicitly): the #19 deflate incompatibility remains. Under Bun 1.4.2, RPC frames reach remote, relay and tunnel clients uncompressed. This retention leaves that problem with no owner, so the maintainer decides whether it gets a separate tracking item outside this program. The dev-runner WS-upgrade timeout carried from #19 also remains unresolved. The JPEG/slow-viewer workload was not run because no candidate reached adoption.
Reopen trigger: a Bun pin whose
Bun.servepreserves a handler-suppliedContent-Lengthon streamed bodies, with valid descriptor-slice framing. The dedicated-compressor WebSocket measurement (53,245 vs 12,974 shared-compressor bytes) is unexplained, and anyone revisiting native HTTP must explain it first.Completed-work review: fresh Claude Opus 5.5 / Gilfoyle thread
mcp:f9c1c66c-86ce-47e8-ae49-66e3db41f7a1. The reviewer confirmed the blocker three ways:744846f8);It also confirmed the branch has no residual changes. Verdict:
AGREE — all #20 acceptance criteria satisfied for a retained decision.Per the parent's sequence, #21 now evaluates only read/write file paths. Native HTTP file responses are out of scope because transport was retained.
Decision: retained — keep the current HTTP/WebSocket transport on Bun 1.4.2.
The eligible deflate issue does not justify adopting a transport that fails another required behavior. Plain pinned Bun.serve removes supplied Content-Length on large streamed HTTP/1.1 responses, including 206 ranges and compressed raw bodies. The candidate cannot preserve the ticket's retained raw-readable framing contract through the allowed narrow conversion. Buffering whole files would sacrifice the required streaming/backpressure behavior; swapping the file platform or upgrading the pin exceeds scope. The early feasibility stopping rule applies.
Independent raw-TCP source and compiled probes, separate Bun compatibility/native processes on native macOS arm64, reproduced:
All bodies matched. This is a correctness rejection, not a speed/regression claim. The compiled fixture is not the actual main archive. Pinned RequestContext.rs explicitly strips the supplied framing headers.
Secret evidence gist, immutable revision: https://gist.github.com/Igloczek/3d6c1a1cd2ae7918841f992f3c2aa7d6/80249e25a5d5968750277f08c029cf06c52104a4. Its seven files were checked byte-for-byte and public=false. They contain standalone synthetic tooling/replay commands, preregistration, redacted prelaunch hashes and results; no repository source, private state, local paths or diagnostic logs. The full report and raw artifacts remain local and unpublished.
Baseline/main/pin/lock/fixture/archive hashes remained unchanged; preregistration SHA 85541c23beee263af2f897eadba79558fdd663ca8229590417a86c91b894bdf5, 2026-10-08T21:13:23.618464+00:00. The branch
native-bun/http-websocketshas zero new commits, HEAD d5cee2d, and a clean working tree. All prototype/composition/doc changes were removed; no pushes, stack commands, PRs, issue comments or browser launches by this worker.Checks: temporary Node-test composition focused suites passed 3 files/20 tests. A native main-source pairing + one catalog RPC pilot passed. Shared raw-body compatibility fixture passed; initial native HEAD cleanup was fixed, then native GET framing failed. The preliminary server-only typecheck failed on unfinished prototype code; no green typecheck is claimed. Decisive plain-runtime body/status/encoding assertions passed and recorded the required native parity failures.
Unrun gates/gaps: no ≥5-launch/60-second-idle alternating adoption batches, CPU/RSS/footprint/heap/tail regression verdicts, native main archive, full client/auth/address/file parity, representative JPEG/slow-viewer workload, or complete upstream-import rehearsal. The avoidable auth import micro-merge was not a gate rehearsal or rejection reason. Existing preservation guidance remains unchanged. The inherited dev-runner WS timeout remains unresolved. Linux arm64 Docker pull failed because daemon storage was full; no container ran; x64 emulation was not launched. Missing Linux evidence would independently prevent acceptance.
Cleanup: all 27 captured process starts have stops, source server PID 18019 stopped normally with scoped SIGTERM exit 130; compiler/test/sidecar PIDs were not exhaustively journaled. Our unique disposable machine was deleted, no test container exists, unrelated stopped containers were preserved, and OrbStack was stopped after verifying no active resources. No live T3 state access or kill by name/pattern.
Model/harness: GPT-6.1-Sol, high reasoning, Codex in T3 Code.
Igloczek commentedon Oct 8, 2026
Closing: retained decision; acceptance and completed-work Opus review gates passed (see the results comment above). No repository changes.