From 82611a8fb81abe5ffa73fcf69fcd39c3ed7bac7f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 15 Sep 2026 05:39:17 +0000
Subject: [PATCH 1/5] Initial plan
From 3c6388d870da982a89b6ccfd27459a86b1c6d334 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 15 Sep 2026 05:43:00 +0000
Subject: [PATCH 2/5] docs: add repo map and repo skills
Co-authored-by: groupthinking <154503486+groupthinking@users.noreply.github.com>
---
.github/skills/codebase-summary/SKILL.md | 51 +++++
.../github-actions-failure-debugging/SKILL.md | 57 +++++
README.md | 10 +-
docs/REPO_MAP.md | 213 ++++++++++++++++++
tests/test_repo_assist_docs.py | 38 ++++
5 files changed, 368 insertions(+), 1 deletion(-)
create mode 100644 .github/skills/codebase-summary/SKILL.md
create mode 100644 .github/skills/github-actions-failure-debugging/SKILL.md
create mode 100644 docs/REPO_MAP.md
create mode 100644 tests/test_repo_assist_docs.py
diff --git a/.github/skills/codebase-summary/SKILL.md b/.github/skills/codebase-summary/SKILL.md
new file mode 100644
index 0000000..d409999
--- /dev/null
+++ b/.github/skills/codebase-summary/SKILL.md
@@ -0,0 +1,51 @@
+---
+name: codebase-summary
+description: Generate a repo-specific map of self-correcting-executor, including the tree, key dependencies, and MCP verification steps. Use this when asked to summarize the architecture or prepare an agent run for this repository.
+---
+
+When asked to summarize or orient an agent in this repository, use the current
+repo structure instead of generic MCP examples.
+
+1. Start from `/home/runner/work/self-correcting-executor/self-correcting-executor`.
+2. Build the summary around these directories:
+ - `agents/`
+ - `connectors/`
+ - `mcp_server/`
+ - `protocols/`
+ - `frontend/`
+ - `tests/`
+3. Call out the primary dependency sources:
+ - `requirements.txt`
+ - `requirements-ci.txt`
+ - `requirements-test.txt`
+ - `frontend/package.json`
+4. When MCP is relevant, explicitly distinguish:
+ - **host**: external Copilot/CLI/operator
+ - **client**: external MCP-aware caller
+ - **server**: the repo's implementations in `mcp_server/` and
+ `quantum_mcp_server/`
+5. Use the live baseline verification sequence before claiming MCP is working:
+
+ ```python
+ import asyncio
+ from mcp_server.main import MCPServer
+
+ async def main():
+ server = MCPServer()
+ await server.handle_request(
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "initialize",
+ "params": {"clientInfo": {"name": "summary-skill", "version": "1.0"}},
+ }
+ )
+ await server.handle_request(
+ {"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}
+ )
+
+ asyncio.run(main())
+ ```
+
+6. Point the reader to `docs/REPO_MAP.md` for the maintained tree, mermaid
+ diagram, dependency snapshot, workflow checklist, and CI/MCP notes.
diff --git a/.github/skills/github-actions-failure-debugging/SKILL.md b/.github/skills/github-actions-failure-debugging/SKILL.md
new file mode 100644
index 0000000..10dc739
--- /dev/null
+++ b/.github/skills/github-actions-failure-debugging/SKILL.md
@@ -0,0 +1,57 @@
+---
+name: github-actions-failure-debugging
+description: Guide for debugging failing GitHub Actions workflows in self-correcting-executor. Use this when asked to investigate Python CI, Frontend CI, or PR workflow failures in this repository.
+---
+
+Use GitHub MCP tools first, then reproduce locally with the repo's existing
+commands.
+
+1. List recent workflow runs for `groupthinking/self-correcting-executor`.
+ Focus on:
+ - `.github/workflows/python-ci.yml`
+ - `.github/workflows/frontend-ci.yml`
+2. Get job logs for the failed run or failed jobs.
+3. Interpret the result against this repo's workflow behavior:
+ - `python-ci.yml` runs `black --check .`
+ - `python-ci.yml` currently masks `flake8` and `pytest` failures with
+ `|| echo ...` and `continue-on-error`, so a green workflow does not always
+ mean imports/tests are healthy
+ - `frontend-ci.yml` runs `npm ci || npm install`, then lint/test/build from
+ `/frontend`
+4. Reproduce only the relevant local command:
+
+ ```bash
+ cd /home/runner/work/self-correcting-executor/self-correcting-executor
+ python -m pytest tests/ -q
+ cd /home/runner/work/self-correcting-executor/self-correcting-executor/frontend
+ npm run lint
+ npm run build
+ ```
+
+5. If the failure touches MCP behavior, also run the repo's live MCP baseline:
+
+ ```bash
+ cd /home/runner/work/self-correcting-executor/self-correcting-executor
+ python -m pytest tests/test_repo_assist_docs.py -q
+ python - <<'PY'
+ import asyncio
+ from mcp_server.main import MCPServer
+
+ async def main():
+ server = MCPServer()
+ response = await server.handle_request(
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "initialize",
+ "params": {"clientInfo": {"name": "ci-debug", "version": "1.0"}},
+ }
+ )
+ print(response["result"]["serverInfo"])
+
+ asyncio.run(main())
+ PY
+ ```
+
+6. Keep fixes surgical. Do not "clean up" unrelated files just because the
+ workflow surfaced pre-existing noise.
diff --git a/README.md b/README.md
index 81997fc..ad4478d 100644
--- a/README.md
+++ b/README.md
@@ -33,4 +33,12 @@ Open http://localhost:8080/health to verify the API is running.
## Development
-The workspace includes a **DevContainer** definition – simply open the folder in VS Code or Cursor and choose *Reopen in Container* to get an IDE connected to the running services.
\ No newline at end of file
+The workspace includes a **DevContainer** definition – simply open the folder in VS Code or Cursor and choose *Reopen in Container* to get an IDE connected to the running services.
+
+## Repo assist
+
+For a repo-specific map of the current tree, dependency snapshot, mermaid
+architecture diagram, MCP capability-verification notes, and agent workflow
+checklist, see
+`/home/runner/work/self-correcting-executor/self-correcting-executor/docs/REPO_MAP.md`
+(also tracked in the repository as [`docs/REPO_MAP.md`](docs/REPO_MAP.md)).
\ No newline at end of file
diff --git a/docs/REPO_MAP.md b/docs/REPO_MAP.md
new file mode 100644
index 0000000..30a0c23
--- /dev/null
+++ b/docs/REPO_MAP.md
@@ -0,0 +1,213 @@
+# Repo Map, MCP Verification, and Agent Workflow Checklist
+
+This repository mixes agent orchestration, MCP servers, connectors, protocols,
+and a small frontend. This document makes the issue's requested "repo assist"
+material specific to `groupthinking/self-correcting-executor` so an agent can
+map the repo, verify the MCP baseline live, and decide what to check before
+commit/merge.
+
+## Repo tree (focused map)
+
+```text
+self-correcting-executor/
+├── agents/ # A2A framework, executor, mutator, MCP integrations
+│ ├── a2a_framework.py
+│ ├── a2a_mcp_integration.py
+│ ├── executor.py
+│ ├── mutator.py
+│ ├── specialized/
+│ └── unified/
+├── analyzers/ # Pattern analysis helpers
+├── auth/ # Auth helpers
+├── config/ # MCP and component configuration
+├── connectors/ # D-Wave, GitHub, LLM, xAI, MCP base connectors
+├── docs/ # Architecture, planning, and task guides
+├── fabric/ # State continuity and integrated MCP fabric
+├── frontend/ # Vite + React UI
+├── llm/ # Continuous learning system
+├── mcp_runtime_template_hg/ # SDK/API/CLI MCP runtime template
+├── mcp_server/ # JSON-RPC MCP server + FastMCP-backed server
+├── middleware/ # Security middleware
+├── protocols/ # Executable protocols/tasks
+├── quantum_mcp_server/ # Quantum-focused MCP server variant
+├── scripts/ # Setup, compliance, cleanup, security scripts
+├── test_data/ # Real input fixtures used by tests/scripts
+├── tests/ # Pytest suite
+├── ui/ # Additional UI assets and guide content
+└── utils/ # Shared logging and DB tracking
+```
+
+## Dependency snapshot
+
+- Python runtime dependencies: `requirements.txt` currently pins **117**
+ packages, including `mcp`, `mcp-use`, FastAPI, D-Wave Ocean SDK, LangChain,
+ SQLAlchemy, Redis, and transformer-related packages.
+- CI/test dependencies: `requirements-ci.txt` contains the lightweight
+ verification stack (`black`, `flake8`, `pytest`, `pytest-cov`,
+ `pytest-asyncio`).
+- Frontend runtime dependencies: `frontend/package.json` currently declares
+ **7** runtime packages (`react`, `react-dom`, `@tanstack/react-query`,
+ `axios`, `framer-motion`, `lucide-react`, `three`) and **12** dev
+ dependencies for TypeScript, ESLint, and Vite.
+
+## Mermaid diagram
+
+```mermaid
+flowchart TD
+ H[Host / Copilot / operator]
+ O[orchestrator.py
orchestrator_mapreduce.py]
+
+ subgraph Servers[MCP servers]
+ M1[mcp_server/main.py
custom JSON-RPC MCPServer]
+ M2[mcp_server/real_mcp_server.py
FastMCP tool server]
+ M3[quantum_mcp_server/]
+ end
+
+ subgraph Tools[Declared MCP tools]
+ T1[code_analyzer]
+ T2[protocol_validator]
+ T3[self_corrector]
+ end
+
+ subgraph Connectors[Connectors]
+ C1[github_mcp_connector.py]
+ C2[dwave_quantum_connector.py]
+ C3[llm_connector.py]
+ C4[xai_connector.py]
+ end
+
+ subgraph Tasks[protocols/*.py]
+ P1[data_processor]
+ P2[file_validator]
+ P3[database_health_check]
+ P4[system_monitor]
+ end
+
+ H --> O
+ O --> M1
+ O --> M2
+ O --> M3
+ M1 --> T1
+ M1 --> T2
+ M1 --> T3
+ M2 --> C1
+ M2 --> C2
+ M2 --> C3
+ M2 --> C4
+ O --> Tasks
+ Tasks --> P1
+ Tasks --> P2
+ Tasks --> P3
+ Tasks --> P4
+```
+
+## Agentic workflow checklist for this repo
+
+- [x] **Agents**: `agents/a2a_framework.py`, `agents/a2a_mcp_integration.py`,
+ and `agents/unified/` contain agent coordination logic.
+- [x] **Tools**: `mcp_server/main.py` declares `code_analyzer`,
+ `protocol_validator`, and `self_corrector`.
+- [x] **MCP**: the repo is actively using MCP packages and MCP-shaped servers
+ (`mcp_server/main.py`, `mcp_server/real_mcp_server.py`,
+ `config/mcp_config.py`, `connectors/mcp_base.py`).
+- [x] **Pull / push / request / commit / merge**: human workflows use GitHub
+ pull requests; cloud-agent workflows in this repo should publish progress
+ via PR updates instead of pushing directly from the sandbox.
+- [x] **Issues**: link changes back to GitHub issues with `Closes #`.
+- [x] **Code**: the main test entrypoint is `pytest` with `pytest.ini`
+ configured to use `tests/`.
+- [x] **Deps**: Python dependencies live in `requirements*.txt`; frontend
+ dependencies live in `frontend/package.json`.
+- [x] **Database**: DB-aware execution paths are visible in `utils/db_tracker.py`
+ and `protocols/database_health_check.py`.
+- [x] **Actions**: `.github/workflows/python-ci.yml` and
+ `.github/workflows/frontend-ci.yml` define CI.
+- [x] **Role assignment / security**: `auth/` and `middleware/` contain auth
+ and security logic.
+
+## MCP baseline: is this repo using MCP?
+
+Yes. The repository is using MCP in two forms:
+
+1. A custom JSON-RPC server in `/home/runner/work/self-correcting-executor/self-correcting-executor/mcp_server/main.py`
+ with explicit MCP methods such as `initialize`, `tools/list`, `tools/call`,
+ `resources/list`, and `resources/read`.
+2. A FastMCP-based server in `/home/runner/work/self-correcting-executor/self-correcting-executor/mcp_server/real_mcp_server.py`
+ built on the `mcp` package.
+
+Compared with the MCP architecture/specification dated `2026-07-28`, this repo
+already covers the **server** side baseline well enough to negotiate tools and
+resources, but it does **not** implement a full host/client runtime in-repo.
+That is acceptable for this codebase because GitHub Copilot/GitHub MCP acts as
+the host environment around these servers.
+
+### Host / client / server mapping for this repo
+
+- **Host**: external agent host (for example Copilot, CLI, or another MCP-aware
+ operator) orchestrates requests and permissions.
+- **Client**: the MCP-aware caller is external to this repo; this repo does not
+ ship a standalone client implementation.
+- **Server**: this repo implements the server side in `mcp_server/` and
+ `quantum_mcp_server/`.
+
+## Live verification steps
+
+The minimum capability-negotiation proof for this repo is to exercise the
+custom MCP server directly and confirm that `initialize` advertises
+capabilities, then `tools/list` and `tools/call` work end-to-end.
+
+```bash
+cd /home/runner/work/self-correcting-executor/self-correcting-executor
+python - <<'PY'
+import asyncio
+import json
+from mcp_server.main import MCPServer
+
+async def main():
+ server = MCPServer()
+ for request in (
+ {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "initialize",
+ "params": {"clientInfo": {"name": "repo-assist", "version": "1.0"}},
+ },
+ {"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}},
+ {
+ "jsonrpc": "2.0",
+ "id": 3,
+ "method": "tools/call",
+ "params": {
+ "name": "code_analyzer",
+ "arguments": {"code": "def verify():\n return 1\n"},
+ },
+ },
+ ):
+ print(json.dumps(await server.handle_request(request), indent=2))
+
+asyncio.run(main())
+PY
+```
+
+Focused automated verification for the repo-assist additions:
+
+```bash
+python -m pytest tests/test_repo_assist_docs.py -q
+```
+
+## CI baseline observed from GitHub Actions
+
+- The repo has active `Python CI` and `Frontend CI` workflows.
+- The inspected recent `Python CI` job logs showed `black` passing.
+- The same logs also showed that `flake8` findings and `pytest` collection
+ errors are currently masked by `|| echo ...` and `continue-on-error`, so the
+ workflow can report success even when Python imports/tests are not clean.
+
+## Skills added for this repo
+
+Project-scoped skills now live under `.github/skills/`:
+
+- `github-actions-failure-debugging`: tailored to the repo's Python/Frontend CI
+ workflows and GitHub MCP debugging flow.
+- `codebase-summary`: tailored to this repo's tree mapping, dependency checks,
+ and MCP verification workflow.
diff --git a/tests/test_repo_assist_docs.py b/tests/test_repo_assist_docs.py
new file mode 100644
index 0000000..26eded7
--- /dev/null
+++ b/tests/test_repo_assist_docs.py
@@ -0,0 +1,38 @@
+from pathlib import Path
+
+
+REPO_ROOT = Path(__file__).resolve().parents[1]
+
+
+def test_repo_map_contains_requested_sections():
+ repo_map = REPO_ROOT / "docs" / "REPO_MAP.md"
+
+ assert repo_map.exists()
+ content = repo_map.read_text()
+ assert "## Repo tree (focused map)" in content
+ assert "## Dependency snapshot" in content
+ assert "## Mermaid diagram" in content
+ assert "## Agentic workflow checklist for this repo" in content
+ assert "## MCP baseline: is this repo using MCP?" in content
+ assert "## Live verification steps" in content
+
+
+def test_repo_skills_are_present_and_repo_specific():
+ skills = {
+ "github-actions-failure-debugging": (
+ REPO_ROOT
+ / ".github"
+ / "skills"
+ / "github-actions-failure-debugging"
+ / "SKILL.md"
+ ),
+ "codebase-summary": (
+ REPO_ROOT / ".github" / "skills" / "codebase-summary" / "SKILL.md"
+ ),
+ }
+
+ for name, skill_path in skills.items():
+ assert skill_path.exists(), f"Missing skill: {name}"
+ content = skill_path.read_text()
+ assert f"name: {name}" in content
+ assert "self-correcting-executor" in content
From e317bfbe23f9728c61b27dd01b00308b6b358ebb Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 15 Sep 2026 05:43:58 +0000
Subject: [PATCH 3/5] test: format repo assist verification
Co-authored-by: groupthinking <154503486+groupthinking@users.noreply.github.com>
---
tests/test_repo_assist_docs.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/tests/test_repo_assist_docs.py b/tests/test_repo_assist_docs.py
index 26eded7..3f2cd6a 100644
--- a/tests/test_repo_assist_docs.py
+++ b/tests/test_repo_assist_docs.py
@@ -1,6 +1,5 @@
from pathlib import Path
-
REPO_ROOT = Path(__file__).resolve().parents[1]
From 3836cb0da46fa2c26c0725c1d04add440a8b79c4 Mon Sep 17 00:00:00 2001
From: Hayden <154503486+groupthinking@users.noreply.github.com>
Date: Thu, 29 Oct 2026 05:27:15 -0500
Subject: [PATCH 4/5] fix: repair review findings and enforce tested CI
behavior
---
.github/dependabot.yml | 21 +-
.github/skills/codebase-summary/SKILL.md | 30 +-
.../github-actions-failure-debugging/SKILL.md | 38 +-
.github/workflows/python-ci.yml | 3 +-
README.md | 4 +-
docs/REPO_MAP.md | 86 ++--
orchestrator_mapreduce.py | 99 ++--
requirements-ci.txt | 10 +-
scripts/verify_mcp_baseline.py | 59 +++
tests/test_dependabot_test.py | 473 +++---------------
tests/test_mcp_baseline_verifier.py | 53 ++
tests/test_mcp_compliance.py | 106 ++--
12 files changed, 349 insertions(+), 633 deletions(-)
create mode 100644 scripts/verify_mcp_baseline.py
create mode 100644 tests/test_mcp_baseline_verifier.py
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index adc776d..9b9da00 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,29 +1,14 @@
-groupthinking-patch-3
- # To get started with Dependabot version updates, you'll need to specify which
- master
-# package ecosystems to update and where the package manifests are located.
-# Please see the documentation for all configuration options:
-# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
-
version: 2
updates:
-groupthinking-patch-3
- - package-ecosystem: "" # See documentation for possible values
-
- groupthinking-patch-2
- - package-ecosystem: "" # See documentation for possible values
-
- package-ecosystem: "pip"
- directory: "/" # Location of package manifests
+ directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "npm"
- directory: "/frontend" # Location of package manifests
+ directory: "/frontend"
schedule:
interval: "weekly"
- package-ecosystem: "docker"
-master
-master
- directory: "/" # Location of package manifests
+ directory: "/"
schedule:
interval: "weekly"
diff --git a/.github/skills/codebase-summary/SKILL.md b/.github/skills/codebase-summary/SKILL.md
index d409999..d75a1dd 100644
--- a/.github/skills/codebase-summary/SKILL.md
+++ b/.github/skills/codebase-summary/SKILL.md
@@ -6,7 +6,7 @@ description: Generate a repo-specific map of self-correcting-executor, including
When asked to summarize or orient an agent in this repository, use the current
repo structure instead of generic MCP examples.
-1. Start from `/home/runner/work/self-correcting-executor/self-correcting-executor`.
+1. Start from the current repository root (`git rev-parse --show-toplevel`).
2. Build the summary around these directories:
- `agents/`
- `connectors/`
@@ -24,28 +24,16 @@ repo structure instead of generic MCP examples.
- **client**: external MCP-aware caller
- **server**: the repo's implementations in `mcp_server/` and
`quantum_mcp_server/`
-5. Use the live baseline verification sequence before claiming MCP is working:
+5. Use the in-process handler checks before reporting that baseline as verified:
- ```python
- import asyncio
- from mcp_server.main import MCPServer
-
- async def main():
- server = MCPServer()
- await server.handle_request(
- {
- "jsonrpc": "2.0",
- "id": 1,
- "method": "initialize",
- "params": {"clientInfo": {"name": "summary-skill", "version": "1.0"}},
- }
- )
- await server.handle_request(
- {"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}
- )
-
- asyncio.run(main())
+ ```bash
+ cd "$(git rev-parse --show-toplevel)"
+ python -m scripts.verify_mcp_baseline
+ python -m pytest tests/test_mcp_baseline_verifier.py -q
```
+ These checks exercise the custom handler in-process; they do not verify
+ an external MCP client/transport connection.
+
6. Point the reader to `docs/REPO_MAP.md` for the maintained tree, mermaid
diagram, dependency snapshot, workflow checklist, and CI/MCP notes.
diff --git a/.github/skills/github-actions-failure-debugging/SKILL.md b/.github/skills/github-actions-failure-debugging/SKILL.md
index 10dc739..e715fb6 100644
--- a/.github/skills/github-actions-failure-debugging/SKILL.md
+++ b/.github/skills/github-actions-failure-debugging/SKILL.md
@@ -13,45 +13,31 @@ commands.
2. Get job logs for the failed run or failed jobs.
3. Interpret the result against this repo's workflow behavior:
- `python-ci.yml` runs `black --check .`
- - `python-ci.yml` currently masks `flake8` and `pytest` failures with
- `|| echo ...` and `continue-on-error`, so a green workflow does not always
- mean imports/tests are healthy
+ - `python-ci.yml` runs pytest as a blocking step. Its existing `flake8`
+ step remains advisory via `|| echo ...` and `continue-on-error`, so a
+ green workflow does not establish a lint-clean repository.
- `frontend-ci.yml` runs `npm ci || npm install`, then lint/test/build from
`/frontend`
4. Reproduce only the relevant local command:
```bash
- cd /home/runner/work/self-correcting-executor/self-correcting-executor
+ cd "$(git rev-parse --show-toplevel)"
python -m pytest tests/ -q
- cd /home/runner/work/self-correcting-executor/self-correcting-executor/frontend
+ cd "$(git rev-parse --show-toplevel)/frontend"
npm run lint
npm run build
```
-5. If the failure touches MCP behavior, also run the repo's live MCP baseline:
+5. If the failure touches MCP behavior, also run the repo's in-process MCP handler checks:
```bash
- cd /home/runner/work/self-correcting-executor/self-correcting-executor
- python -m pytest tests/test_repo_assist_docs.py -q
- python - <<'PY'
- import asyncio
- from mcp_server.main import MCPServer
-
- async def main():
- server = MCPServer()
- response = await server.handle_request(
- {
- "jsonrpc": "2.0",
- "id": 1,
- "method": "initialize",
- "params": {"clientInfo": {"name": "ci-debug", "version": "1.0"}},
- }
- )
- print(response["result"]["serverInfo"])
-
- asyncio.run(main())
- PY
+ cd "$(git rev-parse --show-toplevel)"
+ python -m scripts.verify_mcp_baseline
+ python -m pytest tests/test_mcp_baseline_verifier.py -q
```
+ These checks exercise the custom handler in-process; they do not verify
+ an external MCP client/transport connection.
+
6. Keep fixes surgical. Do not "clean up" unrelated files just because the
workflow surfaced pre-existing noise.
diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml
index c34e41b..81bd812 100644
--- a/.github/workflows/python-ci.yml
+++ b/.github/workflows/python-ci.yml
@@ -31,8 +31,7 @@ jobs:
run: flake8 . || echo "Flake8 found issues but continuing CI"
continue-on-error: true
- name: Run tests with coverage
- run: pytest --cov=. || echo "Tests failed but continuing CI"
- continue-on-error: true
+ run: pytest --cov=.
actions:
runs-on: ubuntu-latest
diff --git a/README.md b/README.md
index ad4478d..c62cc81 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,4 @@ The workspace includes a **DevContainer** definition – simply open the folder
For a repo-specific map of the current tree, dependency snapshot, mermaid
architecture diagram, MCP capability-verification notes, and agent workflow
-checklist, see
-`/home/runner/work/self-correcting-executor/self-correcting-executor/docs/REPO_MAP.md`
-(also tracked in the repository as [`docs/REPO_MAP.md`](docs/REPO_MAP.md)).
\ No newline at end of file
+checklist, see [`docs/REPO_MAP.md`](docs/REPO_MAP.md).
\ No newline at end of file
diff --git a/docs/REPO_MAP.md b/docs/REPO_MAP.md
index 30a0c23..2665bba 100644
--- a/docs/REPO_MAP.md
+++ b/docs/REPO_MAP.md
@@ -3,7 +3,7 @@
This repository mixes agent orchestration, MCP servers, connectors, protocols,
and a small frontend. This document makes the issue's requested "repo assist"
material specific to `groupthinking/self-correcting-executor` so an agent can
-map the repo, verify the MCP baseline live, and decide what to check before
+map the repo, verify the MCP handler in-process, and decide what to check before
commit/merge.
## Repo tree (focused map)
@@ -44,7 +44,8 @@ self-correcting-executor/
SQLAlchemy, Redis, and transformer-related packages.
- CI/test dependencies: `requirements-ci.txt` contains the lightweight
verification stack (`black`, `flake8`, `pytest`, `pytest-cov`,
- `pytest-asyncio`).
+ `pytest-asyncio`) plus the MCP, NumPy, and PostgreSQL imports needed by
+ the collected tests. MCP/Pydantic match the production compatibility pair.
- Frontend runtime dependencies: `frontend/package.json` currently declares
**7** runtime packages (`react`, `react-dom`, `@tanstack/react-query`,
`axios`, `framer-motion`, `lucide-react`, `three`) and **12** dev
@@ -84,16 +85,11 @@ flowchart TD
end
H --> O
- O --> M1
- O --> M2
- O --> M3
M1 --> T1
M1 --> T2
M1 --> T3
- M2 --> C1
M2 --> C2
- M2 --> C3
- M2 --> C4
+ M2 --> P1
O --> Tasks
Tasks --> P1
Tasks --> P2
@@ -101,6 +97,11 @@ flowchart TD
Tasks --> P4
```
+The MCP servers are separate entrypoints; no direct orchestrator-to-server
+call is implied. `real_mcp_server.py` imports the D-Wave connector and the
+data processor. Other connectors are shown as repository components, not
+as dependencies of that server.
+
## Agentic workflow checklist for this repo
- [x] **Agents**: `agents/a2a_framework.py`, `agents/a2a_mcp_integration.py`,
@@ -129,17 +130,16 @@ flowchart TD
Yes. The repository is using MCP in two forms:
-1. A custom JSON-RPC server in `/home/runner/work/self-correcting-executor/self-correcting-executor/mcp_server/main.py`
+1. A custom JSON-RPC server in `mcp_server/main.py`
with explicit MCP methods such as `initialize`, `tools/list`, `tools/call`,
`resources/list`, and `resources/read`.
-2. A FastMCP-based server in `/home/runner/work/self-correcting-executor/self-correcting-executor/mcp_server/real_mcp_server.py`
+2. A FastMCP-based server in `mcp_server/real_mcp_server.py`
built on the `mcp` package.
-Compared with the MCP architecture/specification dated `2026-07-28`, this repo
-already covers the **server** side baseline well enough to negotiate tools and
-resources, but it does **not** implement a full host/client runtime in-repo.
-That is acceptable for this codebase because GitHub Copilot/GitHub MCP acts as
-the host environment around these servers.
+The custom handler advertises protocol version `2024-11-05`. Direct calls
+can verify its advertised tool and resource behavior, but do not establish
+MCP specification compliance or successful transport negotiation with an
+external host/client. Those require a separate integration test.
### Host / client / server mapping for this repo
@@ -152,56 +152,28 @@ the host environment around these servers.
## Live verification steps
-The minimum capability-negotiation proof for this repo is to exercise the
-custom MCP server directly and confirm that `initialize` advertises
-capabilities, then `tools/list` and `tools/call` work end-to-end.
-
-```bash
-cd /home/runner/work/self-correcting-executor/self-correcting-executor
-python - <<'PY'
-import asyncio
-import json
-from mcp_server.main import MCPServer
-
-async def main():
- server = MCPServer()
- for request in (
- {
- "jsonrpc": "2.0",
- "id": 1,
- "method": "initialize",
- "params": {"clientInfo": {"name": "repo-assist", "version": "1.0"}},
- },
- {"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}},
- {
- "jsonrpc": "2.0",
- "id": 3,
- "method": "tools/call",
- "params": {
- "name": "code_analyzer",
- "arguments": {"code": "def verify():\n return 1\n"},
- },
- },
- ):
- print(json.dumps(await server.handle_request(request), indent=2))
-
-asyncio.run(main())
-PY
-```
+The focused verifier calls the custom handler in-process. It asserts the
+initialize response, the advertised/listed tool names, and the actual
+`code_analyzer` result. Any JSON-RPC error, missing capability or incorrect
+analysis raises an exception and makes the command exit unsuccessfully.
+This proves the handler behavior, not an external MCP transport connection.
-Focused automated verification for the repo-assist additions:
+From any directory inside the checkout:
```bash
-python -m pytest tests/test_repo_assist_docs.py -q
+cd "$(git rev-parse --show-toplevel)"
+python -m scripts.verify_mcp_baseline
+python -m pytest tests/test_repo_assist_docs.py tests/test_mcp_baseline_verifier.py -q
```
## CI baseline observed from GitHub Actions
- The repo has active `Python CI` and `Frontend CI` workflows.
-- The inspected recent `Python CI` job logs showed `black` passing.
-- The same logs also showed that `flake8` findings and `pytest` collection
- errors are currently masked by `|| echo ...` and `continue-on-error`, so the
- workflow can report success even when Python imports/tests are not clean.
+- `Python CI` runs `black --check .` as a blocking step. Inspect the current
+ head's logs; a previous run's result is not evidence for a new commit.
+- `pytest --cov=.` is blocking: collection failures and failed assertions fail
+ the matrix job. `flake8` remains advisory in the existing workflow, so a
+ green workflow alone does not prove the repository is free of lint findings.
## Skills added for this repo
diff --git a/orchestrator_mapreduce.py b/orchestrator_mapreduce.py
index f5f6111..d67093b 100644
--- a/orchestrator_mapreduce.py
+++ b/orchestrator_mapreduce.py
@@ -48,7 +48,6 @@
from agents.mutator import mutate_protocol
from utils.tracker import track_outcome, get_protocol_stats
-
# ─── Data Models ───────────────────────────────────────────────
@@ -116,9 +115,7 @@ async def verify(self, job: OrchestratedJob) -> Dict[str, Any]:
"""
# Layer 1: Mechanical gate (fast pre-filter)
total = len(job.subtasks)
- succeeded = sum(
- 1 for st in job.subtasks if st.status == TaskStatus.COMPLETED
- )
+ succeeded = sum(1 for st in job.subtasks if st.status == TaskStatus.COMPLETED)
rate = succeeded / total if total > 0 else 0
if rate < self.threshold:
@@ -127,8 +124,7 @@ async def verify(self, job: OrchestratedJob) -> Dict[str, Any]:
"layer": "mechanical",
"success_rate": rate,
"reason": (
- f"Success rate {rate:.0%} below "
- f"{self.threshold:.0%} threshold"
+ f"Success rate {rate:.0%} below " f"{self.threshold:.0%} threshold"
),
}
@@ -139,7 +135,11 @@ async def verify(self, job: OrchestratedJob) -> Dict[str, Any]:
except Exception as e:
# If LLM is unavailable, fall back to mechanical pass
log(f"⚠️ Semantic gate unavailable ({e}), using mechanical only")
- return {"passed": True, "layer": "mechanical_fallback", "success_rate": rate}
+ return {
+ "passed": True,
+ "layer": "mechanical_fallback",
+ "success_rate": rate,
+ }
async def _llm_evaluate(self, job: OrchestratedJob) -> Dict[str, Any]:
"""Call the LLM to semantically evaluate the job output."""
@@ -209,12 +209,8 @@ class StateStore:
"""
def __init__(self, db_path: Optional[str] = None, md_path: Optional[str] = None):
- self.db_path = db_path or str(
- Path(__file__).parent / "loop_state.db"
- )
- self.md_path = md_path or str(
- Path(__file__).parent / "STATE.md"
- )
+ self.db_path = db_path or str(Path(__file__).parent / "loop_state.db")
+ self.md_path = md_path or str(Path(__file__).parent / "STATE.md")
self._init_db()
def _init_db(self):
@@ -261,12 +257,8 @@ def persist_job(self, job: OrchestratedJob):
conn = sqlite3.connect(self.db_path)
now = datetime.now(timezone.utc).isoformat()
- succeeded = sum(
- 1 for st in job.subtasks if st.status == TaskStatus.COMPLETED
- )
- failed = sum(
- 1 for st in job.subtasks if st.status == TaskStatus.FAILED
- )
+ succeeded = sum(1 for st in job.subtasks if st.status == TaskStatus.COMPLETED)
+ failed = sum(1 for st in job.subtasks if st.status == TaskStatus.FAILED)
conn.execute(
"""INSERT OR REPLACE INTO jobs
@@ -305,12 +297,16 @@ def persist_job(self, job: OrchestratedJob):
st.error,
st.attempts,
(
- datetime.fromtimestamp(st.started_at, tz=timezone.utc).isoformat()
+ datetime.fromtimestamp(
+ st.started_at, tz=timezone.utc
+ ).isoformat()
if st.started_at
else None
),
(
- datetime.fromtimestamp(st.completed_at, tz=timezone.utc).isoformat()
+ datetime.fromtimestamp(
+ st.completed_at, tz=timezone.utc
+ ).isoformat()
if st.completed_at
else None
),
@@ -322,9 +318,7 @@ def persist_job(self, job: OrchestratedJob):
def persist_markdown(self, job: OrchestratedJob):
"""Append a human-readable summary to STATE.md."""
- succeeded = sum(
- 1 for st in job.subtasks if st.status == TaskStatus.COMPLETED
- )
+ succeeded = sum(1 for st in job.subtasks if st.status == TaskStatus.COMPLETED)
entry = (
f"\n## Job: {job.id}\n"
f"- **Intent:** {job.intent}\n"
@@ -458,7 +452,9 @@ async def _mutate_strategy(
subtask.inputs.update(strategy_hints)
- log(f" → Tier 2 (Strategy Mutation): Injected strategy hints for '{protocol_name}'")
+ log(
+ f" → Tier 2 (Strategy Mutation): Injected strategy hints for '{protocol_name}'"
+ )
return {"tier": 2, "strategy_note": strategy_hints["_instruction"]}
async def _mutate_code_sandboxed(
@@ -470,12 +466,12 @@ async def _mutate_code_sandboxed(
The mutation is tested in a sandboxed dry-run before being applied.
"""
# Perform the mutation via the existing mutator
- mutated = await loop.run_in_executor(
- None, mutate_protocol, protocol_name
- )
+ mutated = await loop.run_in_executor(None, mutate_protocol, protocol_name)
if not mutated:
- log(f" → Tier 3 (Code Mutation): mutate_protocol returned None for '{protocol_name}'")
+ log(
+ f" → Tier 3 (Code Mutation): mutate_protocol returned None for '{protocol_name}'"
+ )
return {"tier": 3, "code_mutated": False, "reason": "Mutator returned None"}
# Sandbox test: attempt to load and validate the mutated protocol
@@ -486,7 +482,9 @@ async def _mutate_code_sandboxed(
None, load_protocol, protocol_name
)
if test_protocol and callable(test_protocol.get("task")):
- log(f" → Tier 3 (Code Mutation): Mutation applied and validated for '{protocol_name}'")
+ log(
+ f" → Tier 3 (Code Mutation): Mutation applied and validated for '{protocol_name}'"
+ )
return {"tier": 3, "code_mutated": True}
else:
log(f" → Tier 3 (Code Mutation): Mutated protocol failed validation")
@@ -514,9 +512,7 @@ async def escalate(self, job: OrchestratedJob, reason: str):
Post a structured failure alert to Slack.
Includes job ID, intent, failure reason, and failed subtask details.
"""
- failed_subtasks = [
- st for st in job.subtasks if st.status == TaskStatus.FAILED
- ]
+ failed_subtasks = [st for st in job.subtasks if st.status == TaskStatus.FAILED]
failed_details = "\n".join(
f" • `{st.protocol}` — {st.error or 'unknown error'}"
for st in failed_subtasks[:5]
@@ -535,9 +531,7 @@ async def escalate(self, job: OrchestratedJob, reason: str):
loop = asyncio.get_running_loop()
try:
- await loop.run_in_executor(
- None, self._post_to_slack, message
- )
+ await loop.run_in_executor(None, self._post_to_slack, message)
log(f"📨 Escalation posted to Slack {self.channel}")
except Exception as e:
# If Slack fails, log locally — never let escalation failure crash the system
@@ -684,9 +678,7 @@ async def _execute_one(subtask: SubTask):
try:
result = await asyncio.wait_for(
- self._run_protocol_isolated(
- subtask.protocol, subtask.inputs
- ),
+ self._run_protocol_isolated(subtask.protocol, subtask.inputs),
timeout=self.subtask_timeout,
)
subtask.result = result
@@ -727,9 +719,7 @@ async def _execute_one(subtask: SubTask):
return_exceptions=True,
)
- completed = sum(
- 1 for st in job.subtasks if st.status == TaskStatus.COMPLETED
- )
+ completed = sum(1 for st in job.subtasks if st.status == TaskStatus.COMPLETED)
failed = sum(1 for st in job.subtasks if st.status == TaskStatus.FAILED)
log(f"📊 MAP complete: {completed} succeeded, {failed} failed")
@@ -760,15 +750,16 @@ async def reduce_verify(self, job: OrchestratedJob) -> OrchestratedJob:
log(f"✅ REDUCE: Verification PASSED for job '{job.intent}'")
else:
job.verification_passed = False
- log(f"❌ REDUCE: Verification FAILED — {verification.get('reason', 'unknown')}")
+ log(
+ f"❌ REDUCE: Verification FAILED — {verification.get('reason', 'unknown')}"
+ )
# Step 3: Self-Correct with safe mutation hierarchy
while True:
retryable = [
st
for st in job.subtasks
- if st.status == TaskStatus.FAILED
- and st.attempts < st.max_attempts
+ if st.status == TaskStatus.FAILED and st.attempts < st.max_attempts
]
if not retryable:
@@ -797,11 +788,7 @@ async def reduce_verify(self, job: OrchestratedJob) -> OrchestratedJob:
# Re-verify after retry
job.reduced_result = await self.reducer(
[st.result for st in job.subtasks if st.result],
- [
- st
- for st in job.subtasks
- if st.status == TaskStatus.FAILED
- ],
+ [st for st in job.subtasks if st.status == TaskStatus.FAILED],
)
job.attempt_count += 1
re_verification = await self.verification_gate(job)
@@ -875,9 +862,7 @@ async def _retry_subtask(self, subtask: SubTask):
subtask.started_at = time.time()
try:
result = await asyncio.wait_for(
- self._run_protocol_isolated(
- subtask.protocol, subtask.inputs
- ),
+ self._run_protocol_isolated(subtask.protocol, subtask.inputs),
timeout=self.subtask_timeout,
)
subtask.result = result
@@ -903,9 +888,7 @@ async def _persist_state(self, job: OrchestratedJob):
def _prune_job_history(self):
"""Prevent unbounded memory growth from stored jobs."""
if len(self.jobs) > self.max_job_history:
- sorted_jobs = sorted(
- self.jobs.items(), key=lambda x: x[1].created_at
- )
+ sorted_jobs = sorted(self.jobs.items(), key=lambda x: x[1].created_at)
excess = len(self.jobs) - self.max_job_history
for job_id, _ in sorted_jobs[:excess]:
del self.jobs[job_id]
@@ -918,9 +901,7 @@ async def _default_gate(self, job: OrchestratedJob) -> Dict[str, Any]:
Used only when use_semantic_gate=False and no custom gate provided.
"""
total = len(job.subtasks)
- succeeded = sum(
- 1 for st in job.subtasks if st.status == TaskStatus.COMPLETED
- )
+ succeeded = sum(1 for st in job.subtasks if st.status == TaskStatus.COMPLETED)
rate = succeeded / total if total > 0 else 0
if rate >= 0.8:
diff --git a/requirements-ci.txt b/requirements-ci.txt
index 2cb9651..d0a2908 100644
--- a/requirements-ci.txt
+++ b/requirements-ci.txt
@@ -1,7 +1,8 @@
# Minimal requirements for CI/CD pipeline
# Core dependencies
aiohttp>=3.8.0
-pydantic>=2.0.0
+# Match the production MCP SDK/Pydantic compatibility pair.
+pydantic==2.11.7
fastapi>=0.100.0
uvicorn>=0.20.0
@@ -15,4 +16,9 @@ pytest-cov>=4.0.0
# Basic utilities
requests>=2.28.0
python-dotenv>=1.0.0
-PyYAML>=6.0.0
\ No newline at end of file
+PyYAML>=6.0.0
+# Imports exercised by the real MCP and database unit tests.
+mcp==1.9.4
+numpy>=1.24,<3
+psycopg2-binary>=2.9.9
+packaging>=23.0
diff --git a/scripts/verify_mcp_baseline.py b/scripts/verify_mcp_baseline.py
new file mode 100644
index 0000000..4321ac9
--- /dev/null
+++ b/scripts/verify_mcp_baseline.py
@@ -0,0 +1,59 @@
+"""Verify the custom MCP handler in-process; no network transport is tested."""
+
+import asyncio
+import json
+
+from mcp_server.main import MCPServer, MCP_VERSION
+
+
+async def verify_baseline(server=None):
+ """Raise on RPC errors, missing capabilities, or incorrect analysis."""
+ server = server if server is not None else MCPServer()
+
+ async def request(request_id, method, params):
+ response = await server.handle_request(
+ {"jsonrpc": "2.0", "id": request_id, "method": method, "params": params}
+ )
+ if response.get("error") is not None or "result" not in response:
+ raise RuntimeError(f"{method} failed: {response}")
+ if response.get("jsonrpc") != "2.0" or response.get("id") != request_id:
+ raise RuntimeError(f"{method} returned an invalid response: {response}")
+ return response["result"]
+
+ initialized = await request(
+ 1, "initialize", {"clientInfo": {"name": "repo-assist", "version": "1.0"}}
+ )
+ if initialized["serverInfo"]["mcpVersion"] != MCP_VERSION:
+ raise RuntimeError("initialize returned an unexpected protocol version")
+ expected_tools = {"code_analyzer", "protocol_validator", "self_corrector"}
+ advertised_tools = {tool["name"] for tool in initialized["capabilities"]["tools"]}
+ if not expected_tools <= advertised_tools:
+ raise RuntimeError("initialize did not advertise the expected tools")
+ if not initialized["capabilities"]["resources"]:
+ raise RuntimeError("initialize did not advertise resources")
+ listed = await request(2, "tools/list", {})
+ if {tool["name"] for tool in listed["tools"]} != advertised_tools:
+ raise RuntimeError("tools/list differs from advertised capabilities")
+ called = await request(
+ 3,
+ "tools/call",
+ {
+ "name": "code_analyzer",
+ "arguments": {"code": "def verify():\n return 1\n"},
+ },
+ )
+ if called["tool"] != "code_analyzer":
+ raise RuntimeError("tools/call returned the wrong tool")
+ analysis = json.loads(called["result"]["content"][0]["text"])
+ if analysis != {
+ "lines_of_code": 2,
+ "functions": 1,
+ "complexity": 1,
+ "imports": [],
+ }:
+ raise RuntimeError(f"code_analyzer returned unexpected analysis: {analysis}")
+ return {"serverInfo": initialized["serverInfo"], "analysis": analysis}
+
+
+if __name__ == "__main__":
+ print(json.dumps(asyncio.run(verify_baseline()), indent=2))
diff --git a/tests/test_dependabot_test.py b/tests/test_dependabot_test.py
index bfc326f..aa7ccb3 100644
--- a/tests/test_dependabot_test.py
+++ b/tests/test_dependabot_test.py
@@ -1,412 +1,67 @@
-import os
-import sys
-from io import StringIO
-from unittest.mock import mock_open, patch
+"""Regression checks for the actual Dependabot and CI configuration.
-import pytest
-
-# Add the .github directory to the path to import the module
-sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".github"))
-
-try:
- import dependabot_test
-except ImportError:
- # If the module doesn't exist or has import issues, we'll handle it
- dependabot_test = None
-
-
-class TestDependabotTest:
- """Test suite for dependabot_test.py module"""
-
- def test_module_imports_successfully(self):
- """Test that the dependabot_test module can be imported without errors"""
- assert (
- dependabot_test is not None
- ), "dependabot_test module should be importable"
-
- @pytest.fixture
- def mock_file_system(self):
- """Fixture for mocking file system operations"""
- with patch("builtins.open", mock_open()) as mock_file:
- yield mock_file
-
- @pytest.fixture
- def mock_subprocess(self):
- """Fixture for mocking subprocess operations"""
- with patch("subprocess.run") as mock_run:
- mock_run.return_value.returncode = 0
- mock_run.return_value.stdout = ""
- mock_run.return_value.stderr = ""
- yield mock_run
-
- def test_function_existence_and_callability(self):
- """Test that expected functions exist and are callable"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
- assert functions, "Module should contain at least one function"
-
- for func in functions:
- assert callable(func), f"Function {func.__name__} should be callable"
-
- def test_main_function_exists(self):
- """Test that main function exists if the module is meant to be executable"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- if hasattr(dependabot_test, "main"):
- assert callable(dependabot_test.main), "main function should be callable"
-
- @patch("sys.argv", ["dependabot_test.py"])
- def test_script_execution_with_no_args(self):
- """Test script execution with no arguments"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- if hasattr(dependabot_test, "main"):
- try:
- dependabot_test.main()
- except SystemExit:
- pass
- except Exception as e:
- pytest.fail(f"main() should not raise unexpected exception: {e}")
-
- @patch("sys.argv", ["dependabot_test.py", "--help"])
- def test_script_execution_with_help_flag(self):
- """Test script execution with help flag"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- if hasattr(dependabot_test, "main"):
- with patch("sys.stdout", new_callable=StringIO) as mock_stdout:
- try:
- dependabot_test.main()
- except SystemExit:
- pass
- output = mock_stdout.getvalue()
- assert output is not None
-
- def test_module_constants_and_variables(self):
- """Test module-level constants and variables"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- module_attrs = dir(dependabot_test)
- assert "__name__" in module_attrs
- assert "__doc__" in module_attrs
-
- if hasattr(dependabot_test, "__version__"):
- version = dependabot_test.__version__
- assert isinstance(version, str)
- assert version
-
- def test_error_handling_with_invalid_input(self):
- """Test error handling with various invalid inputs"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
-
- for func in functions:
- try:
- func(None)
- except (TypeError, ValueError, AttributeError):
- pass
- except Exception as e:
- print(f"Unexpected exception in {func.__name__}: {e}")
-
- def test_file_operations_mocked(self, mock_file_system):
- """Test file operations with mocked file system"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- mock_file_system.return_value.read.return_value = "test content"
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
-
- for func in functions:
- try:
- func("test_file.txt")
- except (TypeError, FileNotFoundError):
- pass
- except Exception as e:
- print(f"Unexpected exception in {func.__name__}: {e}")
-
- def test_subprocess_operations_mocked(self, mock_subprocess):
- """Test subprocess operations with mocked subprocess"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
-
- for func in functions:
- try:
- func()
- except TypeError:
- pass
- except Exception as e:
- print(f"Unexpected exception in {func.__name__}: {e}")
-
- def test_environment_variable_handling(self):
- """Test handling of environment variables"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- test_env_vars = {
- "GITHUB_TOKEN": "test_token",
- "GITHUB_REPOSITORY": "test/repo",
- "GITHUB_WORKSPACE": "/tmp/workspace",
- }
-
- with patch.dict(os.environ, test_env_vars):
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
-
- for func in functions:
- try:
- func()
- except Exception as e:
- print(f"Function {func.__name__} with env vars: {e}")
-
- def test_github_api_interaction_mocked(self):
- """Test GitHub API interactions with mocked responses"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- with patch("requests.get") as mock_get:
- mock_get.return_value.status_code = 200
- mock_get.return_value.json.return_value = {"test": "data"}
-
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
-
- for func in functions:
- try:
- func()
- except Exception as e:
- print(f"Function {func.__name__} with mocked HTTP: {e}")
+The repository has no dependabot_test.py runtime module. Validate the shipped
+configuration and the CI dependency set instead of importing a nonexistent helper.
+"""
- def test_edge_cases_and_boundary_conditions(self):
- """Test edge cases and boundary conditions"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
+from pathlib import Path
- edge_cases = [
- "",
- " ",
- "very_long_string_" * 100,
- "special!@#$%^&*()chars",
- None,
- [],
- {},
- 0,
- -1,
- ]
-
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
-
- for func in functions:
- for edge_case in edge_cases:
- try:
- func(edge_case)
- except (TypeError, ValueError, AttributeError):
- pass
- except Exception as e:
- print(
- f"Unexpected exception in {func.__name__} with {edge_case}: {e}"
- )
-
- def test_concurrent_execution(self):
- """Test concurrent execution safety"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- import threading
-
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
-
- if not functions:
- return
-
- results = []
- errors = []
-
- def run_function():
- try:
- result = functions[0]()
- results.append(result)
- except Exception as e:
- errors.append(e)
-
- threads = [threading.Thread(target=run_function) for _ in range(5)]
- for thread in threads:
- thread.start()
- for thread in threads:
- thread.join(timeout=5)
-
- assert not any("thread" in str(e).lower() for e in errors)
-
- def test_memory_usage_and_cleanup(self):
- """Test memory usage and proper cleanup"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- import gc
-
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
-
- initial_objects = len(gc.get_objects())
- for func in functions:
- try:
- func()
- except Exception:
- pass
-
- gc.collect()
- final_objects = len(gc.get_objects())
- assert final_objects < initial_objects * 2, "Potential memory leak detected"
-
- def test_logging_and_output(self):
- """Test logging and output functionality"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- with patch("sys.stdout", new_callable=StringIO) as mock_stdout, patch(
- "sys.stderr", new_callable=StringIO
- ) as mock_stderr:
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
-
- for func in functions:
- try:
- func()
- except Exception:
- pass
-
- stdout_output = mock_stdout.getvalue()
- stderr_output = mock_stderr.getvalue()
- assert isinstance(stdout_output, str)
- assert isinstance(stderr_output, str)
-
- def test_configuration_and_settings(self):
- """Test configuration and settings handling"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- test_configs = [{}, {"key": "value"}, {"nested": {"key": "value"}}]
-
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
-
- for config in test_configs:
- for func in functions:
- try:
- func(config)
- except (TypeError, KeyError, AttributeError):
- pass
- except Exception as e:
- print(
- f"Unexpected exception in {func.__name__} with config {config}: {e}"
- )
-
-
-class TestDependabotTestIntegration:
- """Integration tests for dependabot_test.py in GitHub Actions context"""
-
- def test_github_actions_environment(self):
- """Test behavior in GitHub Actions environment"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- github_env = {
- "GITHUB_ACTIONS": "true",
- "GITHUB_WORKFLOW": "test",
- "GITHUB_RUN_ID": "123456",
- "GITHUB_RUN_NUMBER": "42",
- "GITHUB_ACTOR": "dependabot[bot]",
- "GITHUB_REPOSITORY": "test/repo",
- "GITHUB_EVENT_NAME": "pull_request",
- "GITHUB_SHA": "abc123",
- "GITHUB_REF": "refs/heads/dependabot/npm_and_yarn/test-1.0.0",
- }
-
- with patch.dict(os.environ, github_env):
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
-
- for func in functions:
- try:
- func()
- except Exception as e:
- print(f"Function {func.__name__} failed in GitHub Actions env: {e}")
-
- def test_dependabot_specific_scenarios(self):
- """Test scenarios specific to Dependabot operations"""
- if dependabot_test is None:
- pytest.skip("dependabot_test module not available")
-
- dependabot_env = {
- "GITHUB_ACTOR": "dependabot[bot]",
- "GITHUB_EVENT_NAME": "pull_request",
- "GITHUB_HEAD_REF": "dependabot/npm_and_yarn/package-1.0.0",
- }
-
- with patch.dict(os.environ, dependabot_env):
- functions = [
- getattr(dependabot_test, name)
- for name in dir(dependabot_test)
- if callable(getattr(dependabot_test, name)) and not name.startswith("_")
- ]
-
- for func in functions:
- try:
- func()
- except Exception as e:
- print(f"Function {func.__name__} in Dependabot context: {e}")
-
-
-if __name__ == "__main__":
- pytest.main([__file__])
+import pytest
+import yaml
+from packaging.requirements import Requirement
+
+ROOT = Path(__file__).resolve().parents[1]
+
+
+def read_yaml(path):
+ return yaml.safe_load((ROOT / path).read_text())
+
+
+def test_dependabot_configuration_is_valid_and_complete():
+ config = read_yaml(".github/dependabot.yml")
+ assert config["version"] == 2
+ updates = config["updates"]
+ assert len(updates) == 3
+ assert {(item["package-ecosystem"], item["directory"]) for item in updates} == {
+ ("pip", "/"),
+ ("npm", "/frontend"),
+ ("docker", "/"),
+ }
+ assert all(item["schedule"]["interval"] == "weekly" for item in updates)
+
+
+@pytest.mark.parametrize(
+ "ecosystem,manifest",
+ [("pip", "requirements.txt"), ("npm", "package.json"), ("docker", "Dockerfile")],
+)
+def test_each_dependabot_update_has_a_real_manifest(ecosystem, manifest):
+ update = next(
+ item
+ for item in read_yaml(".github/dependabot.yml")["updates"]
+ if item["package-ecosystem"] == ecosystem
+ )
+ assert (ROOT / update["directory"].lstrip("/") / manifest).is_file()
+
+
+@pytest.mark.parametrize(
+ "package", ["mcp", "numpy", "psycopg2-binary", "PyYAML", "packaging"]
+)
+def test_ci_installs_packages_imported_by_the_suite(package):
+ requirements = {
+ Requirement(line).name.lower()
+ for line in (ROOT / "requirements-ci.txt").read_text().splitlines()
+ if line.strip() and not line.lstrip().startswith("#")
+ }
+ assert package.lower() in requirements
+
+
+def test_ci_propagates_test_failures():
+ workflow = read_yaml(".github/workflows/python-ci.yml")
+ job = workflow["jobs"]["lint-test"]
+ assert job.get("continue-on-error", False) is False
+ assert job["strategy"]["matrix"]["python-version"] == ["3.10", "3.11"]
+ test_step = next(
+ step for step in job["steps"] if step.get("name") == "Run tests with coverage"
+ )
+ assert test_step["run"].strip() == "pytest --cov=."
+ assert test_step.get("continue-on-error", False) is False
diff --git a/tests/test_mcp_baseline_verifier.py b/tests/test_mcp_baseline_verifier.py
new file mode 100644
index 0000000..54385cd
--- /dev/null
+++ b/tests/test_mcp_baseline_verifier.py
@@ -0,0 +1,53 @@
+"""Exercise the verifier's success and failure paths without external services."""
+
+import asyncio
+
+import pytest
+
+from mcp_server.main import MCPServer
+from scripts.verify_mcp_baseline import verify_baseline
+
+
+def test_verifier_checks_actual_handler():
+ result = asyncio.run(verify_baseline())
+ assert result["analysis"]["functions"] == 1
+
+
+@pytest.mark.parametrize("method", ["initialize", "tools/list", "tools/call"])
+def test_verifier_rejects_rpc_error_at_each_step(method):
+ class FailingHandler(MCPServer):
+ async def handle_request(self, request):
+ if request["method"] == method:
+ return {
+ "jsonrpc": "2.0",
+ "id": request["id"],
+ "error": {"code": -32000},
+ }
+ return await super().handle_request(request)
+
+ with pytest.raises(RuntimeError, match=method + " failed"):
+ asyncio.run(verify_baseline(FailingHandler()))
+
+
+def test_verifier_rejects_wrong_analysis_even_when_rpc_succeeds():
+ class IncorrectAnalysis(MCPServer):
+ async def handle_request(self, request):
+ response = await super().handle_request(request)
+ if request["method"] == "tools/call":
+ response["result"]["result"]["content"][0]["text"] = "{}"
+ return response
+
+ with pytest.raises(RuntimeError, match="unexpected analysis"):
+ asyncio.run(verify_baseline(IncorrectAnalysis()))
+
+
+def test_verifier_rejects_missing_advertised_tool():
+ class MissingTool(MCPServer):
+ async def handle_request(self, request):
+ response = await super().handle_request(request)
+ if request["method"] == "initialize":
+ response["result"]["capabilities"]["tools"] = []
+ return response
+
+ with pytest.raises(RuntimeError, match="expected tools"):
+ asyncio.run(verify_baseline(MissingTool()))
diff --git a/tests/test_mcp_compliance.py b/tests/test_mcp_compliance.py
index d11ceda..5bb7c31 100644
--- a/tests/test_mcp_compliance.py
+++ b/tests/test_mcp_compliance.py
@@ -11,7 +11,7 @@
# Import MCP components
from config.mcp_config import MCPConfig
-from mcp_server.real_mcp_server import RealMCPServer
+from mcp_server.real_mcp_server import mcp
from connectors.dwave_quantum_connector import DWaveQuantumConnector
from agents.a2a_mcp_integration import MCPEnabledA2AAgent, a2a_mcp_orchestrator
@@ -20,15 +20,14 @@ class TestMCPCompliance:
"""Test suite to ensure MCP compliance across the codebase"""
@pytest.fixture
- async def mcp_config(self):
+ def mcp_config(self):
"""Get MCP configuration"""
return MCPConfig()
@pytest.fixture
- async def mcp_server(self):
- """Create real MCP server instance"""
- server = RealMCPServer()
- return server
+ def mcp_server(self):
+ """Use the actual registered FastMCP server."""
+ return mcp
def test_no_mock_endpoints(self, mcp_config):
"""Test that no mock endpoints are configured"""
@@ -86,50 +85,79 @@ async def test_quantum_requires_real_qpu(self):
assert "No D-Wave QPU available" in str(e)
@pytest.mark.asyncio
- async def test_data_processor_no_simulation(self):
+ async def test_data_processor_no_simulation(self, tmp_path):
"""Test that data processor doesn't return simulated results"""
from protocols.data_processor import task as process_data
- result = process_data()
+ (tmp_path / "records.json").write_text(json.dumps([{"value": 1}, {"value": 2}]))
+ result = process_data(str(tmp_path))
# Should either succeed with real data or fail
if result["success"]:
assert "simulation" not in str(result).lower()
assert "simulated" not in str(result).lower()
- assert result.get("directory") is not None
+ assert result["directory"] == str(tmp_path)
+ assert result["files_processed"] == 1
+ assert result["total_records"] == 2
else:
# Failed because no data directory - this is expected
assert "error" in result
assert "No data directory found" in result["error"]
@pytest.mark.asyncio
- async def test_mcp_server_tools_are_real(self, mcp_server):
- """Test that MCP server tools perform real operations"""
- # Test data processing tool
- result = await mcp_server.server.tool("process_data")(
- data_path="./test_data", operation="analyze"
+ async def test_mcp_server_tools_are_real(self, mcp_server, tmp_path):
+ """Dispatch the registered tool and verify actual filesystem analysis."""
+ sample = tmp_path / "records.json"
+ sample.write_text(json.dumps([{"value": 1}]))
+ content = await mcp_server.call_tool(
+ "process_data", {"data_path": str(tmp_path), "operation": "analyze"}
)
+ result = json.loads(content[0].text)
+ assert result["status"] == "success"
+ assert result["file_count"] == 1
+ assert result["total_size_bytes"] == sample.stat().st_size
+ assert result["file_types"] == {".json": 1}
- # Should return real analysis or error, never mock data
- assert "mock" not in str(result).lower()
- assert "simulated" not in str(result).lower()
+ @pytest.mark.asyncio
+ async def test_mcp_server_reports_missing_data(self, mcp_server, tmp_path):
+ content = await mcp_server.call_tool(
+ "process_data",
+ {"data_path": str(tmp_path / "missing"), "operation": "analyze"},
+ )
+ result = json.loads(content[0].text)
+ assert result["status"] == "error"
+ assert "does not exist" in result["error"]
@pytest.mark.asyncio
- async def test_agents_use_real_mcp(self):
- """Test that agents use real MCP for communication"""
+ async def test_agents_use_real_mcp(self, mcp_server, tmp_path, monkeypatch):
+ """Exercise the agent against registered tools without a network provider."""
+ sample = tmp_path / "sample.txt"
+ sample.write_text("real fixture data")
agent = MCPEnabledA2AAgent("test_agent", ["analyze"])
+ calls = []
+
+ async def dispatch_registered_tool(name, arguments):
+ calls.append((name, arguments))
+ content = await mcp_server.call_tool(name, arguments)
+ return json.loads(content[0].text)
+
+ monkeypatch.setattr(agent, "_execute_mcp_tool", dispatch_registered_tool)
+ result = await agent._analyze_data({"path": str(tmp_path)})
+ assert calls[0] == (
+ "process_data",
+ {"data_path": str(tmp_path), "operation": "analyze"},
+ )
+ assert result["analysis_type"] == "comprehensive"
+ assert result["status"] == "success"
+ assert result["file_count"] == 1
+ assert result["total_size"] == sample.stat().st_size
+ assert result["confidence"] > 0
- # Test data analysis uses real MCP
- result = await agent._analyze_data({"path": "./data"})
-
- # Should return real analysis results
- assert result["analysis_type"] in ["comprehensive", "failed"]
- assert "confidence" in result
-
- # Test code generation
result = await agent._generate_code({"type": "function", "language": "python"})
-
- assert result["code_type"] in ["function", "error"]
+ assert calls[1][0] == "execute_code"
+ assert calls[1][1]["language"] == "python"
+ assert "def process" in calls[1][1]["code"]
+ assert result["code_type"] == "function"
assert "code" in result
def test_no_placeholder_code_in_production(self):
@@ -226,13 +254,19 @@ def test_integration_points_documented(self):
for doc in required_docs:
doc_path = Path(doc)
- if doc_path.exists():
- content = doc_path.read_text()
-
- # Check for required sections
- assert "Real" in content or "real" in content
- assert "mock" not in content.lower() or "no mock" in content.lower()
- assert "MCP" in content
+ assert doc_path.is_file(), f"Missing integration document: {doc}"
+ assert "MCP" in doc_path.read_text()
+
+ # Migration plans legitimately discuss mocks. Verify the current runtime
+ # map against files that exist instead of banning a word in historical plans.
+ repo_map = Path("docs/REPO_MAP.md").read_text()
+ for source in [
+ "mcp_server/main.py",
+ "mcp_server/real_mcp_server.py",
+ "agents/a2a_mcp_integration.py",
+ ]:
+ assert Path(source).is_file()
+ assert source in repo_map, f"Undocumented integration: {source}"
def test_env_template_exists(self):
"""Test that .env template exists with all required variables"""
From 18057fe078d060b43f758a1031156c18d1f25f9b Mon Sep 17 00:00:00 2001
From: Hayden <154503486+groupthinking@users.noreply.github.com>
Date: Thu, 29 Oct 2026 05:52:37 -0500
Subject: [PATCH 5/5] fix: resolve project imports in CI pytest invocation
---
pytest.ini | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/pytest.ini b/pytest.ini
index 76779c6..da320a2 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -1,4 +1,5 @@
[pytest]
+pythonpath = .
testpaths = tests
python_files = test_*.py
python_classes = Test*
@@ -7,4 +8,4 @@ addopts = -v --tb=short
markers =
slow: marks tests as slow (deselect with '-m "not slow"')
integration: marks tests as integration tests
- unit: marks tests as unit tests
\ No newline at end of file
+ unit: marks tests as unit tests