Skill: 18816132863/xiaoyi-claw-omega-final (version 10.9.0)

# 🦊鸽子王 V10.9.0 Executive Personal OS Agent 六层架构核心引擎，统一入口、三条主链、自动运行机制 ## 简介 这是 V10.9.0 Executive Personal OS Agent 完整版，包含六层架构核心代码、275+ 技能生态、自动运行机制、增强版巡检系统。 ### 核心特性 - **六层架构**: Core → Memory Context → Orchestration → Execution → Governance → Infrastructure - **三条主链**: 生命周期主链、恢复链主链、Metrics反哺主链 - **统一入口**: 策略引擎.评估策略()、技能路由器.选择技能()、工作流引擎.运行工作流() - **自动运行**: Git钩子、守护进程管理器、心跳执行器 - **增强巡检**: 并行执行、自动修复、11项检查 ## 六层架构 ### 第一层：核心层 (Core) - 认知系统（推理、决策、规划、反思、学习） - 事件系统（事件总线、事件类型） - 状态契约（全局、配置、任务） - 查询处理（理解、重写、语言检测） ### 第二层：记忆上下文层 (Memory Context) - 上下文构建（优先级排序、冲突解决） - 检索系统（混合搜索、重排序） - 会话管理（历史、状态） - 向量存储（4096维嵌入） ### 第三层：编排层 (Orchestration) - 工作流引擎（DAG构建、依赖解析） - 执行控制（回退策略、回滚管理、重试策略） - 状态管理（检查点存储） ### 第四层：执行层 (Execution) - 技能路由器、加载器、沙箱、审计、网关 - 技能生命周期管理 - 技能策略（预算、风险、权限） ### 第五层：治理层 (Governance) - 策略引擎（统一入口） - 预算管理（Token、成本） - 风险管理（分类器、高风控） - 权限管理、评估聚合 ### 第六层：基础设施层 (Infrastructure) - 守护进程管理器 - 自动Git同步 - 融合引擎 - 自动化模块 ## 版本演进 ### V10.9.0 Executive Personal OS Agent - Executive OS - 执行层操作系统 - Executive Governance - 执行治理 - 增强版巡检系统 V2.0 ### V10.6.0 Reality Connected OS - 现实连接操作系统 - 授权与执行检查 ### V10.5.0 Continuous OS - 持续运行操作系统 - 隐私与运维检查 ### V10.4.0 Strategic OS - 战略操作系统 - 执行契约检查 ### V10.3.0 Proactive Self-Extending OS - 主动感知用户需求 - 能力自动获取 ### V10.2.0 Autonomous Runtime - 自主编排执行 - 运行时门禁 ### V10.1.0 Self-Evolving Personal OS - 自进化个人OS代理 - 闭环验证系统 ## 验证命令 ```bash # 增强版巡检 python scripts/enhanced_inspection_v2.py # 极限自检 python scripts/run_v10_extreme_self_test.py --internal-only # 完美之门 python scripts/check_v10_perfection_gate.py # 全量测试 python -m pytest -q ``` ## 版本信息 - **版本**: V10.9.0 - **发布日期**: 2026-04-26 - **技能ID**: k977z2jr14tqanspkysfkk1bhh84hvqw - **ClawHub**: xiaoyi-claw-omega-final - **作者**: 18816132863 - **测试结果**: 867 passed, 11 skipped

path: application/response_service/__init__.py
content: """响应服务模块"""

from .renderer import ResponseRenderer
from .evidence_formatter import EvidenceFormatter

__all__ = ['ResponseRenderer', 'EvidenceFormatter']


path: application/response_service/evidence_formatter.py
content: #!/usr/bin/env python3
"""证据格式化器 - 将执行结果转换为可读证据"""

from typing import Dict, List, Any, Optional
from dataclasses import dataclass
from enum import Enum


class EvidenceType(Enum):
    """证据类型"""
    FILE = "file"
    DB_RECORD = "db_record"
    MESSAGE = "message"
    CONTENT = "content"
    TRACE = "trace"
    NONE = "none"


@dataclass
class Evidence:
    """证据"""
    type: EvidenceType
    description: str
    value: Any
    verified: bool = False


class EvidenceFormatter:
    """证据格式化器"""
    
    def __init__(self):
        self.evidences: List[Evidence] = []
    
    def add_file_evidence(self, path: str, exists: bool, size: int = 0) -> Evidence:
        """添加文件证据"""
        evidence = Evidence(
            type=EvidenceType.FILE,
            description=f"文件: {path}",
            value={"path": path, "exists": exists, "size": size},
            verified=exists
        )
        self.evidences.append(evidence)
        return evidence
    
    def add_db_evidence(self, table: str, record_id: str, fields: Dict[str, Any]) -> Evidence:
        """添加数据库记录证据"""
        evidence = Evidence(
            type=EvidenceType.DB_RECORD,
            description=f"数据库记录: {table}.{record_id}",
            value={"table": table, "id": record_id, "fields": fields},
            verified=True
        )
        self.evidences.append(evidence)
        return evidence
    
    def add_message_evidence(self, channel: str, message_id: str, content_preview: str) -> Evidence:
        """添加消息证据"""
        evidence = Evidence(
            type=EvidenceType.MESSAGE,
            description=f"消息: {channel}/{message_id}",
            value={"channel": channel, "id": message_id, "preview": content_preview},
            verified=bool(message_id)
        )
        self.evidences.append(evidence)
        return evidence
    
    def add_content_evidence(self, content_type: str, content: str, length: int) -> Evidence:
        """添加内容证据"""
        evidence = Evidence(
            type=EvidenceType.CONTENT,
            description=f"生成内容: {content_type} ({length}字)",
            value={"type": content_type, "content": content[:500], "length": length},
            verified=length > 0
        )
        self.evidences.append(evidence)
        return evidence
    
    def add_trace_evidence(self, steps: List[Dict[str, Any]]) -> Evidence:
        """添加执行轨迹证据"""
        evidence = Evidence(
            type=EvidenceType.TRACE,
            description=f"执行轨迹: {len(steps)}步",
            value={"steps": steps},
            verified=len(steps) > 0
        )
        self.evidences.append(evidence)
        return evidence
    
    def has_verified_evidence(self) -> bool:
        """是否有已验证的证据"""
        return any(e.verified for e in self.evidences)
    
    def format_evidences(self) -> List[Dict[str, Any]]:
        """格式化证据列表"""
        return [
            {
                "type": e.type.value,
                "description": e.description,
                "verified": e.verified,
                "value": e.value if e.verified else None
            }
            for e in self.evidences
        ]
    
    def format_summary(self) -> str:
        """格式化证据摘要"""
        if not self.evidences:
            return "无证据"
        
        verified = [e for e in self.evidences if e.verified]
        unverified = [e for e in self.evidences if not e.verified]
        
        lines = []
        if verified:
            lines.append(f"✅ 已验证证据 ({len(verified)}):")
            for e in verified:
                lines.append(f"  - {e.description}")
        
        if unverified:
            lines.append(f"⚠️ 未验证证据 ({len(unverified)}):")
            for e in unverified:
                lines.append(f"  - {e.description}")
        
        return "\n".join(lines)
    
    def clear(self):
        """清空证据"""
        self.evidences.clear()


path: application/response_service/renderer.py
content: #!/usr/bin/env python3
"""响应渲染器 - 将内部结构化结果渲染成可读回答"""

from typing import Dict, List, Any, Optional
from dataclasses import dataclass
from .evidence_formatter import EvidenceFormatter, EvidenceType


@dataclass
class RenderedResponse:
    """渲染后的响应"""
    status: str  # success / failed / partial
    summary: str  # 给用户看的总结
    completed_items: List[str]  # 完成项
    incomplete_items: List[str]  # 未完成项
    evidences: List[Dict[str, Any]]  # 证据
    next_steps: List[str]  # 下一步建议
    raw_data: Optional[Dict[str, Any]] = None  # 原始数据


class ResponseRenderer:
    """响应渲染器"""
    
    def __init__(self):
        self.evidence_formatter = EvidenceFormatter()
    
    def render(
        self,
        execution_trace: List[Dict[str, Any]],
        subtasks: List[Dict[str, Any]],
        results: Dict[str, Any],
        intent: str
    ) -> RenderedResponse:
        """渲染响应"""
        
        # 1. 分析执行结果
        completed = []
        incomplete = []
        has_error = False
        
        for subtask in subtasks:
            subtask_id = subtask.get("id", "")
            status = subtask.get("status", "pending")
            skill = subtask.get("skill")
            error = subtask.get("error")
            
            if status == "success" and skill:
                completed.append(f"✅ {subtask_id}: {skill}")
            elif status == "failed":
                has_error = True
                incomplete.append(f"❌ {subtask_id}: {error or '执行失败'}")
            elif status == "pending":
                incomplete.append(f"⏳ {subtask_id}: 未执行")
        
        # 2. 提取证据
        evidences = self._extract_evidences(results, execution_trace)
        
        # 3. 判断整体状态
        if not completed and not incomplete:
            status = "failed"
            summary = f"任务未执行: {intent}"
        elif has_error and not completed:
            status = "failed"
            summary = f"任务失败: {intent}"
        elif incomplete:
            status = "partial"
            summary = f"部分完成: {intent}"
        else:
            status = "success"
            summary = f"任务完成: {intent}"
        
        # 4. 生成下一步建议
        next_steps = self._suggest_next_steps(status, intent, incomplete)
        
        # 5. 生成总结
        summary = self._generate_summary(status, intent, completed, incomplete, evidences)
        
        return RenderedResponse(
            status=status,
            summary=summary,
            completed_items=completed,
            incomplete_items=incomplete,
            evidences=evidences,
            next_steps=next_steps,
            raw_data={
                "execution_trace": execution_trace,
                "results": results
            }
        )
    
    def _extract_evidences(
        self,
        results: Dict[str, Any],
        execution_trace: List[Dict[str, Any]]
    ) -> List[Dict[str, Any]]:
        """从结果中提取证据"""
        evidences = []
        
        for task_id, result in results.items():
            if not isinstance(result, dict):
                continue
            
            # 文件证据
            if "file_path" in result or "output_file" in result:
                path = result.get("file_path") or result.get("output_file")
                evidences.append({
                    "type": "file",
                    "description": f"文件: {path}",
                    "verified": True,
                    "value": path
                })
            
            # 数据库记录证据
            if "record_id" in result or "task_id" in result:
                record_id = result.get("record_id") or result.get("task_id")
                evidences.append({
                    "type": "db_record",
                    "description": f"记录ID: {record_id}",
                    "verified": True,
                    "value": record_id
                })
            
            # 消息证据
            if "message_id" in result:
                evidences.append({
                    "type": "message",
                    "description": f"消息ID: {result['message_id']}",
                    "verified": True,
                    "value": result["message_id"]
                })
            
            # 内容证据
            if "content" in result or "text" in result:
                content = result.get("content") or result.get("text", "")
                evidences.append({
                    "type": "content",
                    "description": f"生成内容: {len(content)}字",
                    "verified": len(content) > 0,
                    "value": content[:200] if content else None
                })
        
        # 执行轨迹证据
        if execution_trace:
            evidences.append({
                "type": "trace",
                "description": f"执行轨迹: {len(execution_trace)}步",
                "verified": True,
                "value": execution_trace
            })
        
        return evidences
    
    def _generate_summary(
        self,
        status: str,
        intent: str,
        completed: List[str],
        incomplete: List[str],
        evidences: List[Dict[str, Any]]
    ) -> str:
        """生成总结"""
        lines = []
        
        # 状态
        if status == "success":
            lines.append(f"✅ {intent} 完成")
        elif status == "partial":
            lines.append(f"⚠️ {intent} 部分完成")
        else:
            lines.append(f"❌ {intent} 失败")
        
        # 完成项
        if completed:
            lines.append(f"\n【完成项】({len(completed)})")
            for item in completed:
                lines.append(f"  {item}")
        
        # 未完成项
        if incomplete:
            lines.append(f"\n【未完成项】({len(incomplete)})")
            for item in incomplete:
                lines.append(f"  {item}")
        
        # 证据
        verified_evidences = [e for e in evidences if e.get("verified")]
        if verified_evidences:
            lines.append(f"\n【证据】({len(verified_evidences)})")
            for e in verified_evidences:
                lines.append(f"  - {e['description']}")
        
        return "\n".join(lines)
    
    def _suggest_next_steps(
        self,
        status: str,
        intent: str,
        incomplete: List[str]
    ) -> List[str]:
        """建议下一步"""
        steps = []
        
        if status == "failed":
            steps.append("检查错误信息，确认失败原因")
            steps.append("修正后重试")
        elif status == "partial":
            steps.append("检查未完成项")
            for item in incomplete:
                if "未执行" in item:
                    steps.append(f"执行: {item}")
        else:
            steps.append("任务已完成，可以进行下一步操作")
        
        return steps
    
    def to_dict(self, response: RenderedResponse) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "status": response.status,
            "summary": response.summary,
            "completed_items": response.completed_items,
            "incomplete_items": response.incomplete_items,
            "evidences": response.evidences,
            "next_steps": response.next_steps
        }
    
    def to_user_message(self, response: RenderedResponse) -> str:
        """转换为用户可读消息"""
        return response.summary


path: application/response_service/response_schema.py
content: #!/usr/bin/env python3
"""响应 Schema - V1.0.0

定义统一的响应结构。
"""

from typing import Dict, List, Any, Optional
from dataclasses import dataclass, field, asdict
from enum import Enum


class ResponseStatus(Enum):
    """响应状态"""
    SUCCESS = "success"
    FAILED = "failed"
    PARTIAL = "partial"


@dataclass
class EvidenceSchema:
    """证据结构"""
    files: List[Dict[str, Any]] = field(default_factory=list)
    db_records: List[Dict[str, Any]] = field(default_factory=list)
    messages: List[Dict[str, Any]] = field(default_factory=list)
    tool_calls: List[Dict[str, Any]] = field(default_factory=list)
    extra: Dict[str, Any] = field(default_factory=dict)
    
    def is_empty(self) -> bool:
        """检查是否为空"""
        return not any([
            self.files,
            self.db_records,
            self.messages,
            self.tool_calls,
            self.extra
        ])
    
    def count(self) -> int:
        """统计证据数量"""
        return (
            len(self.files) +
            len(self.db_records) +
            len(self.messages) +
            len(self.tool_calls) +
            len(self.extra)
        )
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return asdict(self)


@dataclass
class ErrorSchema:
    """错误结构"""
    code: str
    message: str
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return asdict(self)


@dataclass
class FinalResponse:
    """最终响应结构"""
    status: str  # success / failed
    reason: str = ""
    user_response: str = ""
    completed_items: List[str] = field(default_factory=list)
    failed_items: List[str] = field(default_factory=list)
    evidence: EvidenceSchema = field(default_factory=EvidenceSchema)
    next_action: str = ""
    execution_trace: List[Dict[str, Any]] = field(default_factory=list)
    task_id: str = ""
    intent: str = ""
    total_latency_ms: float = 0.0
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "status": self.status,
            "reason": self.reason,
            "user_response": self.user_response,
            "completed_items": self.completed_items,
            "failed_items": self.failed_items,
            "evidence": self.evidence.to_dict() if isinstance(self.evidence, EvidenceSchema) else self.evidence,
            "next_action": self.next_action,
            "execution_trace": self.execution_trace,
            "task_id": self.task_id,
            "intent": self.intent,
            "total_latency_ms": self.total_latency_ms
        }
    
    def validate(self) -> bool:
        """验证响应是否合法"""
        # user_response 必须非空
        if not self.user_response or not self.user_response.strip():
            return False
        
        # success 时 evidence 必须非空
        if self.status == "success" and self.evidence.is_empty():
            return False
        
        # failed 时 failed_items 必须非空
        if self.status == "failed" and not self.failed_items:
            return False
        
        # next_action 必须非空
        if not self.next_action:
            return False
        
        return True


@dataclass
class SkillResultSchema:
    """技能返回结构"""
    success: bool
    data: Dict[str, Any] = field(default_factory=dict)
    error: Optional[ErrorSchema] = None
    evidence: EvidenceSchema = field(default_factory=EvidenceSchema)
    user_summary: str = ""
    machine_summary: str = ""
    artifacts: List[str] = field(default_factory=list)
    verification_hint: str = ""
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "success": self.success,
            "data": self.data,
            "error": self.error.to_dict() if self.error else None,
            "evidence": self.evidence.to_dict(),
            "user_summary": self.user_summary,
            "machine_summary": self.machine_summary,
            "artifacts": self.artifacts,
            "verification_hint": self.verification_hint
        }


path: application/task_service/__init__.py
content: # application/task_service/__init__.py
"""
任务服务模块
"""

from .service import TaskService
from .scheduler import SchedulerService

__all__ = ["TaskService", "SchedulerService"]


path: application/task_service/scheduler.py
content: # application/task_service/scheduler.py
"""
调度服务 V1.0.0

职责：
- 扫描到期任务
- 投递任务到队列
- 管理调度状态
"""

import asyncio
from typing import Optional, List, Dict, Any
from datetime import datetime
from pathlib import Path

import sys
sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent))

from domain.tasks import TaskStatus, TriggerMode
from infrastructure.storage.repositories.sqlite_repo import SQLiteTaskRepository


class SchedulerService:
    """调度服务"""
    
    def __init__(self, task_repo: Optional[SQLiteTaskRepository] = None):
        self.task_repo = task_repo or SQLiteTaskRepository()
        self.root = Path(__file__).resolve().parent.parent.parent
    
    async def scan_and_dispatch(self) -> Dict[str, Any]:
        """扫描到期任务并投递"""
        now = datetime.now()
        
        # 查询待执行的定时任务
        tasks = await self.task_repo.list_pending_scheduled(now, limit=100)
        
        dispatched = 0
        errors = []
        
        for task in tasks:
            try:
                # 获取锁
                locked = await self.task_repo.acquire_lock(task.task_id, lock_ttl=60)
                if not locked:
                    continue
                
                try:
                    # 更新状态为已入队
                    await self.task_repo.update(task.task_id, {
                        "status": TaskStatus.QUEUED.value
                    })
                    
                    # 写入执行队列
                    await self._write_to_queue(task.task_id)
                    
                    dispatched += 1
                
                finally:
                    await self.task_repo.release_lock(task.task_id)
            
            except Exception as e:
                errors.append({
                    "task_id": task.task_id,
                    "error": str(e)
                })
        
        return {
            "scanned": len(tasks),
            "dispatched": dispatched,
            "errors": errors
        }
    
    async def _write_to_queue(self, task_id: str):
        """写入执行队列"""
        import json
        
        queue_file = self.root / "data" / "task_queue.jsonl"
        queue_file.parent.mkdir(parents=True, exist_ok=True)
        
        entry = {
            "task_id": task_id,
            "queued_at": datetime.now().isoformat(),
            "status": "pending"
        }
        
        with open(queue_file, 'a', encoding='utf-8') as f:
            f.write(json.dumps(entry, ensure_ascii=False) + '\n')
    
    async def get_pending_count(self) -> int:
        """获取待执行任务数量"""
        queue_file = self.root / "data" / "task_queue.jsonl"
        
        if not queue_file.exists():
            return 0
        
        import json
        count = 0
        with open(queue_file, 'r', encoding='utf-8') as f:
            for line in f:
                try:
                    entry = json.loads(line.strip())
                    if entry.get("status") == "pending":
                        count += 1
                except:
                    pass
        
        return count


path: application/task_service/service.py
content: """
任务服务 V1.0.0

职责：
- 创建任务
- 校验任务
- 持久化任务
- 查询任务
- 取消/暂停/恢复任务
"""

import uuid
from typing import Optional, List, Dict, Any
from datetime import datetime

from domain.tasks import (
    TaskSpec,
    TaskStatus,
    TriggerMode,
    EventType,
)
from infrastructure.storage.repositories import (
    SQLiteTaskRepository,
    SQLiteTaskEventRepository,
)


class TaskService:
    """任务服务"""
    
    def __init__(
        self,
        task_repo: Optional[SQLiteTaskRepository] = None,
        event_repo: Optional[SQLiteTaskEventRepository] = None
    ):
        self.task_repo = task_repo or SQLiteTaskRepository()
        self.event_repo = event_repo or SQLiteTaskEventRepository()
    
    async def create_task(self, spec: TaskSpec) -> Dict[str, Any]:
        """
        创建任务
        
        流程：
        1. 校验规格
        2. 生成幂等键
        3. 持久化
        4. 记录事件
        """
        # 1. 校验
        errors = spec.validate_spec()
        if errors:
            return {
                "success": False,
                "errors": errors,
                "task_id": None
            }
        
        # 2. 生成幂等键
        if not spec.idempotency_key:
            spec.idempotency_key = spec.generate_idempotency_key()
        
        # 3. 检查幂等
        existing = await self._check_idempotency(spec.idempotency_key)
        if existing:
            return {
                "success": True,
                "task_id": existing,
                "message": "任务已存在（幂等）",
                "idempotent": True
            }
        
        # 4. 设置初始状态
        spec.status = TaskStatus.VALIDATED
        
        # 5. 计算下次运行时间
        if spec.trigger_mode == TriggerMode.SCHEDULED and spec.schedule:
            next_run = spec.schedule.get_next_run_at()
            if next_run:
                # 更新 schedule 的 next_run_at
                spec.schedule.next_run_at = next_run.isoformat()
        
        # 6. 持久化
        task_id = await self.task_repo.create(spec)
        
        # 7. 更新状态
        await self.task_repo.update(task_id, {"status": TaskStatus.PERSISTED.value})
        
        # 8. 记录事件
        await self.event_repo.record_event(
            task_id=task_id,
            event_type=EventType.CREATED.value,
            event_payload={
                "task_type": spec.task_type,
                "goal": spec.goal,
                "trigger_mode": spec.trigger_mode.value
            }
        )
        
        await self.event_repo.record_event(
            task_id=task_id,
            event_type=EventType.VALIDATED.value,
            event_payload={"errors": []}
        )
        
        await self.event_repo.record_event(
            task_id=task_id,
            event_type=EventType.PERSISTED.value,
            event_payload={}
        )
        
        return {
            "success": True,
            "task_id": task_id,
            "status": TaskStatus.PERSISTED.value,
            "idempotent": False
        }
    
    async def get_task(self, task_id: str) -> Optional[TaskSpec]:
        """获取任务"""
        return await self.task_repo.get(task_id)
    
    async def list_tasks(
        self,
        user_id: str,
        status: Optional[TaskStatus] = None,
        limit: int = 100,
        offset: int = 0
    ) -> List[TaskSpec]:
        """列出任务"""
        return await self.task_repo.list_by_user(user_id, status, limit, offset)
    
    async def cancel_task(self, task_id: str) -> Dict[str, Any]:
        """取消任务"""
        task = await self.task_repo.get(task_id)
        if not task:
            return {"success": False, "error": "任务不存在"}
        
        # 检查是否可取消
        if task.status in (TaskStatus.SUCCEEDED, TaskStatus.FAILED, TaskStatus.CANCELLED):
            return {"success": False, "error": f"任务状态 {task.status.value} 不可取消"}
        
        # 更新状态
        await self.task_repo.update(task_id, {"status": TaskStatus.CANCELLED.value})
        
        # 记录事件
        await self.event_repo.record_event(
            task_id=task_id,
            event_type=EventType.CANCELLED.value,
            event_payload={"previous_status": task.status.value}
        )
        
        return {"success": True, "task_id": task_id, "status": TaskStatus.CANCELLED.value}
    
    async def pause_task(self, task_id: str) -> Dict[str, Any]:
        """暂停任务"""
        task = await self.task_repo.get(task_id)
        if not task:
            return {"success": False, "error": "任务不存在"}
        
        # 扩展可暂停状态：PERSISTED, QUEUED, RUNNING, WAITING_RETRY
        if task.status not in (TaskStatus.PERSISTED, TaskStatus.QUEUED, TaskStatus.RUNNING, TaskStatus.WAITING_RETRY):
            return {"success": False, "error": f"任务状态 {task.status.value} 不可暂停"}
        
        previous_status = task.status.value
        await self.task_repo.update(task_id, {"status": TaskStatus.PAUSED.value})
        
        await self.event_repo.record_event(
            task_id=task_id,
            event_type=EventType.PAUSED.value,
            event_payload={"previous_status": previous_status}
        )
        
        return {"success": True, "task_id": task_id, "status": TaskStatus.PAUSED.value, "previous_status": previous_status}
    
    async def resume_task(self, task_id: str) -> Dict[str, Any]:
        """恢复任务"""
        task = await self.task_repo.get(task_id)
        if not task:
            return {"success": False, "error": "任务不存在"}
        
        if task.status != TaskStatus.PAUSED:
            return {"success": False, "error": f"任务状态 {task.status.value} 不可恢复"}
        
        # 从最近一次 PAUSED 事件获取 previous_status
        events = await self.event_repo.list_events(task_id, limit=100)
        previous_status = TaskStatus.QUEUED.value  # 默认恢复到 QUEUED
        
        for event in reversed(events):
            if event.get("event_type") == EventType.PAUSED.value:
                payload = event.get("event_payload", {})
                if isinstance(payload, str):
                    import json
                    payload = json.loads(payload)
                previous_status = payload.get("previous_status", TaskStatus.QUEUED.value)
                break
        
        # 根据之前状态决定恢复目标
        if previous_status == TaskStatus.PERSISTED.value:
            target_status = TaskStatus.PERSISTED.value
        else:
            target_status = TaskStatus.QUEUED.value
        
        await self.task_repo.update(task_id, {"status": TaskStatus.RESUMED.value})
        
        await self.event_repo.record_event(
            task_id=task_id,
            event_type=EventType.RESUMED.value,
            event_payload={"previous_status": previous_status, "target_status": target_status}
        )
        
        # 恢复到目标状态
        await self.task_repo.update(task_id, {"status": target_status})
        
        return {"success": True, "task_id": task_id, "status": target_status, "previous_status": previous_status}
    
    async def get_task_events(self, task_id: str, limit: int = 100) -> List[Dict[str, Any]]:
        """获取任务事件"""
        return await self.event_repo.list_events(task_id, limit)
    
    async def _check_idempotency(self, idempotency_key: str) -> Optional[str]:
        """检查幂等键"""
        # 简化实现：查询数据库
        # 实际应该用专门的索引查询
        return None


path: autonomous_planner/__init__.py
content: """自主规划器"""

from .goal_parser import GoalParser
from .task_decomposer import TaskDecomposer
from .plan_schema import Plan, PlanStep
from .skill_selector import SkillSelector

__all__ = ["GoalParser", "TaskDecomposer", "Plan", "PlanStep", "SkillSelector"]


path: autonomous_planner/goal_parser.py
content: """目标解析器"""

from typing import Dict, Any, List
from dataclasses import dataclass


@dataclass
class ParsedGoal:
    """解析后的目标"""
    original: str
    intent: str  # remind, schedule, notify, query, automate
    entities: Dict[str, Any]
    constraints: List[str]
    priority: str  # high, medium, low


class GoalParser:
    """目标解析器"""
    
    INTENT_KEYWORDS = {
        "remind": ["提醒", "记得", "别忘了", "通知我"],
        "schedule": ["日程", "安排", "预约", "会议", "日历"],
        "notify": ["通知", "推送", "发消息", "告诉"],
        "query": ["查询", "看看", "帮我查", "搜索"],
        "automate": ["自动", "帮我", "操作", "执行"],
        "create": ["创建", "新建", "添加", "写"],
        "delete": ["删除", "移除", "取消"],
        "update": ["更新", "修改", "更改"],
    }
    
    def parse(self, goal: str) -> ParsedGoal:
        """解析目标"""
        goal_lower = goal.lower()
        
        # 确定意图
        intent = "automate"
        for i, keywords in self.INTENT_KEYWORDS.items():
            for kw in keywords:
                if kw in goal_lower:
                    intent = i
                    break
        
        # 提取实体
        entities = self._extract_entities(goal)
        
        # 提取约束
        constraints = self._extract_constraints(goal)
        
        # 确定优先级
        priority = self._determine_priority(goal)
        
        return ParsedGoal(
            original=goal,
            intent=intent,
            entities=entities,
            constraints=constraints,
            priority=priority,
        )
    
    def _extract_entities(self, goal: str) -> Dict[str, Any]:
        """提取实体"""
        import re
        entities = {}
        
        # 时间
        time_patterns = [
            (r"(\d{1,2}:\d{2})", "time"),
            (r"明天", "date"),
            (r"后天", "date"),
            (r"下周", "week"),
            (r"(\d+)月(\d+)日", "date"),
        ]
        
        for pattern, key in time_patterns:
            match = re.search(pattern, goal)
            if match:
                entities[key] = match.group(0)
        
        # 人物
        if "我" in goal:
            entities["subject"] = "user"
        
        # 地点
        location_patterns = ["去", "在", "到"]
        for lp in location_patterns:
            if lp in goal:
                idx = goal.index(lp)
                entities["location_hint"] = goal[idx:idx+10]
        
        return entities
    
    def _extract_constraints(self, goal: str) -> List[str]:
        """提取约束"""
        constraints = []
        
        constraint_keywords = {
            "必须": "required",
            "尽量": "preferred",
            "不要": "avoid",
            "避免": "avoid",
        }
        
        for kw, constraint in constraint_keywords.items():
            if kw in goal:
                constraints.append(constraint)
        
        return constraints
    
    def _determine_priority(self, goal: str) -> str:
        """确定优先级"""
        high_keywords = ["紧急", "重要", "马上", "立即", "尽快"]
        for kw in high_keywords:
            if kw in goal:
                return "high"
        
        low_keywords = ["有空", "方便", "稍后"]
        for kw in low_keywords:
            if kw in goal:
                return "low"
        
        return "medium"


