Skip to content

feat(sdk): pod-runtime L5 — multi-agent collaboration primitives#55

Merged
lIang70 merged 3 commits into
mainfrom
feat/pod-runtime-l5-collab-layer
Apr 30, 2026
Merged

feat(sdk): pod-runtime L5 — multi-agent collaboration primitives#55
lIang70 merged 3 commits into
mainfrom
feat/pod-runtime-l5-collab-layer

Conversation

@lIang70

@lIang70 lIang70 commented Apr 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

Lands the four high-priority L5 items from docs/sdk-pod-runtime-gaps.md
that close the remaining surface gaps in the multi-agent collaboration
layer. Each item was scoped down from the original RFC during review to
keep the change set incremental and avoid over-design.

kanban: Call(ctx, opts) synchronous sugar

  • Subscribes to the board before Submit so a fast executor cannot
    race past the watcher and miss the terminal transition.
  • Returns CallResult{CardID, Status, Output, Error, ElapsedMs};
    CardDone → nil, CardFailed → errdefs.Internal,
    CardCancelled → errdefs.Aborted.
  • ctx cancel triggers a best-effort Cancel via
    context.WithoutCancel and returns ctx.Err(), preserving standard
    context semantics for callers.

kanban: Cancel + CardCancelled terminal status

  • New terminal status distinct from CardFailed so failure-rate
    dashboards stay honest when a Pod controller stops in-flight work.
  • Board.Cancel(id, reason) state machine: Pending/Claimed → Cancelled only; emits EventTaskCancelled + TaskCancelledPayload
    on Bus().
  • Kanban.Cancel(ctx, id, reason) wrapper with NotFound / Conflict
    classifications and a new kanban.tasks.cancelled.total counter.
  • Eviction, callback rendering, and subject helpers updated to treat
    Cancelled as a first-class terminal alongside Done / Failed.

history: LoadOptions filter

  • New LoadOptions{Budget, Roles, SinceSeq, LimitN, IncludeTools}.
    SinceSeq is a position cutoff because model.Message carries no
    wall-clock timestamp — callers needing a time anchor look up the
    sequence index in their own audit log first.
  • Optional FilterableHistory sub-interface keeps the History
    interface non-breaking; LoadFiltered() helper picks the most
    efficient path automatically.
  • ApplyLoadOptions in-memory pass strips RoleTool messages and
    PartToolCall / PartToolResult parts when IncludeTools=false
    (the default for moderation / inspection use cases). Pure tool-call
    assistant turns become empty after stripping and are dropped.
  • buffer + compactor both implement FilterableHistory via the
    shared helper.

graph/runner: stream.delta SPI promotion

  • engine.EmitStreamToken / EmitStreamToolCall /
    EmitStreamToolResult / EmitStreamDelta package the
    SubjectStreamDelta envelope construction + header stamping +
    per-Type field validation so any node — not just LLM nodes — can
    publish in-flight increments without re-implementing the
    boilerplate.
  • Malformed deltas are caught at emit time instead of silently flowing
    to subscribers.
  • engine and graph/runner package docs explain the two paths
    (graph.StreamPublisher.Emit vs direct EmitStream*) and that both
    land on the same SubjectStreamDelta channel.

Test plan

  • make vet — sdk, sdkx, voice, bench, examples, tools/conformance
  • make test — sdk, sdkx, voice, bench, examples, tools/conformance
  • 18 new test cases:
    • sdk/kanban/call_cancel_test.go: Call happy path / failed /
      ctx-cancel; Cancel state machine; Board.Cancel event publish.
    • sdk/history/load_options_test.go: zero-opts no-op, role filter,
      SinceSeq cutoff, LimitN tail-bias, tool stripping behaviour,
      IncludeTools=true, FilterableHistory fallback.
    • sdk/engine/stream_emit_test.go: token happy path,
      tool_call/result required-field validation, nil-publisher no-op,
      empty-Type rejection, forward-compatible Type acceptance.

Made with Cursor

lIang70 added 3 commits April 30, 2026 14:21
Land the four high-priority L5 items from docs/sdk-pod-runtime-gaps.md
that close the remaining surface gaps in the multi-agent collaboration
layer. Each item was scoped down from the original RFC during review to
keep the change set incremental and avoid over-design.

kanban: Call(ctx, opts) sync sugar
- Subscribe to the board BEFORE Submit so a fast executor cannot race
  past the watcher and miss the terminal transition.
- Returns CallResult{CardID, Status, Output, Error, ElapsedMs}; Done
  → nil, Failed → errdefs.Internal, Cancelled → errdefs.Aborted.
- ctx cancel triggers a best-effort Cancel via context.WithoutCancel
  and returns ctx.Err() so callers retain standard ctx semantics.

kanban: Cancel + CardCancelled
- New terminal status distinct from CardFailed so failure-rate metrics
  stay honest when a Pod controller stops in-flight work.
- Board.Cancel(id, reason) state machine: Pending/Claimed → Cancelled
  only; emits EventTaskCancelled + TaskCancelledPayload on Bus().
- Kanban.Cancel(ctx, id, reason) wrapper with NotFound / Conflict
  classifications and a kanban.tasks.cancelled.total counter.
- Eviction, callback rendering, and subject helpers updated to treat
  Cancelled as a first-class terminal alongside Done / Failed.

history: LoadOptions filter
- New LoadOptions{Budget, Roles, SinceSeq, LimitN, IncludeTools};
  SinceSeq is a position cutoff because model.Message has no
  timestamp — callers needing a wall-clock anchor look up the
  sequence index in their own audit log first.
- Optional FilterableHistory sub-interface keeps the History
  interface non-breaking; LoadFiltered() helper picks the most
  efficient path automatically.
- ApplyLoadOptions in-memory pass strips RoleTool messages and
  PartToolCall / PartToolResult parts when IncludeTools=false (the
  default for moderation / inspection use cases).
- buffer + compactor implement FilterableHistory via the shared
  helper.

graph/runner: stream.delta SPI promotion
- engine.EmitStreamToken / EmitStreamToolCall / EmitStreamToolResult
  / EmitStreamDelta package the SubjectStreamDelta envelope
  construction + header stamping + per-Type field validation so any
  node — not just LLM nodes — can publish in-flight increments
  without re-implementing the boilerplate.
- Malformed deltas are caught at emit time instead of silently
  flowing to subscribers.
- engine and graph/runner package docs explain the two paths
  (graph.StreamPublisher.Emit vs direct EmitStream*) and that both
  land on the same SubjectStreamDelta channel.

Tests: 18 new cases across kanban / history / engine; full make vet +
make test pass on sdk, sdkx, voice, bench, examples, tools/conformance.

Made-with: Cursor
…board_test.go

Restore the test-file consolidation that was accidentally reverted while
amending the L5 commit. The concurrency and restore suites belong with
the rest of the Board tests; keeping them in dedicated files added an
extra layer of indirection without organisational benefit.

No production-code changes.

Made-with: Cursor
@lIang70
lIang70 merged commit fa86084 into main Apr 30, 2026
9 checks passed
@lIang70
lIang70 deleted the feat/pod-runtime-l5-collab-layer branch April 30, 2026 06:28
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