chore: push all design docs, V2 plan specs, and current working state

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>
This commit is contained in:
AirCoding
2026-06-12 17:12:29 +08:00
parent 8f55c962bb
commit ae44be31d5
364 changed files with 46779 additions and 2812 deletions

View File

@@ -0,0 +1,372 @@
from __future__ import annotations
import json
from pathlib import Path
from typing import Dict, List
from .airxdb_runtime import ensure_xdb_sessions_for_result, task_requires_xdb
from .contracts import (
DocumentUpdate,
WorkerResult,
default_worker_result,
now_iso,
required_project_artifacts,
)
from .debug_runtime import ensure_debug_sessions_for_result
from .doc_sync import enforce_doc_sync_requirements
from .paths import (
agents_path,
airdo_root,
architecture_adr_dir,
architecture_c4_module_path,
plan_path,
todo_path,
)
from .repair_runtime import load_active_repair_attempt
from .todo_parser import find_task, parse_tasks
def _json_dump(path: Path, payload: Dict[str, object]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
def _artifact_health(project_root: Path) -> Dict[str, bool]:
return {
relative: (project_root / relative).exists()
for relative in required_project_artifacts()
}
def _paths(project_root: Path) -> Dict[str, Path]:
worker_root = airdo_root(project_root)
return {
"root": worker_root,
"state": worker_root / "state.json",
"tasks": worker_root / "tasks",
"results": worker_root / "results",
}
def _ensure_layout(project_root: Path) -> Dict[str, Path]:
paths = _paths(project_root)
paths["tasks"].mkdir(parents=True, exist_ok=True)
paths["results"].mkdir(parents=True, exist_ok=True)
return paths
def _task_dir(project_root: Path, task_id: str) -> Path:
return _paths(project_root)["tasks"] / task_id
def worker_state_path(project_root: Path, task_id: str) -> Path:
return _task_dir(project_root, task_id) / "worker-state.json"
def _load_task_record(project_root: Path, task_id: str):
current_todo = todo_path(project_root)
if not current_todo.exists():
return None
try:
return find_task(parse_tasks(current_todo), task_id)
except ValueError:
return None
def _worker_rules_block() -> List[str]:
return [
"## Worker Rules",
"",
"- Load `AirPlan/AGENTS.md`, `AirPlan/docs/architecture/adr/`, `AirPlan/docs/architecture/c4/module.md`, `AirPlan/plan.md`, and `AirPlan/todo.md` before doing work.",
"- Keep the task scoped to this brief.",
"- Preserve validation evidence on disk.",
"- Do not directly take ownership of global `AirPlan/todo.md`, `AirPlan/AGENTS.md`, ADR, or C4 updates unless explicitly delegated.",
"- If this task touches global docs, `result.json` must include executable `documentUpdates`, not just recommendations.",
"- If this task is GUI or visual acceptance related, `result.json` must end with successful AirXDB evidence before it can close as done.",
"- If the result is blocked, or a validation ends in failed/error, the worker auto-requests AirDbg before finalize.",
"- If the task is GUI-related, the worker auto-captures AirXDB evidence before finalize.",
"- If an active auto-repair attempt exists, continue repairing immediately instead of stopping at the debug request.",
"- Do not stop at an 'about to implement', 'implementation plan ready', or similar midpoint status. Continue editing, validating, and finalizing unless a real blocker or user decision is required.",
"- Do not return only a progress update when the task is actionable. Return only after finalize, or after recording a concrete blocked reason that needs intervention.",
"- Fill `result.json`, then finalize it for engine merge.",
"",
]
def _placeholder_result(project_root: Path, task_id: str) -> WorkerResult:
task_summary = ""
task = _load_task_record(project_root, task_id)
if task:
task_summary = task.task
result = default_worker_result(task_id, task_summary)
if task and task.global_doc_paths:
result.global_doc_paths = list(task.global_doc_paths)
result.recommend_global_doc_updates = list(task.global_doc_paths)
result.document_updates = []
for doc_path in task.global_doc_paths:
if doc_path == "AirPlan/docs/architecture/adr/":
result.document_updates.append(
DocumentUpdate(
path="AirPlan/docs/architecture/adr/ADR-XXXX-task-sync.md",
action="create_file",
content=(
"# ADR-XXXX: task-sync\n\n"
"- Status: Accepted\n"
"- Date: YYYY-MM-DD\n\n"
"## Context\n"
"Replace with the concrete context introduced by this task.\n\n"
"## Decision\n"
"Replace with the concrete decision introduced by this task.\n\n"
"## Consequences\n"
"- Replace with the concrete consequences introduced by this task.\n"
),
)
)
else:
result.document_updates.append(
DocumentUpdate(
path=doc_path,
action="replace_block",
marker=f"{task_id}-{Path(doc_path).name}".replace(".", "-").upper(),
content=(
f"## Sync For {task_id}\n\n"
"- Summary: Replace with a concrete summary.\n"
"- Code Reality: Replace with the actual code outcome.\n"
"- Validation: Replace with the actual validation result.\n"
),
)
)
return result
def _is_untouched_placeholder_result(project_root: Path, result: WorkerResult) -> bool:
placeholder = _placeholder_result(project_root, result.task_id)
return result.to_dict() == placeholder.to_dict()
def resolve_worker_result_path(project_root: Path, task_id: str) -> Path:
state_path = worker_state_path(project_root, task_id)
if state_path.exists():
payload = json.loads(state_path.read_text(encoding="utf-8-sig"))
raw_path = str(payload.get("resultPath", "")).strip()
if raw_path:
candidate = Path(raw_path).expanduser()
if not candidate.is_absolute():
candidate = (project_root / candidate).resolve()
return candidate
return _task_dir(project_root, task_id) / "result.json"
def _write_brief(project_root: Path, task_id: str) -> Path:
task_folder = _task_dir(project_root, task_id)
task_folder.mkdir(parents=True, exist_ok=True)
task = _load_task_record(project_root, task_id)
active_repair = load_active_repair_attempt(project_root, task_id)
lines: List[str] = [f"# Worker Brief: {task_id}", ""]
if task:
requires_xdb = task_requires_xdb(task, None)
lines.extend(
[
f"- Module: `{task.module}`",
f"- Status In TODO: `{task.status}`",
f"- Task: {task.task}",
f"- Write Scope: {', '.join(f'`{path}`' for path in task.write_paths) or '`(not declared)`'}",
f"- Global Doc Paths: {', '.join(f'`{path}`' for path in task.global_doc_paths) or '`none`'}",
f"- Validation: {task.validation or '(not declared)'}",
f"- Document Sync Required: {'yes' if task.global_doc_paths else 'no'}",
f"- AirXDB Required: {'yes' if requires_xdb else 'no'}",
"",
]
)
if active_repair:
lines.extend(
[
"## Active Auto Repair",
"",
f"- Repair ID: `{active_repair.repair_id}`",
f"- Attempt Index: `{active_repair.attempt_index}`",
f"- Status: `{active_repair.status}`",
f"- Reason: {active_repair.reason}",
f"- Repair Brief: `{active_repair.repair_brief_path}`",
f"- Debug Sessions: {', '.join(f'`{item}`' for item in active_repair.debug_session_ids) or '`none`'}",
"",
]
)
lines.extend(_worker_rules_block())
brief_path = task_folder / "brief.md"
brief_path.write_text("\n".join(lines), encoding="utf-8")
return brief_path
def _write_handoff(project_root: Path, task_id: str, brief_path: Path, result_path: Path) -> Path:
task = _load_task_record(project_root, task_id)
current_worker_state_path = worker_state_path(project_root, task_id)
handoff_path = _task_dir(project_root, task_id) / "subagent-handoff.md"
lines = [
f"# AirDo Subagent Handoff: {task_id}",
"",
"You are an isolated AirDo execution subagent launched by AirEng.",
"",
f"- Task ID: `{task_id}`",
f"- Project Root: `{project_root}`",
f"- Brief Path: `{brief_path}`",
f"- Worker State Path: `{current_worker_state_path}`",
f"- Template Result Path: `{result_path}`",
f"- Task Summary: {task.task if task else '(load from brief)'}",
f"- Write Scope: {', '.join(f'`{path}`' for path in (task.write_paths if task else [])) or '`(load from brief)`'}",
"",
"## Required Reads",
"",
f"- `{agents_path(project_root)}`",
f"- `{architecture_adr_dir(project_root)}`",
f"- `{architecture_c4_module_path(project_root)}`",
f"- `{plan_path(project_root)}`",
f"- `{todo_path(project_root)}`",
f"- `{brief_path}`",
"",
"## Execution Contract",
"",
"- Stay inside this task scope and its declared write set.",
"- Do not assume the parent thread history is available; build context from the files above.",
"- Execute the task, gather validation evidence, and update `result.json` with honest status, files changed, risks, blockers, and document updates when required.",
"- Run AirDbg or AirXDB automatically when the runtime rules require them.",
"- Do not pause for intermediate implementation-status replies. Keep going until the task is finalized unless you hit a real blocker that requires external input.",
"- Finalize the result before returning control to AirEng.",
"",
"## Finalize Command",
"",
f"`python \"$HOME/plugins/airdo/scripts/airdo_mode.py\" --mode finish --project . --task-id {task_id}`",
"",
"## Return Contract",
"",
"- Report the final status and the finalized result path.",
"- After `finish`, treat `worker-state.json` `resultPath` as the canonical result location instead of re-reading the template `result.json`.",
"- Do not merge global docs yourself unless the task explicitly delegated document updates through `result.json`.",
"",
]
handoff_path.write_text("\n".join(lines), encoding="utf-8")
return handoff_path
def enter_worker(project_root: Path, task_id: str) -> Dict[str, object]:
paths = _ensure_layout(project_root)
task_folder = _task_dir(project_root, task_id)
task_folder.mkdir(parents=True, exist_ok=True)
result_path = task_folder / "result.json"
if not result_path.exists():
result = _placeholder_result(project_root, task_id)
_json_dump(result_path, result.to_dict())
brief_path = _write_brief(project_root, task_id)
handoff_path = _write_handoff(project_root, task_id, brief_path, result_path)
state_path = worker_state_path(project_root, task_id)
state = {
"enabled": True,
"updatedAt": now_iso(),
"projectRoot": str(project_root),
"artifactHealth": _artifact_health(project_root),
"activeTaskId": task_id,
}
_json_dump(paths["state"], state)
_json_dump(
state_path,
{
"taskId": task_id,
"status": "entered",
"enteredAt": now_iso(),
"templateResultPath": str(result_path),
"resultPath": str(result_path),
"briefPath": str(brief_path),
"handoffPath": str(handoff_path),
},
)
return {
"taskId": task_id,
"briefPath": str(brief_path),
"handoffPath": str(handoff_path),
"resultPath": str(result_path),
"workerStatePath": str(state_path),
}
def handoff_worker(project_root: Path, task_id: str) -> Dict[str, object]:
entered = enter_worker(project_root, task_id)
return {
"taskId": task_id,
"briefPath": entered["briefPath"],
"handoffPath": entered["handoffPath"],
"resultPath": entered["resultPath"],
"workerStatePath": entered["workerStatePath"],
}
def finish_worker(project_root: Path, task_id: str, result_path: Path | None) -> Dict[str, object]:
_ensure_layout(project_root)
task_folder = _task_dir(project_root, task_id)
if result_path is None:
result_path = task_folder / "result.json"
result = WorkerResult.from_dict(json.loads(result_path.read_text(encoding="utf-8-sig")))
if _is_untouched_placeholder_result(project_root, result):
raise ValueError(
"worker result is still the untouched default template; update result.json before finalize"
)
result.validate_for_finalize()
ensure_xdb_sessions_for_result(project_root, result, "worker-finish")
ensure_debug_sessions_for_result(project_root, result, "worker-finish")
result.validate_for_finalize()
enforce_doc_sync_requirements(project_root, result)
if result.task_id != task_id:
raise ValueError("result taskId does not match --task-id")
if not result.finalized_at:
result.finalized_at = now_iso()
finalized_path = _paths(project_root)["results"] / f"{task_id}.json"
_json_dump(finalized_path, result.to_dict())
previous_state: Dict[str, object] = {}
current_state_path = worker_state_path(project_root, task_id)
if current_state_path.exists():
previous_state = json.loads(current_state_path.read_text(encoding="utf-8-sig"))
_json_dump(
current_state_path,
{
"taskId": task_id,
"status": "completed",
"enteredAt": previous_state.get("enteredAt", ""),
"briefPath": previous_state.get("briefPath", ""),
"handoffPath": previous_state.get("handoffPath", ""),
"templateResultPath": previous_state.get("templateResultPath", str(task_folder / "result.json")),
"finalizedAt": result.finalized_at,
"resultPath": str(finalized_path),
},
)
return {
"taskId": task_id,
"status": result.status,
"finalizedResultPath": str(finalized_path),
"workerStatePath": str(current_state_path),
}
def status_worker(project_root: Path) -> Dict[str, object]:
paths = _ensure_layout(project_root)
state_path = paths["state"]
enabled = state_path.exists()
active_task_id = ""
if enabled:
payload = json.loads(state_path.read_text(encoding="utf-8-sig"))
active_task_id = str(payload.get("activeTaskId", ""))
task_ids = sorted(path.name for path in paths["tasks"].iterdir() if path.is_dir())
return {
"enabled": enabled,
"projectRoot": str(project_root),
"artifactHealth": _artifact_health(project_root),
"activeTaskId": active_task_id,
"taskIds": task_ids,
}