path: autonomous_planner/plan_schema.py
content: """计划模式"""

from typing import List, Dict, Any, Optional
from dataclasses import dataclass, field
from datetime import datetime


@dataclass
class PlanStep:
    """计划步骤"""
    step_id: int
    capability: str
    params: Dict[str, Any] = field(default_factory=dict)
    description: str = ""
    risk_level: str = "L0"
    status: str = "pending"  # pending, running, completed, failed, skipped
    result: Optional[Dict[str, Any]] = None
    started_at: Optional[str] = None
    completed_at: Optional[str] = None


@dataclass
class Plan:
    """执行计划"""
    goal: str
    intent: str
    steps: List[PlanStep] = field(default_factory=list)
    estimated_time: int = 0
    created_at: str = field(default_factory=lambda: datetime.now().isoformat())
    status: str = "draft"  # draft, previewing, confirmed, executing, completed, failed
    current_step: int = 0
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            "goal": self.goal,
            "intent": self.intent,
            "steps": [
                {
                    "step_id": s.step_id,
                    "capability": s.capability,
                    "params": s.params,
                    "description": s.description,
                    "risk_level": s.risk_level,
                    "status": s.status,
                }
                for s in self.steps
            ],
            "estimated_time": self.estimated_time,
            "created_at": self.created_at,
            "status": self.status,
            "current_step": self.current_step,
        }
    
    def get_high_risk_steps(self) -> List[PlanStep]:
        """获取高风险步骤"""
        return [s for s in self.steps if s.risk_level in ["L3", "L4"]]
    
    def get_preview(self) -> str:
        """获取预览"""
        lines = [f"目标: {self.goal}", "", "执行计划:"]
        for step in self.steps:
            risk_icon = {"L0": "✅", "L1": "✅", "L2": "⚠️", "L3": "🔴", "L4": "⛔"}.get(step.risk_level, "❓")
            lines.append(f"  {step.step_id}. {risk_icon} {step.description}")
            if step.params:
                for k, v in step.params.items():
                    lines.append(f"     - {k}: {v}")
        return "\n".join(lines)


path: autonomous_planner/route_selector.py
content: """
Route Selector

Planner 使用 route_registry 选择 route
"""

import json
from datetime import datetime
from pathlib import Path
from typing import Optional, List, Dict, Any
from dataclasses import dataclass, asdict


@dataclass
class RouteSelection:
    """Route 选择结果"""
    selected_route_id: str
    candidate_routes: List[str]
    selection_reason: str
    risk_level: str
    policy: str
    requires_confirmation: bool
    fallback_routes: List[str]
    confidence: float
    
    def to_dict(self) -> dict:
        return asdict(self)


class RouteSelector:
    """Route 选择器"""
    
    def __init__(self, registry_path: str = "infrastructure/route_registry.json"):
        self.registry_path = Path(registry_path)
        self.registry = self._load_registry()
        self.intent_index = self._build_intent_index()
    
    def _load_registry(self) -> dict:
        if self.registry_path.exists():
            return json.loads(self.registry_path.read_text())
        return {"routes": {}}
    
    def _build_intent_index(self) -> Dict[str, List[str]]:
        """构建意图索引"""
        index = {}
        for route_id, route in self.registry.get("routes", {}).items():
            intents = route.get("user_intents", [])
            for intent in intents:
                intent_lower = intent.lower()
                if intent_lower not in index:
                    index[intent_lower] = []
                index[intent_lower].append(route_id)
        return index
    
    def _match_intent(self, goal: str) -> List[str]:
        """匹配意图"""
        goal_lower = goal.lower()
        candidates = []
        
        # 精确匹配
        if goal_lower in self.intent_index:
            candidates.extend(self.intent_index[goal_lower])
        
        # 模糊匹配
        for intent, routes in self.intent_index.items():
            if intent in goal_lower or goal_lower in intent:
                for r in routes:
                    if r not in candidates:
                        candidates.append(r)
        
        return candidates
    
    def _calculate_priority(self, route_id: str, route: dict) -> float:
        """计算优先级分数"""
        score = 0.0
        
        # 状态优先级
        status = route.get("status", "generated")
        status_scores = {"active": 100, "verified": 80, "generated": 50, "failed": 0, "deprecated": -100}
        score += status_scores.get(status, 0)
        
        # 风险等级优先级 (低风险优先)
        risk = route.get("risk_level", "L3")
        risk_scores = {"L0": 40, "L1": 30, "L2": 20, "L3": 10, "L4": 5, "BLOCKED": -50}
        score += risk_scores.get(risk, 0)
        
        # 激活次数
        activation = route.get("activation", {})
        score += min(activation.get("activation_count", 0) * 5, 20)
        
        return score
    
    def select_route(self, goal: str, context: dict = None) -> Optional[RouteSelection]:
        """选择 route"""
        context = context or {}
        
        # 匹配候选 routes
        candidates = self._match_intent(goal)
        
        if not candidates:
            return None
        
        # 计算优先级并排序
        scored_candidates = []
        for route_id in candidates:
            route = self.registry["routes"].get(route_id, {})
            score = self._calculate_priority(route_id, route)
            scored_candidates.append((route_id, score, route))
        
        scored_candidates.sort(key=lambda x: x[1], reverse=True)
        
        # 选择最佳 route
        selected_id, selected_score, selected_route = scored_candidates[0]
        
        # 构建选择结果
        return RouteSelection(
            selected_route_id=selected_id,
            candidate_routes=[c[0] for c in scored_candidates[:5]],
            selection_reason=f"Best match for '{goal}' with score {selected_score:.1f}",
            risk_level=selected_route.get("risk_level", "L3"),
            policy=selected_route.get("policy", "confirm_once"),
            requires_confirmation=selected_route.get("requires_confirmation", True),
            fallback_routes=selected_route.get("fallback_routes", []),
            confidence=min(selected_score / 100.0, 1.0)
        )
    
    def get_route(self, route_id: str) -> Optional[dict]:
        """获取 route 详情"""
        return self.registry["routes"].get(route_id)
    
    def get_routes_by_capability(self, capability: str) -> List[str]:
        """按能力查找 routes"""
        return [
            rid for rid, r in self.registry["routes"].items()
            if r.get("capability") == capability
        ]
    
    def get_routes_by_risk(self, risk_level: str) -> List[str]:
        """按风险等级查找 routes"""
        return [
            rid for rid, r in self.registry["routes"].items()
            if r.get("risk_level") == risk_level
        ]


def get_route_selector(registry_path: str = None) -> RouteSelector:
    """获取 Route 选择器实例"""
    if registry_path:
        return RouteSelector(registry_path)
    return RouteSelector()


path: autonomous_planner/skill_selector.py
content: """技能选择器"""

from typing import List, Dict, Any, Optional
from skill_asset_registry import SkillRegistry, SkillAsset


class SkillSelector:
    """技能选择器"""
    
    def __init__(self, registry: Optional[SkillRegistry] = None):
        self.registry = registry or SkillRegistry()
    
    def select_for_goal(self, goal: str, limit: int = 5) -> List[SkillAsset]:
        """为目标选择技能"""
        return self.registry.search(goal, limit)
    
    def select_for_capability(self, capability: str) -> List[SkillAsset]:
        """为能力选择技能"""
        # 从能力名称推断关键词
        keywords = capability.split(".")
        query = " ".join(keywords)
        return self.registry.search(query, limit=3)
    
    def rank_by_success_rate(self, skills: List[SkillAsset]) -> List[SkillAsset]:
        """按成功率排序"""
        return sorted(skills, key=lambda x: x.success_rate, reverse=True)
    
    def get_fallback(self, skill_id: str) -> Optional[SkillAsset]:
        """获取备用技能"""
        skill = self.registry.get(skill_id)
        if skill and skill.fallback_skills:
            for fb_id in skill.fallback_skills:
                fb = self.registry.get(fb_id)
                if fb:
                    return fb
        return None


path: autonomous_planner/task_decomposer.py
content: """任务分解器"""

from typing import List, Dict, Any
from .goal_parser import ParsedGoal
from .plan_schema import Plan, PlanStep


class TaskDecomposer:
    """任务分解器"""
    
    # 意图到能力的映射
    INTENT_CAPABILITY_MAP = {
        "remind": ["schedule.create_calendar_event", "notification.push"],
        "schedule": ["schedule.create_calendar_event"],
        "notify": ["notification.push"],
        "query": ["storage.search_notes"],
        "create": ["storage.create_note"],
        "delete": ["storage.delete_note"],
        "update": ["storage.update_note"],
    }
    
    def decompose(self, parsed_goal: ParsedGoal) -> Plan:
        """分解任务"""
        steps = []
        
        # 根据意图选择能力
        capabilities = self.INTENT_CAPABILITY_MAP.get(parsed_goal.intent, [])
        
        # 如果没有匹配，使用通用流程
        if not capabilities:
            capabilities = ["storage.create_note"]
        
        # 创建步骤
        for i, cap in enumerate(capabilities):
            step = PlanStep(
                step_id=i + 1,
                capability=cap,
                params=self._build_params(cap, parsed_goal),
                description=f"执行 {cap}",
                risk_level=self._assess_risk(cap),
            )
            steps.append(step)
        
        return Plan(
            goal=parsed_goal.original,
            intent=parsed_goal.intent,
            steps=steps,
            estimated_time=len(steps) * 2,  # 每步估计2秒
        )
    
    def _build_params(self, capability: str, parsed_goal: ParsedGoal) -> Dict[str, Any]:
        """构建参数"""
        params = {}
        
        if "calendar" in capability:
            params = {
                "title": parsed_goal.original[:50],
                "time": parsed_goal.entities.get("time", "09:00"),
                "date": parsed_goal.entities.get("date", "tomorrow"),
            }
        elif "notification" in capability:
            params = {
                "message": parsed_goal.original,
            }
        elif "note" in capability:
            params = {
                "content": parsed_goal.original,
                "title": parsed_goal.original[:30],
            }
        
        return params
    
    def _assess_risk(self, capability: str) -> str:
        """评估风险"""
        if "delete" in capability:
            return "L3"
        elif "send" in capability or "push" in capability:
            return "L2"
        elif "create" in capability or "update" in capability:
            return "L1"
        return "L0"


path: capabilities/__init__.py
content: """
Capabilities Layer - 能力层
提供统一的能力注册与执行
"""

from .registry import CapabilityRegistry, register_capability, get_registry, CapabilityStatus
from .bootstrap import (
    register_default_capabilities,
    bootstrap_capabilities,
    ensure_bootstrap,
    get_capability_instance
)
from .send_message import SendMessageCapability
from .schedule_task import ScheduleTaskCapability
from .retry_task import RetryTaskCapability
from .pause_task import PauseTaskCapability
from .resume_task import ResumeTaskCapability
from .cancel_task import CancelTaskCapability
from .diagnostics import DiagnosticsCapability
from .export_history import ExportHistoryCapability
from .replay_run import ReplayRunCapability
from .self_repair import SelfRepairCapability

__all__ = [
    # 注册表
    'CapabilityRegistry', 'register_capability', 'get_registry', 'CapabilityStatus',
    
    # Bootstrap
    'register_default_capabilities', 'bootstrap_capabilities', 'ensure_bootstrap',
    'get_capability_instance',
    
    # 能力类
    'SendMessageCapability',
    'ScheduleTaskCapability',
    'RetryTaskCapability',
    'PauseTaskCapability',
    'ResumeTaskCapability',
    'CancelTaskCapability',
    'DiagnosticsCapability',
    'ExportHistoryCapability',
    'ReplayRunCapability',
    'SelfRepairCapability'
]


path: capabilities/approve_action.py
content: """审批动作能力"""

from typing import Dict, Any, Optional, List
from datetime import datetime
import uuid


# 简单的审批存储（生产环境应使用数据库）
_pending_approvals = {}
_approved_actions = {}


def request_approval(
    action_type: str,
    action_params: Dict[str, Any],
    reason: str,
    approver: Optional[str] = None,
    timeout_hours: int = 24,
) -> Dict[str, Any]:
    """
    请求审批
    
    Args:
        action_type: 操作类型
        action_params: 操作参数
        reason: 审批原因
        approver: 审批人
        timeout_hours: 超时时间（小时）
        
    Returns:
        审批请求结果
    """
    approval_id = f"approval_{uuid.uuid4().hex[:16]}"
    
    approval_request = {
        "approval_id": approval_id,
        "action_type": action_type,
        "action_params": action_params,
        "reason": reason,
        "approver": approver,
        "status": "pending",
        "created_at": datetime.now().isoformat(),
        "expires_at": (datetime.now() + __import__("datetime").timedelta(hours=timeout_hours)).isoformat(),
        "approved_at": None,
        "approved_by": None,
        "rejected_at": None,
        "rejected_by": None,
        "rejection_reason": None
    }
    
    _pending_approvals[approval_id] = approval_request
    
    return {
        "success": True,
        "approval_id": approval_id,
        "status": "pending",
        "message": f"已提交审批请求，等待审批",
        "expires_at": approval_request["expires_at"]
    }


def approve_action(
    approval_id: str,
    approved_by: str,
    note: Optional[str] = None,
) -> Dict[str, Any]:
    """
    批准操作
    
    Args:
        approval_id: 审批ID
        approved_by: 审批人
        note: 备注
        
    Returns:
        批准结果
    """
    if approval_id not in _pending_approvals:
        return {
            "success": False,
            "error": f"审批请求 {approval_id} 不存在"
        }
    
    approval = _pending_approvals[approval_id]
    
    if approval["status"] != "pending":
        return {
            "success": False,
            "error": f"审批请求已处于 {approval['status']} 状态"
        }
    
    # 检查超时
    expires_at = datetime.fromisoformat(approval["expires_at"])
    if datetime.now() > expires_at:
        approval["status"] = "expired"
        return {
            "success": False,
            "error": "审批请求已过期"
        }
    
    # 批准
    approval["status"] = "approved"
    approval["approved_at"] = datetime.now().isoformat()
    approval["approved_by"] = approved_by
    approval["approval_note"] = note
    
    # 移动到已批准列表
    _approved_actions[approval_id] = approval
    del _pending_approvals[approval_id]
    
    return {
        "success": True,
        "approval_id": approval_id,
        "status": "approved",
        "approved_by": approved_by,
        "message": "操作已批准，可以执行"
    }


def reject_action(
    approval_id: str,
    rejected_by: str,
    reason: str,
) -> Dict[str, Any]:
    """
    拒绝操作
    
    Args:
        approval_id: 审批ID
        rejected_by: 拒绝人
        reason: 拒绝原因
        
    Returns:
        拒绝结果
    """
    if approval_id not in _pending_approvals:
        return {
            "success": False,
            "error": f"审批请求 {approval_id} 不存在"
        }
    
    approval = _pending_approvals[approval_id]
    
    if approval["status"] != "pending":
        return {
            "success": False,
            "error": f"审批请求已处于 {approval['status']} 状态"
        }
    
    # 拒绝
    approval["status"] = "rejected"
    approval["rejected_at"] = datetime.now().isoformat()
    approval["rejected_by"] = rejected_by
    approval["rejection_reason"] = reason
    
    del _pending_approvals[approval_id]
    
    return {
        "success": True,
        "approval_id": approval_id,
        "status": "rejected",
        "rejected_by": rejected_by,
        "reason": reason,
        "message": "操作已拒绝"
    }


def check_approval_status(approval_id: str) -> Dict[str, Any]:
    """
    检查审批状态
    
    Args:
        approval_id: 审批ID
        
    Returns:
        审批状态
    """
    # 检查待审批
    if approval_id in _pending_approvals:
        return {
            "success": True,
            "approval_id": approval_id,
            "status": _pending_approvals[approval_id]["status"],
            "is_approved": False
        }
    
    # 检查已批准
    if approval_id in _approved_actions:
        approval = _approved_actions[approval_id]
        return {
            "success": True,
            "approval_id": approval_id,
            "status": "approved",
            "is_approved": True,
            "approved_at": approval["approved_at"],
            "approved_by": approval["approved_by"]
        }
    
    return {
        "success": False,
        "error": f"审批请求 {approval_id} 不存在"
    }


def get_pending_approvals() -> List[Dict[str, Any]]:
    """获取所有待审批请求"""
    return list(_pending_approvals.values())


def execute_with_approval(
    capability: str,
    params: Dict[str, Any],
    approval_id: str,
) -> Dict[str, Any]:
    """
    在审批通过后执行操作
    
    Args:
        capability: 能力名称
        params: 参数
        approval_id: 审批ID
        
    Returns:
        执行结果
    """
    # 检查审批状态
    status = check_approval_status(approval_id)
    
    if not status.get("success"):
        return status
    
    if not status.get("is_approved"):
        return {
            "success": False,
            "error": "操作未获批准",
            "approval_status": status.get("status")
        }
    
    # 执行操作
    import importlib
    try:
        module = importlib.import_module(f"capabilities.{capability}")
        result = module.run(**params)
        
        return {
            "success": result.get("success", False),
            "approval_id": approval_id,
            "result": result
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e)
        }


def run(**kwargs):
    """能力入口"""
    action = kwargs.pop("action", "request")
    
    if action == "request":
        return request_approval(**kwargs)
    elif action == "approve":
        return approve_action(**kwargs)
    elif action == "reject":
        return reject_action(**kwargs)
    elif action == "check":
        return check_approval_status(**kwargs)
    elif action == "execute":
        return execute_with_approval(**kwargs)
    else:
        return {"success": False, "error": f"未知操作: {action}"}


path: capabilities/audit_queries.py
content: """
审计查询能力
提供程序化接口查询 platform_invocations
"""

from typing import Optional, List, Dict, Any
from pathlib import Path
import sys

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from platform_adapter.invocation_ledger import (
    query_by_task_id,
    query_by_capability,
    query_by_status,
    export_recent,
    export_failed_report,
    export_timeout_report,
    export_uncertain_report,
    get_statistics,
    get_invocation_by_id,
    get_invocation_by_idempotency_key,
)


class AuditQueries:
    """审计查询能力"""
    
    @staticmethod
    def get_recent(n: int = 10) -> List[Dict[str, Any]]:
        """获取最近 N 条记录"""
        return export_recent(n)
    
    @staticmethod
    def get_by_task_id(task_id: str) -> List[Dict[str, Any]]:
        """按 task_id 查询"""
        return query_by_task_id(task_id)
    
    @staticmethod
    def get_by_capability(capability: str, limit: int = 100) -> List[Dict[str, Any]]:
        """按 capability 查询"""
        return query_by_capability(capability, limit)
    
    @staticmethod
    def get_by_status(status: str, limit: int = 100) -> List[Dict[str, Any]]:
        """按状态查询"""
        return query_by_status(status, limit)
    
    @staticmethod
    def get_uncertain(limit: int = 100) -> List[Dict[str, Any]]:
        """获取 uncertain 记录"""
        return export_uncertain_report(limit)
    
    @staticmethod
    def get_failed(limit: int = 100) -> List[Dict[str, Any]]:
        """获取 failed 记录"""
        return export_failed_report(limit)
    
    @staticmethod
    def get_timeout(limit: int = 100) -> List[Dict[str, Any]]:
        """获取 timeout 记录"""
        return export_timeout_report(limit)
    
    @staticmethod
    def get_by_id(record_id: int) -> Optional[Dict[str, Any]]:
        """按 ID 查询"""
        return get_invocation_by_id(record_id)
    
    @staticmethod
    def get_by_idempotency_key(key: str) -> Optional[Dict[str, Any]]:
        """按幂等键查询"""
        return get_invocation_by_idempotency_key(key)
    
    @staticmethod
    def get_stats() -> Dict[str, Any]:
        """获取统计信息"""
        return get_statistics()
    
    @staticmethod
    def get_unconfirmed_uncertain(limit: int = 100) -> List[Dict[str, Any]]:
        """获取未确认的 uncertain 记录"""
        records = export_uncertain_report(limit)
        return [r for r in records if not r.get("confirmed_status")]
    
    @staticmethod
    def summarize_status(records: List[Dict[str, Any]]) -> Dict[str, int]:
        """汇总状态分布"""
        summary = {}
        for r in records:
            status = r.get("normalized_status", "unknown")
            summary[status] = summary.get(status, 0) + 1
        return summary


# 便捷函数
def query_recent(n: int = 10) -> List[Dict[str, Any]]:
    """查询最近 N 条记录"""
    return AuditQueries.get_recent(n)


def query_uncertain(limit: int = 100) -> List[Dict[str, Any]]:
    """查询 uncertain 记录"""
    return AuditQueries.get_uncertain(limit)


def query_failed(limit: int = 100) -> List[Dict[str, Any]]:
    """查询 failed 记录"""
    return AuditQueries.get_failed(limit)


def query_timeout(limit: int = 100) -> List[Dict[str, Any]]:
    """查询 timeout 记录"""
    return AuditQueries.get_timeout(limit)


def query_stats() -> Dict[str, Any]:
    """查询统计信息"""
    return AuditQueries.get_stats()


path: capabilities/bootstrap.py
content: """
Capabilities Bootstrap - 能力自动注册
在启动时自动注册所有能力到注册表
"""

from typing import Optional
import logging

from .registry import get_registry, CapabilityStatus
from .send_message import SendMessageCapability
from .schedule_task import ScheduleTaskCapability
from .retry_task import RetryTaskCapability
from .pause_task import PauseTaskCapability
from .resume_task import ResumeTaskCapability
from .cancel_task import CancelTaskCapability
from .diagnostics import DiagnosticsCapability
from .export_history import ExportHistoryCapability
from .replay_run import ReplayRunCapability
from .self_repair import SelfRepairCapability

logger = logging.getLogger(__name__)

# 能力实例缓存
_capability_instances = {}


def get_capability_instance(name: str):
    """获取能力实例"""
    return _capability_instances.get(name)


def register_default_capabilities() -> None:
    """注册所有默认能力"""
    registry = get_registry()
    
    # 创建能力实例
    capabilities = [
        ("send_message", SendMessageCapability()),
        ("schedule_task", ScheduleTaskCapability()),
        ("retry_task", RetryTaskCapability()),
        ("pause_task", PauseTaskCapability()),
        ("resume_task", ResumeTaskCapability()),
        ("cancel_task", CancelTaskCapability()),
        ("diagnostics", DiagnosticsCapability()),
        ("export_history", ExportHistoryCapability()),
        ("replay_run", ReplayRunCapability()),
        ("self_repair", SelfRepairCapability()),
    ]
    
    for name, instance in capabilities:
        _capability_instances[name] = instance
        
        registry.register(
            name=name,
            description=instance.description,
            handler=instance.execute,
            category="task_management" if name in [
                "schedule_task", "retry_task", "pause_task", 
                "resume_task", "cancel_task"
            ] else "system" if name in [
                "diagnostics", "self_repair"
            ] else "messaging" if name == "send_message" else "data"
        )
        
        logger.info(f"Registered capability: {name}")
    
    logger.info(f"Total capabilities registered: {len(capabilities)}")


def bootstrap_capabilities() -> None:
    """
    启动能力系统
    - 注册所有能力
    - 设置初始状态
    """
    # 注册能力
    register_default_capabilities()
    
    # 设置能力状态为可用
    registry = get_registry()
    for name in _capability_instances.keys():
        registry.update_status(name, CapabilityStatus.AVAILABLE)
    
    logger.info("Capabilities bootstrap completed")


# 自动执行 bootstrap（可选）
_auto_bootstrap_done = False


def ensure_bootstrap():
    """确保 bootstrap 已执行"""
    global _auto_bootstrap_done
    if not _auto_bootstrap_done:
        bootstrap_capabilities()
        _auto_bootstrap_done = True


path: capabilities/cancel_notification.py
content: """取消通知能力"""

from typing import Optional, Dict, Any
import uuid


