Skill: popwho/ai-coding-standards (version 1.0.0)

--- name: ai-coding-standards description: AI编码规范与自我修正系统 - 基于Claude Code最佳实践的质量红线、渐进式上下文加载、Plan持久化、Hook拦截机制 --- # AI Coding Standards Skill 基于 Claude Code 最佳实践的 AI 编码规范系统，帮助 AI agent 保持代码质量和上下文整洁。 ## 核心理念 **上下文的熵增才是瓶颈** - 不治这个，迭代越快崩越快 ## 四大规则 ### 1. 📏 质量红线 (Quality Red Lines) 硬性阈值： - 单个文件 ≤ 800 行 - 单个函数 ≤ 30 行 - 嵌套 ≤ 3 层 - 分支 ≤ 3 个 **为什么：** AI 对"要短"理解飘忽，但对"≤30行"执行稳定 ### 2. 📦 渐进式上下文 (Progressive Context Loading) - **查 bug：** 只加载目标模块 - **架构决策：** 才加载全局上下文 - **命中率 > 覆盖率** — 精准加载比塞满上下文更重要 1M 上下文缓解熵增但不根除，渐进加载是必修课。 ### 3. 💾 Plan 文件持久化 - 复杂任务落到文件（memory/tasks/） - 加 checklist 跟踪进度 - 新会话读文件断点恢复 - **文件系统是唯一可靠状态源** ### 4. 🚧 Hook 自动拦截 - 规范写成脚本，违规操作瞬间打回 - 比 prompt 强调一百遍更有效 ## 使用方法 ### 在项目根目录创建 hooks ```bash # 创建质量检查 hook mkdir -p .git/hooks cp pre-commit.sample .git/hooks/pre-commit ``` ### 创建 CLAUDE.md 在项目根目录创建 CLAUDE.md，强制加载规范： ```markdown # 项目编码规范 ## 质量红线 - 函数 ≤ 30 行 - 文件 ≤ 800 行 ## 加载策略 - Bug 修复只加载相关文件 - 重构才加载全貌 ``` ### 使用示例 ```python from ai_coding_standards import QualityChecker checker = QualityChecker() result = checker.check_file("src/main.py") if not result.passed: print(f"违规: {result.issues}") ``` ## 触发信号 - code_quality - function_length - file_size - context_overflow - plan_persistence ## 包含工具 - `QualityChecker` - 代码质量检查 - `ContextManager` - 上下文管理 - `PlanTracker` - Plan 持久化跟踪 - `HookRunner` - Hook 拦截执行

path: plan_tracker.py
content: #!/usr/bin/env python3
"""
AI Coding Standards - Plan Tracker
Plan 持久化跟踪系统
"""
import json
import os
from datetime import datetime
from dataclasses import dataclass, asdict
from typing import List, Optional


@dataclass
class Task:
    """任务项"""
    id: str
    title: str
    status: str  # pending, in_progress, done
    priority: str = "medium"
    created_at: str = None
    updated_at: str = None
    
    def __post_init__(self):
        now = datetime.now().isoformat()
        if not self.created_at:
            self.created_at = now
        self.updated_at = now


@dataclass
class Plan:
    """Plan 文档"""
    id: str
    title: str
    description: str
    tasks: List[Task]
    status: str  # planning, in_progress, completed, paused
    created_at: str = None
    updated_at: str = None
    
    def __post_init__(self):
        now = datetime.now().isoformat()
        if not self.created_at:
            self.created_at = now
        self.updated_at = now


