From cf841145f5de4942568537de1379e962632bfa57 Mon Sep 17 00:00:00 2001 From: admin Date: Mon, 18 May 2026 11:44:54 +0800 Subject: [PATCH] Initial release: airarc --- .claude-plugin/plugin.json | 42 +++++++ commands/airarc.md | 24 ++++ scripts/airarc_mode.py | 191 +++++++++++++++++++++++++++++++ skills/airarc/SKILL.md | 37 ++++++ skills/airarc/agents/openai.yaml | 3 + 5 files changed, 297 insertions(+) create mode 100644 .claude-plugin/plugin.json create mode 100644 commands/airarc.md create mode 100644 scripts/airarc_mode.py create mode 100644 skills/airarc/SKILL.md create mode 100644 skills/airarc/agents/openai.yaml diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..7a7cde8 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,42 @@ +{ + "name": "airarc", + "version": "0.3.1", + "description": "Experimental upgraded AirArc prototype with built-in post-plan parallelization review support.", + "author": { + "name": "14816", + "email": "noreply@example.com", + "url": "https://airlongdian.fun" + }, + "homepage": "https://airlongdian.fun/plugins/airarc", + "repository": "http://git.airlongdian.fun/admin/airarc.git", + "license": "MIT", + "keywords": [ + "airarc", + "architecture", + "planning", + "parallel", + "review" + ], + "skills": "./skills/", + "interface": { + "displayName": "AirArc", + "shortDescription": "Architecture-first planning with built-in parallel review", + "longDescription": "This AirArc prototype keeps architecture-first planning and adds a built-in post-plan review step that emits dependency edges, parallel-safe groups, shared write-set conflicts, serialization points, and an execution plan for Air Engine.", + "developerName": "14816", + "category": "Productivity", + "capabilities": [ + "Interactive", + "Write" + ], + "websiteURL": "https://airlongdian.fun/plugins/airarc", + "privacyPolicyURL": "https://openai.com/policies/row-privacy-policy/", + "termsOfServiceURL": "https://openai.com/policies/row-terms-of-use/", + "defaultPrompt": [ + "Use AirArc to initialize or inspect project planning context.", + "Use AirArc to produce a post-plan parallelization review from todo.md.", + "Use AirArc to identify dependency edges, shared-write conflicts, and serialization points before workers run." + ], + "brandColor": "#0D9488", + "screenshots": [] + } +} diff --git a/commands/airarc.md b/commands/airarc.md new file mode 100644 index 0000000..9600809 --- /dev/null +++ b/commands/airarc.md @@ -0,0 +1,24 @@ +--- +description: Enter, inspect, or run the upgraded AirArc planning flow with built-in parallel review output. AirArc is architecture-only and must not write code. +argument-hint: [enter|status|parallel-review] +allowed-tools: [Read, Glob, Grep, Bash, Write, Edit] +--- + +# /airarc + +Use the upgraded AirArc plugin for architecture-first planning and post-plan parallel review. AirArc only does architecture planning, task decomposition, and document updates; it does not implement code changes. + +## Steps + +1. Parse `$ARGUMENTS`; default to `enter` when empty. +2. Run the matching mode from the current project root: + +```bash +python "$HOME/plugins/airarc/scripts/airarc_mode.py" --mode --project . +``` + +3. The runtime auto-bootstraps missing `AirPlan/` files on first startup and does not overwrite existing project artifacts. +4. If the request is a planning or architecture-change task, keep `AirPlan/AGENTS.md`, ADRs, C4 module docs, `AirPlan/plan.md`, and `AirPlan/todo.md` aligned with the new AirArc output. +5. Do not write code, apply patches, or implement tasks directly from AirArc; hand confirmed execution work off to AirEng or other execution workflows. +6. When planning needs UI or visual evidence, hand off screenshots or minimal GUI exploration to AirXDB before finalizing the plan. +7. When `parallel-review` runs, record the emitted dependency edges, shared-write conflicts, serialization points, and execution-plan artifacts. diff --git a/scripts/airarc_mode.py b/scripts/airarc_mode.py new file mode 100644 index 0000000..54d1ef3 --- /dev/null +++ b/scripts/airarc_mode.py @@ -0,0 +1,191 @@ +#!/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() diff --git a/skills/airarc/SKILL.md b/skills/airarc/SKILL.md new file mode 100644 index 0000000..e0bce16 --- /dev/null +++ b/skills/airarc/SKILL.md @@ -0,0 +1,37 @@ +--- +name: airarc +description: Architecture-first workflow with built-in post-plan parallelization review. Use when planning should emit dependency edges, parallel groups, write-set conflicts, and serialization points for AirEng. AirArc plans and edits planning docs only; it does not write code. +--- + +# AirArc + +## Upgrade Notes + +- Keep the original architecture-first planning role. +- AirArc is an architect-only workflow: it may plan tasks and edit architecture or planning documents, but it must not implement code changes. +- Add built-in post-plan review instead of a separate review-only plugin. +- Emit engine-consumable execution artifacts after planning. + +## Outputs + +- `AirPlan/state/airarc/state.json` +- `AirPlan/state/airarc/reviews/parallel-review.json` +- `AirPlan/state/airarc/reviews/parallel-review.md` +- `AirPlan/state/airarc/reviews/execution-plan.json` +- `AirPlan/state/airarc/reviews/execution-plan.md` + +## Review Responsibilities + +- Compute dependency edges. +- Compute parallel-safe groups. +- Detect shared write-set conflicts. +- Mark serialization points for global docs and merge boundaries. +- Produce an execution plan that AirEng can prefer directly. + +## Commands + +```bash +python "$HOME/plugins/airarc/scripts/airarc_mode.py" --mode enter --project +python "$HOME/plugins/airarc/scripts/airarc_mode.py" --mode status --project +python "$HOME/plugins/airarc/scripts/airarc_mode.py" --mode parallel-review --project --todo +``` diff --git a/skills/airarc/agents/openai.yaml b/skills/airarc/agents/openai.yaml new file mode 100644 index 0000000..60d5ad0 --- /dev/null +++ b/skills/airarc/agents/openai.yaml @@ -0,0 +1,3 @@ +name: airarc +short_description: Architecture-first planning with built-in parallel review and Air Engine handoff +default_prompt: "Use AirArc to build or refresh architecture context, then emit a post-plan parallel review and execution plan for Air Engine."