Skip to content

feat(conformance): wire make testconf-events against the fork's Events suite - #1378

Merged
panyam merged 1 commit into
mainfrom
feat/testconf-events
Sep 15, 2026
Merged

panyam merged 1 commit into
mainfrom
feat/testconf-events

Conversation

@panyam

@panyam panyam commented Sep 15, 2026 •

Copy link
Copy Markdown
Owner

What changes

Adds a make testconf-events target that drives examples/events/kitchen-sink against the two phase-1 Events scenarios proposed upstream in modelcontextprotocol/conformance#504, plus the local-suites.yaml manifest entry and the regenerated path defaults. The suite runs red on purpose: 27 pass / 13 fail / 5 warn, and every failure is a divergence between our events implementation and the design sketch that merged upstream on 2026-09-08.

Wired as INFO at stage 8i, following testconf-skills.

Prerequisite knowledge

  • conformance/NOTES.md — how the testconf-* targets are wired and which upstream changes to watch. The MCPCONFORMANCE_*_PATH convention this target follows is described there.
  • Root CLAUDE.md § Cross-cutting rules — the path-defaults.{mk,sh,just} generation rule. Hand-editing two of the three fails CI as case E drift, which is why gen_conf_paths.py runs here.
  • Events design sketch — what the suite scores against. Skim the Summary and Cursor Lifecycle sections to read the failures.
  • experimental/ext/events/NOTES.md — our side of the same surface, including the earlier spec-alignment sweeps.

Reviewer's guide

A restaurant can cook a dish that is not on the menu. The kitchen has the ingredients and the line knows the recipe, so if you somehow know to ask you get it, but nobody reading the menu ever orders it. Our events server is that dish. events/list answers, all three delivery modes work, and capabilities.events appears nowhere, which is the menu a spec-following client reads before deciding what to ask for. That is the single most consequential thing this target surfaces, and it is the kind of gap that stays invisible precisely because every test we wrote ourselves already knows to ask. The rest of the failures have the same flavour: places where our implementation is self-consistent and internally tested, and diverges from the document anyway. Three of the six were unknown before this run. So read the diff as plumbing, and spend the attention on whether INFO is the right status for a target whose whole value is being red.

Read in this order:

  1. conformance/local-suites.yaml — start here. The note is the finding, recorded with its date and measurement method.
  2. conformance/scripts/conf-events.sh — the runner. Spawns the fixture on :18101, runs the two scenarios, prints each summary, exits 0 and explains why.
  3. conformance/Makefile, Makefile, justfile, conformance/justfile — target plus the three mirrors. just is the one people forget.
  4. scripts/testall.sh — the script map entry and run_stage 8i ... info.
  5. conformance/path-defaults.{mk,sh,just} — generated, skip.