class PlanTracker:
    """Plan 持久化跟踪器"""
    
    def __init__(self, storage_dir: str = None):
        if storage_dir is None:
            storage_dir = os.path.expanduser("~/.ai_plans")
        self.storage_dir = storage_dir
        os.makedirs(storage_dir, exist_ok=True)
    
    def _get_plan_path(self, plan_id: str) -> str:
        return os.path.join(self.storage_dir, f"{plan_id}.json")
    
    def create_plan(self, title: str, description: str = "") -> Plan:
        """创建新 Plan"""
        import uuid
        plan = Plan(
            id=str(uuid.uuid4())[:8],
            title=title,
            description=description,
            tasks=[],
            status="planning"
        )
        self.save_plan(plan)
        return plan
    
    def save_plan(self, plan: Plan) -> None:
        """保存 Plan"""
        path = self._get_plan_path(plan.id)
        with open(path, 'w', encoding='utf-8') as f:
            json.dump({
                'id': plan.id,
                'title': plan.title,
                'description': plan.description,
                'tasks': [asdict(t) for t in plan.tasks],
                'status': plan.status,
                'created_at': plan.created_at,
                'updated_at': plan.updated_at
            }, f, indent=2, ensure_ascii=False)
    
    def load_plan(self, plan_id: str) -> Optional[Plan]:
        """加载 Plan"""
        path = self._get_plan_path(plan_id)
        if not os.path.exists(path):
            return None
        
        with open(path, 'r', encoding='utf-8') as f:
            data = json.load(f)
        
        return Plan(
            id=data['id'],
            title=data['title'],
            description=data.get('description', ''),
            tasks=[Task(**t) for t in data.get('tasks', [])],
            status=data['status'],
            created_at=data.get('created_at'),
            updated_at=data.get('updated_at')
        )
    
    def add_task(self, plan_id: str, title: str, priority: str = "medium") -> Optional[Task]:
        """添加任务"""
        import uuid
        plan = self.load_plan(plan_id)
        if not plan:
            return None
        
        task = Task(id=str(uuid.uuid4())[:8], title=title, status="pending", priority=priority)
        plan.tasks.append(task)
        self.save_plan(plan)
        return task
    
    def complete_task(self, plan_id: str, task_id: str) -> bool:
        """完成任务"""
        plan = self.load_plan(plan_id)
        if not plan:
            return False
        
        for task in plan.tasks:
            if task.id == task_id:
                task.status = "done"
                self.save_plan(plan)
                return True
        return False
    
    def list_plans(self) -> List[Plan]:
        """列出所有 Plan"""
        plans = []
        for f in os.listdir(self.storage_dir):
            if f.endswith('.json'):
                plan = self.load_plan(f[:-5])
                if plan:
                    plans.append(plan)
        return plans


def main():
    """CLI 入口"""
    import sys
    
    tracker = PlanTracker()
    
    if len(sys.argv) < 2:
        # 列出所有 plans
        plans = tracker.list_plans()
        print(f"\n📋 共 {len(plans)} 个 Plan:")
        for plan in plans:
            done = sum(1 for t in plan.tasks if t.status == "done")
            print(f"  [{plan.status}] {plan.title} ({done}/{len(plan.tasks)} tasks)")
        return
    
    cmd = sys.argv[1]
    
    if cmd == "create":
        title = sys.argv[2] if len(sys.argv) > 2 else "新 Plan"
        plan = tracker.create_plan(title)
        print(f"✅ 创建 Plan: {plan.id} - {plan.title}")
    
    elif cmd == "list":
        plans = tracker.list_plans()
        for plan in plans:
            print(f"{plan.id}: {plan.title}")
    
    elif cmd == "add":
        plan_id = sys.argv[2] if len(sys.argv) > 2 else None
        task_title = sys.argv[3] if len(sys.argv) > 3 else "新任务"
        if plan_id:
            task = tracker.add_task(plan_id, task_title)
            print(f"✅ 添加任务: {task.id}")


if __name__ == "__main__":
    main()


path: quality_checker.py
content: #!/usr/bin/env python3
"""
AI Coding Standards - Quality Checker
基于 Claude Code 最佳实践的代码质量检查
"""
import os
import re
from dataclasses import dataclass
from typing import List, Optional


@dataclass
class QualityIssue:
    """质量问题"""
    line: int
    issue_type: str
    message: str
    severity: str = "error"


@dataclass
class QualityResult:
    """检查结果"""
    passed: bool
    issues: List[QualityIssue]
    file_path: str


