Skip to content

[P0][Protocol] SEP-3415 alignment, client lifecycle and delivery-gap-safe CEP #166

Closed

Description

@sarooo17

Parent: #41 (Event Intelligence v1.0). Related: #42 (host integration), #44 (CEP correctness), #45 (security), #50 (release contract). Baseline: main / npm package metadata 0.11.0 as inspected on 2026-10-16.

Objective

Bring EI's MCP Events boundary in line with the current experimental SEP-3415 and ensure delivery gaps cannot silently become false-certain CEP outcomes. Preserve the architecture: MCP Events transports/discovers events; EI persists subscriptions, evaluates conditions/patterns and issues targeted wakeups; the host owns connections, authorization, side effects and wake execution. Poll remains a fallback; push/webhook are host-provided modes, not an assumption that the upstream system is event-driven.

The SEP is still a draft. Pin the exact SEP revision used by tests; recheck upstream and conformance suites before merge/release. This is one tracking issue for three separately reviewed, focused PRs, not permission for an unreviewed rewrite.

A. [P0] MCP Events wire/contract alignment (provider/server)

Verified on main:

  • src/mcpEvents/provider.ts: extension-specific error constants are -32011..-32015 rather than current SEP -32023..-32027.
  • src/mcpEvents/server.ts: unknown events use hardcoded -32011; align the low-level exported server too.
  • src/mcpEvents/provider.ts and src/mcpEvents/server.ts: ok() returns {jsonrpc,id,result} without result.resultType = "complete" on events/list / events/poll.
  • src/mcpEvents/provider.ts requires a result cursor property, although the SEP treats an omitted cursor as null. Confirm exact nullable/optional semantics and avoid coercing malformed supplied cursors to strings.
  • test/mcp-events-current-draft-conformance.test.mjs currently asserts the older -32011.

Acceptance:

  • Update both public provider and low-level server behavior for the current SEP-3415: error codes/data shapes, resultType: "complete", omitted/null cursors, discovery and poll results; reject invalid cursor types without executing coerced values.
  • Preserve the correct capability ID io.modelcontextprotocol/events under capabilities.extensions, and no legacy server/discover surface; do not add obsolete profiles/shims simply to keep pre-v1 consumers compatible.
  • Add positive/negative wire tests for unknown event, invalid arguments, -32601 unsupported method, poll bootstrap cursor:null, null/omitted cursor and maxEvents/pagination; keep advertised modes truthful. Test both createMcpEventsProvider() and ExperimentalMcpEventsServer.
  • Document the targeted SEP commit/assumptions and avoid claiming full SEP conformance if push/webhook server behaviors are host-owned or unimplemented in this adapter.

B. [P1] MCP Events client lifecycle / polling safety

Verified on main:

  • scripts/lib/mcp-events-client.mjs normalizeCursor() rejects undefined instead of treating an omitted cursor as null.
  • nextPollMs currently permits 0; the timer path uses a 250 ms minimum, whereas the SEP recommends a configurable 1,000 ms default floor for normal polling (not backlog drains with hasMore:true).
  • invokeProvider() converts every provider failure to a generic error, protecting diagnostics from sensitive untrusted messages but also discarding useful structured distinctions (e.g. terminal Forbidden / NotFound).

Acceptance:

  • Tolerate missing cursor as null across all permitted client delivery boundaries, and correctly handle replay-unsupported sources.
  • For hasMore:false, enforce configurable default 1,000 ms poll floor while honoring larger producer backoff; for hasMore:true, drain promptly but preserve current hard caps (maxPollBatches, page count, rate/resource safety) and no infinite tight loop.
  • Preserve only allowlisted, structurally validated provider protocol codes/kinds for actionable terminal vs transient handling. Continue scrubbing provider-controlled messages, error objects, telemetry and credentials. No access/authorization bypasses and no blind retry loops after terminal revocation/removal.
  • Test 0-ms producer intervals, repeated empty pages, hasMore bursts, disconnect/reconnect, terminated sessions, late responses and persisted cursor recovery.
  • Review push/webhook handling against SEP cursor/heartbeat/refresh semantics where the host exposes these adapters, without pretending EI owns all native protocol transport details.

C. [P0 investigation] Gap-aware CEP correctness and negative finality

