feat: MACP Phase 1 — Core Protocol Implementation (#9)

This commit was merged in pull request #9.
This commit is contained in:
2026-03-28 01:39:26 +00:00
parent 24496cea01
commit 28392914a7
19 changed files with 1724 additions and 53 deletions

View File

@@ -35,9 +35,9 @@ def split_pipe_row(line: str) -> list[str]:
return [c.strip() for c in row.split("|")]
def parse_tasks_markdown(path: pathlib.Path) -> list[dict[str, str]]:
def parse_tasks_markdown(path: pathlib.Path) -> tuple[set[str], list[dict[str, str]]]:
if not path.exists():
return []
return set(), []
lines = path.read_text(encoding="utf-8").splitlines()
header_idx = -1
@@ -51,7 +51,7 @@ def parse_tasks_markdown(path: pathlib.Path) -> list[dict[str, str]]:
headers = cells
break
if header_idx < 0:
return []
return set(), []
rows: list[dict[str, str]] = []
for line in lines[header_idx + 2 :]:
@@ -67,7 +67,7 @@ def parse_tasks_markdown(path: pathlib.Path) -> list[dict[str, str]]:
if not task_id or task_id.lower() == "id":
continue
rows.append(row)
return rows
return set(headers), rows
def map_status(raw: str) -> str:
@@ -78,9 +78,11 @@ def map_status(raw: str) -> str:
"pending": "pending",
"in-progress": "pending",
"needs-qa": "pending",
"gated": "gated",
"done": "completed",
"completed": "completed",
"failed": "failed",
"escalated": "escalated",
}
return mapping.get(value, "pending")
@@ -91,7 +93,9 @@ def parse_depends(raw: str) -> list[str]:
def build_task(
row: dict[str, str],
headers: set[str],
existing: dict[str, Any],
macp_defaults: dict[str, str],
runtime_default: str,
source_path: str,
) -> dict[str, Any]:
@@ -100,6 +104,9 @@ def build_task(
issue = row.get("issue", "").strip()
repo = row.get("repo", "").strip()
branch = row.get("branch", "").strip()
task_type = row.get("type", "").strip()
dispatch = row.get("dispatch", "").strip()
runtime = row.get("runtime", "").strip()
depends_on = parse_depends(row.get("depends_on", ""))
task = dict(existing)
@@ -108,9 +115,25 @@ def build_task(
task["description"] = description
task["status"] = map_status(row.get("status", "pending"))
task["depends_on"] = depends_on
task["runtime"] = str(task.get("runtime") or runtime_default or "codex")
task["issue"] = issue or str(task.get("issue") or "")
task["command"] = str(task.get("command") or "")
task["quality_gates"] = task.get("quality_gates") or []
if "type" in headers:
task["type"] = task_type or str(task.get("type") or macp_defaults.get("type") or "coding")
else:
task.pop("type", None)
if "dispatch" in headers:
task["dispatch"] = dispatch or str(task.get("dispatch") or macp_defaults.get("dispatch") or "")
else:
task.pop("dispatch", None)
if "runtime" in headers:
task["runtime"] = runtime or str(task.get("runtime") or macp_defaults.get("runtime") or runtime_default or "codex")
else:
task.pop("runtime", None)
if "branch" in headers:
task["branch"] = branch or str(task.get("branch") or macp_defaults.get("branch") or "")
else:
task.pop("branch", None)
metadata = dict(task.get("metadata") or {})
metadata.update(
{
@@ -147,9 +170,16 @@ def main() -> int:
tasks_path = (repo / args.tasks_json).resolve()
config_path = repo / ".mosaic" / "orchestrator" / "config.json"
config = load_json(config_path, {})
runtime_default = str(config.get("worker", {}).get("runtime") or "codex")
macp_config = dict(config.get("macp") or {})
runtime_default = str(config.get("worker", {}).get("runtime") or macp_config.get("default_runtime") or "codex")
macp_defaults = {
"type": "coding",
"dispatch": str(macp_config.get("default_dispatch") or ""),
"runtime": str(macp_config.get("default_runtime") or runtime_default or "codex"),
"branch": "",
}
rows = parse_tasks_markdown(docs_path)
headers, rows = parse_tasks_markdown(docs_path)
try:
source_path = str(docs_path.relative_to(repo))
except ValueError:
@@ -170,7 +200,9 @@ def main() -> int:
out_tasks.append(
build_task(
row,
headers,
existing_by_id.get(task_id, {}),
macp_defaults,
runtime_default,
source_path,
)