def cancel_notification(
    notification_id: str,
    reason: Optional[str] = None,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    取消通知
    
    Args:
        notification_id: 通知ID
        reason: 取消原因
        dry_run: 是否预演模式
        
    Returns:
        包含取消结果的字典
    """
    from platform_adapter import invocation_ledger as ledger_module
    from platform_adapter.xiaoyi_adapter import XiaoyiAdapter
    
    # 先查询通知状态
    pass
    records = ledger_module.query_by_capability(capability="NOTIFICATION", limit=100)
    
    notification_record = None
    for r in records:
        request_params = r.get("request_params", {})
        if isinstance(request_params, str):
            import json
            try:
                request_params = json.loads(request_params)
            except:
                request_params = {}
        
        if request_params.get("notification_id") == notification_id:
            notification_record = r
            break
    
    if not notification_record:
        return {
            "success": False,
            "cancellable": False,
            "reason": "notification_not_found",
            "message": "通知不存在"
        }
    
    normalized_status = notification_record.get("normalized_status")
    
    # 检查是否可取消
    if normalized_status == "completed":
        return {
            "success": False,
            "cancellable": False,
            "reason": "already_sent",
            "message": "通知已发出，无法取消"
        }
    
    if normalized_status == "auth_required":
        return {
            "success": False,
            "cancellable": False,
            "reason": "auth_required",
            "message": "未授权，无法操作"
        }
    
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "cancellable": True,
            "action": "cancel_notification",
            "notification_id": notification_id,
            "message": "预演模式：将取消通知"
        }
    
    # 只有 queued_for_delivery 状态可以取消
    if normalized_status == "queued_for_delivery":
        # 调用平台适配器
        adapter = XiaoyiAdapter()
        result = adapter.cancel_notification(
            notification_id=notification_id,
            idempotency_key=f"cancel_notif_{uuid.uuid4().hex[:16]}"
        )
        
        return {
            "success": result.get("success", False),
            "cancellable": True,
            "cancelled": result.get("success", False),
            "notification_id": notification_id,
            "message": "通知已取消" if result.get("success") else "取消失败"
        }
    
    return {
        "success": False,
        "cancellable": False,
        "reason": "unknown_status",
        "message": f"无法确定通知状态: {normalized_status}"
    }


def run(**kwargs):
    """能力入口"""
    return cancel_notification(**kwargs)


path: capabilities/cancel_task.py
content: """
取消任务能力 - 真实实现
接入 TaskManager 任务内核
"""

from typing import Dict, Any
from datetime import datetime
import sys
from pathlib import Path

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from infrastructure.task_manager import get_task_manager


class CancelTaskCapability:
    """取消任务能力"""
    
    name = "cancel_task"
    description = "取消任务"
    
    async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
        """
        执行任务取消
        
        Args:
            params: {
                "task_id": 任务ID
            }
        
        Returns:
            {
                "success": bool,
                "task_id": str,
                "status": str,
                "cancelled_at": str
            }
        """
        task_id = params.get("task_id")
        
        if not task_id:
            return {
                "success": False,
                "error": "缺少 task_id",
                "error_code": "MISSING_TASK_ID"
            }
        
        try:
            tm = get_task_manager()
            result = await tm.cancel_task(task_id)
            
            return {
                "success": result.get("success", False),
                "task_id": task_id,
                "status": result.get("status", "cancelled"),
                "cancelled_at": datetime.now().isoformat()
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "error_code": "CANCEL_FAILED",
                "task_id": task_id
            }


path: capabilities/check_calendar_conflicts.py
content: """检查日程冲突能力"""

from typing import List, Dict, Any, Optional
from datetime import datetime
import json


def check_calendar_conflicts(
    start_time: str,
    end_time: str,
    exclude_event_id: Optional[str] = None,
    title: Optional[str] = None,
) -> Dict[str, Any]:
    """
    检查日程冲突
    
    Args:
        start_time: 开始时间
        end_time: 结束时间
        exclude_event_id: 排除的事件ID（用于更新时排除自身）
        title: 标题（检查标题重复）
        
    Returns:
        包含冲突信息的字典
    """
    from platform_adapter import invocation_ledger as ledger_module
    
    pass
    
    # 查询所有日程
    records = ledger_module.query_by_capability(capability="TASK_SCHEDULING", limit=200)
    
    conflicts = []
    
    for r in records:
        request_params = r.get("request_params", {})
        if isinstance(request_params, str):
            try:
                request_params = json.loads(request_params)
            except:
                request_params = {}
        
        event_id = request_params.get("event_id")
        
        # 排除指定事件
        if exclude_event_id and event_id == exclude_event_id:
            continue
        
        # 检查时间重叠
        existing_start = request_params.get("start_time")
        existing_end = request_params.get("end_time")
        
        if existing_start and existing_end:
            # 时间重叠检测
            if _times_overlap(start_time, end_time, existing_start, existing_end):
                conflicts.append({
                    "type": "time_overlap",
                    "event_id": event_id,
                    "title": request_params.get("title"),
                    "start_time": existing_start,
                    "end_time": existing_end,
                    "message": f"与 '{request_params.get('title')}' 时间重叠"
                })
        
        # 检查标题重复
        if title and request_params.get("title"):
            if title.lower() == request_params.get("title", "").lower():
                conflicts.append({
                    "type": "title_duplicate",
                    "event_id": event_id,
                    "title": request_params.get("title"),
                    "message": f"标题与现有日程重复: '{title}'"
                })
    
    return {
        "success": True,
        "has_conflicts": len(conflicts) > 0,
        "conflict_count": len(conflicts),
        "conflicts": conflicts,
        "checked_period": {
            "start_time": start_time,
            "end_time": end_time
        }
    }


def _times_overlap(start1: str, end1: str, start2: str, end2: str) -> bool:
    """检查两个时间段是否重叠"""
    try:
        s1 = datetime.fromisoformat(start1.replace("Z", "+00:00"))
        e1 = datetime.fromisoformat(end1.replace("Z", "+00:00"))
        s2 = datetime.fromisoformat(start2.replace("Z", "+00:00"))
        e2 = datetime.fromisoformat(end2.replace("Z", "+00:00"))
        
        # 重叠条件：s1 < e2 AND s2 < e1
        return s1 < e2 and s2 < e1
    except:
        return False


def run(**kwargs):
    """能力入口"""
    return check_calendar_conflicts(**kwargs)


path: capabilities/confirm_invocation.py
content: """
手动确认能力
提供程序化接口确认 platform_invocations
"""

from typing import Optional
from pathlib import Path
import sys

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from platform_adapter.invocation_ledger import (
    confirm_invocation,
    get_invocation_by_id,
    get_statistics,
)


class ConfirmInvocation:
    """手动确认能力"""
    
    # 确认状态
    CONFIRMED_SUCCESS = "confirmed_success"
    CONFIRMED_FAILED = "confirmed_failed"
    CONFIRMED_DUPLICATE = "confirmed_duplicate"
    
    @staticmethod
    def confirm_success(record_id: int, note: Optional[str] = None) -> bool:
        """
        确认成功
        
        Args:
            record_id: 记录 ID
            note: 确认备注
        
        Returns:
            bool: 是否成功
        """
        return confirm_invocation(
            record_id=record_id,
            confirmed_status=ConfirmInvocation.CONFIRMED_SUCCESS,
            confirm_note=note or "用户确认操作已成功",
        )
    
    @staticmethod
    def confirm_failed(record_id: int, note: Optional[str] = None) -> bool:
        """
        确认失败
        
        Args:
            record_id: 记录 ID
            note: 确认备注
        
        Returns:
            bool: 是否成功
        """
        return confirm_invocation(
            record_id=record_id,
            confirmed_status=ConfirmInvocation.CONFIRMED_FAILED,
            confirm_note=note or "用户确认操作失败",
        )
    
    @staticmethod
    def confirm_duplicate(record_id: int, note: Optional[str] = None) -> bool:
        """
        确认重复
        
        Args:
            record_id: 记录 ID
            note: 确认备注
        
        Returns:
            bool: 是否成功
        """
        return confirm_invocation(
            record_id=record_id,
            confirmed_status=ConfirmInvocation.CONFIRMED_DUPLICATE,
            confirm_note=note or "确认为重复操作",
        )
    
    @staticmethod
    def get_record(record_id: int) -> Optional[dict]:
        """获取记录详情"""
        return get_invocation_by_id(record_id)
    
    @staticmethod
    def get_confirmation_stats() -> dict:
        """获取确认统计"""
        stats = get_statistics()
        return {
            "total": stats["total"],
            "uncertain_count": stats["uncertain_count"],
            "confirmed_count": stats["confirmed_count"],
            "unconfirmed_count": stats["uncertain_count"] - stats["confirmed_count"],
            "confirmation_rate": (
                stats["confirmed_count"] / stats["uncertain_count"] * 100
                if stats["uncertain_count"] > 0 else 100
            ),
        }


# 便捷函数
def confirm_success(record_id: int, note: Optional[str] = None) -> bool:
    """确认成功"""
    return ConfirmInvocation.confirm_success(record_id, note)


def confirm_failed(record_id: int, note: Optional[str] = None) -> bool:
    """确认失败"""
    return ConfirmInvocation.confirm_failed(record_id, note)


def confirm_duplicate(record_id: int, note: Optional[str] = None) -> bool:
    """确认重复"""
    return ConfirmInvocation.confirm_duplicate(record_id, note)


path: capabilities/create_alarm.py
content: """创建闹钟能力"""

from typing import Optional, Dict, Any, List
import uuid


def create_alarm(
    time: str,
    label: Optional[str] = None,
    repeat: Optional[List[str]] = None,
    enabled: bool = True,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    创建闹钟
    
    Args:
        time: 闹钟时间（HH:MM 格式）
        label: 闹钟标签
        repeat: 重复日期（["mon", "tue", "wed", "thu", "fri", "sat", "sun"]）
        enabled: 是否启用
        dry_run: 是否预演模式
        
    Returns:
        创建结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "create_alarm",
            "time": time,
            "label": label,
            "message": f"预演模式：将创建 {time} 的闹钟"
        }
    
    alarm_id = f"alarm_{uuid.uuid4().hex[:16]}"
    
    # TODO: 调用小艺闹钟创建接口
    return {
        "success": True,
        "alarm_id": alarm_id,
        "time": time,
        "label": label,
        "repeat": repeat or [],
        "enabled": enabled,
        "message": f"闹钟已创建: {time}"
    }


def run(**kwargs):
    """能力入口"""
    return create_alarm(**kwargs)


path: capabilities/create_album.py
content: """创建相册能力"""

from typing import Optional, Dict, Any
import uuid


def create_album(
    name: str,
    description: Optional[str] = None,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    创建相册
    
    Args:
        name: 相册名称
        description: 相册描述
        dry_run: 是否预演模式
        
    Returns:
        创建结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "create_album",
            "name": name,
            "message": "预演模式：将创建相册"
        }
    
    album_id = f"album_{uuid.uuid4().hex[:16]}"
    
    # TODO: 调用小艺图库创建相册接口
    return {
        "success": True,
        "album_id": album_id,
        "name": name,
        "description": description,
        "message": "相册已创建"
    }


def run(**kwargs):
    """能力入口"""
    return create_album(**kwargs)


path: capabilities/create_contact.py
content: """创建联系人能力"""

from typing import Optional, Dict, Any
import uuid


def create_contact(
    name: str,
    phone: Optional[str] = None,
    email: Optional[str] = None,
    company: Optional[str] = None,
    notes: Optional[str] = None,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    创建联系人
    
    Args:
        name: 姓名
        phone: 电话号码
        email: 邮箱
        company: 公司
        notes: 备注
        dry_run: 是否预演模式
        
    Returns:
        创建结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "create_contact",
            "name": name,
            "message": "预演模式：将创建联系人"
        }
    
    contact_id = f"contact_{uuid.uuid4().hex[:16]}"
    
    # TODO: 调用小艺联系人创建接口
    return {
        "success": True,
        "contact_id": contact_id,
        "name": name,
        "phone": phone,
        "email": email,
        "company": company,
        "notes": notes,
        "message": "联系人已创建"
    }


def run(**kwargs):
    """能力入口"""
    return create_contact(**kwargs)


path: capabilities/delete_alarm.py
content: """删除闹钟能力"""

from typing import Dict, Any


def delete_alarm(
    alarm_id: str,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    删除闹钟
    
    Args:
        alarm_id: 闹钟ID
        dry_run: 是否预演模式
        
    Returns:
        删除结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "delete_alarm",
            "alarm_id": alarm_id,
            "message": "预演模式：将删除闹钟"
        }
    
    # TODO: 调用小艺闹钟删除接口
    return {
        "success": True,
        "alarm_id": alarm_id,
        "deleted": True,
        "message": "闹钟已删除"
    }


def delete_alarms_batch(
    alarm_ids: list,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    批量删除闹钟
    
    Args:
        alarm_ids: 闹钟ID列表
        dry_run: 是否预演模式
        
    Returns:
        删除结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "delete_alarms_batch",
            "count": len(alarm_ids),
            "message": f"预演模式：将删除 {len(alarm_ids)} 个闹钟"
        }
    
    deleted = []
    failed = []
    
    for alarm_id in alarm_ids:
        result = delete_alarm(alarm_id, dry_run=False)
        if result.get("success"):
            deleted.append(alarm_id)
        else:
            failed.append(alarm_id)
    
    return {
        "success": len(failed) == 0,
        "deleted_count": len(deleted),
        "failed_count": len(failed),
        "deleted": deleted,
        "failed": failed
    }


def run(**kwargs):
    """能力入口"""
    if "alarm_ids" in kwargs:
        return delete_alarms_batch(**kwargs)
    else:
        return delete_alarm(**kwargs)


path: capabilities/delete_calendar_event.py
content: """删除日程事件能力"""

from typing import Optional, Dict, Any
import uuid


def delete_calendar_event(
    event_id: str,
    reason: Optional[str] = None,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    删除日程事件
    
    Args:
        event_id: 事件ID
        reason: 删除原因
        dry_run: 是否预演模式
        
    Returns:
        包含删除结果的字典
    """
    from platform_adapter import invocation_ledger as ledger_module
    from platform_adapter.xiaoyi_adapter import XiaoyiAdapter
    
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "delete_calendar_event",
            "event_id": event_id,
            "message": "预演模式：将删除日程事件"
        }
    
    # 调用平台适配器
    adapter = XiaoyiAdapter()
    result = adapter.delete_calendar_event(
        event_id=event_id,
        idempotency_key=f"del_cal_{uuid.uuid4().hex[:16]}",
        metadata={"reason": reason}
    )
    
    # 记录审计
    pass
    ledger_module.record_audit(
        action="delete_calendar_event",
        event_id=event_id,
        reason=reason,
        result=result
    )
    
    # 解释结果
    if result.get("success"):
        result["explanation"] = "日程事件已删除"
    elif result.get("error_code") == "EVENT_NOT_FOUND":
        result["explanation"] = "日程事件不存在或已被删除"
    else:
        result["explanation"] = f"删除失败: {result.get('error', '未知原因')}"
    
    return result


def run(**kwargs):
    """能力入口"""
    return delete_calendar_event(**kwargs)


path: capabilities/delete_contact.py
content: """删除联系人能力"""

from typing import Dict, Any


def delete_contact(
    contact_id: str,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    删除联系人
    
    Args:
        contact_id: 联系人ID
        dry_run: 是否预演模式
        
    Returns:
        删除结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "delete_contact",
            "contact_id": contact_id,
            "message": "预演模式：将删除联系人"
        }
    
    # TODO: 调用小艺联系人删除接口
    return {
        "success": True,
        "contact_id": contact_id,
        "deleted": True,
        "message": "联系人已删除"
    }


def run(**kwargs):
    """能力入口"""
    return delete_contact(**kwargs)


path: capabilities/delete_file.py
content: """删除文件能力"""

from typing import Dict, Any


def delete_file(
    file_id: str,
    permanent: bool = False,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    删除文件
    
    Args:
        file_id: 文件ID
        permanent: 是否永久删除（否则移到回收站）
        dry_run: 是否预演模式
        
    Returns:
        删除结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "delete_file",
            "file_id": file_id,
            "permanent": permanent,
            "message": "预演模式：将删除文件" + ("（永久）" if permanent else "（移到回收站）")
        }
    
    # TODO: 调用小艺文件删除接口
    return {
        "success": True,
        "file_id": file_id,
        "permanent": permanent,
        "deleted": True,
        "message": "文件已删除" + ("（永久）" if permanent else "（已移到回收站）")
    }


def delete_files_batch(
    file_ids: list,
    permanent: bool = False,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    批量删除文件
    
    Args:
        file_ids: 文件ID列表
        permanent: 是否永久删除
        dry_run: 是否预演模式
        
    Returns:
        删除结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "delete_files_batch",
            "count": len(file_ids),
            "message": f"预演模式：将删除 {len(file_ids)} 个文件"
        }
    
    if len(file_ids) > 20:
        return {
            "success": False,
            "error": f"批次大小超过限制: {len(file_ids)} > 20"
        }
    
    deleted = []
    failed = []
    
    for file_id in file_ids:
        result = delete_file(file_id, permanent=permanent, dry_run=False)
        if result.get("success"):
            deleted.append(file_id)
        else:
            failed.append(file_id)
    
    return {
        "success": len(failed) == 0,
        "deleted_count": len(deleted),
        "failed_count": len(failed),
        "deleted": deleted,
        "failed": failed
    }


def run(**kwargs):
    """能力入口"""
    if "file_ids" in kwargs:
        return delete_files_batch(**kwargs)
    else:
        return delete_file(**kwargs)


path: capabilities/delete_note.py
content: """删除备忘录能力"""

from typing import Optional, Dict, Any
import uuid


def delete_note(
    note_id: str,
    reason: Optional[str] = None,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    删除备忘录
    
    Args:
        note_id: 备忘录ID
        reason: 删除原因
        dry_run: 是否预演模式
        
    Returns:
        包含删除结果的字典
    """
    from platform_adapter import invocation_ledger as ledger_module
    from platform_adapter.xiaoyi_adapter import XiaoyiAdapter
    
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "delete_note",
            "note_id": note_id,
            "message": "预演模式：将删除备忘录"
        }
    
    # 调用平台适配器
    adapter = XiaoyiAdapter()
    result = adapter.delete_note(
        note_id=note_id,
        idempotency_key=f"del_note_{uuid.uuid4().hex[:16]}",
        metadata={"reason": reason}
    )
    
    # 记录审计
    pass
    ledger_module.record_audit(
        action="delete_note",
        note_id=note_id,
        reason=reason,
        result=result
    )
    
    return result


def run(**kwargs):
    """能力入口"""
    return delete_note(**kwargs)


path: capabilities/delete_photo.py
content: """删除照片能力"""

from typing import Optional, Dict, Any


def delete_photo(
    photo_id: str,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    删除照片
    
    Args:
        photo_id: 照片ID
        dry_run: 是否预演模式
        
    Returns:
        删除结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "delete_photo",
            "photo_id": photo_id,
            "message": "预演模式：将删除照片"
        }
    
    # TODO: 调用小艺图库删除接口
    return {
        "success": True,
        "photo_id": photo_id,
        "deleted": True,
        "message": "照片已删除"
    }


def delete_photos_batch(
    photo_ids: list,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    批量删除照片
    
    Args:
        photo_ids: 照片ID列表
        dry_run: 是否预演模式
        
    Returns:
        删除结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "delete_photos_batch",
            "count": len(photo_ids),
            "message": f"预演模式：将删除 {len(photo_ids)} 张照片"
        }
    
    # 检查批次大小
    if len(photo_ids) > 20:
        return {
            "success": False,
            "error": f"批次大小超过限制: {len(photo_ids)} > 20"
        }
    
    deleted = []
    failed = []
    
    for photo_id in photo_ids:
        result = delete_photo(photo_id, dry_run=False)
        if result.get("success"):
            deleted.append(photo_id)
        else:
            failed.append(photo_id)
    
    return {
        "success": len(failed) == 0,
        "deleted_count": len(deleted),
        "failed_count": len(failed),
        "deleted": deleted,
        "failed": failed
    }


def run(**kwargs):
    """能力入口"""
    if "photo_ids" in kwargs:
        return delete_photos_batch(**kwargs)
    else:
        return delete_photo(**kwargs)


path: capabilities/delete_xiaoyi_note.py
content: """小艺帮记删除能力"""

from typing import Dict, Any


def delete_xiaoyi_note(
    note_id: str,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    删除小艺帮记中的笔记
    
    Args:
        note_id: 笔记ID
        dry_run: 是否预演模式
        
    Returns:
        删除结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "delete_xiaoyi_note",
            "note_id": note_id,
            "message": "预演模式：将删除笔记"
        }
    
    # TODO: 调用小艺帮记删除接口
    return {
        "success": True,
        "note_id": note_id,
        "deleted": True,
        "message": "笔记已删除"
    }


def run(**kwargs):
    """能力入口"""
    return delete_xiaoyi_note(**kwargs)


path: capabilities/diagnostics.py
content: """
诊断能力 - 真实实现
调用 RuntimeSelfCheck
"""

from typing import Dict, Any
import sys
from pathlib import Path

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

# 简化实现，避免依赖缺失的 diagnostics 模块
class RuntimeSelfCheck:
    """运行时自检"""
    def run(self, full: bool = False) -> Dict[str, Any]:
        return {"status": "ok", "checks": []}


class DiagnosticsCapability:
    """诊断能力"""
    
    name = "diagnostics"
    description = "运行系统诊断"
    
    async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
        """
        执行系统诊断
        
        Args:
            params: {} 或 {"full": true}
        
        Returns:
            {
                "success": bool,
                "overall_status": str,
                "checks": list,
                "summary": dict,
                "timestamp": str
            }
        """
        try:
            checker = RuntimeSelfCheck()
            result = await checker.run_all_checks()
            
            return {
                "success": result.get("success", False),
                "overall_status": result.get("overall_status", "unknown"),
                "checks": result.get("checks", []),
                "summary": result.get("summary", {}),
                "timestamp": result.get("timestamp")
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "error_code": "DIAGNOSTICS_FAILED",
                "overall_status": "error"
            }


path: capabilities/explain_invocation_status.py
content: """
解释调用状态能力
根据 normalized_status / confirmed_status 生成用户友好的解释
"""

from typing import Optional, Dict, Any
from pathlib import Path
import sys

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from platform_adapter.invocation_ledger import get_invocation_by_id


class ExplainInvocationStatus:
    """解释调用状态"""
    
    # 状态解释模板
    EXPLANATIONS = {
        "completed": {
            "title": "操作已完成",
            "description": "该操作已成功执行。",
            "action": "无需额外操作。",
        },
        "queued_for_delivery": {
            "title": "已提交等待处理",
            "description": "请求已提交，正在等待平台处理。",
            "action": "请稍后检查结果。",
        },
        "timeout": {
            "title": "请求超时",
            "description": "请求超时，当前无法确认操作是否已执行。",
            "action": "请检查实际结果，并告知助手以便记录确认状态。",
        },
        "result_uncertain": {
            "title": "结果不确定",
            "description": "操作结果不确定，为避免重复操作，系统未自动重试。",
            "action": "请人工确认实际结果，并告知助手。",
        },
        "auth_required": {
            "title": "需要授权",
            "description": "该能力需要授权才能使用。",
            "action": "请完成授权后再试。",
        },
        "failed": {
            "title": "操作失败",
            "description": "操作执行失败。",
            "action": "可以稍后重试，或联系支持。",
        },
    }
    
    # 确认状态解释
    CONFIRMED_EXPLANATIONS = {
        "confirmed_success": {
            "title": "已确认成功",
            "description": "经人工确认，该操作已成功执行。",
            "action": "无需额外操作。",
        },
        "confirmed_failed": {
            "title": "已确认失败",
            "description": "经人工确认，该操作未能成功执行。",
            "action": "可以手动重试或联系支持。",
        },
        "confirmed_duplicate": {
            "title": "已确认重复",
            "description": "经人工确认，该操作与其他记录重复。",
            "action": "无需额外操作。",
        },
    }
    
    # 能力名称映射
    CAPABILITY_NAMES = {
        "MESSAGE_SENDING": "短信发送",
        "TASK_SCHEDULING": "日程创建",
        "STORAGE": "备忘录",
        "NOTIFICATION": "通知推送",
    }
    
    @staticmethod
    def explain(record_id: int) -> Dict[str, Any]:
        """
        解释指定记录的状态
        
        Args:
            record_id: 记录 ID
        
        Returns:
            dict: 解释结果
        """
        record = get_invocation_by_id(record_id)
        if not record:
            return {
                "found": False,
                "error": f"记录 #{record_id} 不存在",
            }
        
        return ExplainInvocationStatus.explain_record(record)
    
    @staticmethod
    def explain_record(record: Dict[str, Any]) -> Dict[str, Any]:
        """
        解释记录状态
        
        Args:
            record: 记录字典
        
        Returns:
            dict: 解释结果
        """
        status = record.get("normalized_status", "unknown")
        confirmed_status = record.get("confirmed_status")
        capability = record.get("capability", "unknown")
        
        # 获取基础解释
        if confirmed_status and confirmed_status in ExplainInvocationStatus.CONFIRMED_EXPLANATIONS:
            explanation = ExplainInvocationStatus.CONFIRMED_EXPLANATIONS[confirmed_status].copy()
        elif status in ExplainInvocationStatus.EXPLANATIONS:
            explanation = ExplainInvocationStatus.EXPLANATIONS[status].copy()
        else:
            explanation = {
                "title": "未知状态",
                "description": f"状态: {status}",
                "action": "请联系支持。",
            }
        
        # 添加能力名称
        cap_name = ExplainInvocationStatus.CAPABILITY_NAMES.get(capability, capability)
        
        # 构建完整解释
        result = {
            "found": True,
            "record_id": record.get("id"),
            "capability": capability,
            "capability_name": cap_name,
            "status": status,
            "confirmed_status": confirmed_status,
            "title": f"{cap_name}: {explanation['title']}",
            "description": explanation["description"],
            "action": explanation["action"],
            "created_at": record.get("created_at"),
            "elapsed_ms": record.get("elapsed_ms"),
        }
        
        # 添加确认信息
        if confirmed_status:
            result["confirmed_at"] = record.get("confirmed_at")
            result["confirm_note"] = record.get("confirm_note")
        
        # 添加特殊建议
        if status in ["timeout", "result_uncertain"] and not confirmed_status:
            result["recommendation"] = ExplainInvocationStatus._get_recommendation(capability)
        
        return result
    
    @staticmethod
    def _get_recommendation(capability: str) -> str:
        """获取特殊建议"""
        recommendations = {
            "MESSAGE_SENDING": "请检查手机是否收到短信。",
            "TASK_SCHEDULING": "请检查日历是否有该日程。",
            "STORAGE": "请检查备忘录列表。",
            "NOTIFICATION": "请检查负一屏是否有该通知。",
        }
        return recommendations.get(capability, "请检查实际结果。")
    
    @staticmethod
    def format_explanation(explanation: Dict[str, Any]) -> str:
        """
        格式化解释为用户友好的文本
        
        Args:
            explanation: 解释字典
        
        Returns:
            str: 格式化的文本
        """
        if not explanation.get("found"):
            return explanation.get("error", "记录不存在")
        
        lines = [
            f"📋 {explanation['title']}",
            "",
            f"状态: {explanation['status']}",
            f"时间: {explanation.get('created_at', '未知')}",
            "",
            f"📖 {explanation['description']}",
            "",
            f"💡 {explanation['action']}",
        ]
        
        if explanation.get("recommendation"):
            lines.append("")
            lines.append(f"🔍 {explanation['recommendation']}")
        
        if explanation.get("confirmed_status"):
            lines.append("")
            lines.append(f"✅ 已确认: {explanation['confirmed_status']}")
            if explanation.get("confirm_note"):
                lines.append(f"   备注: {explanation['confirm_note']}")
        
        return "\n".join(lines)


# 便捷函数
def explain_status(record_id: int) -> str:
    """解释状态并返回格式化文本"""
    explanation = ExplainInvocationStatus.explain(record_id)
    return ExplainInvocationStatus.format_explanation(explanation)


def explain_record(record: Dict[str, Any]) -> str:
    """解释记录并返回格式化文本"""
    explanation = ExplainInvocationStatus.explain_record(record)
    return ExplainInvocationStatus.format_explanation(explanation)


path: capabilities/explain_message_result.py
content: """解释消息发送结果能力"""

from typing import Dict, Any
from platform_adapter import invocation_ledger as ledger_module
from platform_adapter.user_messages import get_user_message


def explain_message_result(invocation_id: int) -> Dict[str, Any]:
    """
    解释消息发送结果
    
    Args:
        invocation_id: 调用记录ID
        
    Returns:
        包含解释信息的字典
    """
    ledger = ledger_module
    
    records = ledger_module.get_invocation_by_id(invocation_id)
    if not records:
        return {
            "success": False,
            "error": f"未找到记录 #{invocation_id}"
        }
    
    record = records[0] if isinstance(records, list) else records
    
    # 检查是否是消息发送
    if record.get("capability") != "MESSAGE_SENDING":
        return {
            "success": False,
            "error": "只能解释 MESSAGE_SENDING 类型的记录"
        }
    
    normalized_status = record.get("normalized_status", "unknown")
    error_code = record.get("error_code")
    confirmed_status = record.get("confirmed_status")
    
    # 生成用户友好的解释
    explanation = _generate_explanation(
        normalized_status=normalized_status,
        error_code=error_code,
        confirmed_status=confirmed_status
    )
    
    return {
        "success": True,
        "invocation_id": invocation_id,
        "current_status": normalized_status,
        "confirmed_status": confirmed_status,
        "error_code": error_code,
        "is_success": normalized_status == "completed",
        "needs_confirmation": normalized_status == "result_uncertain",
        "explanation": explanation["summary"],
        "details": explanation["details"],
        "next_steps": explanation["next_steps"],
        "user_message": get_user_message(error_code) if error_code else None
    }


def _generate_explanation(
    normalized_status: str,
    error_code: str,
    confirmed_status: str
) -> Dict[str, Any]:
    """生成解释"""
    
    explanations = {
        "completed": {
            "summary": "消息发送成功",
            "details": "消息已成功送达目标设备。",
            "next_steps": ["无需进一步操作"]
        },
        "queued_for_delivery": {
            "summary": "消息正在排队发送",
            "details": "消息已加入发送队列，等待处理。",
            "next_steps": ["稍后查询状态确认是否发送成功"]
        },
        "failed": {
            "summary": "消息发送失败",
            "details": f"发送过程中发生错误: {error_code or '未知错误'}",
            "next_steps": ["检查错误原因", "考虑重发消息"]
        },
        "timeout": {
            "summary": "消息发送超时",
            "details": "发送请求超时，无法确定消息是否送达。",
            "next_steps": ["查询消息状态", "如未送达可考虑重发"]
        },
        "result_uncertain": {
            "summary": "消息发送结果不确定",
            "details": "发送请求已发出，但无法确认是否成功送达。",
            "next_steps": [
                "等待一段时间后查询状态",
                "手动确认发送结果",
                "如确认失败可重发"
            ]
        },
        "auth_required": {
            "summary": "需要授权",
            "details": "消息发送需要授权，请先完成授权流程。",
            "next_steps": ["完成授权后重试"]
        }
    }
    
    base = explanations.get(normalized_status, {
        "summary": f"状态: {normalized_status}",
        "details": "未知状态",
        "next_steps": ["联系支持"]
    })
    
    # 如果已确认，补充确认信息
    if confirmed_status:
        if confirmed_status == "confirmed_success":
            base["summary"] += " (已确认成功)"
            base["next_steps"] = ["无需进一步操作"]
        elif confirmed_status == "confirmed_failed":
            base["summary"] += " (已确认失败)"
            base["next_steps"] = ["考虑重发消息"]
        elif confirmed_status == "confirmed_duplicate":
            base["summary"] += " (已确认重复)"
            base["next_steps"] = ["无需进一步操作"]
    
    return base


def run(**kwargs):
    """能力入口"""
    return explain_message_result(**kwargs)


path: capabilities/explain_notification_auth_state.py
content: """解释通知授权状态能力"""

from typing import Dict, Any


def explain_notification_auth_state() -> Dict[str, Any]:
    """
    解释通知授权状态
    
    Returns:
        包含授权状态解释的字典
    """
    from capabilities.refresh_notification_auth import refresh_notification_auth
    
    # 获取当前状态
    auth_result = refresh_notification_auth()
    status = auth_result.get("auth_status", "unknown")
    
    # 生成用户友好的解释
    explanations = {
        "configured": {
            "summary": "通知授权已配置",
            "details": "您的设备已授权接收通知推送。",
            "can_send_notifications": True,
            "next_steps": ["可以直接发送通知", "无需额外操作"]
        },
        "not_configured": {
            "summary": "通知授权未配置",
            "details": "您尚未授权接收通知推送。需要配置授权后才能发送通知。",
            "can_send_notifications": False,
            "next_steps": [
                "请在设备上打开小艺设置",
                "找到通知权限设置",
                "开启通知授权",
                "完成后重新检查状态"
            ]
        },
        "expired": {
            "summary": "通知授权已过期",
            "details": "您的通知授权已过期，需要重新授权。",
            "can_send_notifications": False,
            "next_steps": [
                "请重新进行授权流程",
                "授权完成后重新检查状态"
            ]
        },
        "unknown": {
            "summary": "无法确定授权状态",
            "details": "系统无法确定当前的通知授权状态。",
            "can_send_notifications": False,
            "next_steps": [
                "请稍后重试",
                "如问题持续，请联系支持"
            ]
        }
    }
    
    explanation = explanations.get(status, explanations["unknown"])
    
    return {
        "success": True,
        "auth_status": status,
        "summary": explanation["summary"],
        "details": explanation["details"],
        "can_send_notifications": explanation["can_send_notifications"],
        "next_steps": explanation["next_steps"]
    }


def run(**kwargs):
    """能力入口"""
    return explain_notification_auth_state()


path: capabilities/export_history.py
content: """
导出历史能力 - 真实实现
读取 tasks / task_runs / task_steps / task_events
"""

from typing import Dict, Any
from datetime import datetime
import sqlite3
import sys
from pathlib import Path

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))


class ExportHistoryCapability:
    """导出历史能力"""
    
    name = "export_history"
    description = "导出任务历史记录"
    
    async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
        """
        导出任务历史
        
        Args:
            params: {
                "task_id": 任务ID,
                "format": "json" | "dict"
            }
        
        Returns:
            {
                "success": bool,
                "task_id": str,
                "task": dict,
                "runs": list,
                "steps": list,
                "events": list,
                "record_count": int,
                "exported_at": str
            }
        """
        task_id = params.get("task_id")
        format_type = params.get("format", "json")
        
        if not task_id:
            return {
                "success": False,
                "error": "缺少 task_id",
                "error_code": "MISSING_TASK_ID"
            }
        
        db_path = project_root / "data" / "tasks.db"
        
        if not db_path.exists():
            return {
                "success": False,
                "error": "数据库不存在",
                "error_code": "DATABASE_NOT_FOUND",
                "task_id": task_id
            }
        
        try:
            conn = sqlite3.connect(str(db_path))
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            # 查询任务
            cursor.execute("SELECT * FROM tasks WHERE id = ?", (task_id,))
            task_row = cursor.fetchone()
            task = dict(task_row) if task_row else None
            
            if not task:
                conn.close()
                return {
                    "success": False,
                    "error": "任务不存在",
                    "error_code": "TASK_NOT_FOUND",
                    "task_id": task_id
                }
            
            # 查询运行记录
            cursor.execute("SELECT * FROM task_runs WHERE task_id = ? ORDER BY created_at DESC", (task_id,))
            runs = [dict(row) for row in cursor.fetchall()]
            
            # 查询步骤记录
            steps = []
            for run in runs:
                cursor.execute("SELECT * FROM task_steps WHERE task_run_id = ? ORDER BY step_no", (run["id"],))
                steps.extend([dict(row) for row in cursor.fetchall()])
            
            # 查询事件记录
            cursor.execute("SELECT * FROM task_events WHERE task_id = ? ORDER BY created_at DESC", (task_id,))
            events = [dict(row) for row in cursor.fetchall()]
            
            conn.close()
            
            record_count = 1 + len(runs) + len(steps) + len(events)
            
            return {
                "success": True,
                "task_id": task_id,
                "task": task,
                "runs": runs,
                "steps": steps,
                "events": events,
                "record_count": record_count,
                "exported_at": datetime.now().isoformat()
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "error_code": "EXPORT_FAILED",
                "task_id": task_id
            }


path: capabilities/get_location.py
content: """获取位置能力"""

from typing import Optional, Dict, Any


def get_location(
    timeout: int = 60,
) -> Dict[str, Any]:
    """
    获取当前位置
    
    Args:
        timeout: 超时时间（秒）
        
    Returns:
        位置信息
    """
    try:
        # 调用内置工具获取位置
        import subprocess
        result = subprocess.run(
            ["python", "-c", "from tools import get_user_location; print(get_user_location())"],
            capture_output=True,
            text=True,
            timeout=timeout
        )
        
        if result.returncode == 0:
            import json
            location = json.loads(result.stdout.strip())
            return {
                "success": True,
                "latitude": location.get("latitude"),
                "longitude": location.get("longitude"),
                "accuracy": location.get("accuracy"),
                "timestamp": location.get("timestamp")
            }
        else:
            return {
                "success": False,
                "error": result.stderr or "获取位置失败"
            }
    except Exception as e:
        return {
            "success": False,
            "error": str(e)
        }


def get_address_from_location(
    latitude: float,
    longitude: float,
) -> Dict[str, Any]:
    """
    根据经纬度获取地址（逆地理编码）
    
    Args:
        latitude: 纬度
        longitude: 经度
        
    Returns:
        地址信息
    """
    # TODO: 调用逆地理编码服务
    return {
        "success": True,
        "latitude": latitude,
        "longitude": longitude,
        "address": "未知地址",
        "country": None,
        "province": None,
        "city": None,
        "district": None,
        "street": None
    }


def get_location_history(
    limit: int = 20,
) -> Dict[str, Any]:
    """
    获取位置历史
    
    Args:
        limit: 返回数量限制
        
    Returns:
        位置历史记录
    """
    # TODO: 调用位置历史接口
    return {
        "success": True,
        "locations": [],
        "count": 0,
        "limit": limit
    }


def run(**kwargs):
    """能力入口"""
    action = kwargs.pop("action", "get")
    
    if action == "get":
        return get_location(**kwargs)
    elif action == "address":
        return get_address_from_location(**kwargs)
    elif action == "history":
        return get_location_history(**kwargs)
    else:
        return {"success": False, "error": f"未知操作: {action}"}


path: capabilities/list_calendar_events.py
content: """列出日程事件能力"""

from typing import Optional, Dict, Any
from datetime import datetime, timedelta
import json


def list_calendar_events(
    limit: int = 20,
    start_after: Optional[str] = None,
    start_before: Optional[str] = None,
    days: int = 7,
    offset: int = 0,
) -> Dict[str, Any]:
    """
    列出日程事件
    
    Args:
        limit: 返回数量限制
        start_after: 开始时间下限
        start_before: 开始时间上限
        days: 查询最近N天
        offset: 偏移量
        
    Returns:
        包含事件列表的字典
    """
    from platform_adapter import invocation_ledger as ledger_module
    
    pass
    
    # 默认时间范围
    if not start_after:
        start_after = datetime.now().isoformat()
    if not start_before:
        start_before = (datetime.now() + timedelta(days=days)).isoformat()
    
    # 查询 TASK_SCHEDULING 类型的记录
    records = ledger_module.query_by_capability(capability="TASK_SCHEDULING", limit=100)
    
    # 过滤和格式化
    events = []
    for r in records:
        request_params = r.get("request_params", {})
        if isinstance(request_params, str):
            try:
                request_params = json.loads(request_params)
            except:
                request_params = {}
        
        start_time = request_params.get("start_time")
        if start_time:
            if start_time < start_after or start_time > start_before:
                continue
        
        events.append({
            "invocation_id": r.get("id"),
            "event_id": request_params.get("event_id"),
            "title": request_params.get("title"),
            "start_time": start_time,
            "end_time": request_params.get("end_time"),
            "location": request_params.get("location"),
            "status": r.get("normalized_status"),
            "created_at": r.get("created_at"),
        })
    
    # 分页
    paginated = events[offset:offset + limit]
    
    return {
        "success": True,
        "count": len(paginated),
        "total": len(events),
        "limit": limit,
        "offset": offset,
        "events": paginated
    }


def run(**kwargs):
    """能力入口"""
    return list_calendar_events(**kwargs)


path: capabilities/list_recent_messages.py
content: """列出最近消息能力"""

from typing import Optional, List, Dict, Any
from datetime import datetime, timedelta
from platform_adapter import invocation_ledger as ledger_module


def list_recent_messages(
    limit: int = 20,
    status: Optional[str] = None,
    normalized_status: Optional[str] = None,
    confirmed_status: Optional[str] = None,
    days: int = 7,
    offset: int = 0,
) -> Dict[str, Any]:
    """
    列出最近的消息发送记录
    
    Args:
        limit: 返回数量限制
        status: 按原始状态过滤
        normalized_status: 按归一化状态过滤
        confirmed_status: 按确认状态过滤
        days: 查询最近N天
        offset: 偏移量
        
    Returns:
        包含消息列表的字典
    """
    ledger = ledger_module
    
    # 构建查询条件
    since = datetime.now() - timedelta(days=days)
    
    records = ledger_module.query_by_capability(
        capability="MESSAGE_SENDING",
        limit=limit + offset
    )
    
    # 过滤
    filtered = []
    for r in records:
        if status and r.get("status") != status:
            continue
        if normalized_status and r.get("normalized_status") != normalized_status:
            continue
        if confirmed_status and r.get("confirmed_status") != confirmed_status:
            continue
        filtered.append(r)
    
    # 分页
    paginated = filtered[offset:offset + limit]
    
    # 格式化输出
    formatted = []
    for r in paginated:
        formatted.append({
            "invocation_id": r.get("id"),
            "status": r.get("status"),
            "normalized_status": r.get("normalized_status"),
            "confirmed_status": r.get("confirmed_status"),
            "created_at": r.get("created_at"),
            "error_code": r.get("error_code"),
            "has_error": bool(r.get("error_code")),
        })
    
    return {
        "success": True,
        "count": len(formatted),
        "total": len(filtered),
        "limit": limit,
        "offset": offset,
        "messages": formatted
    }


def run(**kwargs):
    """能力入口"""
    return list_recent_messages(**kwargs)


path: capabilities/list_recent_notes.py
content: """列出最近备忘录能力"""

from typing import Dict, Any
from datetime import datetime, timedelta
import json


def list_recent_notes(
    limit: int = 20,
    days: int = 7,
    offset: int = 0,
) -> Dict[str, Any]:
    """
    列出最近的备忘录
    
    Args:
        limit: 返回数量限制
        days: 查询最近N天
        offset: 偏移量
        
    Returns:
        包含备忘录列表的字典
    """
    from platform_adapter import invocation_ledger as ledger_module
    
    pass
    
    # 查询 STORAGE 类型的记录
    records = ledger_module.query_by_capability(capability="STORAGE", limit=100)
    
    # 格式化
    notes = []
    for r in records:
        request_params = r.get("request_params", {})
        if isinstance(request_params, str):
            try:
                request_params = json.loads(request_params)
            except:
                request_params = {}
        
        notes.append({
            "invocation_id": r.get("id"),
            "note_id": request_params.get("note_id"),
            "title": request_params.get("title"),
            "content_preview": request_params.get("content", "")[:50] + "..." if len(request_params.get("content", "")) > 50 else request_params.get("content", ""),
            "status": r.get("normalized_status"),
            "created_at": r.get("created_at"),
        })
    
    # 分页
    paginated = notes[offset:offset + limit]
    
    return {
        "success": True,
        "count": len(paginated),
        "total": len(notes),
        "limit": limit,
        "offset": offset,
        "notes": paginated
    }


def run(**kwargs):
    """能力入口"""
    return list_recent_notes(**kwargs)


path: capabilities/make_call.py
content: """拨打电话能力"""

from typing import Optional, Dict, Any


def make_call(
    phone: str,
    contact_id: Optional[str] = None,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    拨打电话
    
    Args:
        phone: 电话号码
        contact_id: 联系人ID（可选）
        dry_run: 是否预演模式
        
    Returns:
        拨打结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "make_call",
            "phone": phone,
            "message": f"预演模式：将拨打 {phone}"
        }
    
    # TODO: 调用小艺电话拨打接口
    return {
        "success": True,
        "phone": phone,
        "contact_id": contact_id,
        "call_initiated": True,
        "message": f"正在拨打 {phone}"
    }


def end_call(dry_run: bool = False) -> Dict[str, Any]:
    """
    挂断电话
    
    Args:
        dry_run: 是否预演模式
        
    Returns:
        挂断结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "end_call",
            "message": "预演模式：将挂断电话"
        }
    
    # TODO: 调用小艺电话挂断接口
    return {
        "success": True,
        "call_ended": True,
        "message": "电话已挂断"
    }