Risk to prove or disprove before implementing a fix: the client persists a producer's truncated:true / onGap() state, but the reviewed paths do not demonstrate that a source-delivery gap is propagated into the temporal evaluator as incomplete evidence. In particular, notFollowedBy, notPresent, notNext and absence/deadline workflows must not conclude not happened from a period in which matching events may have been skipped.

Important: a provider delivery gap (events/poll.truncated, push notifications/events/active gap, webhook gap) is different from Pattern v2's existing internal budget evaluation.truncated. Do not conflate the flags.

Acceptance:

  • Build independent reproducible tests first: same stream with/without a delivery gap, negative temporal window spanning the gap, gap before/after finality, out-of-order/replayed events, interruption + durable restart and cross-tenant/source partition isolation.
  • If the risk reproduces, design and implement a bounded source/subscription gap evidence contract (with durable scope and provenance), propagated to relevant evaluator/finality and wake decisions. When evidence is insufficient, mark the result inconclusive/pending or require host-owned authoritative reconciliation; never emit a falsely certain absence-trigger wake.
  • Preserve normal matches on unaffected sources/windows, idempotent receipts and host-owned authorization; avoid global indefinite suspension because one unrelated source has a gap.
  • Conformance/adversarial tests verify gap signaling for poll, push and webhook adapter callbacks, plus restart and no false-certain negative outcomes. Link any extra formal CEP proof to [P0][B] Formal CEP invariants and adversarial Pattern AST v2 conformance #44.

Delivery / review gates

References

2026-10-17 protocol/client acceptance evidence (A/B)

A is implemented and merged as #174 (exact review HEAD da64489), including provider and direct server contract/wire tests and pinned draft assumptions. B implemented and merged via #175 (poll floor, cursors, backpressure) and #177 (validated terminal error handling and host-session quarantine). Independent reviews and 5/5 CI passed on merged heads. Existing host push/webhook boundary tests cover callback cursor, heartbeat and onGap handling; EI does not implement native server transport refresh endpoints on behalf of the host. Draft external upstream server/client conformance suites: NOT TESTED here, not reported as PASS; where unsupported by EI's transport role, treat as NOT IMPLEMENTED (host-owned).

C diagnostic #179 is merged; runtime correctness PR #180 is MERGED via squash commit a68b2f87. Final reviewed source HEAD 5050253f: 5/5 workflows SUCCESS (CI with PostgreSQL HA, Security Scan, MCP Launch Check, Public Release Check, Clean-room Smoke). Codex exact-head review at 2026-10-17T14:18:36Z: no major issues; no unresolved threads. No npm publish and no downstream Artemis/Muffin changes.

Closure evidence — 2026-10-17

