Skip to content

Commit c2cd76b

Browse files
committed
Merge remote-tracking branch 'origin/feature/handlers-docs' into 17.0
* origin/feature/handlers-docs: docs: document --format md|html for Mermaid exports feat(doctor): support --format md|html for graph exports; wrap output in Markdown or HTML (Mermaid via CDN) feat(doctor): Mermaid exporters (doctor graph, doctor run-graph) + USER_GUIDE Visualization section docs(handlers): add scaffold example and cross-links; feat(cli): --strict-validate flag for run_graph to validate handlers+args docs(orchestrator): add 'Extending Handlers' pointers and sample recipe mixing mcp.call with traditional step docs(orchestrator): add Handlers design & usage guide; link from README feat(orchestrator): per-handler JSON Schema validation; doctor validate-recipe checks handler args; add mcp.call schema feat(orchestrator): add generic mcp.call handler; expose handler registry; doctor commands (list-handlers, validate-recipe, reset-node); docs updated; tests added refactor(orchestrator): decouple node logic via handler registry; add handlers (agent, git, github, tm, odoo); route legacy 'uses' to handlers; keep parallel synthetic feat(orchestrator/graph): support return_to_agent on failure; fix parallel block; tests for interrupt/resume and agent return feat(orchestrator/graph): phase 1–3 — graph IR + SQLite checkpointer + interrupts + parallel (sequential); add CLI run_graph/resume ci: add job to run mcp-task-registry tests from ACN-org/acn-ai monorepo with coverage artifact ci(orchestrator): add GH Action with coverage; tests: e2e commit+PR (gh via PATH), mcp stub in conftest tests(orchestrator): add e2e commit+PR tests; fix formatting tests(orchestrator): add edge-case tests (allowed path guard, gh CLI unexpected output, smoke fail path, agent timeout & if-skip) tests(orchestrator): add retries, github fallback, agent gate, summary and adapter gate tests chore: remove redundant workflow (CI runs in openspp-tooling repo) feat(task-registry): add search resource; expand tests; add CI with coverage
2 parents a3d429e + 2ed1789 commit c2cd76b

28 files changed

Lines changed: 3203 additions & 0 deletions

.github/workflows/orchestrator.yml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: orchestrator
2+
3+
on:
4+
push:
5+
paths:
6+
- 'orchestrator/**'
7+
- '.github/workflows/orchestrator.yml'
8+
pull_request:
9+
paths:
10+
- 'orchestrator/**'
11+
12+
jobs:
13+
tests:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
19+
- name: Setup Python
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: '3.11'
23+
cache: 'pip'
24+
25+
- name: Install test deps
26+
run: |
27+
python -m pip install --upgrade pip
28+
pip install pytest pytest-cov ruff
29+
30+
- name: Run orchestrator tests + coverage
31+
env:
32+
PYTHONPATH: .
33+
run: |
34+
pytest -q orchestrator/tests \
35+
--cov=orchestrator --cov-report=xml --cov-report=term-missing
36+
37+
- name: Upload coverage.xml
38+
uses: actions/upload-artifact@v4
39+
with:
40+
name: coverage-orchestrator
41+
path: coverage.xml
42+
43+
task-registry:
44+
name: mcp-task-registry (monorepo)
45+
runs-on: ubuntu-latest
46+
permissions:
47+
contents: read
48+
steps:
49+
- name: Checkout monorepo ACN-org/acn-ai
50+
uses: actions/checkout@v4
51+
with:
52+
repository: ACN-org/acn-ai
53+
ref: main
54+
fetch-depth: 1
55+
# If the repo is private, create a PAT with repo:read and set as ACN_AI_PAT
56+
# token: ${{ secrets.ACN_AI_PAT }}
57+
58+
- name: Setup Python
59+
uses: actions/setup-python@v5
60+
with:
61+
python-version: '3.11'
62+
cache: 'pip'
63+
64+
- name: Install test deps
65+
run: |
66+
python -m pip install --upgrade pip
67+
pip install pytest pytest-cov
68+
pip install -e packages/mcp-task-registry
69+
70+
- name: Run mcp-task-registry tests
71+
env:
72+
PYTHONPATH: packages/mcp-task-registry/src
73+
run: |
74+
pytest -q packages/mcp-task-registry/tests \
75+
--cov=packages/mcp-task-registry/src/mcp_task_registry \
76+
--cov-report=xml --cov-report=term-missing
77+
78+
- name: Upload coverage.xml
79+
uses: actions/upload-artifact@v4
80+
with:
81+
name: coverage-mcp-task-registry
82+
path: coverage.xml

