From 5e1684b73f9684280e2ec6542d981e578cfc7bc2 Mon Sep 17 00:00:00 2001 From: admin Date: Mon, 18 May 2026 11:45:00 +0800 Subject: [PATCH] Initial release: airdo --- .claude-plugin/plugin.json | 42 +++++++++++++++++ commands/airdo.md | 38 ++++++++++++++++ scripts/airdo_mode.py | 80 +++++++++++++++++++++++++++++++++ skills/airdo/SKILL.md | 47 +++++++++++++++++++ skills/airdo/agents/openai.yaml | 3 ++ 5 files changed, 210 insertions(+) create mode 100644 .claude-plugin/plugin.json create mode 100644 commands/airdo.md create mode 100644 scripts/airdo_mode.py create mode 100644 skills/airdo/SKILL.md create mode 100644 skills/airdo/agents/openai.yaml diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..788f1d2 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,42 @@ +{ + "name": "airdo", + "version": "0.5.0", + "description": "AirDo is the public execution plugin for one scoped task slice. It is designed to run standalone or as an isolated AirEng subagent and to finalize structured results into AirPlan.", + "author": { + "name": "14816", + "email": "noreply@example.com", + "url": "https://airlongdian.fun" + }, + "homepage": "https://airlongdian.fun/plugins/airdo", + "repository": "http://git.airlongdian.fun/admin/airdo.git", + "license": "MIT", + "keywords": [ + "airdo", + "executor", + "subagent", + "todo", + "validation" + ], + "skills": "./skills/", + "interface": { + "displayName": "AirDo", + "shortDescription": "Execute one scoped task and finalize a structured result", + "longDescription": "AirDo is the public execution plugin for one narrow task slice. It can be run directly or launched by AirEng as a fully isolated subagent, auto-routes GUI work into AirXDB, auto-routes blockers into AirDbg, and finalizes one structured result in AirPlan for AirEng to merge.", + "developerName": "14816", + "category": "Productivity", + "capabilities": [ + "Interactive", + "Write" + ], + "websiteURL": "https://airlongdian.fun/plugins/airdo", + "privacyPolicyURL": "https://openai.com/policies/row-privacy-policy/", + "termsOfServiceURL": "https://openai.com/policies/row-terms-of-use/", + "defaultPrompt": [ + "Use AirDo to start one scoped task from AirPlan/todo.md and create a structured result template.", + "Use AirDo to execute a handoff in an isolated subagent context and finalize the AirPlan result.", + "Use AirDo to continue from a repair brief until fixed or a real blocker remains." + ], + "brandColor": "#2563EB", + "screenshots": [] + } +} diff --git a/commands/airdo.md b/commands/airdo.md new file mode 100644 index 0000000..ec912e7 --- /dev/null +++ b/commands/airdo.md @@ -0,0 +1,38 @@ +--- +description: Start, inspect, hand off, or finish one scoped AirDo task slice with automatic AirXDB/AirDbg routing and AirPlan result finalization +argument-hint: [enter|status|handoff|finish] +allowed-tools: [Read, Glob, Grep, Bash, Write, Edit] +--- + +# /airdo + +Use AirDo for one narrow execution slice. It can run directly in the parent thread, but it is primarily designed to be launched as an isolated AirEng subagent. + +## Steps + +1. Parse `$ARGUMENTS`; default to `status` when empty. +2. Always operate from the current project root and store worker state under `AirPlan/state/airdo/`. +3. Run the matching mode: + +```bash +python "$HOME/plugins/airdo/scripts/airdo_mode.py" --mode --project . --task-id +``` + +4. For `enter` or `handoff`, load: + - `AirPlan/AGENTS.md` + - `AirPlan/docs/architecture/adr/` + - `AirPlan/docs/architecture/c4/module.md` + - `AirPlan/plan.md` + - `AirPlan/todo.md` + - `AirPlan/state/airdo/tasks//brief.md` + +5. When AirDo is invoked as an AirEng child: + - Treat the session as isolated and rebuild context only from the files above. + - Stay inside the task write scope from the brief/handoff. + - Finalize exactly one structured result under `AirPlan/state/airdo/results/.json`. + - Treat `AirPlan/state/airdo/tasks//worker-state.json` `resultPath` as the canonical pointer to the latest result artifact. Do not assume the task-local template `result.json` is the finalized output. + - Do not stop at "准备实施", implementation-plan-only, or generic progress replies when the task is actionable. Continue editing, validating, and finalizing unless a real blocker or user decision is required. + - When the task changes planning or architecture reality, include concrete `documentUpdates` for `AirPlan/plan.md`, `AirPlan/docs/architecture/adr/`, and `AirPlan/docs/architecture/c4/module.md` instead of leaving those docs stale. + +6. On GUI-like work, route acceptance through AirXDB before finishing. +7. On blockers or failed validation, route through AirDbg, continue through active repair briefs when present, and return one structured result for AirEng to merge. diff --git a/scripts/airdo_mode.py b/scripts/airdo_mode.py new file mode 100644 index 0000000..0f3d195 --- /dev/null +++ b/scripts/airdo_mode.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import argparse +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.worker import enter_worker, finish_worker, handoff_worker, status_worker + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="AirDo public worker runtime") + parser.add_argument("--mode", choices=["enter", "status", "handoff", "finish"], default="status") + parser.add_argument("--project", default=".") + parser.add_argument("--task-id", default="") + parser.add_argument("--result", default="") + return parser.parse_args() + + +def main() -> None: + args = parse_args() + project_root = Path(args.project).expanduser().resolve() + + if args.mode == "status": + status = status_worker(project_root) + print(f"airdo_mode={'enabled' if status['enabled'] else 'disabled'}") + print(f"project_root={project_root}") + print(f"active_task_id={status['activeTaskId']}") + print(f"known_tasks={','.join(status['taskIds'])}") + for key, value in status["artifactHealth"].items(): + print(f"{key}={'ok' if value else 'missing'}") + return + + if not args.task_id: + raise SystemExit("--task-id is required for enter, handoff, and finish modes") + + if args.mode == "enter": + result = enter_worker(project_root, args.task_id) + print("airdo_mode=entered") + print(f"project_root={project_root}") + print(f"task_id={result['taskId']}") + print(f"brief_path={result['briefPath']}") + print(f"handoff_path={result['handoffPath']}") + print(f"result_path={result['resultPath']}") + print(f"worker_state_path={result['workerStatePath']}") + return + + if args.mode == "handoff": + result = handoff_worker(project_root, args.task_id) + print("airdo_mode=handoff-ready") + print(f"project_root={project_root}") + print(f"task_id={result['taskId']}") + print(f"brief_path={result['briefPath']}") + print(f"handoff_path={result['handoffPath']}") + print(f"result_path={result['resultPath']}") + print(f"worker_state_path={result['workerStatePath']}") + return + + result_path = Path(args.result).expanduser().resolve() if args.result else None + finalized = finish_worker(project_root, args.task_id, result_path) + print("airdo_mode=finished") + print(f"project_root={project_root}") + print(f"task_id={finalized['taskId']}") + print(f"task_status={finalized['status']}") + print(f"finalized_result_path={finalized['finalizedResultPath']}") + print(f"worker_state_path={finalized['workerStatePath']}") + + +if __name__ == "__main__": + main() diff --git a/skills/airdo/SKILL.md b/skills/airdo/SKILL.md new file mode 100644 index 0000000..87c0b79 --- /dev/null +++ b/skills/airdo/SKILL.md @@ -0,0 +1,47 @@ +--- +name: airdo +description: Public Air executor for one scoped todo slice. Use it standalone or as an isolated AirEng subagent and finalize the result into AirPlan. +--- + +# AirDo + +## Role + +- Execute one task or one very small implementation slice. +- Keep AirDo execution guarantees for context loading, evidence, and validation. +- Finalize one structured result package in `AirPlan/state/airdo/results/`. +- Act as the standard AirEng child executor when work is delegated into isolated subagents. + +## Inputs + +- `AirPlan/AGENTS.md` +- `AirPlan/docs/architecture/adr/` +- `AirPlan/docs/architecture/c4/module.md` +- `AirPlan/plan.md` +- `AirPlan/todo.md` +- `AirPlan/state/airdo/tasks//brief.md` +- `AirPlan/state/airdo/tasks//subagent-handoff.md` when launched by AirEng + +## Result Rules + +- Finalize one `result.json` per task. +- Treat `AirPlan/state/airdo/tasks//worker-state.json` `resultPath` as the canonical pointer to the latest result artifact. The task-local `result.json` is only the editable template before finalize. +- Include validations, evidence, risks, blockers, and document updates when needed. +- Do not edit global `AirPlan/todo.md`, `AirPlan/AGENTS.md`, ADR, or C4 files directly unless explicitly delegated through `documentUpdates`. +- If the task changes execution planning or architecture reality, include concrete `documentUpdates` so AirEng can keep `todo`, `plan`, ADR, and C4 synchronized during merge. + +## Automatic Routing + +- On `blocked` results, auto-request AirDbg before finalize. +- On GUI or visual work, auto-request AirXDB before finalize. +- If AirEng queued an active repair attempt, continue repairing automatically instead of stopping at the first blocker. +- Do not stop at implementation-prep or progress-only updates when the task is actionable. Continue until finalize unless a real blocker or explicit user decision is required. + +## Commands + +```bash +python "$HOME/plugins/airdo/scripts/airdo_mode.py" --mode enter --project --task-id T-001 +python "$HOME/plugins/airdo/scripts/airdo_mode.py" --mode status --project +python "$HOME/plugins/airdo/scripts/airdo_mode.py" --mode handoff --project --task-id T-001 +python "$HOME/plugins/airdo/scripts/airdo_mode.py" --mode finish --project --task-id T-001 +``` diff --git a/skills/airdo/agents/openai.yaml b/skills/airdo/agents/openai.yaml new file mode 100644 index 0000000..8c76a64 --- /dev/null +++ b/skills/airdo/agents/openai.yaml @@ -0,0 +1,3 @@ +name: airdo +short_description: Public Air executor for one scoped task, validation evidence, and AirPlan result finalization +default_prompt: "Use AirDo to execute one task, gather validation evidence, auto-route GUI or debug work, and finalize a structured result in AirPlan for AirEng to merge. Do not stop at implementation-prep or progress-only updates when the task is actionable; continue until finalize unless a real blocker or explicit user decision is required."