def get_call_history(
    limit: int = 20,
    call_type: Optional[str] = None,
) -> Dict[str, Any]:
    """
    获取通话记录
    
    Args:
        limit: 返回数量限制
        call_type: 通话类型（incoming/outgoing/missed）
        
    Returns:
        通话记录
    """
    # TODO: 调用小艺通话记录接口
    return {
        "success": True,
        "calls": [],
        "count": 0,
        "limit": limit,
        "call_type": call_type
    }


def run(**kwargs):
    """能力入口"""
    action = kwargs.pop("action", "make")
    
    if action == "make":
        return make_call(**kwargs)
    elif action == "end":
        return end_call(**kwargs)
    elif action == "history":
        return get_call_history(**kwargs)
    else:
        return {"success": False, "error": f"未知操作: {action}"}


path: capabilities/manage_file.py
content: """移动/复制文件能力"""

from typing import Dict, Any


def move_file(
    file_id: str,
    destination: str,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    移动文件
    
    Args:
        file_id: 文件ID
        destination: 目标目录
        dry_run: 是否预演模式
        
    Returns:
        移动结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "move_file",
            "file_id": file_id,
            "destination": destination,
            "message": f"预演模式：将移动文件到 {destination}"
        }
    
    # TODO: 调用小艺文件移动接口
    return {
        "success": True,
        "file_id": file_id,
        "destination": destination,
        "moved": True,
        "message": f"文件已移动到 {destination}"
    }


def copy_file(
    file_id: str,
    destination: str,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    复制文件
    
    Args:
        file_id: 文件ID
        destination: 目标目录
        dry_run: 是否预演模式
        
    Returns:
        复制结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "copy_file",
            "file_id": file_id,
            "destination": destination,
            "message": f"预演模式：将复制文件到 {destination}"
        }
    
    # TODO: 调用小艺文件复制接口
    return {
        "success": True,
        "file_id": file_id,
        "destination": destination,
        "copied": True,
        "message": f"文件已复制到 {destination}"
    }


