Initial release: airarc
This commit is contained in:
42
.claude-plugin/plugin.json
Normal file
42
.claude-plugin/plugin.json
Normal file
@@ -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": []
|
||||||
|
}
|
||||||
|
}
|
||||||
24
commands/airarc.md
Normal file
24
commands/airarc.md
Normal file
@@ -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 <enter|status|parallel-review> --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.
|
||||||
191
scripts/airarc_mode.py
Normal file
191
scripts/airarc_mode.py
Normal file
@@ -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()
|
||||||
37
skills/airarc/SKILL.md
Normal file
37
skills/airarc/SKILL.md
Normal file
@@ -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 <project-root>
|
||||||
|
python "$HOME/plugins/airarc/scripts/airarc_mode.py" --mode status --project <project-root>
|
||||||
|
python "$HOME/plugins/airarc/scripts/airarc_mode.py" --mode parallel-review --project <project-root> --todo <todo-md>
|
||||||
|
```
|
||||||
3
skills/airarc/agents/openai.yaml
Normal file
3
skills/airarc/agents/openai.yaml
Normal file
@@ -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."
|
||||||
Reference in New Issue
Block a user