class QualityChecker:
    """代码质量检查器"""
    
    # 质量红线配置
    MAX_FUNCTION_LINES = 30
    MAX_FILE_LINES = 800
    MAX_NESTING = 3
    MAX_BRANCHES = 3
    
    def __init__(self, config: Optional[dict] = None):
        if config:
            self.MAX_FUNCTION_LINES = config.get('max_function_lines', 30)
            self.MAX_FILE_LINES = config.get('max_file_lines', 800)
            self.MAX_NESTING = config.get('max_nesting', 3)
            self.MAX_BRANCHES = config.get('max_branches', 3)
    
    def check_file(self, file_path: str) -> QualityResult:
        """检查单个文件"""
        if not os.path.exists(file_path):
            return QualityResult(
                passed=False,
                issues=[QualityIssue(0, "file_not_found", f"文件不存在: {file_path}")],
                file_path=file_path
            )
        
        with open(file_path, 'r', encoding='utf-8') as f:
            lines = f.readlines()
        
        issues = []
        
        # 1. 检查文件行数
        if len(lines) > self.MAX_FILE_LINES:
            issues.append(QualityIssue(
                len(lines),
                "file_too_long",
                f"文件超过 {self.MAX_FILE_LINES} 行 (当前 {len(lines)} 行)",
                "warning"
            ))
        
        # 2. 检查函数长度
        issues.extend(self._check_functions(lines, file_path))
        
        # 3. 检查嵌套深度
        issues.extend(self._check_nesting(lines, file_path))
        
        return QualityResult(
            passed=len([i for i in issues if i.severity == "error"]) == 0,
            issues=issues,
            file_path=file_path
        )
    
    def _check_functions(self, lines: List[str], file_path: str) -> List[QualityIssue]:
        """检查函数长度"""
        issues = []
        in_function = False
        function_start = 0
        function_lines = 0
        function_name = ""
        
        for i, line in enumerate(lines):
            # 检测函数定义
            if re.match(r'^\s*(def |function |fn |async def )', line):
                if in_function and function_lines > self.MAX_FUNCTION_LINES:
                    issues.append(QualityIssue(
                        function_start + 1,
                        "function_too_long",
                        f"函数 {function_name} 超过 {self.MAX_FUNCTION_LINES} 行 (当前 {function_lines} 行)"
                    ))
                in_function = True
                function_start = i
                function_lines = 0
                match = re.search(r'(def |function |fn |async def )(\w+)', line)
                function_name = match.group(2) if match else "anonymous"
            
            if in_function:
                # 跳过空行和注释
                stripped = line.strip()
                if stripped and not stripped.startswith('#') and not stripped.startswith('//'):
                    function_lines += 1
        
        return issues
    
    def _check_nesting(self, lines: List[str], file_path: str) -> List[QualityIssue]:
        """检查嵌套深度"""
        issues = []
        max_depth = 0
        
        for i, line in enumerate(lines):
            # 计算缩进
            indent = len(line) - len(line.lstrip())
            depth = indent // 4  # 假设 4 空格 = 1 层
            
            if depth > self.MAX_NESTING and line.strip():
                issues.append(QualityIssue(
                    i + 1,
                    "nesting_too_deep",
                    f"嵌套深度 {depth} 超过限制 {self.MAX_NESTING}"
                ))
        
        return issues
    
    def check_directory(self, dir_path: str, extensions: List[str] = None) -> List[QualityResult]:
        """检查整个目录"""
        if extensions is None:
            extensions = ['.py', '.js', '.ts', '.go', '.rs']
        
        results = []
        for root, _, files in os.walk(dir_path):
            for file in files:
                if any(file.endswith(ext) for ext in extensions):
                    file_path = os.path.join(root, file)
                    results.append(self.check_file(file_path))
        
        return results


def main():
    """CLI 入口"""
    import sys
    
    if len(sys.argv) < 2:
        print("Usage: python quality_checker.py <file_or_directory>")
        sys.exit(1)
    
    path = sys.argv[1]
    checker = QualityChecker()
    
    if os.path.isfile(path):
        result = checker.check_file(path)
        print(f"\n{'✅' if result.passed else '❌'} {result.file_path}")
        for issue in result.issues:
            print(f"  L{issue.line}: {issue.issue_type} - {issue.message}")
    else:
        results = checker.check_directory(path)
        failed = [r for r in results if not r.passed]
        print(f"\n检查 {len(results)} 个文件, {len(failed)} 个有问题")
        for result in failed[:10]:
            print(f"  ❌ {result.file_path}: {len(result.issues)} issues")


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: clean | static analysis:  | VirusTotal: clean | SkillSpector: clean (LOW)