def rename_file(
    file_id: str,
    new_name: str,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    重命名文件
    
    Args:
        file_id: 文件ID
        new_name: 新文件名
        dry_run: 是否预演模式
        
    Returns:
        重命名结果
    """
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "rename_file",
            "file_id": file_id,
            "new_name": new_name,
            "message": f"预演模式：将重命名为 {new_name}"
        }
    
    # TODO: 调用小艺文件重命名接口
    return {
        "success": True,
        "file_id": file_id,
        "new_name": new_name,
        "renamed": True,
        "message": f"文件已重命名为 {new_name}"
    }


def run(**kwargs):
    """能力入口"""
    action = kwargs.pop("action", "move")
    
    if action == "move":
        return move_file(**kwargs)
    elif action == "copy":
        return copy_file(**kwargs)
    elif action == "rename":
        return rename_file(**kwargs)
    else:
        return {"success": False, "error": f"未知操作: {action}"}


path: capabilities/pause_task.py
content: """
暂停任务能力 - 真实实现
接入 TaskManager 任务内核
"""

from typing import Dict, Any
from datetime import datetime
import sys
from pathlib import Path

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from infrastructure.task_manager import get_task_manager


class PauseTaskCapability:
    """暂停任务能力"""
    
    name = "pause_task"
    description = "暂停正在运行的任务"
    
    async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
        """
        执行任务暂停
        
        Args:
            params: {
                "task_id": 任务ID
            }
        
        Returns:
            {
                "success": bool,
                "task_id": str,
                "status": str,
                "paused_at": str
            }
        """
        task_id = params.get("task_id")
        
        if not task_id:
            return {
                "success": False,
                "error": "缺少 task_id",
                "error_code": "MISSING_TASK_ID"
            }
        
        try:
            tm = get_task_manager()
            result = await tm.pause_task(task_id)
            
            return {
                "success": result.get("success", False),
                "task_id": task_id,
                "status": result.get("status", "paused"),
                "paused_at": datetime.now().isoformat()
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "error_code": "PAUSE_FAILED",
                "task_id": task_id
            }


path: capabilities/preview_side_effect.py
content: """副作用预览能力"""

from typing import Dict, Any, List, Optional
from datetime import datetime


def preview_side_effect(
    capability: str,
    params: Dict[str, Any],
) -> Dict[str, Any]:
    """
    预览副作用操作的效果
    
    Args:
        capability: 能力名称
        params: 参数
        
    Returns:
        预览结果
    """
    # 定义副作用能力
    side_effect_capabilities = [
        "send_message",
        "schedule_task",
        "create_note",
        "send_notification",
        "delete_calendar_event",
        "delete_note",
        "cancel_notification",
        "update_calendar_event",
        "update_note"
    ]
    
    if capability not in side_effect_capabilities:
        return {
            "success": True,
            "is_side_effect": False,
            "message": f"{capability} 不是副作用操作"
        }
    
    # 生成预览
    preview = _generate_preview(capability, params)
    
    return {
        "success": True,
        "is_side_effect": True,
        "capability": capability,
        "preview": preview,
        "warnings": preview.get("warnings", []),
        "estimated_effects": preview.get("effects", []),
        "generated_at": datetime.now().isoformat()
    }


def _generate_preview(capability: str, params: Dict[str, Any]) -> Dict[str, Any]:
    """生成预览"""
    previews = {
        "send_message": {
            "effects": [
                f"将发送短信到: {params.get('to', '未知')}",
                f"消息内容: {params.get('message', '')[:100]}...",
                "此操作会产生通信费用"
            ],
            "warnings": ["短信发送不可撤销"],
            "reversible": False
        },
        "schedule_task": {
            "effects": [
                f"将创建日程: {params.get('title', '无标题')}",
                f"开始时间: {params.get('start_time', '未知')}",
                f"结束时间: {params.get('end_time', '未知')}",
                f"地点: {params.get('location', '无')}"
            ],
            "warnings": [],
            "reversible": True,
            "reverse_action": "delete_calendar_event"
        },
        "create_note": {
            "effects": [
                f"将创建备忘录: {params.get('title', '无标题')}",
                f"内容长度: {len(params.get('content', ''))} 字符"
            ],
            "warnings": [],
            "reversible": True,
            "reverse_action": "delete_note"
        },
        "send_notification": {
            "effects": [
                f"将推送通知: {params.get('title', '无标题')}",
                f"内容: {params.get('content', '')[:100]}..."
            ],
            "warnings": [],
            "reversible": False
        },
        "delete_calendar_event": {
            "effects": [
                f"将删除日程: {params.get('event_id', '未知')}",
                "此操作不可撤销"
            ],
            "warnings": ["删除操作不可撤销"],
            "reversible": False
        },
        "delete_note": {
            "effects": [
                f"将删除备忘录: {params.get('note_id', '未知')}",
                "此操作不可撤销"
            ],
            "warnings": ["删除操作不可撤销"],
            "reversible": False
        },
        "cancel_notification": {
            "effects": [
                f"将取消通知: {params.get('notification_id', '未知')}"
            ],
            "warnings": ["取消后需要重新发送"],
            "reversible": False
        },
        "update_calendar_event": {
            "effects": [
                f"将更新日程: {params.get('event_id', '未知')}",
                f"更新内容: {params.get('updates', {})}"
            ],
            "warnings": [],
            "reversible": True,
            "reverse_action": "restore_previous_state"
        },
        "update_note": {
            "effects": [
                f"将更新备忘录: {params.get('note_id', '未知')}",
                f"更新内容: {params.get('updates', {})}"
            ],
            "warnings": [],
            "reversible": True,
            "reverse_action": "restore_previous_state"
        }
    }
    
    return previews.get(capability, {
        "effects": [f"将执行 {capability}"],
        "warnings": [],
        "reversible": False
    })


def batch_preview(
    actions: List[Dict[str, Any]],
) -> Dict[str, Any]:
    """
    批量预览副作用操作
    
    Args:
        actions: 操作列表 [{"capability": "...", "params": {...}}, ...]
        
    Returns:
        批量预览结果
    """
    previews = []
    all_effects = []
    all_warnings = []
    
    for action in actions:
        preview = preview_side_effect(
            capability=action.get("capability"),
            params=action.get("params", {})
        )
        previews.append(preview)
        
        if preview.get("is_side_effect"):
            all_effects.extend(preview.get("estimated_effects", []))
            all_warnings.extend(preview.get("warnings", []))
    
    return {
        "success": True,
        "total_actions": len(actions),
        "side_effect_count": len([p for p in previews if p.get("is_side_effect")]),
        "previews": previews,
        "all_effects": all_effects,
        "all_warnings": all_warnings,
        "has_warnings": len(all_warnings) > 0
    }


def run(**kwargs):
    """能力入口"""
    return preview_side_effect(**kwargs)


path: capabilities/query_alarm.py
content: """查询闹钟能力"""

from typing import Optional, Dict, Any, List


def query_alarm(
    alarm_id: Optional[str] = None,
    enabled: Optional[bool] = None,
) -> Dict[str, Any]:
    """
    查询闹钟
    
    Args:
        alarm_id: 闹钟ID
        enabled: 是否启用
        
    Returns:
        闹钟信息
    """
    try:
        result = _call_xiaoyi_alarm("query", {
            "alarm_id": alarm_id,
            "enabled": enabled
        })
        
        return {
            "success": True,
            "alarms": result.get("alarms", []),
            "count": len(result.get("alarms", []))
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "alarms": []
        }


def list_alarms(
    limit: int = 50,
    enabled_only: bool = False,
) -> Dict[str, Any]:
    """
    列出所有闹钟
    
    Args:
        limit: 返回数量限制
        enabled_only: 只返回启用的闹钟
        
    Returns:
        闹钟列表
    """
    try:
        result = _call_xiaoyi_alarm("list", {
            "limit": limit,
            "enabled_only": enabled_only
        })
        
        return {
            "success": True,
            "alarms": result.get("alarms", []),
            "count": len(result.get("alarms", [])),
            "enabled_only": enabled_only
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "alarms": []
        }


def _call_xiaoyi_alarm(action: str, params: dict) -> dict:
    """调用小艺闹钟能力"""
    from platform_adapter.device_tool_adapter import call_device_tool
    return call_device_tool("alarm", action, params)


def run(**kwargs):
    """能力入口"""
    action = kwargs.pop("action", "query")
    
    if action == "query":
        return query_alarm(**kwargs)
    elif action == "list":
        return list_alarms(**kwargs)
    else:
        return {"success": False, "error": f"未知操作: {action}"}


path: capabilities/query_calendar_event.py
content: """查询日程事件能力"""

from typing import Optional, Dict, Any, List
from datetime import datetime
import json


def query_calendar_event(
    event_id: Optional[str] = None,
    entity_id: Optional[str] = None,
    title: Optional[str] = None,
    start_after: Optional[str] = None,
    start_before: Optional[str] = None,
) -> Dict[str, Any]:
    """
    查询日程事件
    
    Args:
        event_id: 事件ID
        entity_id: 实体ID（用于追踪）
        title: 标题（模糊匹配）
        start_after: 开始时间下限
        start_before: 开始时间上限
        
    Returns:
        包含事件信息的字典
    """
    from platform_adapter import invocation_ledger as ledger_module
    
    pass
    
    # 查询 TASK_SCHEDULING 类型的记录
    records = ledger_module.query_by_capability(capability="TASK_SCHEDULING", limit=100)
    
    # 过滤
    filtered = []
    for r in records:
        request_params = r.get("request_params", {})
        if isinstance(request_params, str):
            try:
                request_params = json.loads(request_params)
            except:
                request_params = {}
        
        # 检查 event_id
        if event_id:
            if request_params.get("event_id") != event_id:
                continue
        
        # 检查 entity_id
        if entity_id:
            if request_params.get("entity_id") != entity_id:
                continue
        
        # 检查标题
        if title:
            event_title = request_params.get("title", "")
            if title.lower() not in event_title.lower():
                continue
        
        # 检查时间范围
        start_time = request_params.get("start_time")
        if start_after and start_time:
            if start_time < start_after:
                continue
        if start_before and start_time:
            if start_time > start_before:
                continue
        
        filtered.append({
            "invocation_id": r.get("id"),
            "event_id": request_params.get("event_id"),
            "entity_id": request_params.get("entity_id"),
            "title": request_params.get("title"),
            "start_time": request_params.get("start_time"),
            "end_time": request_params.get("end_time"),
            "status": r.get("status"),
            "normalized_status": r.get("normalized_status"),
            "created_at": r.get("created_at"),
        })
    
    return {
        "success": True,
        "count": len(filtered),
        "events": filtered
    }


def run(**kwargs):
    """能力入口"""
    return query_calendar_event(**kwargs)


path: capabilities/query_contact.py
content: """查询联系人能力"""

from typing import Optional, Dict, Any, List


def query_contact(
    contact_id: Optional[str] = None,
    name: Optional[str] = None,
    phone: Optional[str] = None,
) -> Dict[str, Any]:
    """
    查询联系人
    
    Args:
        contact_id: 联系人ID
        name: 姓名（模糊匹配）
        phone: 电话号码
        
    Returns:
        联系人信息
    """
    try:
        # 调用小艺联系人能力
        result = _call_xiaoyi_contact("query", {
            "contact_id": contact_id,
            "name": name,
            "phone": phone
        })
        
        return {
            "success": True,
            "contacts": result.get("contacts", []),
            "count": len(result.get("contacts", []))
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "contacts": []
        }


def list_contacts(
    limit: int = 50,
    offset: int = 0,
) -> Dict[str, Any]:
    """
    列出联系人
    
    Args:
        limit: 返回数量限制
        offset: 偏移量
        
    Returns:
        联系人列表
    """
    try:
        result = _call_xiaoyi_contact("list", {
            "limit": limit,
            "offset": offset
        })
        
        return {
            "success": True,
            "contacts": result.get("contacts", []),
            "count": len(result.get("contacts", [])),
            "limit": limit,
            "offset": offset
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "contacts": []
        }


def search_contacts(
    keyword: str,
    limit: int = 20,
) -> Dict[str, Any]:
    """
    搜索联系人
    
    Args:
        keyword: 搜索关键词
        limit: 返回数量限制
        
    Returns:
        搜索结果
    """
    try:
        result = _call_xiaoyi_contact("search", {
            "keyword": keyword,
            "limit": limit
        })
        
        return {
            "success": True,
            "keyword": keyword,
            "contacts": result.get("contacts", []),
            "count": len(result.get("contacts", []))
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "keyword": keyword,
            "contacts": []
        }


def _call_xiaoyi_contact(action: str, params: dict) -> dict:
    """调用小艺联系人能力"""
    from platform_adapter.device_tool_adapter import call_device_tool
    return call_device_tool("contact", action, params)


def run(**kwargs):
    """能力入口"""
    action = kwargs.pop("action", "query")
    
    if action == "query":
        return query_contact(**kwargs)
    elif action == "list":
        return list_contacts(**kwargs)
    elif action == "search":
        return search_contacts(**kwargs)
    else:
        return {"success": False, "error": f"未知操作: {action}"}


path: capabilities/query_file.py
content: """查询文件能力"""

from typing import Optional, Dict, Any, List


def query_file(
    file_id: Optional[str] = None,
    path: Optional[str] = None,
    name: Optional[str] = None,
) -> Dict[str, Any]:
    """
    查询文件
    
    Args:
        file_id: 文件ID
        path: 文件路径
        name: 文件名（模糊匹配）
        
    Returns:
        文件信息
    """
    try:
        result = _call_xiaoyi_file("query", {
            "file_id": file_id,
            "path": path,
            "name": name
        })
        
        return {
            "success": True,
            "files": result.get("files", []),
            "count": len(result.get("files", []))
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "files": []
        }


def list_files(
    directory: str = "/",
    limit: int = 50,
    offset: int = 0,
) -> Dict[str, Any]:
    """
    列出目录下的文件
    
    Args:
        directory: 目录路径
        limit: 返回数量限制
        offset: 偏移量
        
    Returns:
        文件列表
    """
    try:
        result = _call_xiaoyi_file("list", {
            "directory": directory,
            "limit": limit,
            "offset": offset
        })
        
        return {
            "success": True,
            "directory": directory,
            "files": result.get("files", []),
            "count": len(result.get("files", [])),
            "limit": limit,
            "offset": offset
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "files": []
        }


def search_files(
    keyword: str,
    file_type: Optional[str] = None,
    limit: int = 20,
) -> Dict[str, Any]:
    """
    搜索文件
    
    Args:
        keyword: 搜索关键词
        file_type: 文件类型（如 pdf, doc, image）
        limit: 返回数量限制
        
    Returns:
        搜索结果
    """
    try:
        result = _call_xiaoyi_file("search", {
            "keyword": keyword,
            "file_type": file_type,
            "limit": limit
        })
        
        return {
            "success": True,
            "keyword": keyword,
            "file_type": file_type,
            "files": result.get("files", []),
            "count": len(result.get("files", []))
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "keyword": keyword,
            "files": []
        }


def _call_xiaoyi_file(action: str, params: dict) -> dict:
    """调用小艺文件管理能力"""
    from platform_adapter.device_tool_adapter import call_device_tool
    return call_device_tool("file", action, params)


def run(**kwargs):
    """能力入口"""
    action = kwargs.pop("action", "query")
    
    if action == "query":
        return query_file(**kwargs)
    elif action == "list":
        return list_files(**kwargs)
    elif action == "search":
        return search_files(**kwargs)
    else:
        return {"success": False, "error": f"未知操作: {action}"}


path: capabilities/query_message_status.py
content: """查询消息发送状态能力"""

from typing import Optional, Dict, Any
from platform_adapter import invocation_ledger as ledger_module


def query_message_status(
    task_id: Optional[str] = None,
    task_run_id: Optional[str] = None,
    idempotency_key: Optional[str] = None,
    invocation_id: Optional[int] = None,
) -> Dict[str, Any]:
    """
    查询消息发送状态
    
    Args:
        task_id: 任务ID
        task_run_id: 任务运行ID
        idempotency_key: 幂等键
        invocation_id: 调用记录ID
        
    Returns:
        包含状态信息的字典
    """
    ledger = ledger_module
    
    # 枹据不同查询条件查询
    if invocation_id:
        records = ledger_module.get_invocation_by_id(invocation_id)
    elif idempotency_key:
        records = ledger_module.get_invocation_by_idempotency_key(idempotency_key)
    elif task_id:
        records = ledger_module.query_by_task_id(task_id)
    elif task_run_id:
        records = ledger.query_by_task_run_id(task_run_id)
    else:
        return {
            "success": False,
            "error": "必须提供至少一个查询条件",
            "records": []
        }
    
    if not records:
        return {
            "success": True,
            "found": False,
            "message": "未找到匹配的记录",
            "records": []
        }
    
    # 格式化输出
    formatted_records = []
    for r in records:
        formatted_records.append({
            "invocation_id": r.get("id"),
            "capability": r.get("capability"),
            "status": r.get("status"),
            "normalized_status": r.get("normalized_status"),
            "confirmed_status": r.get("confirmed_status"),
            "created_at": r.get("created_at"),
            "error_code": r.get("error_code"),
            "error_message": r.get("error_message"),
            "idempotency_key": r.get("idempotency_key"),
            "task_id": r.get("task_id"),
            "task_run_id": r.get("task_run_id"),
        })
    
    return {
        "success": True,
        "found": True,
        "count": len(formatted_records),
        "records": formatted_records
    }


def run(**kwargs):
    """能力入口"""
    return query_message_status(**kwargs)


path: capabilities/query_note.py
content: """查询备忘录能力"""

from typing import Optional, Dict, Any
import json


def query_note(
    note_id: Optional[str] = None,
    entity_id: Optional[str] = None,
    title: Optional[str] = None,
) -> Dict[str, Any]:
    """
    查询备忘录
    
    Args:
        note_id: 备忘录ID
        entity_id: 实体ID（用于追踪）
        title: 标题（模糊匹配）
        
    Returns:
        包含备忘录信息的字典
    """
    from platform_adapter import invocation_ledger as ledger_module
    
    pass
    
    # 查询 STORAGE 类型的记录
    records = ledger_module.query_by_capability(capability="STORAGE", limit=100)
    
    # 过滤
    filtered = []
    for r in records:
        request_params = r.get("request_params", {})
        if isinstance(request_params, str):
            try:
                request_params = json.loads(request_params)
            except:
                request_params = {}
        
        # 检查 note_id
        if note_id:
            if request_params.get("note_id") != note_id:
                continue
        
        # 检查 entity_id
        if entity_id:
            if request_params.get("entity_id") != entity_id:
                continue
        
        # 检查标题
        if title:
            note_title = request_params.get("title", "")
            if title.lower() not in note_title.lower():
                continue
        
        filtered.append({
            "invocation_id": r.get("id"),
            "note_id": request_params.get("note_id"),
            "entity_id": request_params.get("entity_id"),
            "title": request_params.get("title"),
            "content": request_params.get("content", "")[:100] + "..." if len(request_params.get("content", "")) > 100 else request_params.get("content", ""),
            "status": r.get("status"),
            "normalized_status": r.get("normalized_status"),
            "created_at": r.get("created_at"),
        })
    
    return {
        "success": True,
        "count": len(filtered),
        "notes": filtered
    }


def run(**kwargs):
    """能力入口"""
    return query_note(**kwargs)


path: capabilities/query_notification_status.py
content: """查询通知状态能力"""

from typing import Optional, Dict, Any
import json


def query_notification_status(
    notification_id: Optional[str] = None,
    task_id: Optional[str] = None,
    limit: int = 20,
) -> Dict[str, Any]:
    """
    查询通知状态
    
    Args:
        notification_id: 通知ID
        task_id: 任务ID
        limit: 返回数量限制
        
    Returns:
        包含通知状态的字典
    """
    from platform_adapter import invocation_ledger as ledger_module
    
    pass
    
    # 查询 NOTIFICATION 类型的记录
    records = ledger_module.query_by_capability(capability="NOTIFICATION", limit=100)
    
    # 过滤
    filtered = []
    for r in records:
        request_params = r.get("request_params", {})
        if isinstance(request_params, str):
            try:
                request_params = json.loads(request_params)
            except:
                request_params = {}
        
        if notification_id:
            if request_params.get("notification_id") != notification_id:
                continue
        
        if task_id:
            if r.get("task_id") != task_id:
                continue
        
        filtered.append({
            "invocation_id": r.get("id"),
            "notification_id": request_params.get("notification_id"),
            "title": request_params.get("title"),
            "status": r.get("status"),
            "normalized_status": r.get("normalized_status"),
            "created_at": r.get("created_at"),
            "error_code": r.get("error_code"),
        })
    
    return {
        "success": True,
        "count": len(filtered[:limit]),
        "notifications": filtered[:limit]
    }


def run(**kwargs):
    """能力入口"""
    return query_notification_status(**kwargs)


path: capabilities/query_photo.py
content: """查询图库照片能力"""

from typing import Optional, Dict, Any, List


def query_photo(
    photo_id: Optional[str] = None,
    album_id: Optional[str] = None,
    date: Optional[str] = None,
) -> Dict[str, Any]:
    """
    查询图库照片
    
    Args:
        photo_id: 照片ID
        album_id: 相册ID
        date: 日期（YYYY-MM-DD）
        
    Returns:
        照片信息
    """
    # 调用端侧图库能力
    try:
        from platform_adapter.device_tool_adapter import call_device_tool
        
        result = call_device_tool("photo", "query", {
            "photo_id": photo_id,
            "album_id": album_id,
            "date": date
        })
        
        return result
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "photos": []
        }


def list_photos(
    limit: int = 20,
    offset: int = 0,
    album_id: Optional[str] = None,
) -> Dict[str, Any]:
    """
    列出照片
    
    Args:
        limit: 返回数量限制
        offset: 偏移量
        album_id: 相册ID
        
    Returns:
        照片列表
    """
    try:
        from platform_adapter.device_tool_adapter import call_device_tool
        
        result = call_device_tool("photo", "list", {
            "limit": limit,
            "offset": offset,
            "album_id": album_id
        })
        
        return result
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "photos": []
        }


def search_photos(
    keyword: str,
    limit: int = 20,
) -> Dict[str, Any]:
    """
    搜索照片
    
    Args:
        keyword: 搜索关键词
        limit: 返回数量限制
        
    Returns:
        搜索结果
    """
    try:
        from platform_adapter.device_tool_adapter import call_device_tool
        
        result = call_device_tool("photo", "search", {
            "keyword": keyword,
            "limit": limit
        })
        
        return result
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "keyword": keyword,
            "photos": []
        }


def run(**kwargs):
    """能力入口"""
    action = kwargs.pop("action", "query")
    
    if action == "query":
        return query_photo(**kwargs)
    elif action == "list":
        return list_photos(**kwargs)
    elif action == "search":
        return search_photos(**kwargs)
    else:
        return {"success": False, "error": f"未知操作: {action}"}


path: capabilities/query_xiaoyi_note.py
content: """小艺帮记查询能力"""

from typing import Optional, Dict, Any, List


def query_xiaoyi_note(
    note_id: Optional[str] = None,
    category: Optional[str] = None,
    keyword: Optional[str] = None,
) -> Dict[str, Any]:
    """
    查询小艺帮记中的笔记
    
    Args:
        note_id: 笔记ID
        category: 分类
        keyword: 关键词
        
    Returns:
        笔记信息
    """
    try:
        result = _call_xiaoyi_notes("query", {
            "note_id": note_id,
            "category": category,
            "keyword": keyword
        })
        
        return {
            "success": True,
            "notes": result.get("notes", []),
            "count": len(result.get("notes", []))
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "notes": []
        }


def list_xiaoyi_notes(
    limit: int = 20,
    category: Optional[str] = None,
    offset: int = 0,
) -> Dict[str, Any]:
    """
    列出小艺帮记中的笔记
    
    Args:
        limit: 返回数量限制
        category: 分类
        offset: 偏移量
        
    Returns:
        笔记列表
    """
    try:
        result = _call_xiaoyi_notes("list", {
            "limit": limit,
            "category": category,
            "offset": offset
        })
        
        return {
            "success": True,
            "notes": result.get("notes", []),
            "count": len(result.get("notes", [])),
            "limit": limit,
            "category": category
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "notes": []
        }


def search_xiaoyi_notes(
    keyword: str,
    limit: int = 20,
) -> Dict[str, Any]:
    """
    搜索小艺帮记中的笔记
    
    Args:
        keyword: 搜索关键词
        limit: 返回数量限制
        
    Returns:
        搜索结果
    """
    try:
        result = _call_xiaoyi_notes("search", {
            "keyword": keyword,
            "limit": limit
        })
        
        return {
            "success": True,
            "keyword": keyword,
            "notes": result.get("notes", []),
            "count": len(result.get("notes", []))
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "keyword": keyword,
            "notes": []
        }


def _call_xiaoyi_notes(action: str, params: dict) -> dict:
    """调用小艺帮记能力"""
    from platform_adapter.device_tool_adapter import call_device_tool
    return call_device_tool("note", action, params)


def run(**kwargs):
    """能力入口"""
    action = kwargs.pop("action", "query")
    
    if action == "query":
        return query_xiaoyi_note(**kwargs)
    elif action == "list":
        return list_xiaoyi_notes(**kwargs)
    elif action == "search":
        return search_xiaoyi_notes(**kwargs)
    else:
        return {"success": False, "error": f"未知操作: {action}"}


path: capabilities/refresh_notification_auth.py
content: """刷新通知授权能力"""

from typing import Dict, Any


def refresh_notification_auth() -> Dict[str, Any]:
    """
    刷新通知授权状态
    
    Returns:
        包含授权状态的字典
    """
    import subprocess
    import json
    
    # 调用 check_notification_auth.py
    try:
        result = subprocess.run(
            ["python", "scripts/check_notification_auth.py"],
            capture_output=True,
            text=True,
            cwd="/home/sandbox/.openclaw/workspace"
        )
        
        output = result.stdout + result.stderr
        
        # 解析状态
        if "configured" in output.lower():
            status = "configured"
            message = "授权已配置且有效"
        elif "not_configured" in output.lower():
            status = "not_configured"
            message = "授权未配置"
        elif "expired" in output.lower():
            status = "expired"
            message = "授权已过期"
        else:
            status = "unknown"
            message = "无法确定授权状态"
        
        return {
            "success": True,
            "auth_status": status,
            "message": message,
            "raw_output": output[-500:] if len(output) > 500 else output
        }
    
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "message": "刷新授权状态失败"
        }


def run(**kwargs):
    """能力入口"""
    return refresh_notification_auth()


path: capabilities/registry.py
content: """
Capability Registry - 能力注册表
统一管理所有能力的注册、发现和执行
"""

from typing import Dict, Any, List, Optional, Callable, Type
from dataclasses import dataclass, field
from enum import Enum
import logging
import inspect

logger = logging.getLogger(__name__)


class CapabilityStatus(Enum):
    """能力状态"""
    AVAILABLE = "available"
    DEGRADED = "degraded"
    UNAVAILABLE = "unavailable"


@dataclass
class CapabilityInfo:
    """能力信息"""
    name: str
    description: str
    version: str = "1.0.0"
    status: CapabilityStatus = CapabilityStatus.AVAILABLE
    dependencies: List[str] = field(default_factory=list)
    input_schema: Dict[str, Any] = field(default_factory=dict)
    output_schema: Dict[str, Any] = field(default_factory=dict)
    handler: Optional[Callable] = None
    fallback_handler: Optional[Callable] = None
    deprecation_message: Optional[str] = None


class CapabilityRegistry:
    """
    能力注册表
    管理所有能力的注册、发现和执行
    """
    
    def __init__(self):
        self._capabilities: Dict[str, CapabilityInfo] = {}
        self._categories: Dict[str, List[str]] = {}
    
    def register(
        self,
        name: str,
        description: str,
        handler: Callable,
        version: str = "1.0.0",
        dependencies: List[str] = None,
        input_schema: Dict[str, Any] = None,
        output_schema: Dict[str, Any] = None,
        fallback_handler: Callable = None,
        category: str = "general"
    ) -> None:
        """注册能力"""
        cap_info = CapabilityInfo(
            name=name,
            description=description,
            version=version,
            dependencies=dependencies or [],
            input_schema=input_schema or {},
            output_schema=output_schema or {},
            handler=handler,
            fallback_handler=fallback_handler
        )
        
        self._capabilities[name] = cap_info
        
        # 添加到分类
        if category not in self._categories:
            self._categories[category] = []
        self._categories[category].append(name)
        
        logger.info(f"Registered capability: {name} v{version}")
    
    def get(self, name: str) -> Optional[CapabilityInfo]:
        """获取能力信息"""
        return self._capabilities.get(name)
    
    def list_all(self) -> List[str]:
        """列出所有能力"""
        return list(self._capabilities.keys())
    
    def list_by_category(self, category: str) -> List[str]:
        """按分类列出能力"""
        return self._categories.get(category, [])
    
    def list_available(self) -> List[str]:
        """列出可用能力"""
        return [
            name for name, info in self._capabilities.items()
            if info.status != CapabilityStatus.UNAVAILABLE
        ]
    
    async def execute(self, name: str, params: Dict[str, Any]) -> Dict[str, Any]:
        """执行能力"""
        cap_info = self._capabilities.get(name)
        
        if not cap_info:
            return {
                "success": False,
                "error": f"Capability not found: {name}",
                "error_code": "CAPABILITY_NOT_FOUND"
            }
        
        if cap_info.status == CapabilityStatus.UNAVAILABLE:
            # 尝试使用降级处理器
            if cap_info.fallback_handler:
                logger.warning(f"Using fallback for unavailable capability: {name}")
                return await self._call_handler(cap_info.fallback_handler, params)
            
            return {
                "success": False,
                "error": f"Capability unavailable: {name}",
                "error_code": "CAPABILITY_UNAVAILABLE"
            }
        
        if cap_info.status == CapabilityStatus.DEGRADED and cap_info.fallback_handler:
            logger.info(f"Using fallback for degraded capability: {name}")
            return await self._call_handler(cap_info.fallback_handler, params)
        
        return await self._call_handler(cap_info.handler, params)
    
    async def _call_handler(self, handler: Callable, params: Dict[str, Any]) -> Dict[str, Any]:
        """调用处理器"""
        try:
            if inspect.iscoroutinefunction(handler):
                return await handler(params)
            else:
                return handler(params)
        except Exception as e:
            logger.exception(f"Handler execution failed")
            return {
                "success": False,
                "error": str(e),
                "error_code": "HANDLER_ERROR"
            }
    
    def update_status(self, name: str, status: CapabilityStatus) -> None:
        """更新能力状态"""
        if name in self._capabilities:
            self._capabilities[name].status = status
            logger.info(f"Updated capability {name} status to {status.value}")
    
    def get_capabilities_report(self) -> Dict[str, Any]:
        """获取能力报告"""
        available = sum(1 for c in self._capabilities.values() if c.status == CapabilityStatus.AVAILABLE)
        degraded = sum(1 for c in self._capabilities.values() if c.status == CapabilityStatus.DEGRADED)
        unavailable = sum(1 for c in self._capabilities.values() if c.status == CapabilityStatus.UNAVAILABLE)
        
        return {
            "total": len(self._capabilities),
            "available": available,
            "degraded": degraded,
            "unavailable": unavailable,
            "categories": {
                cat: caps for cat, caps in self._categories.items()
            },
            "capabilities": {
                name: {
                    "status": info.status.value,
                    "version": info.version,
                    "description": info.description
                }
                for name, info in self._capabilities.items()
            }
        }


# 全局注册表实例
_global_registry: Optional[CapabilityRegistry] = None


def get_registry() -> CapabilityRegistry:
    """获取全局注册表"""
    global _global_registry
    if _global_registry is None:
        _global_registry = CapabilityRegistry()
    return _global_registry


def register_capability(
    name: str,
    description: str,
    **kwargs
) -> Callable:
    """装饰器：注册能力"""
    def decorator(func: Callable) -> Callable:
        get_registry().register(
            name=name,
            description=description,
            handler=func,
            **kwargs
        )
        return func
    return decorator


path: capabilities/replay_run.py
content: """
回放运行能力 - 真实实现
读取 task_runs / task_steps
"""

from typing import Dict, Any
from datetime import datetime
import sqlite3
import sys
from pathlib import Path

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))


class ReplayRunCapability:
    """回放运行能力"""
    
    name = "replay_run"
    description = "回放任务运行过程"
    
    async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
        """
        回放任务运行
        
        Args:
            params: {
                "run_id": 运行ID
            }
        
        Returns:
            {
                "success": bool,
                "run_id": str,
                "run": dict,
                "steps": list,
                "timeline": list,
                "replayed_at": str
            }
        """
        run_id = params.get("run_id")
        
        if not run_id:
            return {
                "success": False,
                "error": "缺少 run_id",
                "error_code": "MISSING_RUN_ID"
            }
        
        db_path = project_root / "data" / "tasks.db"
        
        if not db_path.exists():
            return {
                "success": False,
                "error": "数据库不存在",
                "error_code": "DATABASE_NOT_FOUND",
                "run_id": run_id
            }
        
        try:
            conn = sqlite3.connect(str(db_path))
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            # 查询运行记录
            cursor.execute("SELECT * FROM task_runs WHERE id = ?", (run_id,))
            run_row = cursor.fetchone()
            run = dict(run_row) if run_row else None
            
            if not run:
                conn.close()
                return {
                    "success": False,
                    "error": "运行记录不存在",
                    "error_code": "RUN_NOT_FOUND",
                    "run_id": run_id
                }
            
            # 查询步骤记录
            cursor.execute("SELECT * FROM task_steps WHERE task_run_id = ? ORDER BY step_index", (run_id,))
            steps = [dict(row) for row in cursor.fetchall()]
            
            # 构建时间线
            timeline = []
            
            # 添加运行开始
            timeline.append({
                "type": "run_start",
                "timestamp": run.get("started_at"),
                "status": run.get("status")
            })
            
            # 添加步骤
            for step in steps:
                timeline.append({
                    "type": "step",
                    "step_name": step.get("step_name"),
                    "tool_name": step.get("tool_name"),
                    "timestamp": step.get("started_at"),
                    "status": step.get("status"),
                    "duration_ms": step.get("duration_ms")
                })
            
            # 添加运行结束
            timeline.append({
                "type": "run_end",
                "timestamp": run.get("ended_at"),
                "status": run.get("status")
            })
            
            conn.close()
            
            return {
                "success": True,
                "run_id": run_id,
                "run": run,
                "steps": steps,
                "timeline": timeline,
                "replayed_at": datetime.now().isoformat()
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "error_code": "REPLAY_FAILED",
                "run_id": run_id
            }


path: capabilities/resend_message.py
content: """重发消息能力"""

import uuid
from typing import Optional, Dict, Any
from datetime import datetime
from platform_adapter import invocation_ledger as ledger_module
from platform_adapter.xiaoyi_adapter import XiaoyiAdapter


def resend_message(
    original_invocation_id: int,
    reason: Optional[str] = None,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    重发消息
    
    Args:
        original_invocation_id: 原始调用记录ID
        reason: 重发原因
        dry_run: 是否预演模式
        
    Returns:
        包含重发结果的字典
    """
    ledger = ledger_module
    
    # 查询原始记录
    original = ledger_module.get_invocation_by_id(original_invocation_id)
    if not original:
        return {
            "success": False,
            "error": f"未找到原始记录 #{original_invocation_id}",
            "action": "resend_message"
        }
    
    original_record = original[0] if isinstance(original, list) else original
    
    # 检查原始记录是否是消息发送
    if original_record.get("capability") != "MESSAGE_SENDING":
        return {
            "success": False,
            "error": "只能重发 MESSAGE_SENDING 类型的记录",
            "original_capability": original_record.get("capability")
        }
    
    # 解析原始请求参数
    request_params = original_record.get("request_params", {})
    if isinstance(request_params, str):
        import json
        try:
            request_params = json.loads(request_params)
        except:
            request_params = {}
    
    # 生成新的幂等键（重发需要新键）
    new_idempotency_key = f"resend_{uuid.uuid4().hex[:16]}"
    
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "resend_message",
            "original_invocation_id": original_invocation_id,
            "new_idempotency_key": new_idempotency_key,
            "message": "预演模式：将重发消息",
            "original_status": original_record.get("normalized_status"),
            "reason": reason
        }
    
    # 执行重发
    adapter = XiaoyiAdapter()
    result = adapter.send_message(
        to=request_params.get("to"),
        message=request_params.get("message"),
        idempotency_key=new_idempotency_key,
        metadata={
            "resend_from": original_invocation_id,
            "resend_reason": reason,
            "resend_at": datetime.now().isoformat()
        }
    )
    
    # 记录审计
    result["resend_from"] = original_invocation_id
    result["resend_reason"] = reason
    
    return result


def run(**kwargs):
    """能力入口"""
    return resend_message(**kwargs)


path: capabilities/resume_task.py
content: """
恢复任务能力 - 真实实现
接入 TaskManager 任务内核
"""

from typing import Dict, Any
from datetime import datetime
import sys
from pathlib import Path

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from infrastructure.task_manager import get_task_manager


class ResumeTaskCapability:
    """恢复任务能力"""
    
    name = "resume_task"
    description = "恢复暂停的任务"
    
    async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
        """
        执行任务恢复
        
        Args:
            params: {
                "task_id": 任务ID
            }
        
        Returns:
            {
                "success": bool,
                "task_id": str,
                "status": str,
                "resumed_at": str
            }
        """
        task_id = params.get("task_id")
        
        if not task_id:
            return {
                "success": False,
                "error": "缺少 task_id",
                "error_code": "MISSING_TASK_ID"
            }
        
        try:
            tm = get_task_manager()
            result = await tm.resume_task(task_id)
            
            return {
                "success": result.get("success", False),
                "task_id": task_id,
                "status": result.get("status", "resumed"),
                "resumed_at": datetime.now().isoformat()
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "error_code": "RESUME_FAILED",
                "task_id": task_id
            }


path: capabilities/retry_task.py
content: """
重试任务能力 - 真实实现
接入 TaskManager 任务内核
"""

from typing import Dict, Any
from datetime import datetime
import sys
from pathlib import Path

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from infrastructure.task_manager import get_task_manager


class RetryTaskCapability:
    """重试任务能力"""
    
    name = "retry_task"
    description = "重试失败的任务"
    
    async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
        """
        执行任务重试
        
        Args:
            params: {
                "task_id": 任务ID
            }
        
        Returns:
            {
                "success": bool,
                "task_id": str,
                "status": str,
                "delivery_status": str,
                "retry_at": str
            }
        """
        task_id = params.get("task_id")
        
        if not task_id:
            return {
                "success": False,
                "error": "缺少 task_id",
                "error_code": "MISSING_TASK_ID"
            }
        
        try:
            tm = get_task_manager()
            result = await tm.retry_task(task_id)
            
            return {
                "success": result.get("success", False),
                "task_id": task_id,
                "status": result.get("status", "unknown"),
                "delivery_status": result.get("delivery_status", "unknown"),
                "retry_at": datetime.now().isoformat()
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "error_code": "RETRY_FAILED",
                "task_id": task_id
            }


path: capabilities/schedule_task.py
content: """
调度任务能力 - 真实实现
接入 TaskManager 任务内核
"""

from typing import Dict, Any
from datetime import datetime
import sys
from pathlib import Path

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from infrastructure.task_manager import get_task_manager


class ScheduleTaskCapability:
    """调度任务能力"""
    
    name = "schedule_task"
    description = "创建定时任务"
    
    async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
        """
        执行任务调度
        
        Args:
            params: {
                "task_type": "once" | "recurring",
                "run_at": ISO时间字符串（once任务）,
                "cron_expr": cron表达式（recurring任务）,
                "message": 任务内容,
                "user_id": 用户ID
            }
        
        Returns:
            {
                "success": bool,
                "task_id": str,
                "task_type": str,
                "status": str,
                "created_at": str,
                "idempotent": bool
            }
        """
        task_type = params.get("task_type", "once")
        run_at = params.get("run_at")
        cron_expr = params.get("cron_expr")
        message = params.get("message", "")
        user_id = params.get("user_id", "default")
        
        if not message:
            return {
                "success": False,
                "error": "任务内容不能为空",
                "error_code": "EMPTY_MESSAGE"
            }
        
        try:
            tm = get_task_manager()
            
            if task_type == "recurring" or cron_expr:
                # 循环任务
                result = await tm.create_recurring_message(
                    user_id=user_id,
                    message=message,
                    cron_expr=cron_expr or "* * * * *"
                )
            else:
                # 一次性任务
                result = await tm.create_scheduled_message(
                    user_id=user_id,
                    message=message,
                    run_at=run_at or datetime.now().isoformat()
                )
            
            return {
                "success": result.get("success", False),
                "task_id": result.get("task_id"),
                "task_type": task_type,
                "status": result.get("status", "unknown"),
                "created_at": datetime.now().isoformat(),
                "idempotent": result.get("idempotent", False)
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "error_code": "SCHEDULE_FAILED"
            }


path: capabilities/search_notes.py
content: """搜索备忘录能力"""

from typing import Optional, Dict, Any
import json


def search_notes(
    keyword: Optional[str] = None,
    title_contains: Optional[str] = None,
    content_contains: Optional[str] = None,
    limit: int = 20,
    offset: int = 0,
) -> Dict[str, Any]:
    """
    搜索备忘录
    
    Args:
        keyword: 关键词（同时匹配标题和内容）
        title_contains: 标题包含
        content_contains: 内容包含
        limit: 返回数量限制
        offset: 偏移量
        
    Returns:
        包含搜索结果的字典
    """
    from platform_adapter import invocation_ledger as ledger_module
    
    pass
    
    # 查询 STORAGE 类型的记录
    records = ledger_module.query_by_capability(capability="STORAGE", limit=200)
    
    # 搜索
    results = []
    for r in records:
        request_params = r.get("request_params", {})
        if isinstance(request_params, str):
            try:
                request_params = json.loads(request_params)
            except:
                request_params = {}
        
        note_title = request_params.get("title", "")
        note_content = request_params.get("content", "")
        
        # 关键词匹配
        if keyword:
            keyword_lower = keyword.lower()
            if keyword_lower not in note_title.lower() and keyword_lower not in note_content.lower():
                continue
        
        # 标题匹配
        if title_contains:
            if title_contains.lower() not in note_title.lower():
                continue
        
        # 内容匹配
        if content_contains:
            if content_contains.lower() not in note_content.lower():
                continue
        
        results.append({
            "invocation_id": r.get("id"),
            "note_id": request_params.get("note_id"),
            "title": note_title,
            "content_preview": note_content[:100] + "..." if len(note_content) > 100 else note_content,
            "status": r.get("normalized_status"),
            "created_at": r.get("created_at"),
        })
    
    # 分页
    paginated = results[offset:offset + limit]
    
    return {
        "success": True,
        "count": len(paginated),
        "total": len(results),
        "limit": limit,
        "offset": offset,
        "keyword": keyword,
        "results": paginated
    }


def run(**kwargs):
    """能力入口"""
    return search_notes(**kwargs)


path: capabilities/self_repair.py
content: """
自修复能力 - 真实实现
检查并修复系统问题
"""

from typing import Dict, Any, List
from datetime import datetime
import sqlite3
import sys
from pathlib import Path

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))


