Includes AirPlan design documents, AircOding-alpha1-plan, AirPlanV2, AirPlan-ParaV2, AirPlan-Para V1 reference docs, and all working code changes across packages. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
192 lines
7.0 KiB
Python
Executable File
192 lines
7.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def _add_lib_path() -> None:
|
|
root = Path(__file__).resolve().parents[3]
|
|
lib_path = root / "lib"
|
|
if str(lib_path) not in sys.path:
|
|
sys.path.insert(0, str(lib_path))
|
|
|
|
|
|
_add_lib_path()
|
|
|
|
from air_runtime.contracts import now_iso
|
|
from air_runtime.paths import airarc_root, required_project_artifacts, todo_path as workflow_todo_path
|
|
from air_runtime.project_bootstrap import ensure_project_bootstrap
|
|
from air_runtime.review import build_parallel_review, render_review_markdown
|
|
|
|
REQUIRED_ARTIFACTS = required_project_artifacts()
|
|
|
|
|
|
def _paths(project_root: Path) -> dict[str, Path]:
|
|
root = airarc_root(project_root)
|
|
return {
|
|
"root": root,
|
|
"state": root / "state.json",
|
|
"reviews": root / "reviews",
|
|
"execution_plan_json": root / "reviews" / "execution-plan.json",
|
|
"execution_plan_md": root / "reviews" / "execution-plan.md",
|
|
}
|
|
|
|
|
|
def _ensure_layout(project_root: Path) -> dict[str, Path]:
|
|
paths = _paths(project_root)
|
|
paths["reviews"].mkdir(parents=True, exist_ok=True)
|
|
return paths
|
|
|
|
|
|
def _artifact_health(project_root: Path) -> dict[str, bool]:
|
|
return {
|
|
relative: (project_root / relative).exists()
|
|
for relative in REQUIRED_ARTIFACTS
|
|
}
|
|
|
|
|
|
def _write_state(project_root: Path, enabled: bool) -> Path:
|
|
paths = _ensure_layout(project_root)
|
|
payload = {
|
|
"enabled": enabled,
|
|
"updatedAt": now_iso(),
|
|
"projectRoot": str(project_root),
|
|
"artifactHealth": _artifact_health(project_root),
|
|
}
|
|
paths["state"].write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
|
|
return paths["state"]
|
|
|
|
|
|
def enter_mode(project_root: Path) -> dict[str, object]:
|
|
state_path = _write_state(project_root, True)
|
|
return {
|
|
"statePath": str(state_path),
|
|
"artifactHealth": _artifact_health(project_root),
|
|
}
|
|
|
|
|
|
def status_mode(project_root: Path) -> dict[str, object]:
|
|
paths = _ensure_layout(project_root)
|
|
if paths["state"].exists():
|
|
payload = json.loads(paths["state"].read_text(encoding="utf-8-sig"))
|
|
else:
|
|
payload = {
|
|
"enabled": False,
|
|
"projectRoot": str(project_root),
|
|
"artifactHealth": _artifact_health(project_root),
|
|
}
|
|
payload["artifactHealth"] = _artifact_health(project_root)
|
|
return payload
|
|
|
|
|
|
def parallel_review_mode(project_root: Path, todo_path: Path) -> dict[str, object]:
|
|
paths = _ensure_layout(project_root)
|
|
review = build_parallel_review(todo_path)
|
|
json_path = paths["reviews"] / "parallel-review.json"
|
|
markdown_path = paths["reviews"] / "parallel-review.md"
|
|
json_path.write_text(json.dumps(review.to_dict(), indent=2) + "\n", encoding="utf-8")
|
|
markdown_path.write_text(render_review_markdown(review), encoding="utf-8")
|
|
selected_tasks = review.parallel_groups[0].task_ids if review.parallel_groups else []
|
|
execution_plan_payload = {
|
|
"generatedAt": now_iso(),
|
|
"projectRoot": str(project_root),
|
|
"todoPath": str(todo_path),
|
|
"planSource": "airarc-post-plan-review",
|
|
"parallelReview": review.to_dict(),
|
|
"selectedTasks": selected_tasks,
|
|
"parallelGroups": [group.to_dict() for group in review.parallel_groups],
|
|
"conflicts": [conflict.to_dict() for conflict in review.conflicts],
|
|
"serializationPoints": review.serialization_points,
|
|
}
|
|
paths["execution_plan_json"].write_text(
|
|
json.dumps(execution_plan_payload, indent=2) + "\n",
|
|
encoding="utf-8",
|
|
)
|
|
execution_lines = [
|
|
"# AirArc Execution Plan",
|
|
"",
|
|
f"- Generated At: `{execution_plan_payload['generatedAt']}`",
|
|
f"- Todo Path: `{todo_path}`",
|
|
f"- Plan Source: `{execution_plan_payload['planSource']}`",
|
|
"",
|
|
"## Selected Tasks",
|
|
]
|
|
if selected_tasks:
|
|
for task_id in selected_tasks:
|
|
execution_lines.append(f"- `{task_id}`")
|
|
else:
|
|
execution_lines.append("- No selected tasks.")
|
|
execution_lines.extend(["", "## Parallel Groups"])
|
|
if review.parallel_groups:
|
|
for group in review.parallel_groups:
|
|
execution_lines.append(f"- `{group.name}`: {', '.join(group.task_ids)}")
|
|
execution_lines.append(f" Reason: {group.reason}")
|
|
else:
|
|
execution_lines.append("- No parallel groups.")
|
|
execution_lines.extend(["", "## Serialization Points"])
|
|
if review.serialization_points:
|
|
for item in review.serialization_points:
|
|
execution_lines.append(f"- `{item['taskId']}`: {'; '.join(item['reasons'])}")
|
|
else:
|
|
execution_lines.append("- No serialization points.")
|
|
paths["execution_plan_md"].write_text("\n".join(execution_lines) + "\n", encoding="utf-8")
|
|
_write_state(project_root, True)
|
|
return {
|
|
"jsonPath": str(json_path),
|
|
"markdownPath": str(markdown_path),
|
|
"executionPlanJsonPath": str(paths["execution_plan_json"]),
|
|
"executionPlanMarkdownPath": str(paths["execution_plan_md"]),
|
|
"parallelGroupCount": len(review.parallel_groups),
|
|
"conflictCount": len(review.conflicts),
|
|
}
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(description="Upgraded AirArc prototype runtime")
|
|
parser.add_argument("--mode", choices=["enter", "status", "parallel-review"], default="status")
|
|
parser.add_argument("--project", default=".")
|
|
parser.add_argument("--todo", default="")
|
|
return parser.parse_args()
|
|
|
|
|
|
def main() -> None:
|
|
args = parse_args()
|
|
project_root = Path(args.project).expanduser().resolve()
|
|
ensure_project_bootstrap(project_root)
|
|
|
|
if args.mode == "enter":
|
|
result = enter_mode(project_root)
|
|
print("airarc_mode=enabled")
|
|
print(f"project_root={project_root}")
|
|
print(f"state_path={result['statePath']}")
|
|
for key, value in result["artifactHealth"].items():
|
|
print(f"{key}={'ok' if value else 'missing'}")
|
|
return
|
|
|
|
if args.mode == "status":
|
|
result = status_mode(project_root)
|
|
print(f"airarc_mode={'enabled' if result.get('enabled') else 'disabled'}")
|
|
print(f"project_root={project_root}")
|
|
for key, value in result["artifactHealth"].items():
|
|
print(f"{key}={'ok' if value else 'missing'}")
|
|
return
|
|
|
|
current_todo_path = Path(args.todo).expanduser().resolve() if args.todo else workflow_todo_path(project_root)
|
|
result = parallel_review_mode(project_root, current_todo_path)
|
|
print("airarc_mode=parallel-reviewed")
|
|
print(f"project_root={project_root}")
|
|
print(f"todo_path={current_todo_path}")
|
|
print(f"json_path={result['jsonPath']}")
|
|
print(f"markdown_path={result['markdownPath']}")
|
|
print(f"execution_plan_json_path={result['executionPlanJsonPath']}")
|
|
print(f"execution_plan_markdown_path={result['executionPlanMarkdownPath']}")
|
|
print(f"parallel_group_count={result['parallelGroupCount']}")
|
|
print(f"conflict_count={result['conflictCount']}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|