RFC-MACP-0006 passive-subscribe + observer-only hardening#20
Merged
ajit-zer07 merged 1 commit intomainfrom Apr 21, 2026
Merged
Conversation
Wire the control-plane's observer stream to the new RFC-MACP-0006 §3.2
handshake: subscribeSession() now writes a single {subscribeSessionId,
afterSequence} frame before half-closing the write side so the runtime
binds the bidi stream to the session broadcast channel and replays
accepted history from afterSequence (default 0 = full replay). Prune
dead write-path surface (RuntimeSessionOpenResult, KICKOFF_FAILED /
SIGNAL_DISPATCH_FAILED / CONTEXT_UPDATE_FAILED / MESSAGE_SEND_FAILED
error codes) left over from the 2026-04-15 direct-agent-auth refactor
and refresh the docs/CI to match.
- src/runtime/rust-runtime.provider.ts: write passive-subscribe frame
with afterSequence, propagate write failures onto the iterator.
- src/contracts/runtime.ts: add RuntimeSubscribeSessionRequest.afterSequence;
drop unused RuntimeSessionOpenResult.
- src/errors/error-codes.ts: remove write-path-only error codes.
- src/metrics/metrics.service.ts: doc-only — tokenUsage now arrives via
agent-emitted envelopes, not POST /runs/:id/messages.
- .github/workflows/ci.yml: new `conventions` job enforcing the grep
invariants from CLAUDE.md (throw new Error, console.*, process.env,
observer-only write-path), gated before `build`.
- docs/{API,INTEGRATION,TROUBLESHOOTING}.md: document 410 Gone behavior,
afterSequence handshake, and remove stale write-path error codes.
- package.json: bump @multiagentcoordinationprotocol/proto 0.1.0 → 0.1.2.
Tests
- src/runtime/rust-runtime.provider.spec.ts (new, 7 tests): passive-
subscribe frame write, afterSequence forwarding, envelope-free write,
write/end failure paths, opened status frame, cross-session filter.
- src/runs/session-discovery.service.spec.ts (new, 8 tests): lifecycle
event handling for created/resolved/expired, dedup, terminal-state
idempotency, disabled flag.
- test/integration/removed-endpoints.integration.spec.ts (new):
end-to-end 410 Gone contract for POST /runs/:id/{messages,signal,context}.
Verification
- eslint --max-warnings=0 clean
- tsc --noEmit clean (src + integration tsconfigs)
- nest build clean
- jest: 46 suites / 593 tests passing (+1 suite, +7 tests)
- All 4 CI conventions greps return 0 violations locally
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.
Summary
subscribeSession()writes a single{subscribeSessionId, afterSequence}frame, half-closes, and lets the runtime replay accepted history fromafterSequence(default0= full replay) before switching to live broadcast.RuntimeSessionOpenResulttype and the write-only errorcodes (
KICKOFF_FAILED,SIGNAL_DISPATCH_FAILED,CONTEXT_UPDATE_FAILED,MESSAGE_SEND_FAILED). The control-plane is observer-only — these were dead symbols.conventionsCI job that enforces the CLAUDE.md grep invariants (throw new Error,console.*,process.env, no observer-only write-path re-introduction);gated before
build.@multiagentcoordinationprotocol/proto→0.1.2.docs/{API,INTEGRATION,TROUBLESHOOTING}.mdto document the 410 Gone contract, theafterSequencehandshake, and the current error-code set.Tests added
src/runtime/rust-runtime.provider.spec.ts(new — 7 tests): single passive-subscribe write,afterSequenceforwarding, envelope-free write, sync/async write-sidefailure paths, synthetic
openedstatus frame, cross-session envelope filtering.src/runs/session-discovery.service.spec.ts(new — 8 tests):created/resolved/expiredlifecycle handling, dedup, terminal-state idempotency, disabled-flagshort-circuit.
test/integration/removed-endpoints.integration.spec.ts(new): end-to-end 410 Gone contract forPOST /runs/:id/{messages,signal,context}, includingerrorCode: ENDPOINT_REMOVEDand ParseUUIDPipe precedence.Test plan
npm run lint— clean (--max-warnings=0)npx tsc --noEmit— clean (src +test/tsconfig.test.json)npm run build(nest build) — cleannpm test— 46 suites / 593 tests passing (was 45 / 586)conventionsgrep rules return 0 violations locallynpm run test:integrationagainst Postgres :5433 — CI-only (local Docker unavailable)conventionsjob green on pushNODE_AUTH_TOKENsecret still wired in workflow for the@multiagentcoordinationprotocolnpm scope