From 4b9cb6cda1ac98e047a85553612abda163ade970 Mon Sep 17 00:00:00 2001 From: PRAMOD B N Date: Sat, 8 Aug 2026 23:47:37 -0500 Subject: [PATCH 1/6] docs: add feature completion expectations --- AGENTS.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 4cd3ce0..dee21e1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -64,6 +64,18 @@ objects (`ListToolsResult`, `CallToolResult`, `ListResourcesResult`). 4. Add test in `tests/test_server.py` 5. Run `make docs` to regenerate `docs/tools.md` +## Feature Completion Expectations + +- Every behavior change must include tests. +- User-facing tools and workflows must include or update examples in + `README.md`, generated tool docs, or test fixtures that demonstrate expected + usage. +- When a roadmap item or milestone meaningfully changes status, update + `README.md` and the roadmap document in the same change. +- When work is packaged as a release-ready change, also update + `pyproject.toml`, `src/deep_agentic_core_mcp/__init__.py`, and + `CHANGELOG.md`. + ## Package Boundaries - This server is a **thin orchestration layer** — reuse agenticlens and From dafe67ce41407a84b990c49790e3adc620ea1992 Mon Sep 17 00:00:00 2001 From: PRAMOD B N Date: Sat, 8 Aug 2026 23:47:37 -0500 Subject: [PATCH 2/6] docs: tighten contributor completion checklist --- CONTRIBUTING.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cbdd31e..07c355b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,7 +22,14 @@ uv sync --extra dev 1. Create a focused branch from `main`. 2. Add or update tests with every behavior change. -3. Run: +3. Add or update user-facing examples when the tool behavior, CLI contract, or + MCP output changes. +4. If a roadmap item is completed or its status changes, update `README.md` + and the roadmap document in the same pull request. +5. If the work is release-ready, update `pyproject.toml`, + `src/deep_agentic_core_mcp/__init__.py`, and `CHANGELOG.md` as part of the + release. +6. Run: ```bash ruff check . @@ -31,8 +38,8 @@ mypy pytest ``` -4. Keep PRs focused — one concern per pull request. -5. Write clear commit messages describing *why*, not just *what*. +7. Keep PRs focused — one concern per pull request. +8. Write clear commit messages describing *why*, not just *what*. ## Adding a tool @@ -40,6 +47,7 @@ pytest 2. Register in `tools/registry.py` with name, title, description, and `input_schema` 3. Add entry to `_TOOL_DISPATCH` in `server.py` 4. Add tests in `tests/` +5. Add or update usage examples or generated docs for user-facing behavior ## Releases From dfa29d4436976c0abc3bcc530d587ee7f5fb5c69 Mon Sep 17 00:00:00 2001 From: PRAMOD B N Date: Sat, 8 Aug 2026 23:47:37 -0500 Subject: [PATCH 3/6] docs: expand roadmap dependency and security notes --- ROADMAP.md | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/ROADMAP.md b/ROADMAP.md index a0b1e48..f1a74d3 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -23,6 +23,46 @@ Current shipped version: `0.2.0` (2026-08-08) — see [CHANGELOG.md](CHANGELOG.m - **Phase 5: Publishing and Adoption** 🚧 Planned - **Phase 6: Operational Intelligence** 🚧 Planned +## Cross-Project Dependencies + +This server is an orchestration layer across sibling projects, so roadmap +status should explicitly account for upstream and downstream dependencies. + +- `agenticlens` + Provides workflow analysis, evaluation, comparison, and reporting behavior + surfaced through `lens.*` tools. +- `agentic-chaos` + Provides resilience/fault injection behavior surfaced through `chaos.*` + tools. +- `ai-operations-spec` + Provides the canonical artifact model and validation rules surfaced through + `spec.*` tools and used as the ecosystem exchange contract. + +For roadmap work, distinguish: + +- `Depends on`: a sibling capability or spec milestone that must exist first. +- `Blocked by`: a hard upstream constraint that prevents shipping the feature. +- `Coordinate with`: sibling repos whose docs, examples, or contracts should + be updated together. +- `Validate in`: sibling CLIs, fixtures, or adapters that should be checked + before the item is marked done. + +## Definition of Done + +A roadmap item is done only when all applicable work is complete: + +- implementation is merged and reachable through the intended MCP tool, + prompt, or resource surface +- tests cover the behavior, including integration boundaries where practical +- user-facing examples and generated docs are added or updated +- `README.md` and this roadmap are updated when the feature changes user + expectations or milestone status +- sibling-project dependencies and end-to-end checks are recorded for any + cross-repo tool surface +- release metadata (`pyproject.toml`, + `src/deep_agentic_core_mcp/__init__.py`, `CHANGELOG.md`) is updated when the + work is part of a release-ready change set + ## Vision Build one public MCP server for the DeepAgentLabs ecosystem that unifies: @@ -197,6 +237,12 @@ Success criteria: - chaos results are readable as or convertible to AI Operations Specification artifacts — still open; `chaos.run_experiment`'s output is `ChaosReport`-shaped but not yet run through `spec.validate_artifact` +- [ ] script-path allow/deny-list for `chaos.run_experiment`, layered on top + of the existing workspace-root confinement — an opt-in instance-level + allowlist (e.g. `MCP_SERVER_ALLOWED_SCRIPT_GLOBS`) plus a deny-list, modeled + on `devops-open-agent`'s layered MCP-server allowlist/whitelist/blacklist + pattern; tracked as a prerequisite for widening `chaos.run_experiment` + exposure beyond trusted local stdio clients (see Known Limitations) ## Phase 3c: AI Operations Specification Conformance @@ -289,6 +335,17 @@ Goals: or make handlers genuinely async) before any remote/multi-session/SSE transport (Phase 4+) is added — it would otherwise let one slow call stall every other client. +- **`chaos.run_experiment` has no allowlist beyond workspace-path + confinement.** Any script inside the workspace root can be executed today; + there's no further restriction on *which* scripts within that root are + permitted, and per `SECURITY.md` the tool doesn't authenticate or authorize + the calling client either. `devops-open-agent` solves the equivalent + problem for its own MCP integration with a layered allow/deny-list + (instance-level allowlist + per-user whitelist + per-user blacklist) — + the same shape (see Phase 3b) is a reasonable model here. Like the + async-blocking limitation above, this should be closed before any + remote/multi-client transport (Phase 4+) is considered, not concurrently + with it. ## Documentation Backlog From fa322d5add9616b2089d08c9fa7c8ec4042b6116 Mon Sep 17 00:00:00 2001 From: PRAMOD B N Date: Sat, 8 Aug 2026 23:47:37 -0500 Subject: [PATCH 4/6] fix: capture failing system exits from chaos adapter --- src/deep_agentic_core_mcp/adapters/agentic_chaos.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/deep_agentic_core_mcp/adapters/agentic_chaos.py b/src/deep_agentic_core_mcp/adapters/agentic_chaos.py index 67b80fc..0706faf 100644 --- a/src/deep_agentic_core_mcp/adapters/agentic_chaos.py +++ b/src/deep_agentic_core_mcp/adapters/agentic_chaos.py @@ -112,6 +112,9 @@ def _run() -> tuple[Any, Exception | None]: crashed: Exception | None = None try: runpy.run_path(str(script_path), run_name="__main__") + except SystemExit as exc: + if exc.code not in (None, 0): + crashed = exc except Exception as exc: # noqa: BLE001 - reported back, not swallowed silently crashed = exc return session, crashed From 92c3041d0d925c4fc9b863861e777455a908839b Mon Sep 17 00:00:00 2001 From: PRAMOD B N Date: Sat, 8 Aug 2026 23:53:38 -0500 Subject: [PATCH 5/6] fix: widen captured chaos crash type for mypy --- src/deep_agentic_core_mcp/adapters/agentic_chaos.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/deep_agentic_core_mcp/adapters/agentic_chaos.py b/src/deep_agentic_core_mcp/adapters/agentic_chaos.py index 0706faf..398efcb 100644 --- a/src/deep_agentic_core_mcp/adapters/agentic_chaos.py +++ b/src/deep_agentic_core_mcp/adapters/agentic_chaos.py @@ -107,9 +107,9 @@ def run_experiment( script_path = _resolve_sandboxed_script(script) resolved_faults = resolve_faults(faults) # raises ValueError on unknown fault names - def _run() -> tuple[Any, Exception | None]: + def _run() -> tuple[Any, BaseException | None]: with chaos_session(resolved_faults) as session: - crashed: Exception | None = None + crashed: BaseException | None = None try: runpy.run_path(str(script_path), run_name="__main__") except SystemExit as exc: @@ -122,7 +122,7 @@ def _run() -> tuple[Any, Exception | None]: started_at = datetime.now(timezone.utc) timed_out = False session = None - crashed: Exception | None = None + crashed: BaseException | None = None # Deliberately not a `with` block: ThreadPoolExecutor.__exit__ calls # shutdown(wait=True), which would block for the worker thread to finish # regardless of the timeout below - defeating the whole point of it. From d2e9334e5e23f1252c295292777f88f510b10db5 Mon Sep 17 00:00:00 2001 From: PRAMOD B N Date: Sun, 9 Aug 2026 00:15:12 -0500 Subject: [PATCH 6/6] Add SystemExit experiment regression tests --- examples/chaos_exit_nonzero.py | 3 +++ examples/chaos_exit_string.py | 3 +++ examples/chaos_exit_zero.py | 3 +++ tests/test_server.py | 43 ++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 examples/chaos_exit_nonzero.py create mode 100644 examples/chaos_exit_string.py create mode 100644 examples/chaos_exit_zero.py diff --git a/examples/chaos_exit_nonzero.py b/examples/chaos_exit_nonzero.py new file mode 100644 index 0000000..efd9051 --- /dev/null +++ b/examples/chaos_exit_nonzero.py @@ -0,0 +1,3 @@ +import sys + +sys.exit(2) diff --git a/examples/chaos_exit_string.py b/examples/chaos_exit_string.py new file mode 100644 index 0000000..f563373 --- /dev/null +++ b/examples/chaos_exit_string.py @@ -0,0 +1,3 @@ +import sys + +sys.exit("boom") diff --git a/examples/chaos_exit_zero.py b/examples/chaos_exit_zero.py new file mode 100644 index 0000000..a0d1577 --- /dev/null +++ b/examples/chaos_exit_zero.py @@ -0,0 +1,3 @@ +import sys + +sys.exit(0) diff --git a/tests/test_server.py b/tests/test_server.py index 20266df..44c99f5 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -13,6 +13,9 @@ SPEC_V04 = ROOT / "ai-operations-spec" / "specification" / "v0.4" / "examples" AGENTICLENS_ARTIFACTS = ROOT / "agenticlens" / "examples" / "pitch_demo" / "artifacts" CHAOS_TARGET_SCRIPT = "mcp-server/examples/chaos_target.py" +CHAOS_EXIT_ZERO_SCRIPT = "mcp-server/examples/chaos_exit_zero.py" +CHAOS_EXIT_NONZERO_SCRIPT = "mcp-server/examples/chaos_exit_nonzero.py" +CHAOS_EXIT_STRING_SCRIPT = "mcp-server/examples/chaos_exit_string.py" WORKFLOW_ARTIFACT = { "name": "Support workflow", @@ -321,6 +324,46 @@ async def test_handle_call_tool_run_experiment_rejects_unknown_fault() -> None: assert "error" in payload +@pytest.mark.asyncio +async def test_handle_call_tool_run_experiment_treats_system_exit_zero_as_success() -> None: + from deep_agentic_core_mcp.server import handle_call_tool + + result = await handle_call_tool( + "chaos.run_experiment", + {"script": CHAOS_EXIT_ZERO_SCRIPT, "faults": ["silent_degradation"]}, + ) + payload = json.loads(result[0].text) + assert payload["ok"] is True + assert payload["timed_out"] is False + assert payload["crashed"] is None + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + ("script", "exit_code"), + [ + (CHAOS_EXIT_NONZERO_SCRIPT, "2"), + (CHAOS_EXIT_STRING_SCRIPT, "boom"), + ], +) +async def test_handle_call_tool_run_experiment_reports_failing_system_exit( + script: str, + exit_code: str, +) -> None: + from deep_agentic_core_mcp.server import handle_call_tool + + result = await handle_call_tool( + "chaos.run_experiment", + {"script": script, "faults": ["silent_degradation"]}, + ) + payload = json.loads(result[0].text) + assert payload["ok"] is False + assert payload["timed_out"] is False + assert payload["crashed"] is not None + assert "SystemExit" in payload["crashed"] + assert exit_code in payload["crashed"] + + # --------------------------------------------------------------------------- # Prompts # ---------------------------------------------------------------------------