class SelfRepairCapability:
    """自修复能力"""
    
    name = "self_repair"
    description = "自动检测并修复系统问题"
    
    async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
        """
        执行自检和修复
        
        Args:
            params: {
                "auto_fix": bool (是否自动修复，默认False)
            }
        
        Returns:
            {
                "success": bool,
                "repairs": list,
                "fixed_count": int,
                "issues_found": int,
                "timestamp": str
            }
        """
        auto_fix = params.get("auto_fix", False)
        repairs: List[Dict[str, Any]] = []
        issues_found = 0
        fixed_count = 0
        
        db_path = project_root / "data" / "tasks.db"
        
        # 检查1: 数据库完整性
        if db_path.exists():
            try:
                conn = sqlite3.connect(str(db_path))
                cursor = conn.cursor()
                
                # 检查表是否存在
                cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
                tables = [row[0] for row in cursor.fetchall()]
                
                required_tables = ['tasks', 'task_runs', 'task_steps', 'task_events']
                missing_tables = [t for t in required_tables if t not in tables]
                
                if missing_tables:
                    issues_found += 1
                    repairs.append({
                        "check": "database_tables",
                        "status": "issue",
                        "message": f"缺少表: {missing_tables}",
                        "action": "none" if not auto_fix else "create_tables"
                    })
                else:
                    repairs.append({
                        "check": "database_tables",
                        "status": "ok",
                        "message": "所有必需表存在",
                        "action": "none"
                    })
                
                # 检查孤立记录
                cursor.execute("""
                    SELECT COUNT(*) FROM task_runs 
                    WHERE task_id NOT IN (SELECT id FROM tasks)
                """)
                orphan_runs = cursor.fetchone()[0]
                
                if orphan_runs > 0:
                    issues_found += 1
                    repairs.append({
                        "check": "orphaned_runs",
                        "status": "issue",
                        "message": f"发现 {orphan_runs} 条孤立运行记录",
                        "action": "none" if not auto_fix else "deleted",
                        "count": orphan_runs
                    })
                    if auto_fix:
                        cursor.execute("""
                            DELETE FROM task_runs 
                            WHERE task_id NOT IN (SELECT id FROM tasks)
                        """)
                        conn.commit()
                        fixed_count += 1
                else:
                    repairs.append({
                        "check": "orphaned_runs",
                        "status": "ok",
                        "message": "无孤立运行记录",
                        "action": "none"
                    })
                
                # 检查孤立步骤
                cursor.execute("""
                    SELECT COUNT(*) FROM task_steps 
                    WHERE task_run_id NOT IN (SELECT id FROM task_runs)
                """)
                orphan_steps = cursor.fetchone()[0]
                
                if orphan_steps > 0:
                    issues_found += 1
                    repairs.append({
                        "check": "orphaned_steps",
                        "status": "issue",
                        "message": f"发现 {orphan_steps} 条孤立步骤记录",
                        "action": "none" if not auto_fix else "deleted",
                        "count": orphan_steps
                    })
                    if auto_fix:
                        cursor.execute("""
                            DELETE FROM task_steps 
                            WHERE task_run_id NOT IN (SELECT id FROM task_runs)
                        """)
                        conn.commit()
                        fixed_count += 1
                else:
                    repairs.append({
                        "check": "orphaned_steps",
                        "status": "ok",
                        "message": "无孤立步骤记录",
                        "action": "none"
                    })
                
                conn.close()
                
            except Exception as e:
                issues_found += 1
                repairs.append({
                    "check": "database_integrity",
                    "status": "error",
                    "message": str(e),
                    "action": "none"
                })
        else:
            issues_found += 1
            repairs.append({
                "check": "database_exists",
                "status": "issue",
                "message": "数据库文件不存在",
                "action": "none"
            })
        
        # 检查2: pending_sends 文件
        pending_sends_path = project_root / "reports" / "ops" / "pending_sends.jsonl"
        if pending_sends_path.exists():
            repairs.append({
                "check": "pending_sends",
                "status": "ok",
                "message": "pending_sends 文件存在",
                "action": "none"
            })
        else:
            # 创建目录和文件
            pending_sends_path.parent.mkdir(parents=True, exist_ok=True)
            pending_sends_path.touch()
            repairs.append({
                "check": "pending_sends",
                "status": "fixed",
                "message": "已创建 pending_sends 文件",
                "action": "created"
            })
            fixed_count += 1
        
        return {
            "success": True,
            "repairs": repairs,
            "fixed_count": fixed_count,
            "issues_found": issues_found,
            "timestamp": datetime.now().isoformat()
        }


path: capabilities/send_message.py
content: """
发送消息能力 - 真实实现
接入 MessageAdapter 和任务内核
"""

from typing import Dict, Any
from datetime import datetime
import sys
from pathlib import Path

# 添加项目根目录到路径
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from infrastructure.tool_adapters.message_adapter import MessageAdapter


class SendMessageCapability:
    """发送消息能力"""
    
    name = "send_message"
    description = "发送消息到指定渠道"
    
    async def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
        """
        执行消息发送
        
        Args:
            params: {
                "user_id": 用户ID,
                "message": 消息内容,
                "task_id": 关联任务ID（可选）,
                "run_id": 关联运行ID（可选）,
                "channel": 渠道（可选，默认default）
            }
        
        Returns:
            {
                "success": bool,
                "status": "delivered" | "queued_for_delivery" | "failed",
                "task_id": str,
                "run_id": str,
                "message_id": str,
                "sent_at": str
            }
        """
        user_id = params.get("user_id", "default")
        message = params.get("message", "")
        task_id = params.get("task_id")
        run_id = params.get("run_id")
        channel = params.get("channel", "default")
        
        if not message:
            return {
                "success": False,
                "error": "消息内容不能为空",
                "error_code": "EMPTY_MESSAGE"
            }
        
        try:
            # 使用真实的 MessageAdapter
            adapter = MessageAdapter()
            result = await adapter.send_message(
                user_id=user_id,
                message=message,
                task_id=task_id,
                run_id=run_id
            )
            
            return {
                "success": result.get("success", False),
                "status": result.get("delivery_status", "unknown"),
                "task_id": task_id,
                "run_id": run_id,
                "message_id": result.get("message_id"),
                "sent_at": datetime.now().isoformat(),
                "channel": channel
            }
            
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "error_code": "SEND_FAILED",
                "task_id": task_id,
                "run_id": run_id
            }


path: capabilities/update_alarm.py
content: """更新闹钟能力"""

from typing import Optional, Dict, Any, List


def update_alarm(
    alarm_id: str,
    time: Optional[str] = None,
    label: Optional[str] = None,
    repeat: Optional[List[str]] = None,
    enabled: Optional[bool] = None,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    更新闹钟
    
    Args:
        alarm_id: 闹钟ID
        time: 新时间
        label: 新标签
        repeat: 新重复日期
        enabled: 是否启用
        dry_run: 是否预演模式
        
    Returns:
        更新结果
    """
    updates = {}
    if time:
        updates["time"] = time
    if label is not None:
        updates["label"] = label
    if repeat is not None:
        updates["repeat"] = repeat
    if enabled is not None:
        updates["enabled"] = enabled
    
    if not updates:
        return {
            "success": False,
            "error": "没有提供要更新的字段"
        }
    
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "update_alarm",
            "alarm_id": alarm_id,
            "updates": updates,
            "message": "预演模式：将更新闹钟"
        }
    
    # TODO: 调用小艺闹钟更新接口
    return {
        "success": True,
        "alarm_id": alarm_id,
        "updates": updates,
        "message": "闹钟已更新"
    }


def enable_alarm(alarm_id: str, dry_run: bool = False) -> Dict[str, Any]:
    """启用闹钟"""
    return update_alarm(alarm_id, enabled=True, dry_run=dry_run)


def disable_alarm(alarm_id: str, dry_run: bool = False) -> Dict[str, Any]:
    """禁用闹钟"""
    return update_alarm(alarm_id, enabled=False, dry_run=dry_run)


def run(**kwargs):
    """能力入口"""
    action = kwargs.pop("action", "update")
    
    if action == "enable":
        return enable_alarm(**kwargs)
    elif action == "disable":
        return disable_alarm(**kwargs)
    else:
        return update_alarm(**kwargs)


path: capabilities/update_calendar_event.py
content: """更新日程事件能力"""

from typing import Optional, Dict, Any
import uuid


def update_calendar_event(
    event_id: str,
    title: Optional[str] = None,
    start_time: Optional[str] = None,
    end_time: Optional[str] = None,
    location: Optional[str] = None,
    description: Optional[str] = None,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    更新日程事件
    
    Args:
        event_id: 事件ID
        title: 新标题
        start_time: 新开始时间
        end_time: 新结束时间
        location: 新地点
        description: 新描述
        dry_run: 是否预演模式
        
    Returns:
        包含更新结果的字典
    """
    from platform_adapter import invocation_ledger as ledger_module
    from platform_adapter.xiaoyi_adapter import XiaoyiAdapter
    
    # 构建更新参数
    updates = {}
    if title:
        updates["title"] = title
    if start_time:
        updates["start_time"] = start_time
    if end_time:
        updates["end_time"] = end_time
    if location:
        updates["location"] = location
    if description:
        updates["description"] = description
    
    if not updates:
        return {
            "success": False,
            "error": "没有提供要更新的字段"
        }
    
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "update_calendar_event",
            "event_id": event_id,
            "updates": updates,
            "message": "预演模式：将更新日程事件"
        }
    
    # 调用平台适配器
    adapter = XiaoyiAdapter()
    result = adapter.update_calendar_event(
        event_id=event_id,
        updates=updates,
        idempotency_key=f"update_cal_{uuid.uuid4().hex[:16]}"
    )
    
    return result


def run(**kwargs):
    """能力入口"""
    return update_calendar_event(**kwargs)


path: capabilities/update_contact.py
content: """更新联系人能力"""

from typing import Optional, Dict, Any


def update_contact(
    contact_id: str,
    name: Optional[str] = None,
    phone: Optional[str] = None,
    email: Optional[str] = None,
    company: Optional[str] = None,
    notes: Optional[str] = None,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    更新联系人
    
    Args:
        contact_id: 联系人ID
        name: 新姓名
        phone: 新电话
        email: 新邮箱
        company: 新公司
        notes: 新备注
        dry_run: 是否预演模式
        
    Returns:
        更新结果
    """
    updates = {}
    if name:
        updates["name"] = name
    if phone:
        updates["phone"] = phone
    if email:
        updates["email"] = email
    if company:
        updates["company"] = company
    if notes:
        updates["notes"] = notes
    
    if not updates:
        return {
            "success": False,
            "error": "没有提供要更新的字段"
        }
    
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "update_contact",
            "contact_id": contact_id,
            "updates": updates,
            "message": "预演模式：将更新联系人"
        }
    
    # TODO: 调用小艺联系人更新接口
    return {
        "success": True,
        "contact_id": contact_id,
        "updates": updates,
        "message": "联系人已更新"
    }


def run(**kwargs):
    """能力入口"""
    return update_contact(**kwargs)


path: capabilities/update_note.py
content: """更新备忘录能力"""

from typing import Optional, Dict, Any
import uuid


def update_note(
    note_id: str,
    title: Optional[str] = None,
    content: Optional[str] = None,
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    更新备忘录
    
    Args:
        note_id: 备忘录ID
        title: 新标题
        content: 新内容
        dry_run: 是否预演模式
        
    Returns:
        包含更新结果的字典
    """
    from platform_adapter import invocation_ledger as ledger_module
    from platform_adapter.xiaoyi_adapter import XiaoyiAdapter
    
    # 构建更新参数
    updates = {}
    if title:
        updates["title"] = title
    if content:
        updates["content"] = content
    
    if not updates:
        return {
            "success": False,
            "error": "没有提供要更新的字段"
        }
    
    if dry_run:
        return {
            "success": True,
            "dry_run": True,
            "action": "update_note",
            "note_id": note_id,
            "updates": updates,
            "message": "预演模式：将更新备忘录"
        }
    
    # 调用平台适配器
    adapter = XiaoyiAdapter()
    result = adapter.update_note(
        note_id=note_id,
        updates=updates,
        idempotency_key=f"update_note_{uuid.uuid4().hex[:16]}"
    )
    
    # 记录审计
    pass
    ledger_module.record_audit(
        action="update_note",
        note_id=note_id,
        updates=updates
    )
    
    return result


def run(**kwargs):
    """能力入口"""
    return update_note(**kwargs)


path: config/__init__.py
content: """
配置加载器

统一加载所有配置文件
"""

from pathlib import Path
import json

# 配置目录
CONFIG_DIR = Path(__file__).parent

# 导入所有配置
try:
    from .default_skill_config import DefaultSkillConfig
except ImportError:
    DefaultSkillConfig = None

try:
    from .feature_flags import FeatureFlags
except ImportError:
    FeatureFlags = None


def load_capability_timeouts():
    """加载能力超时配置"""
    config_path = CONFIG_DIR / "capability_timeouts.json"
    if config_path.exists():
        with open(config_path, 'r', encoding='utf-8') as f:
            return json.load(f)
    return {}


def load_dual_push_config():
    """加载双通道推送配置"""
    config_path = CONFIG_DIR / "dual_push_config.json"
    if config_path.exists():
        with open(config_path, 'r', encoding='utf-8') as f:
            return json.load(f)
    return {}


# 预加载配置
CAPABILITY_TIMEOUTS = load_capability_timeouts()
DUAL_PUSH_CONFIG = load_dual_push_config()

# 导出
__all__ = [
    'CONFIG_DIR',
    'DefaultSkillConfig',
    'FeatureFlags',
    'load_capability_timeouts',
    'load_dual_push_config',
    'CAPABILITY_TIMEOUTS',
    'DUAL_PUSH_CONFIG',
]


path: config/capability_timeouts.json
content: {
  "MESSAGE_SENDING": {
    "timeout_seconds": 30,
    "retry_count": 0,
    "retry_delay_seconds": 0,
    "description": "短信发送能力"
  },
  "TASK_SCHEDULING": {
    "timeout_seconds": 60,
    "retry_count": 0,
    "retry_delay_seconds": 0,
    "description": "日程调度能力"
  },
  "STORAGE": {
    "timeout_seconds": 30,
    "retry_count": 0,
    "retry_delay_seconds": 0,
    "description": "存储能力（备忘录）"
  },
  "NOTIFICATION": {
    "timeout_seconds": 30,
    "retry_count": 0,
    "retry_delay_seconds": 0,
    "description": "通知推送能力"
  },
  "query_message_status": {
    "timeout_seconds": 10,
    "retry_count": 1,
    "retry_delay_seconds": 1,
    "description": "查询消息状态"
  },
  "resend_message": {
    "timeout_seconds": 30,
    "retry_count": 0,
    "retry_delay_seconds": 0,
    "description": "重发消息"
  },
  "query_calendar_event": {
    "timeout_seconds": 15,
    "retry_count": 1,
    "retry_delay_seconds": 1,
    "description": "查询日程事件"
  },
  "update_calendar_event": {
    "timeout_seconds": 30,
    "retry_count": 0,
    "retry_delay_seconds": 0,
    "description": "更新日程事件"
  },
  "delete_calendar_event": {
    "timeout_seconds": 30,
    "retry_count": 0,
    "retry_delay_seconds": 0,
    "description": "删除日程事件"
  },
  "check_calendar_conflicts": {
    "timeout_seconds": 10,
    "retry_count": 1,
    "retry_delay_seconds": 1,
    "description": "检查日程冲突"
  },
  "query_note": {
    "timeout_seconds": 10,
    "retry_count": 1,
    "retry_delay_seconds": 1,
    "description": "查询备忘录"
  },
  "update_note": {
    "timeout_seconds": 30,
    "retry_count": 0,
    "retry_delay_seconds": 0,
    "description": "更新备忘录"
  },
  "delete_note": {
    "timeout_seconds": 30,
    "retry_count": 0,
    "retry_delay_seconds": 0,
    "description": "删除备忘录"
  },
  "search_notes": {
    "timeout_seconds": 15,
    "retry_count": 1,
    "retry_delay_seconds": 1,
    "description": "搜索备忘录"
  },
  "query_notification_status": {
    "timeout_seconds": 10,
    "retry_count": 1,
    "retry_delay_seconds": 1,
    "description": "查询通知状态"
  },
  "cancel_notification": {
    "timeout_seconds": 15,
    "retry_count": 0,
    "retry_delay_seconds": 0,
    "description": "取消通知"
  },
  "confirm_invocation": {
    "timeout_seconds": 10,
    "retry_count": 1,
    "retry_delay_seconds": 1,
    "description": "确认调用记录"
  },
  "explain_message_result": {
    "timeout_seconds": 5,
    "retry_count": 0,
    "retry_delay_seconds": 0,
    "description": "解释消息结果"
  },
  "explain_notification_auth_state": {
    "timeout_seconds": 10,
    "retry_count": 0,
    "retry_delay_seconds": 0,
    "description": "解释通知授权状态"
  }
}


path: config/component_classification.json
content: {
  "layers": {
    "L1": {
      "name": "Core",
      "description": "核心认知、身份、规则",
      "mutable": false,
      "allowed_types": [
        "core",
        "identity",
        "rule"
      ],
      "directories": [
        "core/"
      ],
      "priority": 1
    },
    "L2": {
      "name": "Memory",
      "description": "记忆上下文、知识库",
      "mutable": true,
      "allowed_types": [
        "memory",
        "knowledge",
        "embedding"
      ],
      "directories": [
        "memory/",
        "memory_context/"
      ],
      "priority": 2
    },
    "L3": {
      "name": "Orchestration",
      "description": "任务编排、工作流",
      "mutable": true,
      "allowed_types": [
        "orchestration",
        "workflow",
        "router"
      ],
      "directories": [
        "orchestration/"
      ],
      "priority": 3
    },
    "L4": {
      "name": "Execution",
      "description": "能力执行、技能网关",
      "mutable": true,
      "allowed_types": [
        "execution",
        "skill",
        "gateway",
        "module"
      ],
      "directories": [
        "execution/",
        "skills/"
      ],
      "priority": 4
    },
    "L5": {
      "name": "Governance",
      "description": "稳定治理、安全审计",
      "mutable": true,
      "allowed_types": [
        "governance",
        "audit",
        "security",
        "policy"
      ],
      "directories": [
        "governance/"
      ],
      "priority": 5
    },
    "L6": {
      "name": "Infrastructure",
      "description": "基础设施、工具链",
      "mutable": true,
      "allowed_types": [
        "infrastructure",
        "tool",
        "config",
        "script"
      ],
      "directories": [
        "infrastructure/",
        "scripts/"
      ],
      "priority": 6
    }
  },
  "types": {
    "core": {
      "name": "核心文件",
      "description": "架构、规则、身份等核心定义",
      "required_layer": "L1",
      "can_call": [
        "L2",
        "L3",
        "L4",
        "L5",
        "L6"
      ],
      "can_be_called_by": [],
      "examples": [
        "ARCHITECTURE.md",
        "RULE_REGISTRY.json",
        "SOUL.md"
      ]
    },
    "engine": {
      "name": "引擎",
      "description": "核心引擎，如融合引擎、规则引擎",
      "required_layer": "L1",
      "can_call": [
        "L2",
        "L3",
        "L4",
        "L5",
        "L6"
      ],
      "can_be_called_by": [
        "L3",
        "L4",
        "L5",
        "L6"
      ],
      "examples": [
        "fusion_index.json",
        "run_rule_engine.py"
      ]
    },
    "module": {
      "name": "模块",
      "description": "功能模块，如例外管理器、依赖管理器",
      "required_layer": "L6",
      "can_call": [
        "L4",
        "L5",
        "L6"
      ],
      "can_be_called_by": [
        "L3",
        "L4",
        "L5",
        "L6"
      ],
      "examples": [
        "exception_manager.py",
        "dependency_manager.py"
      ]
    },
    "skill": {
      "name": "技能",
      "description": "技能包，如 llm-memory-integration",
      "required_layer": "L4",
      "can_call": [
        "L4",
        "L5",
        "L6"
      ],
      "can_be_called_by": [
        "L3",
        "L4"
      ],
      "examples": [
        "llm-memory-integration",
        "find-skills"
      ]
    },
    "tool": {
      "name": "工具",
      "description": "辅助工具脚本",
      "required_layer": "L6",
      "can_call": [
        "L4",
        "L5",
        "L6"
      ],
      "can_be_called_by": [
        "L3",
        "L4",
        "L5",
        "L6"
      ],
      "examples": [
        "full_backup.py",
        "unified_inspector.py"
      ]
    },
    "config": {
      "name": "配置",
      "description": "配置文件",
      "required_layer": "L6",
      "can_call": [],
      "can_be_called_by": [
        "L1",
        "L2",
        "L3",
        "L4",
        "L5",
        "L6"
      ],
      "examples": [
        "unified.json",
        "dependency_manifest.json"
      ]
    },
    "registry": {
      "name": "注册表",
      "description": "索引、注册表",
      "required_layer": "L6",
      "can_call": [],
      "can_be_called_by": [
        "L1",
        "L2",
        "L3",
        "L4",
        "L5",
        "L6"
      ],
      "examples": [
        "skill_registry.json",
        "fusion_index.json"
      ]
    },
    "doc": {
      "name": "文档",
      "description": "说明文档",
      "required_layer": "L6",
      "can_call": [],
      "can_be_called_by": [
        "L1",
        "L2",
        "L3",
        "L4",
        "L5",
        "L6"
      ],
      "examples": [
        "ARCHITECTURE.md",
        "PERMANENT_KEEPER_MODULE.md"
      ]
    },
    "report": {
      "name": "报告",
      "description": "运行报告",
      "required_layer": "L6",
      "can_call": [],
      "can_be_called_by": [
        "L3",
        "L4",
        "L5",
        "L6"
      ],
      "examples": [
        "rule_engine_report.json",
        "delete_log.json"
      ]
    }
  },
  "components": {
    "ARCHITECTURE.md": {
      "layer": "L1",
      "type": "core",
      "name": "架构文档"
    },
    "RULE_REGISTRY.json": {
      "layer": "L1",
      "type": "core",
      "name": "规则注册表"
    },
    "RULE_EXCEPTIONS.json": {
      "layer": "L1",
      "type": "core",
      "name": "例外注册表"
    },
    "SOUL.md": {
      "layer": "L1",
      "type": "core",
      "name": "身份定义"
    },
    "USER.md": {
      "layer": "L1",
      "type": "core",
      "name": "用户信息"
    },
    "IDENTITY.md": {
      "layer": "L1",
      "type": "core",
      "name": "身份标识"
    },
    "AGENTS.md": {
      "layer": "L1",
      "type": "core",
      "name": "工作空间规则"
    },
    "TOOLS.md": {
      "layer": "L1",
      "type": "core",
      "name": "工具规则"
    },
    "MEMORY.md": {
      "layer": "L1",
      "type": "core",
      "name": "长期记忆"
    },
    "fusion_index.json": {
      "layer": "L6",
      "type": "engine",
      "name": "融合引擎"
    },
    "unified.json": {
      "layer": "L6",
      "type": "config",
      "name": "统一配置"
    },
    "run_rule_engine.py": {
      "layer": "L6",
      "type": "engine",
      "name": "规则引擎"
    },
    "unified_inspector.py": {
      "layer": "L6",
      "type": "tool",
      "name": "统一巡检器"
    },
    "exception_manager.py": {
      "layer": "L6",
      "type": "module",
      "name": "例外管理器"
    },
    "dependency_manager.py": {
      "layer": "L6",
      "type": "module",
      "name": "依赖管理器"
    },
    "delete_manager.py": {
      "layer": "L6",
      "type": "module",
      "name": "删除管理器"
    },
    "permanent_keeper.py": {
      "layer": "L6",
      "type": "module",
      "name": "永久守护模块"
    },
    "full_backup.py": {
      "layer": "L6",
      "type": "tool",
      "name": "备份工具"
    },
    "skill_registry.json": {
      "layer": "L6",
      "type": "registry",
      "name": "技能注册表"
    },
    "dependency_manifest.json": {
      "layer": "L6",
      "type": "config",
      "name": "依赖清单"
    },
    "permanent_keepers.json": {
      "layer": "L6",
      "type": "config",
      "name": "守护配置"
    },
    "llm-memory-integration": {
      "layer": "L4",
      "type": "skill",
      "name": "LLM记忆集成"
    },
    "find-skills": {
      "layer": "L4",
      "type": "skill",
      "name": "技能发现"
    },
    "check_skill_security.py": {
      "layer": "L5",
      "type": "governance",
      "name": "技能安全检查"
    },
    "check_change_impact.py": {
      "layer": "L5",
      "type": "governance",
      "name": "变更影响检查"
    }
  },
  "version": "1.0.0"
}

path: config/default_skill_config.py
content: """
Default Skill Config - 默认技能配置
"""

from typing import Dict, Any
from dataclasses import dataclass, field
from pathlib import Path


@dataclass
class StorageConfig:
    """存储配置"""
    type: str = "sqlite"
    database_url: str = "data/tasks.db"
    pool_size: int = 5
    timeout_seconds: int = 30


@dataclass
class ExecutionConfig:
    """执行配置"""
    max_concurrent_tasks: int = 10
    default_timeout_seconds: int = 300
    max_retry_attempts: int = 3
    retry_backoff_seconds: int = 60


@dataclass
class SchedulerConfig:
    """调度配置"""
    enabled: bool = True
    check_interval_seconds: int = 60
    max_scheduled_tasks: int = 1000


@dataclass
class LoggingConfig:
    """日志配置"""
    level: str = "INFO"
    format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    file: str = "logs/skill.log"


@dataclass
class DefaultSkillConfig:
    """默认技能配置"""
    
    storage: StorageConfig = field(default_factory=StorageConfig)
    execution: ExecutionConfig = field(default_factory=ExecutionConfig)
    scheduler: SchedulerConfig = field(default_factory=SchedulerConfig)
    logging: LoggingConfig = field(default_factory=LoggingConfig)
    
    # 运行时模式
    runtime_mode: str = "skill_default"
    
    # 功能开关
    enable_diagnostics: bool = True
    enable_export: bool = True
    enable_replay: bool = True
    enable_self_repair: bool = True
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'DefaultSkillConfig':
        """从字典创建配置"""
        config = cls()
        
        if "storage" in data:
            config.storage = StorageConfig(**data["storage"])
        if "execution" in data:
            config.execution = ExecutionConfig(**data["execution"])
        if "scheduler" in data:
            config.scheduler = SchedulerConfig(**data["scheduler"])
        if "logging" in data:
            config.logging = LoggingConfig(**data["logging"])
        
        config.runtime_mode = data.get("runtime_mode", "skill_default")
        config.enable_diagnostics = data.get("enable_diagnostics", True)
        config.enable_export = data.get("enable_export", True)
        config.enable_replay = data.get("enable_replay", True)
        config.enable_self_repair = data.get("enable_self_repair", True)
        
        return config
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "storage": {
                "type": self.storage.type,
                "database_url": self.storage.database_url,
                "pool_size": self.storage.pool_size,
                "timeout_seconds": self.storage.timeout_seconds
            },
            "execution": {
                "max_concurrent_tasks": self.execution.max_concurrent_tasks,
                "default_timeout_seconds": self.execution.default_timeout_seconds,
                "max_retry_attempts": self.execution.max_retry_attempts,
                "retry_backoff_seconds": self.execution.retry_backoff_seconds
            },
            "scheduler": {
                "enabled": self.scheduler.enabled,
                "check_interval_seconds": self.scheduler.check_interval_seconds,
                "max_scheduled_tasks": self.scheduler.max_scheduled_tasks
            },
            "logging": {
                "level": self.logging.level,
                "format": self.logging.format,
                "file": self.logging.file
            },
            "runtime_mode": self.runtime_mode,
            "enable_diagnostics": self.enable_diagnostics,
            "enable_export": self.enable_export,
            "enable_replay": self.enable_replay,
            "enable_self_repair": self.enable_self_repair
        }


path: config/dependency_manifest.json
content: {
  "version": "1.0.0",
  "description": "依赖清单 - 定义所有需要的依赖",
  "categories": {
    "core": {
      "description": "核心依赖 - 必须安装",
      "required": true,
      "packages": [
        "numpy",
        "scipy",
        "scikit-learn",
        "requests",
        "aiosqlite",
        "cryptography",
        "pycryptodome"
      ]
    },
    "llm": {
      "description": "LLM 集成依赖",
      "required": false,
      "packages": [
        "openai",
        "anthropic",
        "langchain",
        "tiktoken"
      ]
    },
    "embedding": {
      "description": "Embedding 依赖",
      "required": false,
      "packages": [
        "sentence-transformers",
        "transformers"
      ]
    },
    "vector": {
      "description": "向量存储依赖",
      "required": false,
      "packages": [
        "qdrant-client",
        "chromadb",
        "faiss-cpu"
      ]
    },
    "ml": {
      "description": "机器学习依赖",
      "required": false,
      "packages": [
        "torch",
        "numba",
        "llvmlite"
      ]
    },
    "performance": {
      "description": "性能优化依赖",
      "required": false,
      "packages": [
        "numexpr",
        "bottleneck"
      ]
    },
    "document": {
      "description": "文档处理依赖",
      "required": false,
      "packages": [
        "reportlab",
        "weasyprint",
        "pdfkit"
      ]
    }
  },
  "auto_install": {
    "enabled": true,
    "on_import_error": true,
    "timeout_seconds": 300
  },
  "notes": [
    "核心依赖必须安装，其他依赖按需安装",
    "当检测到 ImportError 时自动安装对应依赖",
    "可通过 dependency_manager.py 管理依赖"
  ]
}


path: config/dual_push_config.json
content: {
  "enabled": true,
  "channels": {
    "negative_screen": {
      "enabled": true,
      "skill": "today-task",
      "script": "skills/today-task/scripts/task_push.py"
    },
    "xiaoyi": {
      "enabled": true,
      "channel": "xiaoyi-channel",
      "queue_file": "reports/ops/pending_sends.jsonl"
    }
  },
  "scheduled_tasks": {
    "weather_reminder": {
      "enabled": true,
      "schedule": "0 8 * * *",
      "description": "每日天气提醒"
    },
    "daily_summary": {
      "enabled": true,
      "schedule": "0 22 * * *",
      "description": "每日工作总结"
    },
    "weekly_report": {
      "enabled": true,
      "schedule": "0 20 * * 0",
      "description": "每周报告"
    }
  },
  "created_at": "2026-04-21T23:38:00",
  "updated_at": "2026-04-21T23:38:00"
}


path: config/feature_flags.py
content: """
Feature Flags - 功能开关
"""

from typing import Dict, Any, Optional
from enum import Enum


