feat(I203/M3): InvocationContext + streaming parity + schema-sync (post-I198/I199) #1

Merged
buildagent merged 2 commits from feat/i203-go-streaming into main 2026-05-29 16:44:48 +02:00
Member

Summary

Mission I203 / M3 — Go SDK parity with the Rust SDK for InvocationContext (spec 21) + streaming (spec 23). Closes the 13-commit nested-ixt-public lag and extends the schema-sync tooling.

Phase A — schema sync + post-I198 migration

  • Bump nested ixt-public eaf4205117319c37e78.
  • Extend sync-schemas.sh (was ipc.capnp-only): now copies + Go-annotates ipc_streaming.capnp + module.capnp and regenerates all bindings (capnp compile -ogosdk/ipc/, sdk/streamcapnp/, sdk/modulecapnp/). Idempotent (re-run = zero diff). Two shared-schema accommodations, documented in the script header: drop the unused ModuleContext.services field (module↔services capnp import cycle, never consumed by the SDK) and the unused interface IxtModule RPC block (server collides with capnp's Shutdowner under go vet).
  • New sdk/context.go: full Go InvocationContext mirror (ActorSubject/ActorIdentity with capabilities + opaque tokenRef, MessageTarget union, bounded metadata + conventional keys) with capnp encode/decode against module.capnp. sdk.Context now carries the decoded *InvocationContext (Actor()/HasCapability()); handleMessage decodes HandlePayload.context. (Go SDK had zero RequestContext/SecurityContext refs — its sdk.Context was a thin struct.)

Phase B — streaming API

  • New sdk/streaming.go: StreamID, 4 InteractionKinds, CloseReason/CancelReason/13-code StreamErrorCode, 6-variant StreamFrame union with Encode/DecodeStreamFrame (structurally identical to Rust stream_wire.rs). StreamSender (callee): SendData w/ auto-sequence + credit accounting (ErrRejected on exhaustion), GrantCredit/Close/Cancel/SendError. StreamHandle + AcceptStream (Phase-2a callee): decodes embedded InvocationContext, derives a context.Context honoring the spec-21 deadline, Incoming channel + Feed() routing. No bespoke flow control.

Test plan

  • go build ./... + go test ./... green — 30 streaming tests (all 6 frame variants + full InvocationContext round-trip + sender credit/sequence/lifecycle)
  • go vet ./... clean; gofmt -l . clean
  • sync-schemas.sh idempotent

Lockstep: superproject pin bumps after merge. Schema-pin drift (this SDK) clears. Tier-B cross-runtime e2e candidate (M7).

🤖 Generated with Claude Code

## Summary Mission I203 / M3 — Go SDK parity with the Rust SDK for **InvocationContext** (spec 21) + **streaming** (spec 23). Closes the 13-commit nested-`ixt-public` lag and extends the schema-sync tooling. ## Phase A — schema sync + post-I198 migration - Bump nested `ixt-public` `eaf4205` → `117319c37e78`. - **Extend `sync-schemas.sh`** (was `ipc.capnp`-only): now copies + Go-annotates `ipc_streaming.capnp` + `module.capnp` and regenerates all bindings (`capnp compile -ogo` → `sdk/ipc/`, `sdk/streamcapnp/`, `sdk/modulecapnp/`). Idempotent (re-run = zero diff). Two shared-schema accommodations, documented in the script header: drop the unused `ModuleContext.services` field (module↔services capnp import cycle, never consumed by the SDK) and the unused `interface IxtModule` RPC block (server collides with capnp's `Shutdowner` under `go vet`). - New `sdk/context.go`: full Go `InvocationContext` mirror (`ActorSubject`/`ActorIdentity` with capabilities + opaque `tokenRef`, `MessageTarget` union, bounded metadata + conventional keys) with capnp encode/decode against `module.capnp`. `sdk.Context` now carries the decoded `*InvocationContext` (`Actor()`/`HasCapability()`); `handleMessage` decodes `HandlePayload.context`. (Go SDK had zero `RequestContext`/`SecurityContext` refs — its `sdk.Context` was a thin struct.) ## Phase B — streaming API - New `sdk/streaming.go`: `StreamID`, 4 `InteractionKind`s, `CloseReason`/`CancelReason`/13-code `StreamErrorCode`, 6-variant `StreamFrame` union with `Encode`/`DecodeStreamFrame` (structurally identical to Rust `stream_wire.rs`). `StreamSender` (callee): `SendData` w/ auto-sequence + credit accounting (`ErrRejected` on exhaustion), `GrantCredit`/`Close`/`Cancel`/`SendError`. `StreamHandle` + `AcceptStream` (Phase-2a callee): decodes embedded `InvocationContext`, derives a `context.Context` honoring the spec-21 deadline, `Incoming` channel + `Feed()` routing. No bespoke flow control. ## Test plan - [x] `go build ./...` + `go test ./...` green — 30 streaming tests (all 6 frame variants + full InvocationContext round-trip + sender credit/sequence/lifecycle) - [x] `go vet ./...` clean; `gofmt -l .` clean - [x] `sync-schemas.sh` idempotent Lockstep: superproject pin bumps after merge. Schema-pin drift (this SDK) clears. Tier-B cross-runtime e2e candidate (M7). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Phase A — bring the Go SDK onto the post-I198 schemas.

Pin bump: nested ixt-public eaf4205 -> 117319c (13 commits; adds
ipc_streaming.capnp, the spec-21 InvocationContext/ActorIdentity model in
module.capnp, and the I199 streaming primitives).

sync-schemas.sh: extended from ipc.capnp-only to also copy + Go-annotate
ipc_streaming.capnp and module.capnp, and regenerate all bindings via
`capnp compile -ogo`. Produces:
  sdk/ipc/ipc.capnp.go                 (package ipc)
  sdk/streamcapnp/ipc_streaming.capnp.go (package streamcapnp)
  sdk/modulecapnp/module.capnp.go      (package modulecapnp)
The module<->services two-file capnp import cycle (only link:
ModuleContext.services, which the SDK never consumes) is broken by dropping
that single field + the services import from the derived module.capnp copy.
The unused capnp `interface IxtModule` RPC block is also dropped — its
generated server collides with capnp's server.Shutdowner under `go vet`.
ipc_services.capnp / services.capnp are copied for reference only (Go
bindings remain hand-written in service_payloads.go). Script is idempotent.

InvocationContext migration (spec 21): new sdk/context.go provides the Go
mirror of the Rust SDK InvocationContext — ActorSubject (system/module/
operator/external), ActorIdentity (capabilities + opaque tokenRef),
MessageTarget union, bounded metadata + conventional keys — with Cap'n Proto
encode/decode against module.capnp. sdk.Context now carries the decoded
*InvocationContext (Actor()/HasCapability() helpers); handleMessage decodes
HandlePayload.context. The pre-spec-21 RequestContext/SecurityContext/
SecurityLevel model is superseded (no compat shim, pre-1.0).

Verification: `go build ./...`, `go test ./...` (sdk: ok), `go vet ./...`
clean, `gofmt -l .` empty (pre-existing alignment in serialization.go /
service_payloads.go / examples also formatted).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase B — Go streaming surface mirroring the Rust SDK (spec 23, I199 part 2).

New sdk/streaming.go:
  * StreamID (16-byte UUID, lowercase-hex String mirroring Rust Display).
  * InteractionKind (Unary/ClientStream/ServerStream/BidiStream, wire
    ordinals preserved), CloseReason, CancelReason, StreamErrorCode (full
    13-code set) — Go enums whose integer values equal the capnp wire
    ordinals, so conversion to/from streamcapnp is a direct cast.
  * StreamData / StreamError / StreamFrame (six-variant tagged union) with
    EncodeStreamFrame / DecodeStreamFrame Cap'n Proto round-trip via the
    generated streamcapnp types — structurally identical to Rust
    stream_wire.rs.
  * StreamSender (callee side): SendData (auto-sequence + credit-window
    accounting; returns *StreamSendError{ErrRejected} when credit is
    exhausted rather than blocking — backpressure is the receiver's credit
    grant per I203 "no bespoke flow control"), GrantCredit, Close, Cancel,
    SendError; idempotent terminal state.
  * StreamHandle + AcceptStream (callee semantics matching Rust Phase 2a):
    decodes the open frame's embedded InvocationContext, derives a
    context.Context honoring the spec-21 deadline, exposes Incoming (buffered
    by bufferCapFrames) and Feed() which routes Data/Credit/Close/Cancel/Error
    and tears the stream down (closes Incoming, cancels Ctx with cause) on a
    terminal frame. FrameSink abstracts the reply transport (runtime supplies
    the real one; tests an in-memory capture).

Tests (sdk/streaming_test.go, +15 funcs): all six StreamFrame variants
round-trip; StreamID hex + length validation; full InvocationContext
round-trip (operator subject, tokenRef, capabilities, metadata, service +
reply targets, system actor wildcard); empty-context decode; StreamSender
credit/sequence/close-final-sequence; AcceptStream decode + Feed
data/credit/close lifecycle.

Verification: `go build ./...`, `go test ./...` (sdk: ok, 30 tests),
`go vet ./...` clean, `gofmt -l .` empty. sync-schemas.sh idempotent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
h-dv/ixt-sdk-go!1
No description provided.