orchestrator/README.md

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# Orchestrator (MCP‑First)
2+
3+
This CLI coordinates Task Master tasks, Odoo operations via the Odoo MCP server, and
4+
code edits via agents, executing declarative recipes with guardrails and artifacts.
5+
6+
Status: fully implemented. Uses persistent MCP sessions for Odoo and Task Master, runs
7+
declarative recipes with retries/timeouts, readiness gates, guardrails, artifacts,
8+
evidence/decisions, and PR creation via `gh` CLI. Steps are executed via pluggable
9+
handlers (no hardcoded nodes): `git.apply`, `github.open_pr`, `odoo.call`, `tm.*`,
10+
`agent.wait`, `mcp.call`.
11+
12+
Quick Start (uv venv)
13+
14+
- Requires: Python 3.10+ and `uv` (https://docs.astral.sh/uv/)
15+
- Requires: Node.js 18+ for Task Master MCP server
16+
- Requires: GitHub CLI `gh` (authenticated) for PR creation
17+
- From repo root:
18+
- `uv venv`
19+
- `source .venv/bin/activate`
20+
- `uv pip install -r orchestrator/requirements.txt --python $(which python)`
21+
- Copy `orchestrator/config.example.yaml` to `orchestrator/config.yaml` and adjust.
22+
- `python -m orchestrator.main --help`
23+
24+
Commands
25+
26+
- `orchestrator loop` — polls Task Master (`next_task`) and runs the default recipe per
27+
task.
28+
- `orchestrator run --task-id <ID> --recipe <name>` — runs a specific task using a named
29+
recipe.
30+
- `orchestrator verify --task-id <ID>` — runs only `lint` + `test_addons` from the
31+
default recipe.
32+
- `orchestrator pr --task-id <ID>` — opens a PR for `feature/<ID>` and adds PR evidence
33+
to the task.
34+
- `orchestrator run_graph --task-id <ID> --recipe <name>` — graph execution with
35+
checkpoints. Resume with `--resume <run_id>`.
36+
37+
Layout
38+
39+
```
40+
orchestrator/
41+
main.py
42+
adapters/
43+
tm_mcp.py
44+
odoo_mcp.py
45+
agents.py
46+
git.py
47+
github.py
48+
engine/
49+
recipes.py
50+
events.py
51+
utils.py
52+
schemas/
53+
config.v1.json
54+
recipe.v1.json
55+
recipes/
56+
odoo_create_or_update_module.yaml
57+
odoo_upgrade_addon.yaml
58+
engine/handlers/
59+
(built-in handlers)
60+
engine/registry.py
61+
config.example.yaml
62+
README.md
63+
COOKBOOK.md
64+
```
65+
66+
Notes
67+
68+
- Odoo operations go through the Odoo MCP server (see `servers/odoo_mcp/server.py`) via
69+
persistent stdio sessions. Ensure `uv` and `invoke` are available.
70+
- Task Master adapter maps spec names to server tools: `decision→log_decision`,
71+
`evidence→add_evidence`.
72+
- Guardrails: diff budgets enforced in `adapters/git.py`.
73+
- Optional streaming logs: add `stream_logs: true` to an Odoo step to collect a follow
74+
log tail in artifacts.
75+
- Handlers: the engine runs steps via pluggable handlers (no hardcoded nodes). See
76+
`orchestrator/docs/HANDLERS.md` for details.
77+
78+
Configuration Reference
79+
80+
- File: `orchestrator/config.yaml` (validated by `schemas/config.v1.json`)
81+
- Key sections used at runtime:
82+
- `odoo.mcp.cmd`: stdio command to start the Odoo MCP server. Defaults to
83+
`uv run --with modelcontextprotocol --with invoke python servers/odoo_mcp/server.py`.
84+
- `tm.mcp.cmd`: stdio command to start Task Master MCP server. Defaults to
85+
`node servers/claude-task-master/mcp-server/server.js`.
86+
- `odoo.db` and `odoo.module`: default database and module name used in recipes.
87+
- `odoo.readiness`: readiness probe defaults for `smoke_test` after restarts
88+
(`attempts`, `timeout_seconds`).
89+
- `guards`:
90+
- `max_files_changed`, `max_total_additions`: diff budgets enforced before
91+
committing.
92+
- `require_confirm_for_destructive`: if true, destructive Odoo tools require
93+
`confirm: true`.
94+
- `allowed_environment`: destructive ops are blocked unless they target this
95+
environment.
96+
- Applies to `reset_db`/`restore_snapshot` when the target
97+
`dbname`/`destination_db` equals `allowed_environment`.
98+
- Applies to `stop_env` only when `purge: true`; in that case, the configured
99+
`odoo.db` must equal `allowed_environment`.
100+
- `github.base_branch`, `github.pr_labels`: PR base branch and default labels.
101+
- `secrets.github_token_from_env`: env var for GitHub REST fallback (PRs currently
102+
require `gh`).
103+
104+
Recipe Format
105+
106+
- Validated by `schemas/recipe.v1.json`.
107+
- Step keys supported:
108+
- `uses`: `odoo | agent | git | github | tm | mcp`
109+
- Odoo: `tool`, `args`, `timeout_seconds`, `retries`, `on_error`, `stream_logs`
110+
- Agent: `goal`, `mode`, `context`
111+
- Git: `branch`, `commit`
112+
- GitHub: `pr { base, title, bodyFrom }`
113+
- Task Master: `status { id }`, `value`, `decision { id, note }`
114+
115+
Agent Behavior
116+
117+
- Interactive agent steps write `agent/GOAL.md`, then wait until one of:
118+
- working tree has changes (`git diff` not empty), or
119+
- HEAD changes vs the initial `git rev-parse HEAD`, or
120+
- `.orchestrator/continue` file exists in repo root.
121+
- Timeout controlled by `agents.timeout_seconds`.
122+
123+
Destructive Operation Safety
124+
125+
- The orchestrator enforces confirm + environment gates client‑side before calling Odoo
126+
tools:
127+
- `reset_db` / `restore_snapshot`: require `confirm: true` and
128+
`dbname`/`destination_db` must equal `guards.allowed_environment` (when configured).
129+
- `stop_env(purge=true)`: require `confirm: true` and configured `odoo.db` must equal
130+
`guards.allowed_environment`.
131+
- Non‑purge `stop_env` is allowed without confirm by default.
132+
133+
Artifacts & Summary
134+
135+
- Artifacts live in `orchestrator/artifacts/<task-id>/`:
136+
- `events.jsonl` (token‑redacted), `summary.json`, `odoo/<tool>.log`, optional
137+
`odoo/logs_<id>.log`, `agent/GOAL.md`.
138+
- `summary.json` contains: `status`, `pr_url`, `commit`, `guards` diff stats, and
139+
`timings { start, end }`.
140+
141+
PR Creation
142+
143+
- Uses `gh` CLI: `gh pr create --json url --jq .url` for a robust URL parse.
144+
- Adds PR evidence to Task Master automatically.
145+
146+
Leasing
147+
148+
- A local lease file is written to `.orchestrator/lease.json` when a run starts and
149+
removed after completion.
150+
- Stale leases older than `locks.ttl_seconds` are cleared on startup.
151+
152+
Testing
153+
154+
- Tests run only for orchestrator code (see `pytest.ini`).
155+
- Run in the uv venv: `pytest -q`.
156+
- Coverage highlights:
157+
- Readiness gate (smoke after restart), Odoo arg normalization, guardrail violation
158+
path, token redaction, util helpers.
159+
160+
See Also
161+
162+
- Configuration cookbook with copy‑paste snippets: `orchestrator/COOKBOOK.md`
163+
- Handlers design & usage: `orchestrator/docs/HANDLERS.md`
164+
165+
Sample: mixing a traditional step with a generic MCP call
166+
167+
```
168+
steps:
169+
- id: tests
170+
uses: odoo
171+
tool: test_addons
172+
args: { modules: ["my_module"], dbname: "devel" }
173+
- id: note
174+
uses: mcp
175+
server: tm
176+
tool: add_evidence
177+
arguments: { id: T1, type: note, ref: "tests:ok" }
178+
```

0 commit comments

Comments
 (0)