Decision log

  • INFO, not a gate. Two reasons, both outlasting this PR. The suite scores against a design sketch with no SEP number, so its check ids still carry a placeholder sep-9999- prefix that will be renamed. And the failures are ours to fix, so gating would block the umbrella on work this PR deliberately does not do. The precedent is testconf-scope-challenge, INFO for tracking an unmerged PR head. Flip to a gate once the divergences close and the spec text stabilises.
  • Points at the fork branch while the upstream PR is in review. feat/events-conformance-suite on panyam/mcpconformance, default path ../conf-events, matching how every other fork-based suite here resolves. The scenarios are proposed upstream as a draft (feat(sep-xxxx): Conformance suite for triggers and events modelcontextprotocol/conformance#504); retarget source.branch to upstream main once it lands, the same way testconf-scope-challenge is meant to.
  • Fixture defaults left alone. The synthetic feeders emit every 2-4s, which is what gives the EventOccurrence checks a chance to grade something real. A silenced fixture reports them untestable, which is correct but tells us less.
  • No implementation fixes in this PR. The six divergences want their own changes, some wire-breaking. Bundling them would bury the wiring and make the target's first run green for the wrong reason.

Risk / blast radius

Before / after

Before, nothing scored our events surface against the spec text. After:

$ make testconf-events
Spawning fixture on :18101, scratch dir /tmp/conf-events.XXXX
  events-discovery: Passed: 8/11, 3 failed, 1 warnings
  events-poll: Passed: 19/29, 10 failed, 4 warnings

The six divergences, each observed against the running fixture:

Check What we do
sep-9999-capability-events-object answer events/list, declare no capabilities.events
sep-9999-poll-events-array omit events rather than return an empty array
sep-9999-descriptor-delivery-subset events.topology sends delivery: null where an array is required
sep-9999-descriptor-input-schema events.topology carries no inputSchema
sep-9999-poll-mode-unsupported answer events/poll for events.topology, which advertises no poll delivery

All five are tracked in #1380. The bottom three collapse into one question rather than three fixes: with #1381 having added inputSchema to the three real sources, every remaining descriptor-level failure is the events.topology meta-source not keeping the descriptor contract. Whether a meta-source belongs in events/list as a peer of real event types is worth settling before patching the symptoms.

The first one is the one I would fix first. It is not that a field is wrong; it is that a client reading capabilities never learns the surface exists.

#1379 and #1381 landed while this PR was open and closed three earlier findings: the nextPollSeconds rename (G31), and list_changed plus termination (G34, G30). The suite confirms all three, which is the first useful thing it has done as a regression check rather than a discovery tool.

Out of scope

Refs #1374

🤖 Generated with Claude Code

https://claude.ai/code/session_017kyEZdgh1zjdhURgdcZ4nL

@panyam

panyam commented Sep 15, 2026

Copy link
Copy Markdown
Owner Author

Filed the four previously-untracked divergences as #1380. G31 stays with feat/events-spec-wire-alignment, G30 and G34 keep their existing tracking.

Once #1380 lands, the counts recorded in conformance/local-suites.yaml go stale by design — re-run make testconf-events and update the note.

@panyam
panyam force-pushed the feat/testconf-events branch from 8e26857 to 6861e17 Compare September 15, 2026 01:38
Adds the testconf-events target, its runner-agnostic script, and the
local-suites manifest entry, driving examples/events/kitchen-sink against the
two phase-1 scenarios (events-discovery, events-poll). Those are proposed
upstream as a draft in modelcontextprotocol/conformance#504 and tracked on the
panyam/mcpconformance fork branch until it lands.

INFO rather than a gate. The suite scores against the Events design sketch
that merged upstream on 2026-09-08, which has no SEP number yet, so its check
IDs still carry a placeholder sep-9999- prefix. And the run is red on purpose:
the failures are our divergences from that document, which is what the suite
was built to surface.

27 pass / 13 fail / 5 warn against kitchen-sink at c9160cf. Five divergences,
all tracked in #1380: events/list answers while no capabilities.events is
declared, so the whole surface is unreachable for a client that reads
capabilities first; events/poll omits the events key instead of returning an
empty array; and the events.topology meta-source does not keep the descriptor
contract, sending delivery null, carrying no inputSchema, and answering
events/poll despite advertising no poll delivery.

#1379 closed the nextPollSeconds rename and #1381 added list_changed and
termination plus inputSchema on the three real sources, so those no longer
show up here. Flip this to a gate once #1380 closes and the spec text
stabilises.

path-defaults.{mk,sh,just} are regenerated via gen_conf_paths.py rather than
hand-edited. check_local_suites.py reports no drift across 9 suites.

Refs #1374

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017kyEZdgh1zjdhURgdcZ4nL
@panyam
panyam force-pushed the feat/testconf-events branch from 6861e17 to ce674fb Compare September 15, 2026 05:19
@panyam
panyam merged commit b70b741 into main Sep 15, 2026
12 checks passed
@panyam
panyam deleted the feat/testconf-events branch September 15, 2026 06:34
panyam added a commit that referenced this pull request Sep 15, 2026
CLAUDE.md
- testconf-events joins the conformance target list; the Conformance section
  records what the Events suite is, why it is red, and that its check ids carry
  a placeholder SEP number.
- Adding a testconf-* target trips TWO independent CI gates. Passing
  check-local-suites-stale says nothing about check-conformance-stale, because
  CONFORMANCE.md and the badge are rendered from local-suites.yaml and go stale
  the moment an entry is added. This cost #1378 a round-trip after everything
  else had gone green.
- The docs-site conformance page is a shim over CONFORMANCE.md, so regenerating
  that file is the site update. No separate page edit.
- Corrected the GitHub-credential guidance. The claim that upstream PR writes
  need the web UI or a classic PAT is true only of the fine-grained PAT; gh's
  own stored gho_ login has full repo scope and creates, edits and comments on
  modelcontextprotocol/* fine (verified on conformance#504). Also corrected the
  SSH recipe: ~/.ssh/id_github does not exist in the container, only the agent
  socket.
- Removed two stale claims: that conformance/ has a nested CLAUDE.md (there are
  none in the tree), and a CAPABILITIES.md retirement SHA that does not resolve
  (the real one is bc402a0, 2026-07-18). Kept the do-not-recreate guard, since
  that is the half that still does work.

conformance/NOTES.md
- New "Adding a testconf-* target" checklist: six places, two gates.
- New "MCP Events suite" section: the placeholder-SEP reasoning and why the
  rename is a merge blocker rather than a follow-up, why new-sep needs
  --spec-url here, the severity rule for the 85 of 131 rows that quote no RFC
  2119 keyword, and why the capability gate probes before it skips.
- Corrected "Writing to a repo we do not own" with the working credential.
- Path table gains MCPCONFORMANCE_EVENTS_PATH; the skills row was still
  pointing at the retired fork branch.

ROADMAP.md
- Events conformance phases 2-4 under Near-term, with what #1374 actually
  requires to close.

CONSTRAINTS.md reviewed, no change: it holds architectural rules about the Go
surface, and the conformance checklist is build process.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017kyEZdgh1zjdhURgdcZ4nL
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