class Feature(Enum):
    """功能枚举"""
    DIAGNOSTICS = "diagnostics"
    EXPORT_HISTORY = "export_history"
    REPLAY_RUN = "replay_run"
    SELF_REPAIR = "self_repair"
    BATCH_TASKS = "batch_tasks"
    WORKFLOW_ENGINE = "workflow_engine"
    PLATFORM_SCHEDULING = "platform_scheduling"
    ADVANCED_RETRY = "advanced_retry"
    CHECKPOINT_RECOVERY = "checkpoint_recovery"


class FeatureFlags:
    """功能开关管理"""
    
    def __init__(self):
        self._flags: Dict[str, bool] = {
            # 默认启用的功能
            Feature.DIAGNOSTICS.value: True,
            Feature.EXPORT_HISTORY.value: True,
            Feature.REPLAY_RUN.value: True,
            Feature.SELF_REPAIR.value: True,
            Feature.BATCH_TASKS.value: True,
            Feature.WORKFLOW_ENGINE.value: True,
            
            # 默认禁用的功能（需要特定环境）
            Feature.PLATFORM_SCHEDULING.value: False,
            Feature.ADVANCED_RETRY.value: True,
            Feature.CHECKPOINT_RECOVERY.value: True,
        }
    
    def is_enabled(self, feature: Feature) -> bool:
        """检查功能是否启用"""
        return self._flags.get(feature.value, False)
    
    def enable(self, feature: Feature) -> None:
        """启用功能"""
        self._flags[feature.value] = True
    
    def disable(self, feature: Feature) -> None:
        """禁用功能"""
        self._flags[feature.value] = False
    
    def set(self, feature: Feature, enabled: bool) -> None:
        """设置功能状态"""
        self._flags[feature.value] = enabled
    
    def get_all(self) -> Dict[str, bool]:
        """获取所有功能状态"""
        return dict(self._flags)
    
    def update_from_config(self, config: Dict[str, Any]) -> None:
        """从配置更新"""
        for key, value in config.items():
            if key in self._flags and isinstance(value, bool):
                self._flags[key] = value
    
    def auto_configure(self) -> None:
        """自动配置（根据运行环境）"""
        from platform_adapter.runtime_probe import RuntimeProbe
        env = RuntimeProbe.detect_environment()
        
        # 根据环境自动启用/禁用功能
        if env.get("is_xiaoyi"):
            self.enable(Feature.PLATFORM_SCHEDULING)
        
        if env.get("has_database") and env.get("has_redis"):
            self.enable(Feature.ADVANCED_RETRY)
            self.enable(Feature.CHECKPOINT_RECOVERY)


# 全局实例
_global_flags: Optional[FeatureFlags] = None


def get_feature_flags() -> FeatureFlags:
    """获取全局功能开关"""
    global _global_flags
    if _global_flags is None:
        _global_flags = FeatureFlags()
        _global_flags.auto_configure()
    return _global_flags


path: config/injection_config.json
content: {
  "version": "1.0.0",
  "mode": "minimal",
  "description": "精简注入配置 - 减少 Token 消耗",
  "inject": {
    "always": [
      "AGENTS.md",
      "SOUL.md",
      "USER.md",
      "TOOLS.md",
      "MEMORY.md"
    ],
    "daily": [
      "memory/{date}.md"
    ],
    "indexes": [
      "infrastructure/inventory/fusion_index.json",
      "infrastructure/inventory/skill_registry_summary.json"
    ]
  },
  "exclude": [
    "skills/**",
    "reports/**",
    "docs/**",
    "tests/**",
    "repo/**",
    "archive/**",
    "*.pyc",
    "*.pyo",
    "__pycache__/**"
  ],
  "lazy_load": {
    "skills": "find-skills",
    "memory": "memory_search",
    "reports": "read on demand"
  }
}

path: config/injection_config_minimal.json
content: {
  "version": "2.0.0",
  "mode": "ultra-minimal",
  "description": "极简注入 - 最小 Token 消耗",
  "inject": {
    "core": [
      "SOUL.md",
      "USER.md",
      "MEMORY.md"
    ],
    "compressed": [
      "core/compressed/AGENTS_summary.md",
      "core/compressed/TOOLS_summary.md"
    ],
    "indexes": [
      "infrastructure/inventory/skill_registry_summary.json"
    ]
  },
  "exclude": [
    "skills/**",
    "reports/**",
    "docs/**",
    "tests/**",
    "repo/**",
    "archive/**",
    "memory_context/**",
    "infrastructure/**",
    "governance/**",
    "execution/**",
    "orchestration/**"
  ],
  "lazy_load": {
    "skills": "find-skills",
    "memory": "memory_search",
    "config": "read on demand",
    "reports": "read on demand"
  },
  "estimated_tokens": 2500
}

path: config/injection_config_smart.json
content: {
  "version": "3.0.0",
  "mode": "smart",
  "description": "智能注入 - 自动压缩 + 增量更新",
  "features": {
    "smart_compress": true,
    "incremental_update": true,
    "auto_summary": true,
    "cache_enabled": true
  },
  "inject": {
    "core": [
      "SOUL.md",
      "USER.md",
      "MEMORY.md"
    ],
    "auto_compress": [
      "AGENTS.md",
      "TOOLS.md"
    ],
    "indexes": [
      "infrastructure/inventory/skill_registry_summary.json"
    ]
  },
  "tools": {
    "compressor": "scripts/smart_compressor.py",
    "updater": "scripts/incremental_updater.py",
    "summarizer": "scripts/auto_summarizer.py"
  },
  "estimated_tokens": 2000,
  "cache_ttl": 3600
}

path: config/permanent_keepers.json
content: {
  "keepers": {
    "fusion_engine": {
      "name": "融合引擎",
      "type": "engine",
      "priority": "critical",
      "files": [
        "infrastructure/inventory/fusion_index.json",
        "infrastructure/config/unified.json"
      ],
      "refresh_interval_hours": 1,
      "auto_restore": true,
      "description": "统一融合索引，保证技能路由和模块发现"
    },
    "memory_engine": {
      "name": "记忆引擎",
      "type": "engine",
      "priority": "critical",
      "files": [
        "MEMORY.md",
        "memory_context/vector/embedding_config.json",
        "memory_context/index/",
        "skills/llm-memory-integration/config/llm_config.json"
      ],
      "refresh_interval_hours": 1,
      "auto_restore": true,
      "description": "长期记忆和向量索引，保证上下文连续性"
    },
    "rule_engine": {
      "name": "规则引擎",
      "type": "engine",
      "priority": "critical",
      "files": [
        "core/RULE_REGISTRY.json",
        "core/RULE_EXCEPTIONS.json",
        "scripts/run_rule_engine.py"
      ],
      "refresh_interval_hours": 1,
      "auto_restore": true,
      "description": "规则注册和执行，保证门禁行为一致"
    },
    "exception_manager": {
      "name": "例外管理器",
      "type": "module",
      "priority": "high",
      "files": [
        "scripts/exception_manager.py",
        "reports/ops/rule_exception_history.json",
        "reports/ops/rule_exception_status.json"
      ],
      "refresh_interval_hours": 1,
      "auto_restore": true,
      "description": "例外操作和历史，保证例外状态连续"
    },
    "dependency_manager": {
      "name": "依赖管理器",
      "type": "module",
      "priority": "high",
      "files": [
        "scripts/dependency_manager.py",
        "infrastructure/config/dependency_manifest.json",
        "reports/ops/dependency_status.json"
      ],
      "refresh_interval_hours": 24,
      "auto_restore": true,
      "description": "依赖状态，保证环境一致性"
    },
    "delete_manager": {
      "name": "删除管理器",
      "type": "module",
      "priority": "high",
      "files": [
        "scripts/delete_manager.py",
        "archive/trash/",
        "reports/ops/delete_log.json"
      ],
      "refresh_interval_hours": 24,
      "auto_restore": true,
      "description": "删除确认和回收站，防止误删"
    },
    "skill_registry": {
      "name": "技能注册表",
      "type": "registry",
      "priority": "critical",
      "files": [
        "infrastructure/inventory/skill_registry.json",
        "infrastructure/inventory/skill_registry_summary.json"
      ],
      "refresh_interval_hours": 1,
      "auto_restore": true,
      "description": "技能发现和路由，保证技能可用"
    },
    "core_identity": {
      "name": "核心身份",
      "type": "identity",
      "priority": "critical",
      "files": [
        "SOUL.md",
        "USER.md",
        "IDENTITY.md",
        "AGENTS.md",
        "TOOLS.md"
      ],
      "refresh_interval_hours": 24,
      "auto_restore": true,
      "description": "身份和规则，保证行为一致"
    },
    "architecture": {
      "name": "架构文档",
      "type": "docs",
      "priority": "critical",
      "files": [
        "core/ARCHITECTURE.md",
        "core/LAYER_DEPENDENCY_MATRIX.md",
        "core/LAYER_DEPENDENCY_RULES.json",
        "core/LAYER_IO_CONTRACTS.md"
      ],
      "refresh_interval_hours": 24,
      "auto_restore": true,
      "description": "架构定义，保证结构一致"
    }
  },
  "version": "1.0.0"
}

path: config/resource_paths.py
content: """
资源路径访问层 - Config
统一配置资源路径访问，避免业务代码硬编码路径
"""

from pathlib import Path

# 唯一真源配置目录
CONFIG_DIR = Path(__file__).parent


def get_config_path(filename: str) -> Path:
    """获取配置文件路径"""
    return CONFIG_DIR / filename


def get_settings_path() -> Path:
    """获取 settings.py 路径"""
    return CONFIG_DIR / "settings.py"


def get_injection_config_path(mode: str = "default") -> Path:
    """获取注入配置路径
    
    Args:
        mode: 配置模式 (default, minimal, smart)
    """
    config_map = {
        "default": "injection_config.json",
        "minimal": "injection_config.json",
        "ultra_minimal": "injection_config_minimal.json",
        "smart": "injection_config_smart.json"
    }
    return CONFIG_DIR / config_map.get(mode, "injection_config.json")


def get_component_classification_path() -> Path:
    """获取组件分类配置路径"""
    return CONFIG_DIR / "component_classification.json"


def get_dependency_manifest_path() -> Path:
    """获取依赖清单路径"""
    return CONFIG_DIR / "dependency_manifest.json"


def get_permanent_keepers_path() -> Path:
    """获取永久守护配置路径"""
    return CONFIG_DIR / "permanent_keepers.json"


def get_unified_config_path() -> Path:
    """获取统一配置路径"""
    return CONFIG_DIR / "unified.json"


path: config/runtime_modes.py
content: """
Runtime Mode Definitions

Defines 4 runtime modes for device interaction:
- dry_run: No side effects, for CI/testing
- fake_device: Mock device responses, for E2E testing
- probe_only: Real device connection, read-only probing
- connected_runtime: Real device with controlled execution
"""

from enum import Enum
from dataclasses import dataclass
from typing import Optional


class RuntimeMode(str, Enum):
    """Runtime execution modes."""
    DRY_RUN = "dry_run"
    FAKE_DEVICE = "fake_device"
    PROBE_ONLY = "probe_only"
    CONNECTED_RUNTIME = "connected_runtime"


@dataclass
class RuntimeModeConfig:
    """Configuration for a runtime mode."""
    allow_side_effects: bool
    require_device: bool
    allow_screen_read: bool = False
    allow_click: bool = False
    allow_type: bool = False
    allow_delete: bool = False
    allow_send: bool = False
    allow_call: bool = False
    enforce_safety_governor: bool = False


RUNTIME_MODE_CONFIGS: dict[RuntimeMode, RuntimeModeConfig] = {
    RuntimeMode.DRY_RUN: RuntimeModeConfig(
        allow_side_effects=False,
        require_device=False,
    ),
    RuntimeMode.FAKE_DEVICE: RuntimeModeConfig(
        allow_side_effects=False,
        require_device=False,
        allow_screen_read=True,
    ),
    RuntimeMode.PROBE_ONLY: RuntimeModeConfig(
        allow_side_effects=False,
        require_device=True,
        allow_screen_read=True,
        allow_click=False,
        allow_type=False,
        allow_delete=False,
        allow_send=False,
        allow_call=False,
    ),
    RuntimeMode.CONNECTED_RUNTIME: RuntimeModeConfig(
        allow_side_effects=True,
        require_device=True,
        allow_screen_read=True,
        allow_click=True,
        allow_type=True,
        allow_delete=True,
        allow_send=True,
        allow_call=True,
        enforce_safety_governor=True,
    ),
}


def get_runtime_mode_config(mode: RuntimeMode) -> RuntimeModeConfig:
    """Get configuration for a runtime mode."""
    return RUNTIME_MODE_CONFIGS.get(mode, RUNTIME_MODE_CONFIGS[RuntimeMode.DRY_RUN])


def is_side_effect_allowed(mode: RuntimeMode, action: str) -> bool:
    """Check if a side-effecting action is allowed in the given mode."""
    config = get_runtime_mode_config(mode)
    
    if not config.allow_side_effects:
        return False
    
    action_map = {
        "click": config.allow_click,
        "type": config.allow_type,
        "delete": config.allow_delete,
        "send": config.allow_send,
        "call": config.allow_call,
    }
    
    return action_map.get(action, False)


def is_probe_only(mode: RuntimeMode) -> bool:
    """Check if the mode is probe-only (no side effects)."""
    return mode == RuntimeMode.PROBE_ONLY


def requires_device(mode: RuntimeMode) -> bool:
    """Check if the mode requires a real device."""
    return get_runtime_mode_config(mode).require_device


path: config/runtime_policy.yaml
content: # Runtime Policy Configuration
# Defines behavior for each runtime mode

default_mode: dry_run

modes:
  dry_run:
    allow_side_effects: false
    require_device: false
    description: "No side effects, for CI/testing"

  fake_device:
    allow_side_effects: false
    require_device: false
    allow_screen_read: true
    description: "Mock device responses, for E2E testing"

  probe_only:
    allow_side_effects: false
    require_device: true
    allow_screen_read: true
    allow_click: false
    allow_type: false
    allow_delete: false
    allow_send: false
    allow_call: false
    description: "Real device connection, read-only probing"

  connected_runtime:
    allow_side_effects: true
    require_device: true
    allow_screen_read: true
    allow_click: true
    allow_type: true
    allow_delete: true
    allow_send: true
    allow_call: true
    enforce_safety_governor: true
    description: "Real device with controlled execution"

# Risk level policies for connected_runtime
risk_policies:
  L0:
    auto_execute: true
    require_confirmation: false
    audit_required: true
  
  L1:
    auto_execute: true
    require_confirmation: false
    audit_required: true
  
  L2:
    auto_execute: true
    require_confirmation: optional
    rate_limit: true
    audit_required: true
  
  L3:
    auto_execute: false
    require_confirmation: true
    confirmation_type: confirm_once
    audit_required: true
  
  L4:
    auto_execute: false
    require_confirmation: true
    confirmation_type: strong_confirm
    requires_preview: true
    requires_stepwise: true
    audit_required: true
  
  BLOCKED:
    auto_execute: false
    blocked: true

# Safe routes whitelist for connected smoke
safe_routes:
  - route.query_note
  - route.search_notes
  - route.list_recent_messages
  - route.query_message_status
  - route.query_alarm
  - route.query_contact
  - route.get_location
  - route.check_calendar_conflicts

# Routes that require confirmation (cannot auto-execute)
confirmation_required_routes:
  - route.send_message
  - route.delete_note
  - route.update_note
  - route.delete_alarm
  - route.make_call
  - route.xiaoyi_gui_agent
  - route.bootstrap


path: config/safety_controls.py
content: """安全控制配置"""

from typing import Dict, Any, Optional, List
from dataclasses import dataclass
from enum import Enum
import json
from pathlib import Path


class ControlLevel(Enum):
    OFF = "off"
    WARN = "warn"
    ENFORCE = "enforce"


@dataclass
class SafetyControl:
    """安全控制项"""
    name: str
    level: ControlLevel
    threshold: Optional[int] = None
    message: Optional[str] = None


# 默认安全控制配置
DEFAULT_CONTROLS = {
    "dry_run": SafetyControl(
        name="dry_run",
        level=ControlLevel.ENFORCE,
        message="副作用操作必须支持 dry_run 模式"
    ),
    "approval_required": SafetyControl(
        name="approval_required",
        level=ControlLevel.ENFORCE,
        message="批量操作需要审批"
    ),
    "max_batch_size": SafetyControl(
        name="max_batch_size",
        level=ControlLevel.ENFORCE,
        threshold=20,
        message="批次大小不能超过 20"
    ),
    "rate_limit": SafetyControl(
        name="rate_limit",
        level=ControlLevel.ENFORCE,
        threshold=10,  # 每分钟最大请求数
        message="请求频率超过限制"
    ),
    "safe_mode": SafetyControl(
        name="safe_mode",
        level=ControlLevel.WARN,
        message="安全模式已启用"
    ),
    "side_effect_preview": SafetyControl(
        name="side_effect_preview",
        level=ControlLevel.ENFORCE,
        message="副作用操作必须可预览"
    ),
    "idempotency_scope": SafetyControl(
        name="idempotency_scope",
        level=ControlLevel.ENFORCE,
        message="幂等键必须在正确的作用域内"
    )
}

# 需要审批的操作
APPROVAL_REQUIRED_ACTIONS = {
    "batch_sms": {"threshold": 5, "message": "批量短信超过 5 条需要审批"},
    "batch_notification": {"threshold": 10, "message": "批量通知超过 10 条需要审批"},
    "batch_calendar": {"threshold": 10, "message": "批量日程创建超过 10 条需要审批"},
    "delete_all": {"threshold": 1, "message": "批量删除需要审批"}
}

# 能力限流配置
RATE_LIMITS = {
    "send_message": {"per_minute": 10, "per_hour": 100},
    "send_notification": {"per_minute": 20, "per_hour": 200},
    "schedule_task": {"per_minute": 30, "per_hour": 300},
    "create_note": {"per_minute": 30, "per_hour": 300}
}


def check_approval_required(action_type: str, count: int) -> Dict[str, Any]:
    """
    检查是否需要审批
    
    Args:
        action_type: 操作类型
        count: 操作数量
        
    Returns:
        检查结果
    """
    config = APPROVAL_REQUIRED_ACTIONS.get(action_type, {})
    threshold = config.get("threshold", float("inf"))
    
    approval_required = count >= threshold
    
    return {
        "action_type": action_type,
        "count": count,
        "threshold": threshold,
        "approval_required": approval_required,
        "message": config.get("message") if approval_required else None
    }


def check_batch_size(action_type: str, count: int) -> Dict[str, Any]:
    """
    检查批次大小
    
    Args:
        action_type: 操作类型
        count: 操作数量
        
    Returns:
        检查结果
    """
    control = DEFAULT_CONTROLS["max_batch_size"]
    max_size = control.threshold
    
    if count > max_size:
        return {
            "allowed": False,
            "count": count,
            "max_batch_size": max_size,
            "message": control.message
        }
    
    return {
        "allowed": True,
        "count": count,
        "max_batch_size": max_size
    }


def check_rate_limit(capability: str, requests_in_window: int, window: str = "per_minute") -> Dict[str, Any]:
    """
    检查限流
    
    Args:
        capability: 能力名称
        requests_in_window: 时间窗口内的请求数
        window: 时间窗口 (per_minute / per_hour)
        
    Returns:
        检查结果
    """
    limits = RATE_LIMITS.get(capability, {})
    limit = limits.get(window, float("inf"))
    
    if requests_in_window >= limit:
        return {
            "allowed": False,
            "capability": capability,
            "requests": requests_in_window,
            "limit": limit,
            "window": window,
            "message": f"请求频率超过限制: {requests_in_window}/{limit} ({window})"
        }
    
    return {
        "allowed": True,
        "capability": capability,
        "requests": requests_in_window,
        "limit": limit,
        "window": window
    }


def validate_safety_controls(
    capability: str,
    params: Dict[str, Any],
    dry_run: bool = False,
) -> Dict[str, Any]:
    """
    验证安全控制
    
    Args:
        capability: 能力名称
        params: 参数
        dry_run: 是否预演模式
        
    Returns:
        验证结果
    """
    violations = []
    warnings = []
    
    # 检查 dry_run 支持
    if not dry_run and capability in ["send_message", "schedule_task", "create_note", "send_notification"]:
        # 这些能力应该支持 dry_run
        pass  # 仅警告，不阻止
    
    # 检查批次大小
    if "recipients" in params or "notifications" in params or "messages" in params:
        batch = params.get("recipients") or params.get("notifications") or params.get("messages", [])
        if len(batch) > DEFAULT_CONTROLS["max_batch_size"].threshold:
            violations.append({
                "control": "max_batch_size",
                "message": DEFAULT_CONTROLS["max_batch_size"].message,
                "count": len(batch),
                "max": DEFAULT_CONTROLS["max_batch_size"].threshold
            })
    
    # 检查幂等键
    if capability in ["send_message", "schedule_task", "send_notification"]:
        if "idempotency_key" not in params:
            warnings.append({
                "control": "idempotency_scope",
                "message": "建议提供 idempotency_key 以确保幂等性"
            })
    
    return {
        "valid": len(violations) == 0,
        "violations": violations if violations else None,
        "warnings": warnings if warnings else None,
        "dry_run": dry_run
    }


def get_safety_controls_config() -> Dict[str, Any]:
    """获取安全控制配置"""
    return {
        "controls": {k: {"level": v.level.value, "threshold": v.threshold, "message": v.message} 
                     for k, v in DEFAULT_CONTROLS.items()},
        "approval_required_actions": APPROVAL_REQUIRED_ACTIONS,
        "rate_limits": RATE_LIMITS
    }


def save_safety_controls_config(config: Dict[str, Any], path: str = "config/safety_controls.json"):
    """保存安全控制配置"""
    config_path = Path("/home/sandbox/.openclaw/workspace") / path
    config_path.parent.mkdir(parents=True, exist_ok=True)
    
    with open(config_path, "w") as f:
        json.dump(config, f, indent=2)
    
    return {"success": True, "path": str(config_path)}


path: config/settings.py
content: """
配置中心 V1.0.0

支持多环境配置：local / test / prod
"""

import os
from pathlib import Path
from typing import Optional
from enum import Enum
from pydantic import BaseModel, Field


class Environment(str, Enum):
    """运行环境"""
    LOCAL = "local"
    TEST = "test"
    PROD = "prod"


class DatabaseConfig(BaseModel):
    """数据库配置"""
    type: str = "sqlite"
    url: Optional[str] = None
    host: str = "localhost"
    port: int = 5432
    name: str = "openclaw"
    user: str = "openclaw"
    password: str = ""


class RedisConfig(BaseModel):
    """Redis 配置"""
    enabled: bool = False
    host: str = "localhost"
    port: int = 6379
    db: int = 0
    [REDACTED_SECRET] = None


class MessageServerConfig(BaseModel):
    """消息服务配置"""
    host: str = "localhost"
    port: int = 18790
    timeout: int = 5


class DaemonConfig(BaseModel):
    """守护进程配置"""
    check_interval: float = 5.0
    max_concurrent_tasks: int = 10
    log_level: str = "INFO"


class ObservabilityConfig(BaseModel):
    """可观测性配置"""
    log_dir: str = "logs"
    metrics_dir: str = "reports/metrics"
    enable_tracing: bool = True
    enable_metrics: bool = True


class Settings(BaseModel):
    """全局配置"""
    env: Environment = Environment.LOCAL
    debug: bool = False
    
    database: DatabaseConfig = Field(default_factory=DatabaseConfig)
    redis: RedisConfig = Field(default_factory=RedisConfig)
    message_server: MessageServerConfig = Field(default_factory=MessageServerConfig)
    daemon: DaemonConfig = Field(default_factory=DaemonConfig)
    observability: ObservabilityConfig = Field(default_factory=ObservabilityConfig)
    
    @classmethod
    def from_env(cls) -> "Settings":
        """从环境变量加载配置"""
        env_str = os.getenv("OPENCLAW_ENV", "local").lower()
        env = Environment(env_str) if env_str in [e.value for e in Environment] else Environment.LOCAL
        
        settings = cls(env=env)
        
        # 数据库配置
        if db_url := os.getenv("DATABASE_URL"):
            settings.database.url = db_url
        if db_host := os.getenv("DB_HOST"):
            settings.database.host = db_host
        if db_port := os.getenv("DB_PORT"):
            settings.database.port = int(db_port)
        if db_name := os.getenv("DB_NAME"):
            settings.database.name = db_name
        if db_user := os.getenv("DB_USER"):
            settings.database.user = db_user
        if db_pass := os.getenv("DB_PASSWORD"):
            settings.database.[REDACTED_SECRET]
        
        # Redis 配置
        if redis_host := os.getenv("REDIS_HOST"):
            settings.redis.host = redis_host
            settings.redis.enabled = True
        if redis_port := os.getenv("REDIS_PORT"):
            settings.redis.port = int(redis_port)
        
        # 消息服务配置
        if msg_port := os.getenv("MESSAGE_SERVER_PORT"):
            settings.message_server.port = int(msg_port)
        
        # 守护进程配置
        if interval := os.getenv("DAEMON_CHECK_INTERVAL"):
            settings.daemon.check_interval = float(interval)
        
        # Debug 模式
        settings.debug = os.getenv("OPENCLAW_DEBUG", "").lower() in ("true", "1", "yes")
        
        return settings
    
    def get_database_url(self) -> str:
        """获取数据库 URL"""
        if self.database.url:
            return self.database.url
        
        if self.database.type == "sqlite":
            return "sqlite:///data/tasks.db"
        
        return f"postgresql://{self.database.user}:{self.database.password}@{self.database.host}:{self.database.port}/{self.database.name}"
    
    def get_redis_url(self) -> Optional[str]:
        """获取 Redis URL"""
        if not self.redis.enabled:
            return None
        
        auth = f":{self.redis.password}@" if self.redis.password else ""
        return f"redis://{auth}{self.redis.host}:{self.redis.port}/{self.redis.db}"


# 全局配置实例
_settings: Optional[Settings] = None


def get_settings() -> Settings:
    """获取全局配置"""
    global _settings
    if _settings is None:
        _settings = Settings.from_env()
    return _settings


path: config/unified.json
content: {
  "version": "7.2.0",
  "description": "唯一运行时配置 - 其他配置文件仅作兼容或实验用途",
  "search": {
    "top_k": 10,
    "mode": "balanced",
    "timeout_ms": 3000,
    "use_semantic": true
  },
  "cache": {
    "max_size": 1000,
    "default_ttl": 300,
    "l1_max_items": 100,
    "l2_max_size_mb": 10
  },
  "router": {
    "mode": "balanced",
    "confidence_threshold": 0.5,
    "max_alternatives": 3
  },
  "weights": {
    "keyword": 0.3,
    "semantic": 0.4,
    "popularity": 0.2,
    "recency": 0.1
  },
  "token_budget": {
    "total": 10000,
    "l1_core": 3000,
    "l2_memory": 2000,
    "l3_orchestration": 1500,
    "l4_execution": 1500,
    "l5_governance": 800,
    "l6_infrastructure": 700
  },
  "ecommerce": {
    "default_commission_rate": 0.25,
    "min_follower_count": 10000,
    "max_risk_level": "medium"
  },
  "performance": {
    "parallel_inspection": true,
    "cache_ttl": 3600,
    "lazy_load_skills": true,
    "batch_operations": true,
    "async_io": true,
    "numba_enabled": true,
    "numpy_enabled": true,
    "max_workers": 4
  },
  "updated": "2026-04-14",
  "inspector": {
    "version": "7.2.0",
    "workers": 8,
    "checks": [
      "层间依赖",
      "JSON契约",
      "仓库完整性",
      "变更影响",
      "技能安全",
      "架构完整性",
      "Token优化",
      "注入配置"
    ]
  },
  "token_optimization": {
    "enabled": true,
    "default_mode": "smart",
    "estimated_tokens": 2000
  },
  "llm_integration": {
    "skill": "llm-memory-integration",
    "version": "7.2.0",
    "embedding": {
      "provider": "Gitee AI",
      "model": "Qwen3-Embedding-8B",
      "dimensions": 4096
    },
    "llm": {
      "provider": "Gitee AI",
      "model": "Qwen3-235B-A22B"
    },
    "vector_engines": {
      "primary": "sqlite-vec",
      "secondary": "qdrant",
      "backup": "tfidf"
    }
  },
  "modules": {
    "dependency_manager": {
      "enabled": true,
      "auto_check": true,
      "auto_install": false
    },
    "delete_manager": {
      "enabled": true,
      "require_confirmation": true,
      "trash_enabled": true,
      "trash_retention_days": 7
    }
  },
  "ocr": {
    "provider": "deepseek",
    "service_id": "deepseek-ocr-2sk-u3qymvvjrvxh26j6",
    "enabled": true,
    "timeout_ms": 30000,
    "max_image_size_mb": 10,
    "supported_formats": ["jpg", "jpeg", "png", "gif", "webp", "bmp"],
    "languages": ["zh", "en", "ja", "ko"],
    "features": {
      "text_detection": true,
      "text_recognition": true,
      "table_detection": false,
      "handwriting": true,
      "formula": false
    },
    "cache": {
      "enabled": true,
      "ttl_seconds": 3600
    },
    "fallback": {
      "enabled": true,
      "provider": "tesseract"
    }
  }
}

