Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 4 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,14 @@ jobs:
- name: Build the workspace
run: cargo build --locked --workspace --all-features

- name: Prepare the conformance binary artifact
run: |
mkdir -p target/conformance
cp target/debug/contextforge-data-plane target/conformance/contextforge-data-plane
strip target/conformance/contextforge-data-plane
- name: Strip the conformance binary
run: strip target/debug/contextforge-data-plane

- name: Upload the conformance binary
uses: actions/upload-artifact@v7.0.1
with:
name: contextforge-data-plane-conformance
path: target/conformance/contextforge-data-plane
name: contextforge-data-plane-conformance-${{ github.sha }}
path: target/debug/contextforge-data-plane
if-no-files-found: error
retention-days: 1

Expand All @@ -102,7 +99,3 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2.9.1
- run: cargo bench --locked --workspace --no-run

conformance:
needs: build
uses: ./.github/workflows/mcp_conformance.yml
118 changes: 118 additions & 0 deletions .github/workflows/conformance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: Conformance
run-name: Conformance for PR #${{ github.event.issue.number }}

on:
issue_comment:
types: [created]

permissions:
actions: read
contents: read

concurrency:
group: conformance-pr-${{ github.event.issue.number }}
cancel-in-progress: true

env:
CARGO_TERM_COLOR: always

jobs:
acknowledge:
name: acknowledge command
if: >-
github.event.issue.pull_request &&
github.event.comment.body == '/conformance' &&
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)
permissions:
issues: write
runs-on: ubuntu-latest
steps:
- name: Acknowledge the command
env:
COMMENT_ID: ${{ github.event.comment.id }}
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
run: gh api --method POST "repos/$REPOSITORY/issues/comments/$COMMENT_ID/reactions" -f content=eyes

conformance:
name: conformance
if: >-
github.event.issue.pull_request &&
github.event.comment.body == '/conformance' &&
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Check out data plane
uses: actions/checkout@v6.0.2
with:
fetch-depth: 0
persist-credentials: false
ref: refs/pull/${{ github.event.issue.number }}/merge

- uses: taiki-e/install-action@v2.75.27
with:
tool: cargo-binstall

- name: Install cf-integration 0.2.0 binary
run: cargo binstall cf-integration@0.2.0 --no-confirm

- name: Prepare the exact data-plane image
env:
GH_TOKEN: ${{ github.token }}
run: >-
cf-integration ci prepare-image
--artifact contextforge-data-plane-conformance
--binary contextforge-data-plane
--image contextforge-data-plane:conformance

- name: Install Node.js 22
uses: actions/setup-node@v6.5.0
with:
node-version: 22

- name: Run strict modern conformance
env:
CF_DATAPLANE_IMAGE: contextforge-data-plane:conformance
CF_DATAPLANE_PULL_POLICY: never
CF_DATAPLANE_REF: ""
run: make conformance

- name: Upload conformance diagnostics
if: failure()
uses: actions/upload-artifact@v7.0.1
with:
name: conformance-diagnostics-${{ github.run_id }}-${{ github.run_attempt }}
path: |
.integration/conformance/
.integration/reports/
if-no-files-found: warn
include-hidden-files: true
retention-days: 7

report:
name: report conformance result
if: >-
always() &&
needs.conformance.result != 'skipped'
needs: conformance
permissions:
issues: write
runs-on: ubuntu-latest
steps:
- name: Report the result
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.issue.number }}
REPOSITORY: ${{ github.repository }}
RESULT: ${{ needs.conformance.result }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
case "$RESULT" in
success) marker="✅" ;;
failure) marker="❌" ;;
cancelled) marker="⚪" ;;
*) marker="⚠️" ;;
esac
body="$marker Conformance **$RESULT** — [view workflow run]($RUN_URL)."
gh api --method POST "repos/$REPOSITORY/issues/$PR_NUMBER/comments" -f body="$body"
138 changes: 0 additions & 138 deletions .github/workflows/mcp_conformance.yml

This file was deleted.

11 changes: 6 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ target

# Generated by gateway local runs
contextforge-data-plane.log.*
# Generated by local MCP conformance runs
.conformance-suite/
conformance-logs/
conformance-results/
# Generated by cf-integration
.integration/
/.conformance-suite/
/conformance-logs/
/conformance-results/
# Generated by mdBook (wiki)
_context/wiki/book/

