--- model: claude-opus-5 service: claude session: 7b9c97c4-fff7-4ac4-97fb-35720453308e timestamp: 2026-08-13T00:11:02Z git_ref: 27c34aeb scope: docs+code substantive: true raw_file: 20260813T001102Z_27c34aeb_prompt_io.raw.md --- ## Prompt > draft hyper detailed implementation plans for [three] > prospective new transport (tpt) backends for tractor's `.ipc` > layer, from four GitHub issues: TIPC (gh #378) using built-in > linux socket API w/ `trio` interfacing, leveraging TIPC's > built-in discovery machinery; QUIC (gh #353) using the `iroh` > lib, ideally with the py asyncio support (via ffi) rewritten > for trio; wg (gh #482 and/or #443) with other shuttle-able > tpts, using `pyroute2`, as much trio wrapping as possible > where any other async support can be replaced. With constraints: "be only slightly speculative"; realistic given the linked info; the plans must be workable "by another model/provider without much discrepancy on the design or lib selections needed"; do it all in a new `/open-wkt` off main; and be "as modular and modern-async-python-as-nearly-functional-style as possible." Key follow-up prompts that changed the design mid-session: > wg requires binding a socket on both ends of the tunnel, the > new support we added to `py-multiaddr` in their #108 enables > declaring this in the maddr? […] so the > `/ip4/10.0.0.1/udp/666/ip4/192.168.0.13/tcp/80` bullet example > from #443 isn't correct for a wg tunnel maddr and would > actually end up looking like, > `/ip4/10.0.0.1/udp/666/wg//ip4/192.168.0.13/tcp/80` no? > right, we're likely going to need less `tuple`-formed > `UnwrappedAddress` usage to make them all work and/or to extend > the unwrapped form with a proto-str, likely the key from > `multiaddrs` no? > better encapsulating `UnwrappedAddress` for use externally is > really way overdue; we should likely be encouraging (if not > preventing unwrapped) wrapped addrs always much like other > (std) libs, `ipaddress` comes to mind. > so iirc netns mgmt becomes a lower-level runtime config-api > rather then an actor-app-code API which can be dynamically > changed once the actor is up ya? ## Response summary A research-and-planning branch, `ng_tpts_planning` — **no runtime code touched**. Five plan docs under `ai/tpt-backends/` plus a corrected `wg` example set under `examples/multihost/wg_lan/`, across 9 commits. Three design conclusions came out of the planning that outlive the branch: 1. **`wg` is a bindspace, not a `MsgTransport`.** The `/wg/` maddr segment is *infix*: bearer (underlay ip+udp `ListenPort`, bound by the kernel) → `/wg/u` (an identity, bound by nothing) → overlay (the only part tractor binds). Verified empirically by installing `baudco/py-multiaddr@wg_support` (py-multiaddr#108) in a throwaway venv and round-tripping each candidate form; gh #482's original suffix form parses but is semantically inverted. 2. **Proto-key the `UnwrappedAddress` form**, spelled with the `multiaddr` protocol names, dispatched via `_address_types[addr[0]]`. Kills a whole collision class (TIPC's `(str, int)` ≡ `TCPAddress`; iroh's `(str, str)` swallowed by the UDS case) and is the recommended migration *before* any new backend lands. 3. **netns is a runtime/boot-time config API, not an app-code one** — `setns(2)` is per-thread and won't move already-created sockets, so there is deliberately no `await actor.enter_netns(...)`. Also verified that `trio.SocketStream`/`SocketListener` are address-family agnostic (no `AF_*` check anywhere), which is what makes TIPC the cheapest of the three backends to add. Four related issues were annotated with the results (#378, #353, #482, #443); #443's body was rewritten to reflect the corrected grammar, with no existing checkbox state changed. ## Files changed - `ai/tpt-backends/00_shared_backend_contract.md` — normative backend duck-type contract, registration checklist, §1.1 proto-key conclusion - `ai/tpt-backends/01_tipc_backend.md` — TIPC plan; service addressing, `TIPC_TOP_SRV` push registry, instance-collision hazard, step-0 probe - `ai/tpt-backends/02_quic_iroh_backend.md` — `iroh` plan; `uniffi`→`trio` bridge, listener/stream adapters, API-truth table - `ai/tpt-backends/03_wg_tunnel_bindspace.md` — `wg`-as-bindspace plan; verified maddr grammar, 3-owner split, netns reality - `ai/tpt-backends/README.md` — index - `examples/multihost/wg_lan/wg_maddr.py` — frozen `msgspec` tunnelled addr + pure parse/render helpers; impure `verify_wg_peer()` kept separate - `examples/multihost/wg_lan/host_a_srv.py` — host-A actor tree - `examples/multihost/wg_lan/host_b_client.py` — host-B dialer - `examples/multihost/wg_lan/README.md` — grammar, owner table, setup, "what changed vs #482" ## Human edits Substantial human steering rather than post-hoc editing; the corrections were applied by the model in-session after being challenged: - rejected an initial claim that `wg` has "nothing to bind at the tunnel layer" and supplied the correct composed maddr form, which forced a rewrite of plan 03 §3.2 and a retraction in the already-posted #443 comment - rejected a supporting claim that `/ip4/../udp/443/quic-v1` was "also composed" - directed the proto-key/`ipaddress`-discipline conclusion and the netns-as-runtime-config framing, both of which were then folded back into the docs - chose the commit boundaries and authored all commits; ran every `git` mutation (commit, rebase, push) themselves One model-initiated correction pre-publication: a self-review downgraded two overconfident claims (the `uniffi`/asyncio thesis and TIPC duplicate-binder behaviour) to explicitly-flagged assumptions before the #353/#378 comments were posted.