path: core/README_UPGRADE.md
content: # L1 Core Layer - 升级版

核心层监控模块，包含CLI工具、性能监控、健康监控等功能。

## 模块列表

### monitoring/ - 性能监控系统
- `cli_tool.py` - 命令行工具、交互式配置
- `performance_monitor.py` - 实时性能指标
- `health_monitor.py` - 健康检查、告警系统

## 升级效果

| 功能 | 提升 |
|------|------|
| CLI工具 | 操作效率 ↑ 100% |
| 性能监控 | 监控效率 ↑ 200%, 故障发现 ↓ 5min |
| 健康监控 | 系统稳定性 ↑ 50% |


path: core/audit.py
content: """Audit Queries - 审计查询 (shim)"""

from typing import Dict, Any


def audit_queries(time_range: str = "24h") -> Dict[str, Any]:
    """审计查询
    
    Args:
        time_range: 时间范围
        
    Returns:
        审计结果
    """
    return {
        "status": "dry_run",
        "message": "audit_queries is planned feature",
        "time_range": time_range,
        "queries": [],
        "side_effects": False
    }


path: core/authorization/__init__.py
content: from .authorization_intent_gateway import AuthorizationIntentGateway
from .consent_scope_model import ConsentScopeModel
from .action_risk_attestation import ActionRiskAttestation
from .user_confirmation_contract import UserConfirmationContract

__all__ = [
    "AuthorizationIntentGateway",
    "ConsentScopeModel",
    "ActionRiskAttestation",
    "UserConfirmationContract",
]


path: core/authorization/action_risk_attestation.py
content: class ActionRiskAttestation:
    def attest(self, action: dict) -> dict:
        risk = action.get("risk_level", "L1")
        side_effect = bool(action.get("side_effect", False))
        return {
            "status": "attested",
            "risk_level": risk,
            "side_effect": side_effect,
            "requires_confirmation": risk in {"L3", "L4", "BLOCKED"} or side_effect,
            "human_readable_summary": action.get("summary", action.get("title", "planned action")),
        }


path: core/authorization/authorization_intent_gateway.py
content: from __future__ import annotations

from .consent_scope_model import ConsentScopeModel
from .action_risk_attestation import ActionRiskAttestation
from .user_confirmation_contract import UserConfirmationContract


class AuthorizationIntentGateway:
    """Gate user intent before any external write/device/connector action."""

    def __init__(self) -> None:
        self.scope = ConsentScopeModel()
        self.attestation = ActionRiskAttestation()
        self.confirmation = UserConfirmationContract()

    def gate(self, action: dict) -> dict:
        scopes = action.get("scopes", [])
        scope = self.scope.evaluate(scopes)
        attestation = self.attestation.attest(action)
        needs_confirm = scope["requires_explicit_consent"] or attestation["requires_confirmation"]
        contract = None
        if needs_confirm:
            contract = self.confirmation.create(
                action.get("action_id", "unknown"),
                attestation["human_readable_summary"],
                attestation["risk_level"],
                scopes,
            )
        return {
            "status": "waiting_confirmation" if needs_confirm else "authorized_for_planning_only",
            "scope": scope,
            "attestation": attestation,
            "confirmation_contract": contract,
            "can_execute_now": False if needs_confirm else not action.get("side_effect", False),
        }


path: core/authorization/consent_scope_model.py
content: class ConsentScopeModel:
    HIGH_RISK = {"send", "delete", "publish", "payment", "account", "call", "install"}

    def evaluate(self, scopes: list[str]) -> dict:
        high = sorted(set(scopes) & self.HIGH_RISK)
        return {
            "status": "evaluated",
            "scopes": scopes,
            "high_risk_scopes": high,
            "least_privilege": True,
            "requires_explicit_consent": bool(high),
        }


path: core/authorization/user_confirmation_contract.py
content: from __future__ import annotations

from datetime import datetime


class UserConfirmationContract:
    """Never fabricate confirmation. Create exact confirmation contract."""

    def create(self, action_id: str, summary: str, risk_level: str, scopes: list[str]) -> dict:
        return {
            "confirmation_id": f"confirm_{abs(hash(action_id + summary))}",
            "action_id": action_id,
            "summary": summary,
            "risk_level": risk_level,
            "scopes": scopes,
            "status": "pending_user_confirmation",
            "confirmed": False,
            "created_at": datetime.utcnow().isoformat() + "Z",
        }


path: core/autonomy/__init__.py
content: from .goal_strategy_kernel import GoalStrategyKernel, GoalModel, StrategyOption
from .task_graph_compiler import TaskGraphCompiler, ExecutionGraph, TaskNode

__all__ = [
    "GoalStrategyKernel",
    "GoalModel",
    "StrategyOption",
    "TaskGraphCompiler",
    "ExecutionGraph",
    "TaskNode",
]


path: core/autonomy/goal_strategy_kernel.py
content: """V10 Goal-Strategy Kernel.

Turns a one-sentence user goal into a governed objective model and execution graph.
This is deliberately deterministic and side-effect-free: real execution is delegated to
route/capability layers after governance approval.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any


@dataclass
class GoalModel:
    raw_goal: str
    objective: str
    constraints: list[str] = field(default_factory=list)
    success_criteria: list[str] = field(default_factory=list)
    required_capabilities: list[str] = field(default_factory=list)
    risk_hints: list[str] = field(default_factory=list)
    autonomy_level: str = "bounded_autonomy"


@dataclass
class StrategyOption:
    name: str
    priority: int
    expected_value: float
    risk_level: str
    requires_approval: bool
    steps: list[str]


class GoalStrategyKernel:
    """Goal modeling + strategy selection for the personal autonomous agent."""

    DEFAULT_SUCCESS = (
        "goal_understood",
        "risk_checked",
        "capabilities_resolved_or_gap_reported",
        "execution_graph_ready",
    )

    def model_goal(self, goal: str, context: dict[str, Any] | None = None) -> GoalModel:
        if not isinstance(goal, str) or not goal.strip():
            raise ValueError("goal must be a non-empty string")
        context = context or {}
        text = goal.strip()
        required = self._infer_required_capabilities(text)
        risk_hints = self._infer_risk_hints(text)
        constraints = list(context.get("constraints", []))
        if "不要问" in text or "自动" in text or "一句话" in text:
            constraints.append("minimize_follow_up_questions")
        if "像我" in text or "我的风格" in text:
            constraints.append("use_personalization_profile")
        return GoalModel(
            raw_goal=text,
            objective=text,
            constraints=constraints,
            success_criteria=list(self.DEFAULT_SUCCESS),
            required_capabilities=required,
            risk_hints=risk_hints,
            autonomy_level=context.get("autonomy_level", "bounded_autonomy"),
        )

    def generate_strategies(self, model: GoalModel) -> list[StrategyOption]:
        base_steps = [
            "compile_goal_tree",
            "judge_risk_and_rules",
            "resolve_capabilities",
            "build_execution_graph",
            "run_safe_steps",
            "pause_for_approval_on_high_risk",
            "verify_result_and_learn",
        ]
        conservative = StrategyOption(
            name="safe_first",
            priority=1,
            expected_value=0.72,
            risk_level="L1",
            requires_approval=False,
            steps=base_steps,
        )
        balanced = StrategyOption(
            name="personal_autonomy_balanced",
            priority=2,
            expected_value=0.86,
            risk_level="L2",
            requires_approval=bool(model.risk_hints),
            steps=base_steps + ["use_personal_style_model", "auto_recover_failures"],
        )
        self_extending = StrategyOption(
            name="self_extending_if_gap",
            priority=3,
            expected_value=0.91,
            risk_level="L3" if model.risk_hints else "L2",
            requires_approval=True,
            steps=base_steps + ["detect_capability_gap", "search_solution", "sandbox_new_capability"],
        )
        return [conservative, balanced, self_extending]

    def choose_strategy(self, model: GoalModel, strategies: list[StrategyOption]) -> StrategyOption:
        if not strategies:
            raise ValueError("strategies must not be empty")
        if model.risk_hints:
            return sorted(strategies, key=lambda s: (s.requires_approval, -s.expected_value))[0]
        return sorted(strategies, key=lambda s: (-s.expected_value, s.priority))[0]

    def compile(self, goal: str, context: dict[str, Any] | None = None) -> dict[str, Any]:
        model = self.model_goal(goal, context)
        strategies = self.generate_strategies(model)
        chosen = self.choose_strategy(model, strategies)
        return {
            "status": "compiled",
            "agent_type": "self_evolving_personal_operating_agent",
            "goal": model.__dict__,
            "chosen_strategy": chosen.__dict__,
            "alternatives": [s.__dict__ for s in strategies],
        }

    @staticmethod
    def _infer_required_capabilities(text: str) -> list[str]:
        capabilities = ["goal_modeling", "risk_judgement", "execution_graph"]
        rules = [
            ("邮件", "email_access"),
            ("日程", "calendar_access"),
            ("手机", "device_operation"),
            ("查找", "solution_search"),
            ("搜索", "solution_search"),
            ("安装", "capability_extension"),
            ("技能", "skill_registry"),
            ("外部", "external_capability_bus"),
            ("API", "external_capability_bus"),
            ("像我", "personalization_memory"),
            ("自动", "autonomous_execution"),
        ]
        for keyword, capability in rules:
            if keyword.lower() in text.lower() and capability not in capabilities:
                capabilities.append(capability)
        return capabilities

    @staticmethod
    def _infer_risk_hints(text: str) -> list[str]:
        risk_hints = []
        for keyword in ("支付", "转账", "删除", "发给", "安装", "账号", "密码", "隐私", "群发", "交易"):
            if keyword in text:
                risk_hints.append(keyword)
        return risk_hints


path: core/autonomy/task_graph_compiler.py
content: """V10 task graph compiler for one-sentence goals."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any


@dataclass
class TaskNode:
    id: str
    name: str
    node_type: str
    risk_level: str = "L1"
    requires_approval: bool = False
    depends_on: list[str] = field(default_factory=list)


@dataclass
class ExecutionGraph:
    graph_id: str
    nodes: list[TaskNode]
    completion_criteria: list[str]
    reversible: bool = True

    def to_dict(self) -> dict[str, Any]:
        return {
            "graph_id": self.graph_id,
            "nodes": [n.__dict__ for n in self.nodes],
            "completion_criteria": list(self.completion_criteria),
            "reversible": self.reversible,
        }


class TaskGraphCompiler:
    def compile_from_goal_model(self, goal_model: dict[str, Any]) -> ExecutionGraph:
        raw = goal_model.get("objective") or goal_model.get("raw_goal") or "unknown_goal"
        required = goal_model.get("required_capabilities", [])
        risk_hints = goal_model.get("risk_hints", [])
        nodes = [
            TaskNode("n1", "understand_goal", "reasoning", "L0"),
            TaskNode("n2", "check_rules_and_risk", "governance", "L1", depends_on=["n1"]),
            TaskNode("n3", "resolve_capabilities", "capability_resolution", "L1", depends_on=["n2"]),
        ]
        if "solution_search" in required:
            nodes.append(TaskNode("n4", "search_solution", "research", "L1", depends_on=["n3"]))
        if "capability_extension" in required:
            nodes.append(TaskNode("n5", "sandbox_capability_extension", "self_extension", "L3", True, ["n3"]))
        nodes.append(TaskNode("n9", "verify_and_learn", "verification", "L1", depends_on=[nodes[-1].id]))
        return ExecutionGraph(
            graph_id="graph_" + str(abs(hash(raw)))[:10],
            nodes=nodes,
            completion_criteria=["safe_steps_finished", "result_verified", "learning_written_back"],
            reversible=not bool(risk_hints),
        )


path: core/bootstrap.py
content: """Bootstrap - 启动引导模块 (shim)"""

from typing import Dict, Any


def run_bootstrap(mode: str = "standard") -> Dict[str, Any]:
    """运行启动引导
    
    Args:
        mode: 启动模式
        
    Returns:
        启动结果
    """
    return {
        "status": "dry_run",
        "message": "bootstrap is planned feature",
        "mode": mode,
        "steps": [],
        "side_effects": False
    }


path: core/collaboration/__init__.py
content: from .agent_role_registry import AgentRoleRegistry
from .delegation_planner import DelegationPlanner
from .collaboration_protocol import CollaborationProtocol
from .consensus_gate import ConsensusGate
from .collaborative_autonomy_kernel import CollaborativeAutonomyKernel

__all__ = [
    "AgentRoleRegistry",
    "DelegationPlanner",
    "CollaborationProtocol",
    "ConsensusGate",
    "CollaborativeAutonomyKernel",
]


path: core/collaboration/agent_role_registry.py
content: class AgentRoleRegistry:
    """Define internal roles for multi-agent reasoning without spawning unsafe actors."""

    DEFAULT_ROLES = {
        "strategist": {"capabilities": ["goal_strategy", "risk_reward"], "side_effect": False},
        "critic": {"capabilities": ["assumption_check", "contradiction_detection"], "side_effect": False},
        "operator": {"capabilities": ["execution_preparation", "tool_selection"], "side_effect": False},
        "verifier": {"capabilities": ["result_check", "rollback_check"], "side_effect": False},
        "learner": {"capabilities": ["memory_update", "pattern_promotion"], "side_effect": False},
    }

    def list_roles(self) -> dict:
        return {"status": "roles_ready", "roles": self.DEFAULT_ROLES}

    def get(self, role: str) -> dict:
        return self.DEFAULT_ROLES.get(role, {"capabilities": [], "side_effect": False})


path: core/collaboration/collaboration_protocol.py
content: class CollaborationProtocol:
    """Internal collaboration rules: debate before execution, verify before claim."""

    def apply(self, delegated: dict) -> dict:
        return {
            "status": "protocol_applied",
            "rules": [
                "critic_reviews_before_operator",
                "verifier_checks_before_success_claim",
                "learner_updates_only_after_verified_outcome",
                "no_role_can_bypass_authorization_gateway",
            ],
            "delegated": delegated,
        }


path: core/collaboration/collaborative_autonomy_kernel.py
content: from __future__ import annotations

from .agent_role_registry import AgentRoleRegistry
from .delegation_planner import DelegationPlanner
from .collaboration_protocol import CollaborationProtocol
from .consensus_gate import ConsensusGate


class CollaborativeAutonomyKernel:
    """V10.7 internal multi-agent collaboration mesh."""

    def __init__(self) -> None:
        self.roles = AgentRoleRegistry()
        self.delegation = DelegationPlanner()
        self.protocol = CollaborationProtocol()
        self.consensus = ConsensusGate()

    def run(self, mission: dict) -> dict:
        roles = self.roles.list_roles()["roles"]
        delegated = self.delegation.delegate(mission, roles)
        protocol = self.protocol.apply(delegated)
        role_outputs = [{"role": t["role"], "status": "ok"} for t in delegated["tasks"]]
        consensus = self.consensus.decide(role_outputs)
        return {
            "status": "collaboration_ready",
            "shape": "Collaborative Autonomy Mesh",
            "roles": roles,
            "delegation": delegated,
            "protocol": protocol,
            "consensus": consensus,
            "side_effect": False,
        }


path: core/collaboration/consensus_gate.py
content: class ConsensusGate:
    """Gate role outputs before execution."""

    def decide(self, role_outputs: list[dict]) -> dict:
        blockers = []
        for item in role_outputs:
            if item.get("status") in {"blocked", "unsafe", "contradiction"}:
                blockers.append(item)
        return {
            "status": "blocked" if blockers else "consensus_ready",
            "blockers": blockers,
            "requires_user_review": bool(blockers),
        }


path: core/collaboration/delegation_planner.py
content: from __future__ import annotations


class DelegationPlanner:
    """Break a mission into role-owned subtasks."""

    def delegate(self, mission: dict, roles: dict) -> dict:
        objective = mission.get("objective") or mission.get("goal") or "unknown"
        tasks = []
        for role in ["strategist", "critic", "operator", "verifier", "learner"]:
            tasks.append({
                "role": role,
                "task": f"{role}_work_for_{objective}",
                "side_effect": False,
                "requires_confirmation": False,
                "capabilities": roles.get(role, {}).get("capabilities", []),
            })
        return {"status": "delegated", "objective": objective, "tasks": tasks}


path: core/continuous/__init__.py
content: from .continuous_intelligence_kernel import ContinuousIntelligenceKernel
from .attention_manager import AttentionManager
from .initiative_engine import InitiativeEngine
from .runtime_budget_manager import RuntimeBudgetManager
from .context_refresh_planner import ContextRefreshPlanner

__all__ = [
    "ContinuousIntelligenceKernel",
    "AttentionManager",
    "InitiativeEngine",
    "RuntimeBudgetManager",
    "ContextRefreshPlanner",
]


path: core/continuous/attention_manager.py
content: from __future__ import annotations


class AttentionManager:
    """Decide what deserves attention without spamming the user."""

    def rank(self, signals: list[dict]) -> dict:
        ranked = []
        for idx, signal in enumerate(signals):
            priority = signal.get("priority", "normal")
            score = {"urgent": 100, "high": 80, "normal": 50, "low": 20}.get(priority, 50)
            if signal.get("deadline"):
                score += 10
            ranked.append({**signal, "attention_score": score, "rank_id": idx})
        ranked.sort(key=lambda x: x["attention_score"], reverse=True)
        return {
            "status": "ranked",
            "top": ranked[:5],
            "should_interrupt_user": bool(ranked and ranked[0]["attention_score"] >= 90),
        }


path: core/continuous/context_refresh_planner.py
content: class ContextRefreshPlanner:
    """Plan which context sources should be refreshed before decisions."""

    def plan(self, goal: str, stale_sources: list[str] | None = None) -> dict:
        stale_sources = stale_sources or []
        required = ["personal_preferences", "recent_goals", "risk_policy"]
        if any(k in goal for k in ["外部", "API", "设备", "连接"]):
            required.append("connector_state")
        if "长期" in goal or "项目" in goal:
            required.append("goal_portfolio")
        refresh = sorted(set(required + stale_sources))
        return {"status": "refresh_plan_ready", "sources": refresh, "side_effect": False}


path: core/continuous/continuous_intelligence_kernel.py
content: from __future__ import annotations

from .attention_manager import AttentionManager
from .runtime_budget_manager import RuntimeBudgetManager
from .context_refresh_planner import ContextRefreshPlanner
from .initiative_engine import InitiativeEngine


class ContinuousIntelligenceKernel:
    """V10.5 always-on intelligence layer.

    It does not execute external actions by itself; it decides what to observe,
    when to refresh context, and what initiative should be prepared next.
    """

    def __init__(self) -> None:
        self.attention = AttentionManager()
        self.budget = RuntimeBudgetManager()
        self.refresh = ContextRefreshPlanner()
        self.initiative = InitiativeEngine()

    def tick(self, goal: str = "", signals: list[dict] | None = None, mode: str = "bounded_high") -> dict:
        budget = self.budget.allocate(mode)
        attention = self.attention.rank(signals or [])
        refresh = self.refresh.plan(goal)
        initiatives = self.initiative.propose(attention, budget)
        return {
            "status": "continuous_tick_ready",
            "shape": "Continuous Intelligence Kernel",
            "budget": budget,
            "attention": attention,
            "context_refresh": refresh,
            "initiatives": initiatives,
            "external_side_effect": False,
            "next_decision": "prepare_initiative" if initiatives["initiatives"] else "idle",
        }


path: core/continuous/initiative_engine.py
content: from __future__ import annotations


class InitiativeEngine:
    """Generate proactive but bounded initiatives."""

    def propose(self, attention: dict, budget: dict) -> dict:
        top = attention.get("top", [])
        initiatives = []
        for item in top:
            if item.get("attention_score", 0) >= 80:
                initiatives.append({
                    "title": f"handle_{item.get('type', 'signal')}",
                    "reason": item.get("reason", "high_attention_signal"),
                    "side_effect": False,
                    "requires_confirmation": False,
                })
        if not initiatives:
            initiatives.append({
                "title": "memory_and_goal_maintenance",
                "reason": "low_attention_cycle",
                "side_effect": False,
                "requires_confirmation": False,
            })
        return {
            "status": "initiatives_ready",
            "initiatives": initiatives[:budget.get("budget", {}).get("max_background_checks_per_hour", 4)],
        }


path: core/continuous/runtime_budget_manager.py
content: from __future__ import annotations


class RuntimeBudgetManager:
    """Token/time/action budget guard for always-on autonomy."""

    DEFAULT_BUDGET = {
        "max_background_checks_per_hour": 4,
        "max_external_reads_per_cycle": 3,
        "max_external_writes_without_confirmation": 0,
        "max_device_actions_without_confirmation": 0,
        "max_cost_without_confirmation": 0,
    }

    def allocate(self, mode: str = "bounded_high") -> dict:
        budget = dict(self.DEFAULT_BUDGET)
        if mode == "quiet":
            budget["max_background_checks_per_hour"] = 1
        if mode == "intensive":
            budget["max_background_checks_per_hour"] = 8
            budget["max_external_reads_per_cycle"] = 6
        return {"status": "budget_allocated", "mode": mode, "budget": budget}


path: core/diagnostics.py
content: """Diagnostics - 诊断模块 (shim)"""

from typing import Dict, Any


def run_diagnostics(scope: str = "full") -> Dict[str, Any]:
    """运行诊断
    
    Args:
        scope: 诊断范围
        
    Returns:
        诊断结果
    """
    return {
        "status": "dry_run",
        "message": "diagnostics is planned feature",
        "scope": scope,
        "checks": [],
        "side_effects": False
    }


path: core/digital_twin/__init__.py
content: from .personal_digital_twin import PersonalDigitalTwin
from .preference_twin import PreferenceTwin
from .decision_twin import DecisionTwin
from .risk_twin import RiskTwin
from .habit_twin import HabitTwin
from .identity_drift_guard import IdentityDriftGuard

__all__ = [
    "PersonalDigitalTwin",
    "PreferenceTwin",
    "DecisionTwin",
    "RiskTwin",
    "HabitTwin",
    "IdentityDriftGuard",
]


path: core/digital_twin/decision_twin.py
content: class DecisionTwin:
    def model(self, decisions: list[dict]) -> dict:
        return {
            "decision_style": "high_autonomy_with_rules",
            "prefers_complete_delivery": any("complete" in str(d) or "一次性" in str(d) for d in decisions),
            "requires_precision": True,
        }


path: core/digital_twin/habit_twin.py
content: class HabitTwin:
    def extract(self, events: list[dict]) -> dict:
        return {
            "iteration_speed": "fast" if len(events) >= 3 else "normal",
            "handoff_preference": "zip_and_command",
            "validation_preference": "direct_check_then_package",
        }


path: core/digital_twin/identity_drift_guard.py
content: class IdentityDriftGuard:
    """Ensure the digital twin remains a helpful preference model, not a fake identity claim."""

    def check(self, twin: dict) -> dict:
        forbidden = ["I am the user", "act as user without consent", "bypass_confirmation"]
        text = str(twin)
        violations = [v for v in forbidden if v in text]
        return {
            "status": "safe" if not violations else "drift_detected",
            "violations": violations,
            "must_not_impersonate_user": True,
        }


path: core/digital_twin/personal_digital_twin.py
content: from __future__ import annotations

from .preference_twin import PreferenceTwin
from .decision_twin import DecisionTwin
from .risk_twin import RiskTwin
from .habit_twin import HabitTwin
from .identity_drift_guard import IdentityDriftGuard


class PersonalDigitalTwin:
    """V10.8 personal digital twin: preferences, decision style, risk and habits."""

    def __init__(self) -> None:
        self.preference = PreferenceTwin()
        self.decision = DecisionTwin()
        self.risk = RiskTwin()
        self.habit = HabitTwin()
        self.guard = IdentityDriftGuard()

    def build(self, signals: list[dict] | None = None, decisions: list[dict] | None = None, feedback: list[dict] | None = None, events: list[dict] | None = None) -> dict:
        twin = {
            "preference": self.preference.infer(signals or []),
            "decision": self.decision.model(decisions or []),
            "risk": self.risk.calibrate(feedback or []),
            "habit": self.habit.extract(events or []),
        }
        guard = self.guard.check(twin)
        return {
            "status": "digital_twin_ready",
            "shape": "Personal Digital Twin",
            "twin": twin,
            "guard": guard,
            "privacy": "local_only",
        }


path: core/digital_twin/preference_twin.py
content: class PreferenceTwin:
    def infer(self, signals: list[dict]) -> dict:
        text = " ".join(str(s) for s in signals)
        return {
            "style": "direct" if "直接" in text or "一次性" in text else "balanced",
            "artifact_first": "压缩包" in text or "文件" in text,
            "avoid": ["反复确认低风险问题", "让对方猜", "只说下一步不交付"],
        }


path: core/digital_twin/risk_twin.py
content: class RiskTwin:
    def calibrate(self, feedback: list[dict]) -> dict:
        return {
            "low_risk_auto": True,
            "medium_risk_auto_with_audit": True,
            "high_risk_requires_strong_confirmation": True,
            "external_write_requires_confirmation": True,
        }


path: core/execution_contract/__init__.py
content: from .execution_contract import ExecutionContract
from .side_effect_budget import SideEffectBudget
from .confirmation_ledger import ConfirmationLedger
from .execution_readiness_gate import ExecutionReadinessGate

__all__ = [
    "ExecutionContract",
    "SideEffectBudget",
    "ConfirmationLedger",
    "ExecutionReadinessGate",
]


path: core/execution_contract/confirmation_ledger.py
content: from __future__ import annotations

from datetime import datetime


class ConfirmationLedger:
    """Confirmation ledger contract. Does not fake user confirmation."""

    def require(self, action_id: str, reason: str, risk_level: str) -> dict:
        return {
            "action_id": action_id,
            "status": "confirmation_required",
            "reason": reason,
            "risk_level": risk_level,
            "created_at": datetime.utcnow().isoformat() + "Z",
            "confirmed": False,
        }


path: core/execution_contract/execution_contract.py
content: from __future__ import annotations

from .side_effect_budget import SideEffectBudget
from .confirmation_ledger import ConfirmationLedger


class ExecutionContract:
    """Contract created before any real-world execution."""

    def build(self, mission: dict, risk_level: str) -> dict:
        budget = SideEffectBudget().resolve(risk_level)
        requires_confirmation = risk_level in {"L3", "L4", "BLOCKED"}
        confirmation = None
        if requires_confirmation:
            confirmation = ConfirmationLedger().require(
                mission.get("mission_id", "unknown"),
                "risk_level_requires_confirmation",
                risk_level,
            )
        return {
            "status": "contract_ready",
            "mission_id": mission.get("mission_id", "unknown"),
            "risk_level": risk_level,
            "side_effect_budget": budget,
            "confirmation": confirmation,
            "audit_required": True,
            "rollback_required": True,
            "verification_required": True,
            "can_execute_without_confirmation": not requires_confirmation,
        }


path: core/execution_contract/execution_readiness_gate.py
content: class ExecutionReadinessGate:
    def check(self, contract: dict) -> dict:
        if contract.get("risk_level") == "BLOCKED":
            return {"status": "blocked", "reason": "blocked_risk"}
        if not contract.get("can_execute_without_confirmation") and not (contract.get("confirmation") or {}).get("confirmed", False):
            return {"status": "waiting_confirmation", "reason": "confirmation_not_recorded"}
        return {"status": "ready", "reason": "contract_satisfied"}


path: core/execution_contract/side_effect_budget.py
content: class SideEffectBudget:
    """Define how much real-world impact is allowed before confirmation."""

    LIMITS = {
        "L0": {"external_write": 0, "device_action": 0, "money": 0},
        "L1": {"external_write": 0, "device_action": 0, "money": 0},
        "L2": {"external_write": 0, "device_action": 0, "money": 0},
        "L3": {"external_write": "confirm_required", "device_action": "confirm_required", "money": 0},
        "L4": {"external_write": "strong_confirm_required", "device_action": "strong_confirm_required", "money": 0},
        "BLOCKED": {"external_write": 0, "device_action": 0, "money": 0},
    }

    def resolve(self, risk_level: str) -> dict:
        return {"risk_level": risk_level, "budget": self.LIMITS.get(risk_level, self.LIMITS["L2"])}


path: governance/review/__init__.py
content: # governance/review package

from .change_review import change_review

__all__ = ["change_review"]


path: infrastructure/legacy/layer_bridge/clean_arch/DEPRECATED.txt
content: DEPRECATED - 不参与主运行


path: orchestration/collaboration/__init__.py
content: 


path: orchestration/contracts/__init__.py
content: 


path: orchestration/execution_control/__init__.py
content: 


path: orchestration/planner/__init__.py
content: 


path: orchestration/product/__init__.py
content: 


path: orchestration/router/__init__.py
content: 


path: orchestration/router/routing/__init__.py
content: 


path: orchestration/strategy/__init__.py
content: 


path: orchestration/workflow/__init__.py
content: 


path: orchestration/workflows/__init__.py
content: 


path: tests/benchmarks/__init__.py
content: 


Security scan verdicts — ClawScan: suspicious | static analysis: malicious | VirusTotal: suspicious | SkillSpector:  ()