Expand All @@ -34,4 +35,4 @@ _context/wiki/book/


# Personal dev tooling (wt worktree manager, etc.)
.config/
.config/
48 changes: 42 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
IMAGE_NAME := contextforge-data-plane:latest
CF_DATAPLANE_IMAGE ?= contextforge-data-plane:conformance
SERVICES ?= nginx control-plane redis postgres pgbouncer data-plane fast_time_server register_fast_time
ARGS ?=
CF_INTEGRATION ?= cf-integration
CF_INTEGRATION_DIR ?= $(CURDIR)/.integration
CF_DATAPLANE_REPO ?= $(CURDIR)
CF_DATAPLANE_REF ?= $(shell git -C "$(CF_DATAPLANE_REPO)" rev-parse HEAD)
CONFORMANCE_BASELINE_DIR := $(CURDIR)/tests/conformance/baselines

# IBM detect-secrets hardened fork — pinned to the same commit used in mcp-context-forge.
DETECT_SECRETS_SPEC ?= git+https://github.com/ibm/detect-secrets.git@076672a9a01abdfc7ecee2e7d14f08cdccb73976
Expand All @@ -25,12 +29,44 @@ compose-up: ## Launch stack: nginx, control plane, redis, postgres, pgbouncer, d
compose-down: ## Tear down the stack
docker compose -f docker/docker-compose.yml stop $(SERVICES) $(ARGS)

conformance: ## Build the data plane and run official MCP 2026-07-28 conformance locally
docker build -t "$(CF_DATAPLANE_IMAGE)" -f docker/conformance.Dockerfile .
CF_DATAPLANE_IMAGE="$(CF_DATAPLANE_IMAGE)" tests/conformance/run-local.sh
conformance: ## Run strict modern MCP conformance against the committed data-plane HEAD
@if ! command -v "$(CF_INTEGRATION)" >/dev/null 2>&1; then \
echo "cf-integration not found: install its published binary with cargo binstall or set CF_INTEGRATION to its path."; \
exit 1; \
fi
@if [ -n "$$(git -C "$(CF_DATAPLANE_REPO)" status --porcelain --untracked-files=no)" ]; then \
echo "Tracked data-plane changes are not committed; commit or stash them before conformance."; \
exit 1; \
fi
@CF_INTEGRATION_DIR="$(CF_INTEGRATION_DIR)" \
CF_DATAPLANE_REPO="$(CF_DATAPLANE_REPO)" \
CF_DATAPLANE_REF="$(CF_DATAPLANE_REF)" \
"$(CF_INTEGRATION)" conformance run \
--client-era modern \
--server-era modern \
--lane external-data-plane \
--baseline-dir "$(CONFORMANCE_BASELINE_DIR)" \
--output-dir "$(CF_INTEGRATION_DIR)/reports"

conformance-bless: ## Run conformance and update the server and client expected-failure baselines
MCP_CONFORMANCE_BLESS=true $(MAKE) conformance
conformance-bless: ## Run strict modern conformance and atomically update its baselines
@if ! command -v "$(CF_INTEGRATION)" >/dev/null 2>&1; then \
echo "cf-integration not found: install its published binary with cargo binstall or set CF_INTEGRATION to its path."; \
exit 1; \
fi
@if [ -n "$$(git -C "$(CF_DATAPLANE_REPO)" status --porcelain --untracked-files=no)" ]; then \
echo "Tracked data-plane changes are not committed; commit or stash them before conformance."; \
exit 1; \
fi
@CF_INTEGRATION_DIR="$(CF_INTEGRATION_DIR)" \
CF_DATAPLANE_REPO="$(CF_DATAPLANE_REPO)" \
CF_DATAPLANE_REF="$(CF_DATAPLANE_REF)" \
"$(CF_INTEGRATION)" conformance run \
--client-era modern \
--server-era modern \
--lane external-data-plane \
--baseline-dir "$(CONFORMANCE_BASELINE_DIR)" \
--output-dir "$(CF_INTEGRATION_DIR)/reports" \
--bless

docs-serve: ## Serve the wiki book locally at http://127.0.0.1:3000
mdbook serve _context/wiki --hostname 127.0.0.1 --port 3000 --open
Expand Down
Loading