feat(compass): SEA-1561 swap runner durable-frame ingest to CommitConversationFrame - #45
Merged
Merged
Conversation
Contributor
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
…versationFrame PostConversationFrame now commits conversation frames request/response via the dedicated CommitConversationFrame unary (delivered-or-erred) instead of acking on a lossy PublishEvents buffer-accept, closing the OQ-3 silent-drop gap; the Publish spine becomes trace/session-only. Co-Authored-By: seal <noreply@sealedsecurity.com>
seal-agent
force-pushed
the
compass-runner-1364-sink-ack-swap
branch
from
July 30, 2026 20:46
b52300a to
517f767
Compare
seal-agent
marked this pull request as ready for review
July 31, 2026 01:01
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What
Swaps the Runner's durable-conversation-frame ingest from the loss-tolerant
PublishEventsbuffer-accept path to the dedicated unaryRunnerService.CommitConversationFramesink-ack, closing the OQ-3 delivered-or-erred gap (SEA-1561, downstream of #24's OQ-3).Before:
PostConversationFrameacked the agent on aPublishEventsbuffer-accept (the shared client-streamSendreturned), so any Server-side loss after Send-accept permanently dropped a durable conversation frame while the agent's retry was suppressed.After: durable conversation frames leave the loss-tolerant Publish spine entirely and commit request/response via the dedicated
CommitConversationFrameunary (proto/stub landed in #42, Server handler in #43). Success is returned only after the Server acknowledges the commit; a Server-side loss is a Connect error the agent's sink retries on the same idempotency key.Design (per #42's Matt-ratified proto)
RelayCommsCall): resolves the session structurally from the socket, sends{session_id, frame, idempotency_key}, asserts no account. The Server resolves session→account fail-closed.RunnerSeq, so the two paths no longer contend on one monotonic counter.idempotency_keyis reused verbatim; the Server commits at-most-once per key. An in-process advisorycommittedKeysLRU short-circuits a retry without a redundant upstream forward — it is not the durability boundary (the store's atomic commit on the same key is), so a Runner crash that loses the map is safe.PostConversationFrameResponsestays empty — the swap is Runner-internal, no agent-facing contract change.Tests (red-green,
-race)TestPostConversationFrameDeliveredOrErred— a commit failure surfaces the Server's Connect error, never a silent success.TestPostConversationFrameAtLeastOnceRetryability(permanent-not-found / permanent-invalid-argument / transient-unavailable) — closes feat(runner): SEA-1364 C2 - Gateway telemetry-ingest handlers #24 OQ-3 item 5: a transient failure surfaces retryable and does not mark the key committed (a retry re-forwards); a permanent failure surfaces terminal.TestPostConversationFrameDedupOnKey/…EmptyKeyNeverDedups/…AdvisorySetLossReforwards— the advisory fast-path is correct and never the boundary.TestConcurrencyNoFalseGap— Publish-only ordering after the durable path leaves the spine.All gateway tests green under
-race;hkgate green (lint 0 issues, vet, vuln, licenses, drift, full test suite).Refs SEA-1561, SEA-1364. Downstream of #24 (OQ-3); consumes #42 (proto/stub) + #43 (Server handler).
Review (
skill://review, one adversarial pass)0 high, 3 medium, 1 low. Contract verified sound end to end: success marks the key; a transient commit error returns unmarked (agent re-commits the same key); a permanent error returns unmarked (agent drops); a committed-but-response-lost retry short-circuits on the advisory LRU while the store's atomic commit stays the real boundary. No false-hub-gap regression — durable frames left the publisher, so the seq critical section now guards only the serial Publish stream.
gateway.gopub/seq field comments) — fixed in this PR: the comments described the deleted pre-swap shared-publisher mechanism; rewritten to the current model (pub driven only by Publish; seq on the Gateway because the publisher is replaceable viaacquirePublisher's session-change reset).isConversationFramefail-closed guard) — fixed in this PR: addedTestPostConversationFrameRejectsNonConversationFrame(trace/session, empty-oneof, nil →CodeInvalidArgumentwith commit-count 0).NewGateway/Serve6/7 positional args, 3 same interface-typed) — deferred to SEA-1572 (reviewer framed it as a judgment call / legitimate trade-off; the signature shape is a design fork for Matt). Non-blocking; no behavior impact.resp.GetCommitted()it structurally ignores) — left as the strict pure-forwarder shape; safe today per the seam contract (runner.protosurfaces a non-commit as a retryability-split status, nevercommitted=falsewith nil err).