From 2338772d7d9be04a40ae46efc87c2ffcfa3a807a Mon Sep 17 00:00:00 2001 From: PRAMOD B N Date: Wed, 12 Aug 2026 11:07:13 -0500 Subject: [PATCH 1/5] docs: add DeepAgentLabs ecosystem context to AGENTS --- AGENTS.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index dee21e1..ef0bff0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,57 @@ ## deep-agentic-core-mcp Development Reference +## Ecosystem Context + +### Role in DeepAgentLabs + +`deep-agentic-core-mcp` is the MCP-native control surface for DeepAgentLabs. It +exposes spec-aligned operational artifacts and selected capabilities from the +ecosystem through a unified interface for hosts, agents, and external systems. + +### Owns + +- MCP server wiring, handler registration, tool/resource exposure, and transport + boundaries +- Thin orchestration that composes capabilities from sibling packages without + redefining their core logic +- The contract for how DeepAgentLabs capabilities are presented through MCP + +### Does Not Own + +- The canonical operational model or schema definitions — those belong in + `ai-operations-spec` +- Primary instrumentation, trace analysis, or evaluation logic — those belong + in `agenticlens` +- Fault injection and resilience simulation logic — those belong in + `agentic-chaos` +- Agent-decision supervision or governance policy logic — those belong in + `agentic-sidecar` + +### Integrates With + +- `ai-operations-spec` so returned artifacts and tool semantics align with the + shared contract +- `agenticlens` as a source of analysis, provenance, and workflow evidence +- `agentic-chaos` as a source of resilience and degradation workflows +- `agentic-sidecar` when supervised-decision capabilities need MCP exposure in + the future + +### Current Roadmap Focus + +The next major work is provenance verification on `lens.analyze_workflow`, +multi-version AIOS schema support, and more unified observability-plus-chaos +workflows. Changes here should strengthen composition and interoperability, not +duplicate implementation logic from sibling repos. + +### Before You Build Here + +- Prefer adapting and exposing sibling-package behavior over rebuilding it in + server-local modules +- If a new concept changes artifact meaning or shape across the ecosystem, + update `ai-operations-spec` first +- Keep this package thin: MCP is the access layer, not the place to invent a + second analysis engine, chaos engine, or policy runtime + ## Build and Run - Install: `make install` (runs `uv sync --extra dev`) From 90536e1fe4d28449fdef5c0cfb6bee5b0f477b74 Mon Sep 17 00:00:00 2001 From: PRAMOD B N Date: Wed, 12 Aug 2026 13:49:18 -0500 Subject: [PATCH 2/5] feat: add agentic-sidecar MCP discovery support --- README.md | 28 +++-- ROADMAP.md | 41 ++++++- docs/tools.md | 48 +++++++- pyproject.toml | 1 + scripts/generate_tools_doc.py | 3 +- .../adapters/agentic_sidecar.py | 114 ++++++++++++++++++ src/deep_agentic_core_mcp/server.py | 3 + src/deep_agentic_core_mcp/tools/core.py | 2 + src/deep_agentic_core_mcp/tools/registry.py | 28 ++++- src/deep_agentic_core_mcp/tools/sidecar.py | 33 +++++ tests/test_imports.py | 9 +- tests/test_registry.py | 4 +- tests/test_server.py | 37 +++++- 13 files changed, 333 insertions(+), 18 deletions(-) create mode 100644 src/deep_agentic_core_mcp/adapters/agentic_sidecar.py create mode 100644 src/deep_agentic_core_mcp/tools/sidecar.py diff --git a/README.md b/README.md index 6f69d5c..4b774a8 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ ecosystem. It is designed to expose a single MCP interface that combines: - `agenticlens` style workflow inspection, profiling, and analysis - `agentic-chaos` style resilience testing and fault-injection workflows +- `agentic-sidecar` style supervision-readiness and module-surface discovery It sits above the **AI Operations Workflow Specification**, exposing a unified MCP-native control surface over the shared operational model used by the @@ -22,11 +23,12 @@ libraries: - `agenticlens` remains the core profiling and analysis engine - `agentic-chaos` remains the core chaos and resilience engine +- `agentic-sidecar` remains the core decision-supervision and governance engine - the `AI Operations Workflow Specification` remains the shared data contract - `deep-agentic-core-mcp` becomes the MCP-native interface that hosts can call -That means MCP clients can connect once and access both observability and chaos -testing capabilities through one server. +That means MCP clients can connect once and access observability, chaos, and +sidecar discovery capabilities through one server. ## What This Server Should Eventually Do @@ -35,6 +37,8 @@ Planned capability areas: - profile an agentic workflow and return structured telemetry summaries - analyze workflow artifacts and surface optimization recommendations - run controlled chaos experiments against target workflows +- expose sidecar readiness and scaffold inventory while the upstream runtime + is still under construction - compare normal versus chaos runs - expose shared resources such as workflow schemas, run metadata, and saved reports @@ -43,8 +47,8 @@ Planned capability areas: - One MCP identity: publish a single server to the MCP Registry - Python-first: package and publish through PyPI -- Thin orchestration layer: reuse `agenticlens` and `agentic-chaos` instead of - re-implementing their logic +- Thin orchestration layer: reuse `agenticlens`, `agentic-chaos`, and + `agentic-sidecar` instead of re-implementing their logic - Local-first: work well as a stdio MCP server for developer workflows — this matters because `chaos.run_experiment` executes real code (see [SECURITY.md](SECURITY.md)), so this server is meant for trusted, @@ -56,7 +60,7 @@ Planned capability areas: - `core.health` — rich diagnostics: adapter availability/version, loaded tool/resource/prompt counts, workspace root, recent successful calls - `core.version` — server package version -- `core.verify` — checks agenticlens/agentic-chaos/ai-operations-spec +- `core.verify` — checks agenticlens/agentic-chaos/agentic-sidecar/ai-operations-spec connectivity and reports readiness - `core.session_state` — inspect what the active session has accumulated - `lens.analyze_workflow` — run AgenticLens recommendations against a @@ -70,6 +74,10 @@ Planned capability areas: - `chaos.list_faults` — list the supported fault types - `chaos.run_experiment` — run a workspace-sandboxed target script under selected faults ([executes real code — see `SECURITY.md`](SECURITY.md)) +- `sidecar.status` — report whether `agentic-sidecar` is connected and + whether its runtime is implemented yet +- `sidecar.module_inventory` — inspect the current scaffolded sidecar + modules, framework adapters, and integration placeholders - `spec.validate_artifact` — validate a workflow/run artifact against the AI Operations v0.4 draft @@ -120,6 +128,7 @@ mcp-server/ │ │ ├── __init__.py │ │ ├── agentic_chaos.py │ │ ├── agenticlens.py +│ │ ├── agentic_sidecar.py │ │ └── ai_operations_spec.py │ └── tools/ │ ├── __init__.py @@ -127,6 +136,7 @@ mcp-server/ │ ├── chaos.py │ ├── core.py │ ├── lens.py +│ ├── sidecar.py │ └── spec.py └── tests/ ├── test_degraded_boot.py @@ -149,8 +159,9 @@ MCP server: - `services/` for shared orchestration logic that keeps tool modules thin, including the in-memory session store (`services/session.py`) - `adapters/` for integration boundaries to `agenticlens`, `agentic-chaos`, - and `ai-operations-spec` — each degrades to `"available": false` rather - than crashing server boot if its sibling repo is missing + `agentic-sidecar`, and `ai-operations-spec` — each degrades to + `"available": false` rather than crashing server boot if its sibling repo is + missing ## Packaging and Publishing Model @@ -170,6 +181,9 @@ registry, `core.verify`) and Phase 3b (Agentic Chaos) are complete as of - **Phase 3a (AgenticLens)** — provenance verification on `lens.analyze_workflow`'s response shape +- **Phase 3d (Agentic Sidecar Discovery)** — now implemented in the current + development line; richer sidecar control surfaces still depend on upstream + runtime milestones landing first - **Phase 3c (AI Operations Specification)** — multi-version schema support and conformance-style reporting, both blocked on upstream `ai-operations-spec` work landing first diff --git a/ROADMAP.md b/ROADMAP.md index f1a74d3..3c907f6 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -15,6 +15,9 @@ Current shipped version: `0.2.0` (2026-08-08) — see [CHANGELOG.md](CHANGELOG.m `lens.slo_summary`, and `lens.audit_report` shipped in `0.2.0` - **Phase 3b: Agentic Chaos Integration** ✅ Complete — `chaos.list_faults` shipped in `0.1.3`; `chaos.run_experiment` shipped in `0.2.0` +- **Phase 3d: Agentic Sidecar Discovery** ✅ Complete — `sidecar.status` + and `sidecar.module_inventory` ship in the current development line as + MCP-visible discovery/readiness tools - **Phase 3c: AI Operations Specification Conformance** 🏗️ In progress — `spec.validate_artifact` and schema resources shipped in `0.1.3`, ahead of where this roadmap originally planned them; remaining work still blocked on @@ -34,6 +37,11 @@ status should explicitly account for upstream and downstream dependencies. - `agentic-chaos` Provides resilience/fault injection behavior surfaced through `chaos.*` tools. +- `agentic-sidecar` + Provides decision-supervision and governance behavior. Today the MCP server + only exposes discovery/readiness information because the sidecar runtime is + still scaffold-only upstream; richer `sidecar.*` control surfaces depend on + that package shipping real runtime behavior first. - `ai-operations-spec` Provides the canonical artifact model and validation rules surfaced through `spec.*` tools and used as the ecosystem exchange contract. @@ -69,6 +77,7 @@ Build one public MCP server for the DeepAgentLabs ecosystem that unifies: - workflow observability from `agenticlens` - resilience testing from `agentic-chaos` +- decision-supervision surfaces from `agentic-sidecar` The result should feel like a coherent platform surface rather than two loosely connected products. @@ -77,6 +86,7 @@ The product boundary should mirror the PyPI ecosystem: - `agenticlens` observes, evaluates, explains, and recommends - `agentic-chaos` injects, validates, tests, and proves resilience +- `agentic-sidecar` governs, challenges, and escalates agent decisions - `deep-agentic-core-mcp` exposes those capabilities through one MCP-native control surface @@ -88,6 +98,7 @@ eventually make it easy to: - analyze prompts, tools, and retrieval - compare workflows - run chaos experiments +- inspect sidecar readiness and governance surface - summarize incidents and reliability findings - expose readiness evidence through one MCP-native interface @@ -157,8 +168,8 @@ Goals: - ✅ implement prompt registry support — `prompts/list`/`prompts/get` are wired into the server, with real arguments and rendered templates - ✅ add integration verification flow — a `core.verify` tool that checks - agenticlens, agentic-chaos, and ai-operations-spec connectivity and reports - readiness + agenticlens, agentic-chaos, agentic-sidecar, and ai-operations-spec + connectivity and reports readiness Success criteria: @@ -244,6 +255,32 @@ Success criteria: pattern; tracked as a prerequisite for widening `chaos.run_experiment` exposure beyond trusted local stdio clients (see Known Limitations) +## Phase 3d: Agentic Sidecar Discovery + +Status: complete in the current development line. `agentic-sidecar` is still a +scaffold upstream, so this phase intentionally exposes discovery/readiness +information rather than pretending a decision runtime already exists. + +Goals: + +- wire `agentic-sidecar` into the MCP server through a degrading adapter +- expose a first `sidecar.*` surface that is honest about scaffold vs runtime +- let MCP hosts discover the sidecar module/adapters/integrations footprint + without importing the sibling repo themselves + +Tools: + +- [x] `sidecar.status` +- [x] `sidecar.module_inventory` + +Success criteria: + +- `core.verify` and `core.health` report `agentic-sidecar` separately from the + other siblings +- MCP clients can distinguish "package importable" from "runtime implemented" +- the server surfaces current scaffold inventory without reimplementing sidecar + logic locally + ## Phase 3c: AI Operations Specification Conformance Status: in progress — delivered ahead of where this roadmap had it planned. diff --git a/docs/tools.md b/docs/tools.md index 9503f36..d408445 100644 --- a/docs/tools.md +++ b/docs/tools.md @@ -3,7 +3,7 @@ # Tool Reference -12 tools, generated from `tools/registry.py` - the same data MCP +14 tools, generated from `tools/registry.py` - the same data MCP clients see via `tools/list`. See [README.md](../README.md) for a one-line-per-tool overview and [ROADMAP.md](../ROADMAP.md) for what's shipped per phase. @@ -58,7 +58,7 @@ Input schema: ### `core.verify` — Verify Integrations -Check connectivity to agenticlens, agentic-chaos, and ai-operations-spec, and report readiness. +Check connectivity to agenticlens, agentic-chaos, agentic-sidecar, and ai-operations-spec, and report readiness. | | | | --- | --- | @@ -339,6 +339,50 @@ Input schema: } ``` +## Agentic Sidecar (`sidecar.*`) + +### `sidecar.module_inventory` — Sidecar Module Inventory + +List the current scaffolded modules, framework adapters, and integration placeholders present in agentic-sidecar. + +| | | +| --- | --- | +| Category | `sidecar` | +| Prerequisites | `agentic_sidecar` | +| Expected duration | instant | +| Mutates session | no | + +Input schema: + +```json +{ + "type": "object", + "properties": {}, + "additionalProperties": false +} +``` + +### `sidecar.status` — Sidecar Status + +Report whether agentic-sidecar is importable and whether its decision runtime is actually ready yet. + +| | | +| --- | --- | +| Category | `sidecar` | +| Prerequisites | `agentic_sidecar` | +| Expected duration | instant | +| Mutates session | no | + +Input schema: + +```json +{ + "type": "object", + "properties": {}, + "additionalProperties": false +} +``` + ## AI Operations Specification (`spec.*`) ### `spec.validate_artifact` — Validate AI Operations Artifact diff --git a/pyproject.toml b/pyproject.toml index bf84fc8..a3d4c56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,6 +77,7 @@ mypy_path = "src" module = [ "agenticlens.*", "agentic_chaos.*", + "agentic_sidecar.*", ] ignore_missing_imports = true diff --git a/scripts/generate_tools_doc.py b/scripts/generate_tools_doc.py index 840543a..c30af20 100644 --- a/scripts/generate_tools_doc.py +++ b/scripts/generate_tools_doc.py @@ -25,11 +25,12 @@ # (a category added to registry.py without updating this map) still renders, # alphabetically, at the end - so a new category can't silently vanish from # the doc, it just looks less polished until this map is updated too. -_CATEGORY_ORDER = ["core", "lens", "chaos", "spec"] +_CATEGORY_ORDER = ["core", "lens", "chaos", "sidecar", "spec"] _CATEGORY_TITLES = { "core": "Core", "lens": "AgenticLens (`lens.*`)", "chaos": "Agentic Chaos (`chaos.*`)", + "sidecar": "Agentic Sidecar (`sidecar.*`)", "spec": "AI Operations Specification (`spec.*`)", } diff --git a/src/deep_agentic_core_mcp/adapters/agentic_sidecar.py b/src/deep_agentic_core_mcp/adapters/agentic_sidecar.py new file mode 100644 index 0000000..196126a --- /dev/null +++ b/src/deep_agentic_core_mcp/adapters/agentic_sidecar.py @@ -0,0 +1,114 @@ +"""Adapter boundary for agentic-sidecar integration.""" + +from __future__ import annotations + +from pathlib import Path +from typing import Any + +from deep_agentic_core_mcp.adapters import AdapterUnavailableError, ensure_repo_on_path + +_IMPORT_ERROR: Exception | None = None +_version: str | None = None +_repo_root: Path | None = None + +_CURRENT_STATUS = { + "package_status": "scaffold", + "release_stage": "pre-alpha", + "runtime_ready": False, + "summary": ( + "agentic-sidecar is importable, but its decision runtime is still planned rather " + "than implemented." + ), + "first_runtime_milestone": "v0.1 — Sidecar Runtime, Policy Advisor & Rule-Based Decision Gate", + "current_focus": "LangGraph adapter first, deterministic policy/risk Decision Gate.", +} + +_PLANNED_MODULES = [ + "core", + "gate", + "intent", + "evaluators", + "status", + "adapters", + "integrations", + "cli", +] + +try: + _repo_root = ensure_repo_on_path("agentic-sidecar") + + import agentic_sidecar as _agentic_sidecar_pkg + + _version = _agentic_sidecar_pkg.__version__ +except Exception as exc: # noqa: BLE001 - captured for core.verify/core.health reporting + _IMPORT_ERROR = exc + + +def _require_available() -> None: + if _IMPORT_ERROR is not None: + raise AdapterUnavailableError("agentic_sidecar", _IMPORT_ERROR) + + +def probe() -> dict[str, Any]: + """Report whether the agentic-sidecar integration is reachable.""" + if _IMPORT_ERROR is not None: + return { + "available": False, + "version": None, + "error": str(_IMPORT_ERROR), + "package_status": "unavailable", + "release_stage": None, + "runtime_ready": False, + "summary": "agentic-sidecar could not be imported in this environment.", + "first_runtime_milestone": _CURRENT_STATUS["first_runtime_milestone"], + "current_focus": None, + } + return {"available": True, "version": _version, "error": None, **_CURRENT_STATUS} + + +def describe_capabilities() -> list[str]: + """Return the currently supported MCP-facing sidecar capabilities.""" + return ["status", "module_inventory"] + + +def status_summary() -> dict[str, Any]: + """Return importability plus honest readiness information for sidecar.""" + _require_available() + return { + "package": "agentic-sidecar", + "version": _version, + **_CURRENT_STATUS, + } + + +def _list_package_modules(package_root: Path) -> list[str]: + return sorted( + child.name + for child in package_root.iterdir() + if child.is_dir() and child.name != "__pycache__" + ) + + +def _list_python_stems(package_root: Path, subdir: str) -> list[str]: + return sorted( + path.stem for path in (package_root / subdir).glob("*.py") if path.stem != "__init__" + ) + + +def module_inventory() -> dict[str, Any]: + """Return the current scaffold inventory exposed by the sidecar package.""" + _require_available() + if _repo_root is None: + raise AdapterUnavailableError("agentic_sidecar", RuntimeError("repo root unavailable")) + + package_root = _repo_root / "src" / "agentic_sidecar" + modules = _list_package_modules(package_root) + return { + "package": "agentic-sidecar", + "version": _version, + "package_status": _CURRENT_STATUS["package_status"], + "top_level_modules": modules, + "framework_adapters": _list_python_stems(package_root, "adapters"), + "integrations": _list_python_stems(package_root, "integrations"), + "planned_runtime_modules": list(_PLANNED_MODULES), + } diff --git a/src/deep_agentic_core_mcp/server.py b/src/deep_agentic_core_mcp/server.py index 3f71d49..abfeda4 100644 --- a/src/deep_agentic_core_mcp/server.py +++ b/src/deep_agentic_core_mcp/server.py @@ -43,6 +43,7 @@ slo_summary, ) from deep_agentic_core_mcp.tools.registry import list_tools as _registry_tools +from deep_agentic_core_mcp.tools.sidecar import module_inventory, status from deep_agentic_core_mcp.tools.spec import validate_artifact # --------------------------------------------------------------------------- @@ -67,6 +68,8 @@ "lens.audit_report": audit_report, "chaos.list_faults": list_faults, "chaos.run_experiment": run_experiment, + "sidecar.status": status, + "sidecar.module_inventory": module_inventory, "spec.validate_artifact": validate_artifact, } diff --git a/src/deep_agentic_core_mcp/tools/core.py b/src/deep_agentic_core_mcp/tools/core.py index cc04ac7..750f0c3 100644 --- a/src/deep_agentic_core_mcp/tools/core.py +++ b/src/deep_agentic_core_mcp/tools/core.py @@ -3,6 +3,7 @@ from typing import Any from deep_agentic_core_mcp.adapters import agentic_chaos as agentic_chaos_adapter +from deep_agentic_core_mcp.adapters import agentic_sidecar as agentic_sidecar_adapter from deep_agentic_core_mcp.adapters import agenticlens as agenticlens_adapter from deep_agentic_core_mcp.adapters import ai_operations_spec as ai_operations_spec_adapter from deep_agentic_core_mcp.adapters import workspace_root @@ -15,6 +16,7 @@ _ADAPTER_PROBES = { "agenticlens": agenticlens_adapter.probe, "agentic_chaos": agentic_chaos_adapter.probe, + "agentic_sidecar": agentic_sidecar_adapter.probe, "ai_operations_spec": ai_operations_spec_adapter.probe, } diff --git a/src/deep_agentic_core_mcp/tools/registry.py b/src/deep_agentic_core_mcp/tools/registry.py index 86deba5..7158e0b 100644 --- a/src/deep_agentic_core_mcp/tools/registry.py +++ b/src/deep_agentic_core_mcp/tools/registry.py @@ -17,7 +17,7 @@ def list_tools() -> list[dict[str, Any]]: each entry carries server-specific metadata surfaced to hosts via `Tool._meta`/`Tool.annotations` in `server.py`: - - `category`: rough grouping (`core`, `lens`, `chaos`, `spec`) + - `category`: rough grouping (`core`, `lens`, `chaos`, `sidecar`, `spec`) - `prerequisites`: adapter names (see `adapters/`) that must be available for the tool to succeed - `expected_duration`: `"instant" | "fast" | "slow"`, a rough hint for @@ -50,8 +50,8 @@ def list_tools() -> list[dict[str, Any]]: { "name": "core.verify", "title": "Verify Integrations", - "description": "Check connectivity to agenticlens, agentic-chaos, and " - "ai-operations-spec, and report readiness.", + "description": "Check connectivity to agenticlens, agentic-chaos, " + "agentic-sidecar, and ai-operations-spec, and report readiness.", "input_schema": {"type": "object", "properties": {}, "additionalProperties": False}, "category": "core", "prerequisites": [], @@ -194,6 +194,28 @@ def list_tools() -> list[dict[str, Any]]: "expected_duration": "slow", "mutates_session": True, }, + { + "name": "sidecar.status", + "title": "Sidecar Status", + "description": "Report whether agentic-sidecar is importable and whether " + "its decision runtime is actually ready yet.", + "input_schema": {"type": "object", "properties": {}, "additionalProperties": False}, + "category": "sidecar", + "prerequisites": ["agentic_sidecar"], + "expected_duration": "instant", + "mutates_session": False, + }, + { + "name": "sidecar.module_inventory", + "title": "Sidecar Module Inventory", + "description": "List the current scaffolded modules, framework adapters, " + "and integration placeholders present in agentic-sidecar.", + "input_schema": {"type": "object", "properties": {}, "additionalProperties": False}, + "category": "sidecar", + "prerequisites": ["agentic_sidecar"], + "expected_duration": "instant", + "mutates_session": False, + }, { "name": "spec.validate_artifact", "title": "Validate AI Operations Artifact", diff --git a/src/deep_agentic_core_mcp/tools/sidecar.py b/src/deep_agentic_core_mcp/tools/sidecar.py new file mode 100644 index 0000000..58ade39 --- /dev/null +++ b/src/deep_agentic_core_mcp/tools/sidecar.py @@ -0,0 +1,33 @@ +"""Agentic Sidecar-backed MCP tools.""" + +from __future__ import annotations + +from typing import Any + +from deep_agentic_core_mcp.adapters import AdapterUnavailableError +from deep_agentic_core_mcp.adapters.agentic_sidecar import describe_capabilities +from deep_agentic_core_mcp.adapters.agentic_sidecar import ( + module_inventory as adapter_module_inventory, +) +from deep_agentic_core_mcp.adapters.agentic_sidecar import status_summary as adapter_status_summary + + +def capabilities() -> dict[str, list[str]]: + """Return sidecar capabilities.""" + return {"sidecar": describe_capabilities()} + + +def status(_: dict[str, Any] | None = None) -> dict[str, Any]: + """Return sidecar package availability and runtime readiness.""" + try: + return {"ok": True, **adapter_status_summary()} + except AdapterUnavailableError as exc: + return {"ok": False, "error": str(exc)} + + +def module_inventory(_: dict[str, Any] | None = None) -> dict[str, Any]: + """Return the scaffolded module, adapter, and integration inventory.""" + try: + return {"ok": True, **adapter_module_inventory()} + except AdapterUnavailableError as exc: + return {"ok": False, "error": str(exc)} diff --git a/tests/test_imports.py b/tests/test_imports.py index 314ef46..74379ee 100644 --- a/tests/test_imports.py +++ b/tests/test_imports.py @@ -1,13 +1,19 @@ from deep_agentic_core_mcp.tools.chaos import capabilities as chaos_capabilities from deep_agentic_core_mcp.tools.core import health, version from deep_agentic_core_mcp.tools.lens import capabilities as lens_capabilities +from deep_agentic_core_mcp.tools.sidecar import capabilities as sidecar_capabilities from deep_agentic_core_mcp.tools.spec import capabilities as spec_capabilities def test_health_payload() -> None: payload = health() assert payload["status"] == "ok" - assert set(payload["adapters"]) == {"agenticlens", "agentic_chaos", "ai_operations_spec"} + assert set(payload["adapters"]) == { + "agenticlens", + "agentic_chaos", + "agentic_sidecar", + "ai_operations_spec", + } assert all(info["available"] for info in payload["adapters"].values()) @@ -19,4 +25,5 @@ def test_version_payload() -> None: def test_capability_placeholders() -> None: assert "chaos" in chaos_capabilities() assert "lens" in lens_capabilities() + assert "sidecar" in sidecar_capabilities() assert "spec" in spec_capabilities() diff --git a/tests/test_registry.py b/tests/test_registry.py index f5c59de..5c735d9 100644 --- a/tests/test_registry.py +++ b/tests/test_registry.py @@ -13,6 +13,7 @@ def test_tool_registry_has_core_health() -> None: assert "core.health" in names assert "lens.analyze_workflow" in names assert "chaos.list_faults" in names + assert "sidecar.status" in names assert "spec.validate_artifact" in names @@ -26,12 +27,13 @@ def test_tool_registry_has_phase_2_and_3_additions() -> None: "lens.slo_summary", "lens.audit_report", "chaos.run_experiment", + "sidecar.module_inventory", } <= names def test_tool_registry_entries_carry_metadata() -> None: for tool in list_tools(): - assert tool["category"] in {"core", "lens", "chaos", "spec"} + assert tool["category"] in {"core", "lens", "chaos", "sidecar", "spec"} assert isinstance(tool["prerequisites"], list) assert tool["expected_duration"] in {"instant", "fast", "slow"} assert isinstance(tool["mutates_session"], bool) diff --git a/tests/test_server.py b/tests/test_server.py index 44c99f5..a0ae192 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -63,6 +63,7 @@ def test_tools_registered() -> None: assert "core.version" in tool_names assert "lens.analyze_workflow" in tool_names assert "chaos.list_faults" in tool_names + assert "sidecar.status" in tool_names assert "spec.validate_artifact" in tool_names @@ -175,7 +176,12 @@ async def test_handle_call_tool_verify() -> None: result = await handle_call_tool("core.verify", {}) payload = json.loads(result[0].text) assert payload["ok"] is True - assert set(payload["adapters"]) == {"agenticlens", "agentic_chaos", "ai_operations_spec"} + assert set(payload["adapters"]) == { + "agenticlens", + "agentic_chaos", + "agentic_sidecar", + "ai_operations_spec", + } @pytest.mark.asyncio @@ -338,6 +344,35 @@ async def test_handle_call_tool_run_experiment_treats_system_exit_zero_as_succes assert payload["crashed"] is None +# --------------------------------------------------------------------------- +# Phase 3d: Agentic Sidecar discovery additions +# --------------------------------------------------------------------------- + + +@pytest.mark.asyncio +async def test_handle_call_tool_sidecar_status() -> None: + from deep_agentic_core_mcp.server import handle_call_tool + + result = await handle_call_tool("sidecar.status", {}) + payload = json.loads(result[0].text) + assert payload["ok"] is True + assert payload["package"] == "agentic-sidecar" + assert payload["package_status"] == "scaffold" + assert payload["runtime_ready"] is False + + +@pytest.mark.asyncio +async def test_handle_call_tool_sidecar_module_inventory() -> None: + from deep_agentic_core_mcp.server import handle_call_tool + + result = await handle_call_tool("sidecar.module_inventory", {}) + payload = json.loads(result[0].text) + assert payload["ok"] is True + assert "core" in payload["top_level_modules"] + assert "langgraph" in payload["framework_adapters"] + assert "agenticlens" in payload["integrations"] + + @pytest.mark.asyncio @pytest.mark.parametrize( ("script", "exit_code"), From f64e8b586f918a55e40b0fceaf4a673c0ed0cda7 Mon Sep 17 00:00:00 2001 From: PRAMOD B N Date: Wed, 12 Aug 2026 13:55:45 -0500 Subject: [PATCH 3/5] test: support degraded sidecar adapter in CI --- tests/test_imports.py | 9 ++++++--- tests/test_server.py | 38 +++++++++++++++++++++++++++----------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/tests/test_imports.py b/tests/test_imports.py index 74379ee..a9d01e5 100644 --- a/tests/test_imports.py +++ b/tests/test_imports.py @@ -7,14 +7,17 @@ def test_health_payload() -> None: payload = health() - assert payload["status"] == "ok" - assert set(payload["adapters"]) == { + expected_adapters = { "agenticlens", "agentic_chaos", "agentic_sidecar", "ai_operations_spec", } - assert all(info["available"] for info in payload["adapters"].values()) + assert set(payload["adapters"]) == expected_adapters + if all(info["available"] for info in payload["adapters"].values()): + assert payload["status"] == "ok" + else: + assert payload["status"] == "degraded" def test_version_payload() -> None: diff --git a/tests/test_server.py b/tests/test_server.py index a0ae192..c4b2e67 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -45,6 +45,12 @@ def _load_json(path: Path) -> dict: return json.loads(path.read_text(encoding="utf-8")) +def _sidecar_available() -> bool: + from deep_agentic_core_mcp.tools.core import health + + return bool(health()["adapters"]["agentic_sidecar"]["available"]) + + @pytest.fixture(autouse=True) def _isolated_default_session(): """Keep the shared in-memory session from leaking state between tests.""" @@ -88,7 +94,8 @@ async def test_handle_call_tool_health() -> None: result = await handle_call_tool("core.health", None) payload = json.loads(result[0].text) - assert payload["status"] == "ok" + expected_status = "ok" if all(info["available"] for info in payload["adapters"].values()) else "degraded" + assert payload["status"] == expected_status @pytest.mark.asyncio @@ -175,13 +182,14 @@ async def test_handle_call_tool_verify() -> None: result = await handle_call_tool("core.verify", {}) payload = json.loads(result[0].text) - assert payload["ok"] is True - assert set(payload["adapters"]) == { + expected_adapters = { "agenticlens", "agentic_chaos", "agentic_sidecar", "ai_operations_spec", } + assert set(payload["adapters"]) == expected_adapters + assert payload["ok"] is all(info["available"] for info in payload["adapters"].values()) @pytest.mark.asyncio @@ -355,10 +363,14 @@ async def test_handle_call_tool_sidecar_status() -> None: result = await handle_call_tool("sidecar.status", {}) payload = json.loads(result[0].text) - assert payload["ok"] is True - assert payload["package"] == "agentic-sidecar" - assert payload["package_status"] == "scaffold" - assert payload["runtime_ready"] is False + if _sidecar_available(): + assert payload["ok"] is True + assert payload["package"] == "agentic-sidecar" + assert payload["package_status"] == "scaffold" + assert payload["runtime_ready"] is False + else: + assert payload["ok"] is False + assert "error" in payload @pytest.mark.asyncio @@ -367,10 +379,14 @@ async def test_handle_call_tool_sidecar_module_inventory() -> None: result = await handle_call_tool("sidecar.module_inventory", {}) payload = json.loads(result[0].text) - assert payload["ok"] is True - assert "core" in payload["top_level_modules"] - assert "langgraph" in payload["framework_adapters"] - assert "agenticlens" in payload["integrations"] + if _sidecar_available(): + assert payload["ok"] is True + assert "core" in payload["top_level_modules"] + assert "langgraph" in payload["framework_adapters"] + assert "agenticlens" in payload["integrations"] + else: + assert payload["ok"] is False + assert "error" in payload @pytest.mark.asyncio From 534fb62a173f216c87aa2580e1fab20a59a62a22 Mon Sep 17 00:00:00 2001 From: PRAMOD B N Date: Wed, 12 Aug 2026 14:01:04 -0500 Subject: [PATCH 4/5] test: wrap degraded-health expectation --- tests/test_server.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_server.py b/tests/test_server.py index c4b2e67..a7e4e70 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -94,7 +94,9 @@ async def test_handle_call_tool_health() -> None: result = await handle_call_tool("core.health", None) payload = json.loads(result[0].text) - expected_status = "ok" if all(info["available"] for info in payload["adapters"].values()) else "degraded" + expected_status = ( + "ok" if all(info["available"] for info in payload["adapters"].values()) else "degraded" + ) assert payload["status"] == expected_status From bb4da1603245cb72e241b895c16be980a2b756d6 Mon Sep 17 00:00:00 2001 From: PRAMOD B N Date: Wed, 12 Aug 2026 14:04:03 -0500 Subject: [PATCH 5/5] fix: derive sidecar inventory from imported package --- .../adapters/agentic_sidecar.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/deep_agentic_core_mcp/adapters/agentic_sidecar.py b/src/deep_agentic_core_mcp/adapters/agentic_sidecar.py index 196126a..b99d803 100644 --- a/src/deep_agentic_core_mcp/adapters/agentic_sidecar.py +++ b/src/deep_agentic_core_mcp/adapters/agentic_sidecar.py @@ -8,6 +8,7 @@ from deep_agentic_core_mcp.adapters import AdapterUnavailableError, ensure_repo_on_path _IMPORT_ERROR: Exception | None = None +_package_root: Path | None = None _version: str | None = None _repo_root: Path | None = None @@ -39,6 +40,7 @@ import agentic_sidecar as _agentic_sidecar_pkg + _package_root = Path(_agentic_sidecar_pkg.__file__).resolve().parent _version = _agentic_sidecar_pkg.__version__ except Exception as exc: # noqa: BLE001 - captured for core.verify/core.health reporting _IMPORT_ERROR = exc @@ -98,17 +100,16 @@ def _list_python_stems(package_root: Path, subdir: str) -> list[str]: def module_inventory() -> dict[str, Any]: """Return the current scaffold inventory exposed by the sidecar package.""" _require_available() - if _repo_root is None: - raise AdapterUnavailableError("agentic_sidecar", RuntimeError("repo root unavailable")) + if _package_root is None: + raise AdapterUnavailableError("agentic_sidecar", RuntimeError("package root unavailable")) - package_root = _repo_root / "src" / "agentic_sidecar" - modules = _list_package_modules(package_root) + modules = _list_package_modules(_package_root) return { "package": "agentic-sidecar", "version": _version, "package_status": _CURRENT_STATUS["package_status"], "top_level_modules": modules, - "framework_adapters": _list_python_stems(package_root, "adapters"), - "integrations": _list_python_stems(package_root, "integrations"), + "framework_adapters": _list_python_stems(_package_root, "adapters"), + "integrations": _list_python_stems(_package_root, "integrations"), "planned_runtime_modules": list(_PLANNED_MODULES), }