feat(I203/M4): InvocationContext + streaming parity + license/changelog hygiene #1

Merged
buildagent merged 3 commits from feat/i203-m4-csharp-parity into main 2026-05-29 17:03:26 +02:00
Member

Mission I203 / M4 — C# SDK parity with Rust for InvocationContext (spec 21) + streaming (spec 23), + license/changelog hygiene. Nested ixt-public eaf4205117319c.

  • Phase A: InvocationContext.cs (ActorSubject/ActorIdentity + opaque TokenRef + wildcard caps, MessageTarget, bounded Metadata, MetadataKeys) decoded into ModuleContext.Invocation. The SDK hand-writes the capnp wire format (no capnpc-csharp) — added a tree-based CapnpStructNode builder + canonical Reader (legacy builder couldn't do deep nesting / canonical composite-list counts); every encoder verified byte-identical to capnp encode/decode.
  • Phase B: StreamId, 6-variant StreamFrame wire codec, InteractionKind/CloseReason/CancelReason/StreamErrorCode, StreamSender (SendDataAsync + credit → StreamSendException(Rejected); Close/Cancel/Error/GrantCredit), StreamHandle.Accept (decodes InvocationContext, deadline-honoring CancellationToken, bounded Channel<StreamData>, FeedAsync). Union discriminants are 0-based positional (verified vs capnp), not the schema field ordinals.
  • Phase C (hygiene): MIT LICENSE; csproj PackageId=Ixt.Sdk + Authors + PackageLicenseExpression=MIT + repo URLs (validated via dotnet packIxt.Sdk.0.17.13.nupkg); CHANGELOG.md.

Tests: dotnet build + dotnet test green — 73 passed (+26), byte-identical golden vectors, dotnet format clean. Lockstep pin bump follows.

🤖 Generated with Claude Code

Mission I203 / M4 — C# SDK parity with Rust for InvocationContext (spec 21) + streaming (spec 23), + license/changelog hygiene. Nested `ixt-public` `eaf4205`→`117319c`. - **Phase A**: `InvocationContext.cs` (ActorSubject/ActorIdentity + opaque TokenRef + wildcard caps, MessageTarget, bounded Metadata, MetadataKeys) decoded into `ModuleContext.Invocation`. The SDK hand-writes the capnp wire format (no capnpc-csharp) — added a tree-based `CapnpStructNode` builder + canonical Reader (legacy builder couldn't do deep nesting / canonical composite-list counts); every encoder verified byte-identical to `capnp encode`/`decode`. - **Phase B**: StreamId, 6-variant StreamFrame wire codec, InteractionKind/CloseReason/CancelReason/StreamErrorCode, StreamSender (SendDataAsync + credit → `StreamSendException(Rejected)`; Close/Cancel/Error/GrantCredit), StreamHandle.Accept (decodes InvocationContext, deadline-honoring CancellationToken, bounded `Channel<StreamData>`, FeedAsync). Union discriminants are 0-based positional (verified vs capnp), not the schema field ordinals. - **Phase C (hygiene)**: MIT `LICENSE`; csproj `PackageId=Ixt.Sdk` + `Authors` + `PackageLicenseExpression=MIT` + repo URLs (validated via `dotnet pack` → `Ixt.Sdk.0.17.13.nupkg`); `CHANGELOG.md`. **Tests:** `dotnet build` + `dotnet test` green — 73 passed (+26), byte-identical golden vectors, `dotnet format` clean. Lockstep pin bump follows. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Bump nested ixt-public eaf4205 → 117319c (post-I198 / spec-21 schemas:
adds ipc_streaming.capnp, rewrites module.capnp's identity section).

The C# SDK hand-writes Cap'n Proto (no capnpc-csharp codegen), so the
"regen" step is hand-writing the new wire types against the canonical
schema layouts (derived via `capnp compile -oc++`).

Add the spec-21 InvocationContext surface mirroring the Rust/Python/Go
siblings: ActorSubject (system/module/operator/external), ActorIdentity
(subject + opaque tokenRef + capability set), MessageTarget union,
bounded metadata bag, MetadataKeys conventional keys. Supersedes the
pre-spec-21 RequestContext/SecurityContext/SecurityLevel (the C# SDK
never carried those as typed fields — context was opaque bytes on
HandlePayload.context; it is now decoded into ModuleContext.Invocation).

The previous CapnpMessageBuilder only handles shallow IPC shapes; add a
tree-based CapnpStructNode builder + a canonical Reader supporting
arbitrary nesting, unions, composite struct lists, and List(Text).
Encoder output is byte-identical to `capnp encode` (verified both
directions against ixt-public @117319c).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mirror the Rust/Python/Go streaming surface (spec 23), minimal-but-
complete and idiomatic C#:

- StreamId (16-byte UUID, lowercase-hex Display).
- StreamFrame wire codec: 6-variant union (Open/Data/Error/Close/
  Cancel/Credit) with the canonical 0-based union discriminants (NOT the
  @1..@6 schema field ordinals, which are offset by streamId @0) and the
  clientStream@1 / serverStream@2 wire-ordinal mapping. Byte-identical to
  `capnp encode` (golden vector embedded in tests).
- 4 InteractionKinds + CloseReason/CancelReason/StreamErrorCode enums.
- StreamSender: SendDataAsync (auto sequence, credit window — exhaustion
  throws StreamSendException(Rejected) rather than blocking), CloseAsync,
  CancelAsync, ErrorAsync, GrantCredit/RemainingCredit. Thread-safe.
- StreamHandle.Accept (callee side): decodes the embedded
  InvocationContext, derives a deadline-honoring CancellationToken
  (spec 21 §8), bounded Channel<StreamData> for Incoming, FeedAsync
  routing inbound Data/Credit/terminal frames.

Scope mirrors Rust Phase 2a — module-as-callee only; opening a stream
from a handler lands with the async ABI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add MIT LICENSE (matches the ixt-public / sibling-SDK license text).
- Add NuGet package metadata to IxtSdk.csproj: PackageId (Ixt.Sdk),
  Authors (IXT Framework Team), PackageLicenseExpression (MIT),
  project/repository URLs, and packed README + LICENSE.
- Add CHANGELOG.md with the 0.17.13 I203 parity entry.

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-csharp!1
No description provided.