Activity

  1. sarooo17 commented on Oct 16, 2026

    @sarooo17
    OwnerAuthor

    2026-10-16 development continuation (unmerged work; acceptance remains pending independent review/merge):

    Part A — PR #174 7f0a61e: provider + ExperimentalMcpEventsServer aligned to draft SEP-3415 (revision c47fd24): complete result envelope, -32023..-32027 error family, strict cursor typing, null/omitted cursors, pagination/maxEvents tests for both surfaces. Public draft assumptions documented in docs/SEP-3415-WIRE-ALIGNMENT.md. 5/5 exact-head CI checks passing.

    Part B first slice — PR #175 8495d2c: host-configurable 1000ms normal poll floor (larger producer backoff honored), bounded fast hasMore draining, missing cursor => null and hasMore-without-cursor fail closed before durable ingestion. Includes seeded/fixed-clock schedule, backoff, persisted checkpoint, invalid-type and backlog tests. 5/5 exact-head CI checks passing. Part B error kind classification and terminal revocation handling still outstanding; Part C provider-gap propagation into negative CEP not yet addressed.

    No PRs merged and no npm/Artemis/Muffin changes; reviewer quota is currently exhausted. Do not check acceptance sections A/B/C or close #166 without independent reviewed final heads and merged evidence. Draft SEP still subject to change.

  2. sarooo17 commented on Oct 16, 2026

    @sarooo17
    OwnerAuthor

    2026-10-16 follow-up (unmerged #166 Part B implementation): PR #177 on independent main-based head 528fdbe adds a strictly allowlisted SEP-3415 terminal error classifier (-32023 NotFound, -32024 Forbidden with own-data data.kind) and an exact-session MCP client polling circuit-breaker. NotFound quarantines just the affected subscription; Forbidden prevents further polls on the current host-owned connection object. Producer-controlled messages/stack/data are discarded (including accessor/Proxy hazards), transient/unrecognized codes remain generic and retryable. Tests cover hostile errors, no repeated terminal RPC, unaffected-source progression, sanitized diagnostics. Documented limit: session-local in-memory suppression only, host remains responsible for reauthorization and recovery on restart; no #166 C delivery-gap proof yet. CI under evaluation; review-required, no merge, no npm/Artemis/Muffin changes.

  3. sarooo17 commented on Oct 16, 2026

    @sarooo17
    OwnerAuthor

    2026-10-16 reviewer-gated progress update: Part A PR #174 merged as squash 75819e2d976899f8df3f37b1247e5f36ad32ef05 after exact-head Codex clean review, zero unresolved threads and five green CI workflows. Part B terminal error slice PR #177 merged as squash 72ba4a8ff31c51c457cfeba9a653e721045e1568, also independently reviewed clean on exact head with five green CI workflows. The separate Part B polling floor/cursor PR #175 remains open with 5/5 green tests and new exact-head Codex review underway after addressing deadline scheduling feedback. Part C gap-aware CEP negative finality is not implemented and this parent issue remains OPEN. No downstream changes or npm release.

  4. sarooo17 commented on Oct 16, 2026

    @sarooo17
    OwnerAuthor

    2026-10-16 further merge evidence: Part B polling floor PR #175 merged as squash e5a28c547762baadcd7050b9777dc7e71a1796f8 after 5/5 exact-head CI and clean latest-head Codex review, no unresolved findings. This follows merged Part A #174 and Part B terminal handling #177. Part C (gap-aware negative temporal finality) remains unimplemented, and full Part B reconnect/transport-adapter lifecycle matrix still requires audit; keep #166 OPEN. No npm/Artemis/Muffin update.

  5. sarooo17 commented on Oct 16, 2026

    @sarooo17
    OwnerAuthor

    2026-10-16 scoped #166 C investigation (no semantic change yet; proof still required): checked current main source paths. scripts/lib/mcp-events-client.mjs persists poll truncated and forwards onGap to onActive({truncated:true}) in per-subscription MCP client state. scripts/lib/composite-event-consumer.mjs calls triggerEngine.ingest(correlatable) with just the event; no source delivery-completeness/gap proof is forwarded. src/composite/engine.ts timer/negative pattern evaluation sees match/deadline evidence, not source subscription gap state. Potential safety gap, not yet a demonstrated false-positive: an event missing in an upstream truncated window might incorrectly let absence/notFollowedBy finalize. The provider truncated flag is a different kind of incompleteness from the pattern evaluator's internal evaluation.truncated flag (being improved by #173); do not substitute one for the other.

    Next code slice should start with a reproducible negative-finality witness on (i) intact stream, (ii) gap crossing forbidden interval, (iii) gap outside interval, (iv) restart and replay, (v) another tenant/source; then implement per-subscription durable gap provenance and interval-aware finality/wake guard, allowing unaffected sources to progress. No premature issue closure or conformance claim.

  6. sarooo17 commented on Oct 16, 2026

    @sarooo17
    OwnerAuthor

    2026-10-16 #166 C update: PR #179 opened as a test-first diagnostic witness, exact head 89aae75c5840ce71b415ec27b0b7dcc830f38aae, 4/4 checks green at observation; independent Codex review requested and running, no merge yet. This is not a production safety fix or proof of conformance. It uses actual JSONL PersistentEventStore + CompositeTriggerEngine + TemporalDeadlineScheduler to demonstrate the current unsafe behavior: store mcp_client_state.truncated:true for exactly the forbidden MCP source before a notFollowedBy deadline and the engine still persists a matched negative on timer finality, including after physical store reopen. Clean/no-gap, unrelated-source, gap-after-finality and isolated-store controls distinguish the failure. Poll/push/webhook are persisted-state delivery-mode fixtures, not end-to-end transport tests. Documentation docs/MCP-EVENTS-DELIVERY-GAP-NEGATIVE-WITNESS.md names required durable gap evidence, scoped finality gate, explicit reconciliation and host responsibility. A separate reviewed implementation must invert the unsafe assertions and handle other negative nodes, timer retryability, producer callback tests and scoped isolation. Keep #166 OPEN.

  7. sarooo17 commented on Oct 17, 2026

    @sarooo17
    OwnerAuthor

    2026-10-17 continuation for #166 C: diagnostic PR #179 is merged with latest-head independent clean Codex review and 4/4 CI; provider-gap falsified negative finality was independently reproduced. Implementation PR #180 (HEAD 09714c5a8a3a5e929fca45c823d63546ad0bc4d2) has 5/5 CI green, all previous five P1 review threads resolved, and a new independent exact-head Codex review currently running. Added durable snapshot (notPresent/notNext) and temporal (notFollowedBy/absence) retry deadlines, real JSONL engine/scheduler/host acknowledgment/restart regression, sticky JSONL/Postgres gap evidence, and malformed-truncated-page early persistence. Not yet merged or accepted. No package publish or downstream Muffin/Artemis changes. Parent #166 remains OPEN pending latest-head review, merge, scope/conformance/migration evidence checks.

  8. sarooo17 commented on Oct 17, 2026

    @sarooo17
    OwnerAuthor

    2026-10-17 — #166 C finality closeout status

  9. sarooo17 commented on Oct 17, 2026

    @sarooo17
    OwnerAuthor

    #166 C — 2026-10-17 updated merge gate

    PR #180 implementation is at exact head 6b1bd9e. All 5 latest-head GitHub workflow gates PASS: CI (including real PostgreSQL HA), Security Scan, MCP Launch Check, Public Release Check and packed-package Clean-room Smoke.

    Codex's two latest P1s were addressed: (a) a persistent monotonic per-source completeness revision prevents gap→reconcile ABA; (b) conditional negative persistence atomically checks source state AND latest buffer, and on stale comparison the engine reloads current buffer. Regressions include forced ABA+forbidden replay, buffer-only concurrent replay, JSONL reopen/forged revision, and two-worker PostgreSQL fences. Earlier repeated-stale retry P1 is resolved. All pre-existing review threads have been replied to and marked resolved.

    Still required to merge/close: independent latest-head Codex review requested on PR #180; no such new review receipt yet, so #180 and #166 remain OPEN. Upstream experimental conformance runs #521/#541 are still NOT TESTED; host-owned modes are NOT IMPLEMENTED in EI, not falsely reported as conformance PASS. No npm publish or consumer repository update.

  10. sarooo17 commented on Oct 17, 2026

    @sarooo17
    OwnerAuthor

    #166 final blocker status — 2026-10-17

    PR #180 at exact head ac982ca2f4e79d60fde5e4bd4a757bc161953843 fixes the latest Codex P1: host reconcilers now must supply expectedCompletenessRevision with their verified replay evidence, and JSONL/PG enforce revision CAS inside their serialized/locked state transition. An older host acknowledgement cannot clear a newly reported gap from another PostgreSQL worker. Dedicated JSONL/manager injection and multiworker PG tests pass; all 5 exact-head CI gates SUCCESS (including PostgreSQL HA and packed clean-room). Original P1 review thread answered/resolved.

    Only outstanding merge condition: independent Codex review of exact head ac982ca2 requested on PR #180 but not yet submitted. Do not merge based on the earlier Codex review of 6b1bd9; retain #166 OPEN until latest-head review is clean, #180 is merged and acceptance/checklist evidence is updated. Upstream draft conformance suites #521/#541 remain NOT TESTED; host-owned modes are NOT IMPLEMENTED, not claimed PASS.

  11. sarooo17 commented on Oct 17, 2026

    @sarooo17
    OwnerAuthor

    2026-10-17 #180 latest-head closeout gate

    Fix for latest independent Codex P1 (Do not expose mutable gap records) is committed in PR #180 at exact HEAD 27f4f81dbefe20b328bca087f451618aea57a54c. The JSONL MCP state store now creates a deep clone at the write boundary and returns independent deep clones from put/get/list/snapshot so no host-exposed alias can bypass durable gap/revision CAS; added adversarial regression for mutated direct input, returned records, nested arguments, physical restart and valid host reconciliation. All 5/5 exact-head GitHub Actions workflows SUCCESS including PostgreSQL HA, Security, MCP Launch, Public Release and packed-package clean-room. All previously raised inline review threads are resolved.

    Remaining gate: latest-head independent Codex review requested on #180 at 27f4f81, but a new Codex review receipt has not yet been returned. PR #180 and issue #166 intentionally remain OPEN until the review is confirmed clean and the merge is verified. Upstream experimental external SEP conformance suites #521/#541: NOT TESTED (host-owned transports NOT IMPLEMENTED in EI), not represented as PASS. No npm publish or downstream Artemis/Muffin updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions