From 9922d455da14c53bc57754aa62fabc6922375c37 Mon Sep 17 00:00:00 2001 From: catlog22 Date: Sat, 3 Jan 2026 15:58:31 +0800 Subject: [PATCH] feat: Add templates for autonomous actions, orchestrators, sequential phases, and skill documentation - Introduced a comprehensive template for autonomous actions, detailing structure, execution, and error handling. - Added an orchestrator template to manage state and decision logic for autonomous actions. - Created a sequential phase template to outline execution steps and objectives for structured workflows. - Developed a skill documentation template to standardize the generation of skill entry files. - Implemented a Python script to compare search results between hybrid and cascade methods, analyzing ranking changes. --- .claude/skills/_shared/SKILL-DESIGN-SPEC.md | 693 ++++++++++++++++++ .claude/skills/skill-generator/SKILL.md | 187 +++++ .../phases/01-requirements-discovery.md | 239 ++++++ .../phases/02-structure-generation.md | 208 ++++++ .../phases/03-phase-generation.md | 396 ++++++++++ .../phases/04-specs-templates.md | 328 +++++++++ .../skill-generator/phases/05-validation.md | 334 +++++++++ .../skill-generator/specs/execution-modes.md | 396 ++++++++++ .../specs/skill-requirements.md | 344 +++++++++ .../templates/autonomous-action.md | 506 +++++++++++++ .../templates/autonomous-orchestrator.md | 276 +++++++ .../templates/sequential-phase.md | 393 ++++++++++ .../skill-generator/templates/skill-md.md | 144 ++++ codex-lens/src/codexlens/cli/commands.py | 26 +- codex-lens/src/codexlens/config.py | 22 + .../src/codexlens/search/chain_search.py | 28 +- compare_search.py | 119 +++ 17 files changed, 4625 insertions(+), 14 deletions(-) create mode 100644 .claude/skills/_shared/SKILL-DESIGN-SPEC.md create mode 100644 .claude/skills/skill-generator/SKILL.md create mode 100644 .claude/skills/skill-generator/phases/01-requirements-discovery.md create mode 100644 .claude/skills/skill-generator/phases/02-structure-generation.md create mode 100644 .claude/skills/skill-generator/phases/03-phase-generation.md create mode 100644 .claude/skills/skill-generator/phases/04-specs-templates.md create mode 100644 .claude/skills/skill-generator/phases/05-validation.md create mode 100644 .claude/skills/skill-generator/specs/execution-modes.md create mode 100644 .claude/skills/skill-generator/specs/skill-requirements.md create mode 100644 .claude/skills/skill-generator/templates/autonomous-action.md create mode 100644 .claude/skills/skill-generator/templates/autonomous-orchestrator.md create mode 100644 .claude/skills/skill-generator/templates/sequential-phase.md create mode 100644 .claude/skills/skill-generator/templates/skill-md.md create mode 100644 compare_search.py diff --git a/.claude/skills/_shared/SKILL-DESIGN-SPEC.md b/.claude/skills/_shared/SKILL-DESIGN-SPEC.md new file mode 100644 index 00000000..d61d5dd4 --- /dev/null +++ b/.claude/skills/_shared/SKILL-DESIGN-SPEC.md @@ -0,0 +1,693 @@ +# Skill 设计规范 v1.0 + +> 基于 `software-manual` 和 `copyright-docs` 两个成熟 Skill 的设计模式提炼 + +--- + +## 目录 + +1. [设计理念](#1-设计理念) +2. [目录结构规范](#2-目录结构规范) +3. [核心组件定义](#3-核心组件定义) +4. [SKILL.md 入口规范](#4-skillmd-入口规范) +5. [Phase 阶段设计规范](#5-phase-阶段设计规范) +6. [Specs 规范文件设计](#6-specs-规范文件设计) +7. [Templates 模板设计](#7-templates-模板设计) +8. [Scripts 脚本规范](#8-scripts-脚本规范) +9. [Prompt 工程规范](#9-prompt-工程规范) +10. [质量控制规范](#10-质量控制规范) +11. [最佳实践清单](#11-最佳实践清单) +12. [示例模板](#12-示例模板) + +--- + +## 1. 设计理念 + +### 1.1 核心原则 + +| 原则 | 说明 | 实践 | +|------|------|------| +| **阶段化执行** | 复杂任务分解为有序阶段 | 使用 `phases/` 目录,数字前缀控制顺序 | +| **关注点分离** | 逻辑、配置、视图分离 | `phases/`(逻辑) + `specs/`(配置) + `templates/`(视图) | +| **简要返回** | Agent 返回路径+摘要,避免上下文溢出 | 返回 JSON 简要信息,文件存储完整内容 | +| **配置驱动** | 规范作为"配置文件",易于调整行为 | 修改 `specs/` 无需触及 `phases/` | +| **模板复用** | 提取通用片段,确保一致性 | `templates/` 存放可复用内容 | + +### 1.2 架构模式 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Context-Optimized Architecture │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ SKILL.md (入口) → 描述目标、定义阶段、链接资源 │ +│ ↓ │ +│ Phase 1: 收集 → 用户输入 + 自动检测 → config.json │ +│ ↓ │ +│ Phase 2: 分析 → 并行 Agent → sections/*.md │ +│ ↓ │ +│ Phase N: 汇总 → 交叉检查 → summary.md │ +│ ↓ │ +│ Phase N+1: 组装 → 合并文件 → 最终产物 │ +│ ↓ │ +│ Phase N+2: 迭代 → 用户反馈 → 优化 │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 2. 目录结构规范 + +### 2.1 标准目录结构 + +``` +[skill-name]/ +├── SKILL.md # 【必需】技能入口:元数据 + 架构 + 执行流程 +├── phases/ # 【必需】执行阶段 Prompt +│ ├── 01-{first-step}.md # 数字前缀定义顺序 +│ ├── 02-{second-step}.md +│ ├── 02.5-{sub-step}.md # 小数点用于插入子步骤 +│ └── ... +├── specs/ # 【必需】规范与约束 +│ ├── {domain}-requirements.md # 领域特定要求 +│ ├── quality-standards.md # 质量标准 +│ └── writing-style.md # 写作风格(如适用) +├── templates/ # 【推荐】可复用模板 +│ ├── agent-base.md # Agent 基础 Prompt 模板 +│ ├── output-shell.{ext} # 输出外壳模板(html/md) +│ └── css/ # 样式文件(如适用) +├── scripts/ # 【可选】辅助脚本 +│ ├── {tool}.py # Python 脚本 +│ └── {tool}-runner.md # 脚本使用说明 +└── outputs/ # 【运行时】执行产物(不纳入版本控制) +``` + +### 2.2 命名约定 + +| 类型 | 规则 | 示例 | +|------|------|------| +| Skill 目录 | 小写-连字符 | `software-manual`, `copyright-docs` | +| Phase 文件 | `NN-{动作}.md` | `01-metadata-collection.md` | +| Spec 文件 | `{领域}-{类型}.md` | `cpcc-requirements.md` | +| Template 文件 | `{用途}-{类型}.{ext}` | `agent-base.md`, `tiddlywiki-shell.html` | +| 输出文件 | `section-{N}-{名称}.md` | `section-2-architecture.md` | + +--- + +## 3. 核心组件定义 + +### 3.1 组件职责矩阵 + +| 组件 | 职责 | 内容类型 | 修改频率 | +|------|------|----------|----------| +| `SKILL.md` | 入口 + 编排 | 元数据、架构图、执行流程 | 低(结构稳定) | +| `phases/*.md` | 执行逻辑 | 步骤说明、Prompt、代码示例 | 中(优化迭代) | +| `specs/*.md` | 约束配置 | 规则、标准、检查清单 | 中(需求变更) | +| `templates/*` | 可复用片段 | Prompt 模板、输出格式 | 低(通用稳定) | +| `scripts/*` | 自动化 | Python/JS 脚本 | 高(功能增强) | + +### 3.2 组件依赖关系 + +```mermaid +graph TD + SKILL[SKILL.md] --> P1[phases/01-*] + P1 --> P2[phases/02-*] + P2 --> PN[phases/N-*] + + P1 -.->|引用| SPEC[specs/*] + P2 -.->|引用| SPEC + PN -.->|引用| SPEC + + P1 -.->|使用| TPL[templates/*] + PN -.->|使用| TPL + + P2 -->|调用| SCR[scripts/*] + + style SKILL fill:#e1f5fe + style SPEC fill:#fff3e0 + style TPL fill:#e8f5e9 + style SCR fill:#fce4ec +``` + +--- + +## 4. SKILL.md 入口规范 + +### 4.1 必需结构 + +```markdown +--- +name: {skill-name} +description: {一句话描述}. {触发关键词}. Triggers on "{关键词1}", "{关键词2}". +allowed-tools: Task, AskUserQuestion, Read, Bash, Glob, Grep, Write, {其他MCP工具} +--- + +# {Skill 标题} + +{一段话描述 Skill 的用途和产出} + +## Architecture Overview + +{ASCII 或 Mermaid 架构图} + +## Key Design Principles + +1. **原则1**: 说明 +2. **原则2**: 说明 +... + +## Execution Flow + +{阶段执行流程图} + +## Agent Configuration (如适用) + +| Agent | Role | Output File | Focus Areas | +|-------|------|-------------|-------------| +| ... | ... | ... | ... | + +## Directory Setup + +{工作目录创建代码} + +## Output Structure + +{输出目录结构} + +## Reference Documents + +| Document | Purpose | +|----------|---------| +| [phases/01-xxx.md](phases/01-xxx.md) | ... | +| ... | ... | +``` + +### 4.2 Front Matter 规范 + +```yaml +--- +name: skill-name # 必需:Skill 唯一标识 +description: | # 必需:描述 + 触发词 + Generate XXX documents. + Triggers on "keyword1", "keyword2". +allowed-tools: | # 必需:允许使用的工具 + Task, AskUserQuestion, Read, Bash, + Glob, Grep, Write, mcp__chrome__* +--- +``` + +--- + +## 5. Phase 阶段设计规范 + +### 5.1 Phase 文件结构 + +```markdown +# Phase N: {阶段名称} + +{一句话描述此阶段目标} + +## Objective + +{详细目标说明} +- 目标1 +- 目标2 + +## Execution Steps + +### Step 1: {步骤名称} + +{代码或说明} + +### Step 2: {步骤名称} + +{代码或说明} + +## Output + +- **File**: `{输出文件名}` +- **Location**: `{输出路径}` +- **Format**: {JSON/Markdown/HTML} + +## Next Phase + +Proceed to [Phase N+1: xxx](0N+1-xxx.md) with the generated {产出}. +``` + +### 5.2 Phase 类型 + +| 类型 | 特点 | 示例 | +|------|------|------| +| **收集型** | 用户交互 + 自动检测 | `01-requirements-discovery.md` | +| **探索型** | 代码分析 + 结构识别 | `02-project-exploration.md` | +| **并行型** | 多 Agent 并行执行 | `03-parallel-analysis.md` | +| **汇总型** | 交叉检查 + 质量验证 | `03.5-consolidation.md` | +| **组装型** | 合并产出 + 格式化 | `04-document-assembly.md` | +| **迭代型** | 用户反馈 + 优化 | `05-iterative-refinement.md` | + +### 5.3 Phase 编号规则 + +``` +01-xxx.md # 主阶段 +02-xxx.md # 主阶段 +02.5-xxx.md # 子阶段(插入 02 和 03 之间) +03-xxx.md # 主阶段 +``` + +--- + +## 6. Specs 规范文件设计 + +### 6.1 Specs 类型 + +| 类型 | 用途 | 示例 | +|------|------|------| +| **领域要求** | 领域特定合规性 | `cpcc-requirements.md` | +| **质量标准** | 输出质量评估 | `quality-standards.md` | +| **写作风格** | 内容风格指南 | `writing-style.md` | +| **模板规范** | 输出格式定义 | `html-template.md` | + +### 6.2 Specs 结构模板 + +```markdown +# {规范名称} + +{规范用途说明} + +## When to Use + +| Phase | Usage | Section | +|-------|-------|---------| +| Phase N | {使用场景} | {引用章节} | +| ... | ... | ... | + +--- + +## Requirements + +### Category 1 + +- [ ] 检查项1 +- [ ] 检查项2 + +### Category 2 + +| 项目 | 要求 | 检查方式 | +|------|------|----------| +| ... | ... | ... | + +## Validation Function + +{验证函数代码} + +## Error Handling + +| Error | Recovery | +|-------|----------| +| ... | ... | +``` + +### 6.3 质量标准示例结构 + +```markdown +# Quality Standards + +## Quality Dimensions + +### 1. Completeness (25%) +{评分标准} + +### 2. Consistency (25%) +{评分标准} + +### 3. Depth (25%) +{评分标准} + +### 4. Readability (25%) +{评分标准} + +## Quality Gates + +| Gate | Threshold | Action | +|------|-----------|--------| +| Pass | ≥ 80% | 继续执行 | +| Review | 60-79% | 处理警告后继续 | +| Fail | < 60% | 必须修复 | + +## Issue Classification + +### Errors (Must Fix) +- ... + +### Warnings (Should Fix) +- ... + +### Info (Nice to Have) +- ... +``` + +--- + +## 7. Templates 模板设计 + +### 7.1 Agent 基础模板 + +```markdown +# Agent Base Template + +## 通用提示词结构 + +[ROLE] 你是{角色},专注于{职责}。 + +[TASK] +{任务描述} +- 输出: {output_path} +- 格式: {format} +- 范围: {scope} + +[CONSTRAINTS] +- 约束1 +- 约束2 + +[OUTPUT_FORMAT] +1. 直接写入文件 +2. 返回 JSON 简要信息 + +[QUALITY_CHECKLIST] +- [ ] 检查项1 +- [ ] 检查项2 + +## 变量说明 + +| 变量 | 来源 | 示例 | +|------|------|------| +| {output_dir} | Phase 1 | .workflow/.scratchpad/xxx | +| ... | ... | ... | + +## Agent 配置映射 + +{AGENT_ROLES, AGENT_SECTIONS, AGENT_FILES, AGENT_FOCUS} +``` + +### 7.2 输出模板规范 + +```html + + + + + + {{title}} + + + +
+ {{content}} +
+ + + +``` + +### 7.3 占位符规范 + +| 占位符格式 | 用途 | 示例 | +|------------|------|------| +| `{{variable}}` | 简单变量替换 | `{{title}}` | +| `${variable}` | JavaScript 模板字符串 | `${workDir}` | +| `{placeholder}` | Prompt 占位 | `{intro}`, `{diagram}` | + +--- + +## 8. Scripts 脚本规范 + +### 8.1 脚本类型 + +| 类型 | 用途 | 命名 | +|------|------|------| +| **提取器** | 从代码提取信息 | `extract_*.py` | +| **组装器** | 合并/转换文件 | `assemble_*.py` | +| **验证器** | 检查合规性 | `validate_*.py` | +| **辅助器** | 工具函数 | `*_helper.py` | + +### 8.2 脚本使用说明文件 + +每个脚本应有对应的 `.md` 说明文件: + +```markdown +# {Script Name} Runner + +## Purpose + +{脚本用途} + +## Usage + +{命令行使用方式} + +## Parameters + +| 参数 | 说明 | 默认值 | +|------|------|--------| +| ... | ... | ... | + +## Output + +{输出说明} + +## Example + +{使用示例} +``` + +--- + +## 9. Prompt 工程规范 + +### 9.1 Prompt 结构标准 + +``` +[ROLE] {角色定义} + +[PROJECT CONTEXT] +项目类型: {type} +语言: {language} +名称: {name} + +[TASK] +{任务描述} +输出: {output_path} + +[INPUT] +- 配置: {config_path} +- 扫描路径: {scan_paths} + +[CONTENT REQUIREMENTS] +- 标题层级: # ## ### (最多3级) +- 代码块: ```language ... ``` (必须标注语言) +- 表格: | col1 | col2 | 格式 +- 列表: 有序 1. 2. 3. / 无序 - - - + +[FOCUS] +{重点关注项} + +[OUTPUT FORMAT] +{输出格式说明} + +[RETURN JSON] +{返回结构} +``` + +### 9.2 效率优化原则 + +| 原则 | Before (冗余) | After (精简) | +|------|---------------|--------------| +| **角色简化** | "你是一个专业的系统架构师,具有丰富的软件设计经验..." | `[ROLE] 系统架构师,专注于分层设计和模块依赖` | +| **模板驱动** | "请按照以下格式输出: 首先写一个二级标题..." | `[TEMPLATE] ## 2. 标题 {content}` | +| **焦点明确** | "分析项目的各个方面,包括架构、模块、依赖等" | `[FOCUS] 1. 分层 2. 模块 3. 依赖 4. 数据流` | +| **返回简洁** | "请返回详细的分析结果,包括所有发现的问题..." | `[RETURN] {"status":"completed","output_file":"xxx.md","summary":"<50字"}` | + +### 9.3 Agent 返回格式标准 + +```typescript +interface AgentReturn { + status: "completed" | "partial" | "failed"; + output_file: string; // 输出文件路径 + summary: string; // 最多 50 字摘要 + cross_module_notes?: string[]; // 跨模块备注 + stats?: { // 统计信息 + diagrams?: number; + words?: number; + }; + screenshots_needed?: Array<{ // 截图需求(如适用) + id: string; + url: string; + description: string; + }>; +} +``` + +--- + +## 10. 质量控制规范 + +### 10.1 质量维度 + +| 维度 | 权重 | 检查项 | +|------|------|--------| +| **完整性** | 25% | 所有必需章节存在且有实质内容 | +| **一致性** | 25% | 术语、格式、风格统一 | +| **深度** | 25% | 内容详尽、示例充分 | +| **可读性** | 25% | 结构清晰、语言简洁 | + +### 10.2 质量门控 + +```javascript +const QUALITY_GATES = { + pass: { threshold: 80, action: "继续执行" }, + review: { threshold: 60, action: "处理警告后继续" }, + fail: { threshold: 0, action: "必须修复后重试" } +}; +``` + +### 10.3 问题分类 + +| 级别 | 前缀 | 含义 | 处理方式 | +|------|------|------|----------| +| **Error** | E | 阻塞性问题 | 必须修复 | +| **Warning** | W | 影响质量 | 建议修复 | +| **Info** | I | 可改进项 | 可选修复 | + +### 10.4 自动化检查函数模板 + +```javascript +function runQualityChecks(workDir) { + const results = { + completeness: checkCompleteness(workDir), + consistency: checkConsistency(workDir), + depth: checkDepth(workDir), + readability: checkReadability(workDir) + }; + + results.overall = Object.values(results).reduce((a, b) => a + b) / 4; + + return { + score: results.overall, + gate: results.overall >= 80 ? 'pass' : + results.overall >= 60 ? 'review' : 'fail', + details: results + }; +} +``` + +--- + +## 11. 最佳实践清单 + +### 11.1 Skill 设计 + +- [ ] **单一职责**: 每个 Skill 专注一个领域 +- [ ] **清晰入口**: SKILL.md 完整描述目标和流程 +- [ ] **阶段分解**: 复杂任务拆分为 3-7 个阶段 +- [ ] **顺序命名**: 使用数字前缀控制执行顺序 + +### 11.2 Phase 设计 + +- [ ] **明确目标**: 每个 Phase 有清晰的输入输出 +- [ ] **独立可测**: 每个 Phase 可单独调试 +- [ ] **链接下一步**: 明确说明后续阶段 + +### 11.3 Prompt 设计 + +- [ ] **角色明确**: 使用 `[ROLE]` 定义 Agent 身份 +- [ ] **任务具体**: 使用 `[TASK]` 明确执行目标 +- [ ] **约束清晰**: 使用 `[CONSTRAINTS]` 定义边界 +- [ ] **返回简洁**: Agent 返回路径+摘要,非完整内容 + +### 11.4 质量控制 + +- [ ] **规范驱动**: 使用 `specs/` 定义可验证的标准 +- [ ] **汇总检查**: 设置 Consolidation 阶段交叉验证 +- [ ] **问题分级**: 区分 Error/Warning/Info +- [ ] **迭代优化**: 支持用户反馈循环 + +--- + +## 12. 示例模板 + +### 12.1 新 Skill 快速启动模板 + +```bash +# 创建 Skill 目录结构 +mkdir -p my-skill/{phases,specs,templates,scripts} + +# 创建核心文件 +touch my-skill/SKILL.md +touch my-skill/phases/{01-collection,02-analysis,03-assembly}.md +touch my-skill/specs/{requirements,quality-standards}.md +touch my-skill/templates/agent-base.md +``` + +### 12.2 SKILL.md 最小模板 + +```markdown +--- +name: my-skill +description: Generate XXX. Triggers on "keyword1", "keyword2". +allowed-tools: Task, AskUserQuestion, Read, Bash, Glob, Grep, Write +--- + +# My Skill + +Generate XXX through multi-phase analysis. + +## Execution Flow + +1. Phase 1: Collection → config.json +2. Phase 2: Analysis → sections/*.md +3. Phase 3: Assembly → output.md + +## Reference Documents + +| Document | Purpose | +|----------|---------| +| [phases/01-collection.md](phases/01-collection.md) | 信息收集 | +| [phases/02-analysis.md](phases/02-analysis.md) | 代码分析 | +| [phases/03-assembly.md](phases/03-assembly.md) | 文档组装 | +``` + +--- + +## 附录 A: 设计对比 + +| 设计点 | software-manual | copyright-docs | +|--------|-----------------|----------------| +| 阶段数 | 6 | 5 | +| 并行 Agent | 6 | 6 | +| 输出格式 | HTML | Markdown | +| 质量检查 | 4 维度评分 | CPCC 合规检查 | +| 截图支持 | Chrome MCP | 无 | +| 迭代优化 | 用户反馈循环 | 合规验证循环 | + +## 附录 B: 工具依赖 + +| 工具 | 用途 | 适用 Skill | +|------|------|------------| +| `Task` | 启动子 Agent | 所有 | +| `AskUserQuestion` | 用户交互 | 所有 | +| `Read/Write/Glob/Grep` | 文件操作 | 所有 | +| `Bash` | 脚本执行 | 需要自动化 | +| `mcp__chrome__*` | 浏览器截图 | UI 相关 | + +--- + +*规范版本: 1.0* +*基于: software-manual, copyright-docs* +*最后更新: 2026-01-03* diff --git a/.claude/skills/skill-generator/SKILL.md b/.claude/skills/skill-generator/SKILL.md new file mode 100644 index 00000000..40291269 --- /dev/null +++ b/.claude/skills/skill-generator/SKILL.md @@ -0,0 +1,187 @@ +--- +name: skill-generator +description: Meta-skill for creating new Claude Code skills with configurable execution modes. Supports sequential (fixed order) and autonomous (stateless) phase patterns. Use for skill scaffolding, skill creation, or building new workflows. Triggers on "create skill", "new skill", "skill generator", "生成技能", "创建技能". +allowed-tools: Task, AskUserQuestion, Read, Bash, Glob, Grep, Write +--- + +# Skill Generator + +Meta-skill for creating new Claude Code skills with configurable execution modes. + +## Architecture Overview + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Skill Generator Architecture │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Phase 1: Requirements → skill-config.json │ +│ Discovery (name, type, mode, agents) │ +│ ↓ │ +│ Phase 2: Structure → 目录结构 + 核心文件骨架 │ +│ Generation │ +│ ↓ │ +│ Phase 3: Phase → phases/*.md (根据 mode 生成) │ +│ Generation Sequential | Autonomous │ +│ ↓ │ +│ Phase 4: Specs & → specs/*.md + templates/*.md │ +│ Templates │ +│ ↓ │ +│ Phase 5: Validation → 验证完整性 + 生成使用说明 │ +│ & Documentation │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +## Execution Modes + +### Mode 1: Sequential (固定顺序) + +传统线性执行模式,阶段按数字前缀顺序执行。 + +``` +Phase 01 → Phase 02 → Phase 03 → ... → Phase N +``` + +**适用场景**: +- 流水线式任务(收集 → 分析 → 生成) +- 阶段间有强依赖关系 +- 输出结构固定 + +**示例**: `software-manual`, `copyright-docs` + +### Mode 2: Autonomous (无状态自主选择) + +智能路由模式,根据上下文动态选择执行路径。 + +``` +┌─────────────────────────────────────────┐ +│ Orchestrator Agent │ +│ (读取状态 → 选择 Phase → 执行 → 更新) │ +└───────────────┬─────────────────────────┘ + │ + ┌───────────┼───────────┐ + ↓ ↓ ↓ +┌───────┐ ┌───────┐ ┌───────┐ +│Phase A│ │Phase B│ │Phase C│ +│(独立) │ │(独立) │ │(独立) │ +└───────┘ └───────┘ └───────┘ +``` + +**适用场景**: +- 交互式任务(对话、问答) +- 阶段间无强依赖 +- 需要动态响应用户意图 + +**示例**: `issue-manage`, `workflow-debug` + +## Key Design Principles + +1. **模式感知**: 根据任务特性自动推荐执行模式 +2. **骨架生成**: 生成完整目录结构和文件骨架 +3. **规范遵循**: 严格遵循 `_shared/SKILL-DESIGN-SPEC.md` +4. **可扩展性**: 生成的 Skill 易于扩展和修改 + +## Execution Flow + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Phase 1: Requirements Discovery │ +│ → AskUserQuestion: Skill 名称、目标、执行模式 │ +│ → Output: skill-config.json │ +├─────────────────────────────────────────────────────────────────┤ +│ Phase 2: Structure Generation │ +│ → 创建目录结构: phases/, specs/, templates/, scripts/ │ +│ → 生成 SKILL.md 入口文件 │ +│ → Output: 完整目录结构 │ +├─────────────────────────────────────────────────────────────────┤ +│ Phase 3: Phase Generation │ +│ → Sequential: 生成 01-xx.md, 02-xx.md, ... │ +│ → Autonomous: 生成 orchestrator.md + actions/*.md │ +│ → Output: phases/*.md │ +├─────────────────────────────────────────────────────────────────┤ +│ Phase 4: Specs & Templates │ +│ → 生成领域规范: specs/{domain}-requirements.md │ +│ → 生成质量标准: specs/quality-standards.md │ +│ → 生成模板: templates/agent-base.md │ +│ → Output: specs/*.md, templates/*.md │ +├─────────────────────────────────────────────────────────────────┤ +│ Phase 5: Validation & Documentation │ +│ → 验证文件完整性 │ +│ → 生成 README.md 使用说明 │ +│ → Output: 验证报告 + README.md │ +└─────────────────────────────────────────────────────────────────┘ +``` + +## Directory Setup + +```javascript +const skillName = config.skill_name; +const skillDir = `.claude/skills/${skillName}`; + +// 创建目录结构 +Bash(`mkdir -p "${skillDir}/phases"`); +Bash(`mkdir -p "${skillDir}/specs"`); +Bash(`mkdir -p "${skillDir}/templates"`); + +// Autonomous 模式额外目录 +if (config.execution_mode === 'autonomous') { + Bash(`mkdir -p "${skillDir}/phases/actions"`); +} +``` + +## Output Structure + +### Sequential Mode + +``` +.claude/skills/{skill-name}/ +├── SKILL.md +├── phases/ +│ ├── 01-{step-one}.md +│ ├── 02-{step-two}.md +│ └── 03-{step-three}.md +├── specs/ +│ ├── {domain}-requirements.md +│ └── quality-standards.md +└── templates/ + └── agent-base.md +``` + +### Autonomous Mode + +``` +.claude/skills/{skill-name}/ +├── SKILL.md +├── phases/ +│ ├── orchestrator.md # 编排器:读取状态 → 选择动作 +│ ├── state-schema.md # 状态结构定义 +│ └── actions/ # 独立动作(无顺序) +│ ├── action-{a}.md +│ ├── action-{b}.md +│ └── action-{c}.md +├── specs/ +│ ├── {domain}-requirements.md +│ ├── action-catalog.md # 动作目录(描述、前置条件、效果) +│ └── quality-standards.md +└── templates/ + ├── orchestrator-base.md # 编排器模板 + └── action-base.md # 动作模板 +``` + +## Reference Documents + +| Document | Purpose | +|----------|---------| +| [phases/01-requirements-discovery.md](phases/01-requirements-discovery.md) | 收集 Skill 需求 | +| [phases/02-structure-generation.md](phases/02-structure-generation.md) | 生成目录结构 | +| [phases/03-phase-generation.md](phases/03-phase-generation.md) | 生成 Phase 文件 | +| [phases/04-specs-templates.md](phases/04-specs-templates.md) | 生成规范和模板 | +| [phases/05-validation.md](phases/05-validation.md) | 验证和文档 | +| [specs/execution-modes.md](specs/execution-modes.md) | 执行模式规范 | +| [specs/skill-requirements.md](specs/skill-requirements.md) | Skill 需求规范 | +| [templates/skill-md.md](templates/skill-md.md) | SKILL.md 模板 | +| [templates/sequential-phase.md](templates/sequential-phase.md) | Sequential Phase 模板 | +| [templates/autonomous-orchestrator.md](templates/autonomous-orchestrator.md) | Autonomous 编排器模板 | +| [templates/autonomous-action.md](templates/autonomous-action.md) | Autonomous Action 模板 | +| [../_shared/SKILL-DESIGN-SPEC.md](../_shared/SKILL-DESIGN-SPEC.md) | 通用设计规范 | diff --git a/.claude/skills/skill-generator/phases/01-requirements-discovery.md b/.claude/skills/skill-generator/phases/01-requirements-discovery.md new file mode 100644 index 00000000..4d5d3f7a --- /dev/null +++ b/.claude/skills/skill-generator/phases/01-requirements-discovery.md @@ -0,0 +1,239 @@ +# Phase 1: Requirements Discovery + +收集新 Skill 的需求信息,生成配置文件。 + +## Objective + +- 收集 Skill 基本信息(名称、描述、触发词) +- 确定执行模式(Sequential / Autonomous) +- 定义阶段/动作 +- 配置工具依赖和输出格式 + +## Execution Steps + +### Step 1: 基本信息收集 + +```javascript +const basicInfo = await AskUserQuestion({ + questions: [ + { + question: "新 Skill 的名称是什么?(英文,小写-连字符格式,如 'api-docs')", + header: "Skill 名称", + multiSelect: false, + options: [ + { label: "自动生成", description: "根据后续描述自动生成名称" }, + { label: "手动输入", description: "现在输入自定义名称" } + ] + }, + { + question: "Skill 的主要用途是什么?", + header: "用途类型", + multiSelect: false, + options: [ + { label: "文档生成", description: "生成 Markdown/HTML 文档(如手册、报告)" }, + { label: "代码分析", description: "分析代码结构、质量、安全性" }, + { label: "交互管理", description: "管理 Issue、任务、工作流(CRUD 操作)" }, + { label: "数据处理", description: "ETL、格式转换、报告生成" } + ] + } + ] +}); + +// 如果选择手动输入,进一步询问 +if (basicInfo["Skill 名称"] === "手动输入") { + // 用户会在 "Other" 中输入 +} + +// 根据用途类型推断描述模板 +const purposeTemplates = { + "文档生成": "Generate {type} documents from {source}", + "代码分析": "Analyze {target} for {purpose}", + "交互管理": "Manage {entity} with interactive operations", + "数据处理": "Process {data} and generate {output}" +}; +``` + +### Step 2: 执行模式选择 + +```javascript +const modeInfo = await AskUserQuestion({ + questions: [ + { + question: "选择执行模式:", + header: "执行模式", + multiSelect: false, + options: [ + { + label: "Sequential (顺序模式)", + description: "阶段按固定顺序执行(收集→分析→生成),适合流水线任务(推荐)" + }, + { + label: "Autonomous (自主模式)", + description: "动态选择执行路径,适合交互式任务(如 Issue 管理)" + }, + { + label: "Hybrid (混合模式)", + description: "初始化和收尾固定,中间交互灵活" + } + ] + } + ] +}); + +const executionMode = modeInfo["执行模式"].includes("Sequential") ? "sequential" : + modeInfo["执行模式"].includes("Autonomous") ? "autonomous" : "hybrid"; +``` + +### Step 3: 阶段/动作定义 + +#### Sequential 模式 + +```javascript +if (executionMode === "sequential") { + const phaseInfo = await AskUserQuestion({ + questions: [ + { + question: "需要多少个执行阶段?", + header: "阶段数量", + multiSelect: false, + options: [ + { label: "3 阶段(简单)", description: "收集 → 处理 → 输出" }, + { label: "5 阶段(标准)", description: "收集 → 探索 → 分析 → 组装 → 验证" }, + { label: "7 阶段(完整)", description: "含并行处理、汇总、迭代优化" } + ] + } + ] + }); + + // 根据选择生成阶段定义 + const phaseTemplates = { + "3 阶段": [ + { id: "01-collection", name: "Data Collection" }, + { id: "02-processing", name: "Processing" }, + { id: "03-output", name: "Output Generation" } + ], + "5 阶段": [ + { id: "01-collection", name: "Requirements Collection" }, + { id: "02-exploration", name: "Project Exploration" }, + { id: "03-analysis", name: "Deep Analysis" }, + { id: "04-assembly", name: "Document Assembly" }, + { id: "05-validation", name: "Validation" } + ], + "7 阶段": [ + { id: "01-collection", name: "Requirements Collection" }, + { id: "02-exploration", name: "Project Exploration" }, + { id: "03-parallel", name: "Parallel Analysis" }, + { id: "03.5-consolidation", name: "Consolidation" }, + { id: "04-assembly", name: "Document Assembly" }, + { id: "05-refinement", name: "Iterative Refinement" }, + { id: "06-output", name: "Final Output" } + ] + }; +} +``` + +#### Autonomous 模式 + +```javascript +if (executionMode === "autonomous") { + const actionInfo = await AskUserQuestion({ + questions: [ + { + question: "核心动作有哪些?(可多选)", + header: "动作定义", + multiSelect: true, + options: [ + { label: "初始化 (init)", description: "设置初始状态" }, + { label: "列表 (list)", description: "显示当前项目列表" }, + { label: "创建 (create)", description: "创建新项目" }, + { label: "编辑 (edit)", description: "修改现有项目" }, + { label: "删除 (delete)", description: "删除项目" }, + { label: "搜索 (search)", description: "搜索/过滤项目" } + ] + } + ] + }); +} +``` + +### Step 4: 工具和输出配置 + +```javascript +const toolsInfo = await AskUserQuestion({ + questions: [ + { + question: "需要哪些特殊工具?(基础工具已默认包含)", + header: "工具选择", + multiSelect: true, + options: [ + { label: "用户交互 (AskUserQuestion)", description: "需要与用户对话" }, + { label: "Chrome 截图 (mcp__chrome__*)", description: "需要网页截图" }, + { label: "外部搜索 (mcp__exa__search)", description: "需要搜索外部信息" }, + { label: "无特殊需求", description: "仅使用基础工具" } + ] + }, + { + question: "输出格式是什么?", + header: "输出格式", + multiSelect: false, + options: [ + { label: "Markdown", description: "适合文档和报告" }, + { label: "HTML", description: "适合交互式文档" }, + { label: "JSON", description: "适合数据和配置" } + ] + } + ] +}); +``` + +### Step 5: 生成配置文件 + +```javascript +const config = { + skill_name: skillName, + display_name: displayName, + description: description, + triggers: triggers, + execution_mode: executionMode, + + // 模式特定配置 + ...(executionMode === "sequential" ? { + sequential_config: { phases: phases } + } : { + autonomous_config: { + state_schema: stateSchema, + actions: actions, + termination_conditions: ["user_exit", "error_limit", "task_completed"] + } + }), + + allowed_tools: [ + "Task", "Read", "Write", "Glob", "Grep", "Bash", + ...selectedTools + ], + + output: { + format: outputFormat.toLowerCase(), + location: `.workflow/.scratchpad/${skillName}-{timestamp}`, + filename_pattern: `{name}-output.${outputFormat === "HTML" ? "html" : outputFormat === "JSON" ? "json" : "md"}` + }, + + created_at: new Date().toISOString(), + version: "1.0.0" +}; + +// 写入配置文件 +const workDir = `.workflow/.scratchpad/skill-gen-${timestamp}`; +Bash(`mkdir -p "${workDir}"`); +Write(`${workDir}/skill-config.json`, JSON.stringify(config, null, 2)); +``` + +## Output + +- **File**: `skill-config.json` +- **Location**: `.workflow/.scratchpad/skill-gen-{timestamp}/` +- **Format**: JSON + +## Next Phase + +→ [Phase 2: Structure Generation](02-structure-generation.md) diff --git a/.claude/skills/skill-generator/phases/02-structure-generation.md b/.claude/skills/skill-generator/phases/02-structure-generation.md new file mode 100644 index 00000000..f846fdfa --- /dev/null +++ b/.claude/skills/skill-generator/phases/02-structure-generation.md @@ -0,0 +1,208 @@ +# Phase 2: Structure Generation + +根据配置创建 Skill 目录结构和入口文件。 + +## Objective + +- 创建标准目录结构 +- 生成 SKILL.md 入口文件 +- 根据执行模式创建对应的子目录 + +## Input + +- 依赖: `skill-config.json` (Phase 1 产出) + +## Execution Steps + +### Step 1: 读取配置 + +```javascript +const config = JSON.parse(Read(`${workDir}/skill-config.json`)); +const skillDir = `.claude/skills/${config.skill_name}`; +``` + +### Step 2: 创建目录结构 + +```javascript +// 基础目录 +Bash(`mkdir -p "${skillDir}/phases"`); +Bash(`mkdir -p "${skillDir}/specs"`); +Bash(`mkdir -p "${skillDir}/templates"`); + +// Autonomous 模式额外目录 +if (config.execution_mode === 'autonomous' || config.execution_mode === 'hybrid') { + Bash(`mkdir -p "${skillDir}/phases/actions"`); +} + +// 可选: scripts 目录 +if (config.needs_scripts) { + Bash(`mkdir -p "${skillDir}/scripts"`); +} +``` + +### Step 3: 生成 SKILL.md + +```javascript +const skillMdTemplate = `--- +name: ${config.skill_name} +description: ${config.description}. Triggers on ${config.triggers.map(t => `"${t}"`).join(", ")}. +allowed-tools: ${config.allowed_tools.join(", ")} +--- + +# ${config.display_name} + +${config.description} + +## Architecture Overview + +\`\`\` +${generateArchitectureDiagram(config)} +\`\`\` + +## Key Design Principles + +${generateDesignPrinciples(config)} + +## Execution Flow + +${generateExecutionFlow(config)} + +## Directory Setup + +\`\`\`javascript +const timestamp = new Date().toISOString().slice(0,19).replace(/[-:T]/g, ''); +const workDir = \`${config.output.location.replace('{timestamp}', '${timestamp}')}\`; + +Bash(\`mkdir -p "\${workDir}"\`); +${config.execution_mode === 'sequential' ? + `Bash(\`mkdir -p "\${workDir}/sections"\`);` : + `Bash(\`mkdir -p "\${workDir}/state"\`);`} +\`\`\` + +## Output Structure + +\`\`\` +${generateOutputStructure(config)} +\`\`\` + +## Reference Documents + +${generateReferenceTable(config)} +`; + +Write(`${skillDir}/SKILL.md`, skillMdTemplate); +``` + +### Step 4: 架构图生成函数 + +```javascript +function generateArchitectureDiagram(config) { + if (config.execution_mode === 'sequential') { + return config.sequential_config.phases.map((p, i) => + `│ Phase ${i+1}: ${p.name.padEnd(15)} → ${p.output || 'output-' + (i+1) + '.json'}${' '.repeat(10)}│` + ).join('\n│ ↓' + ' '.repeat(45) + '│\n'); + } else { + return ` +┌─────────────────────────────────────────────────────────────────┐ +│ Orchestrator (状态驱动决策) │ +└───────────────┬─────────────────────────────────────────────────┘ + │ + ┌───────────┼───────────┐ + ↓ ↓ ↓ +${config.autonomous_config.actions.slice(0, 3).map(a => + `┌─────────┐ `).join('')} +${config.autonomous_config.actions.slice(0, 3).map(a => + `│${a.name.slice(0, 7).padEnd(7)}│ `).join('')} +${config.autonomous_config.actions.slice(0, 3).map(a => + `└─────────┘ `).join('')}`; + } +} + +function generateDesignPrinciples(config) { + const common = [ + "1. **规范遵循**: 严格遵循 `_shared/SKILL-DESIGN-SPEC.md`", + "2. **简要返回**: Agent 返回路径+摘要,避免上下文溢出" + ]; + + if (config.execution_mode === 'sequential') { + return [...common, + "3. **阶段隔离**: 每个阶段独立可测", + "4. **链式输出**: 阶段产出作为下阶段输入" + ].join('\n'); + } else { + return [...common, + "3. **状态驱动**: 显式状态管理,动态决策", + "4. **动作独立**: 每个动作无副作用依赖" + ].join('\n'); + } +} + +function generateExecutionFlow(config) { + if (config.execution_mode === 'sequential') { + return '```\n' + config.sequential_config.phases.map((p, i) => + `├─ Phase ${i+1}: ${p.name}\n│ → Output: ${p.output || 'output.json'}` + ).join('\n') + '\n```'; + } else { + return `\`\`\` +┌─────────────────────────────────────────────────────────────────┐ +│ Orchestrator Loop │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ +│ │ Read │────▶│ Select │────▶│ Execute │ │ +│ │ State │ │ Action │ │ Action │ │ +│ └──────────┘ └──────────┘ └──────────┘ │ +│ ▲ │ │ +│ └──────────── Update State ◀───────┘ │ +└─────────────────────────────────────────────────────────────────┘ +\`\`\``; + } +} + +function generateOutputStructure(config) { + const base = `${config.output.location}/ +├── ${config.execution_mode === 'sequential' ? 'sections/' : 'state.json'}`; + + if (config.execution_mode === 'sequential') { + return base + '\n' + config.sequential_config.phases.map(p => + `│ └── ${p.output || 'section-' + p.id + '.md'}` + ).join('\n') + `\n└── ${config.output.filename_pattern}`; + } else { + return base + ` +├── actions-log.json +└── ${config.output.filename_pattern}`; + } +} + +function generateReferenceTable(config) { + const rows = []; + + if (config.execution_mode === 'sequential') { + config.sequential_config.phases.forEach(p => { + rows.push(`| [phases/${p.id}.md](phases/${p.id}.md) | ${p.name} |`); + }); + } else { + rows.push(`| [phases/orchestrator.md](phases/orchestrator.md) | 编排器 |`); + rows.push(`| [phases/state-schema.md](phases/state-schema.md) | 状态定义 |`); + config.autonomous_config.actions.forEach(a => { + rows.push(`| [phases/actions/${a.id}.md](phases/actions/${a.id}.md) | ${a.name} |`); + }); + } + + rows.push(`| [specs/${config.skill_name}-requirements.md](specs/${config.skill_name}-requirements.md) | 领域规范 |`); + rows.push(`| [specs/quality-standards.md](specs/quality-standards.md) | 质量标准 |`); + + return `| Document | Purpose |\n|----------|---------||\n` + rows.join('\n'); +} +``` + +## Output + +- **Directory**: `.claude/skills/{skill-name}/` +- **Files**: + - `SKILL.md` (入口文件) + - `phases/` (空目录) + - `specs/` (空目录) + - `templates/` (空目录) + +## Next Phase + +→ [Phase 3: Phase Generation](03-phase-generation.md) diff --git a/.claude/skills/skill-generator/phases/03-phase-generation.md b/.claude/skills/skill-generator/phases/03-phase-generation.md new file mode 100644 index 00000000..fd360479 --- /dev/null +++ b/.claude/skills/skill-generator/phases/03-phase-generation.md @@ -0,0 +1,396 @@ +# Phase 3: Phase Generation + +根据执行模式生成 Phase 文件。 + +## Objective + +- Sequential 模式:生成顺序 Phase 文件 (`01-xx.md`, `02-xx.md`, ...) +- Autonomous 模式:生成编排器和动作文件 + +## Input + +- 依赖: `skill-config.json`, SKILL.md (Phase 1-2 产出) +- 模板: `templates/sequential-phase.md`, `templates/autonomous-*.md` + +## Execution Steps + +### Step 1: 读取配置和模板 + +```javascript +const config = JSON.parse(Read(`${workDir}/skill-config.json`)); +const skillDir = `.claude/skills/${config.skill_name}`; + +// 读取模板 +const sequentialTemplate = Read(`${skillRoot}/templates/sequential-phase.md`); +const orchestratorTemplate = Read(`${skillRoot}/templates/autonomous-orchestrator.md`); +const actionTemplate = Read(`${skillRoot}/templates/autonomous-action.md`); +``` + +### Step 2: Sequential 模式 - 生成阶段文件 + +```javascript +if (config.execution_mode === 'sequential') { + const phases = config.sequential_config.phases; + + for (let i = 0; i < phases.length; i++) { + const phase = phases[i]; + const prevPhase = i > 0 ? phases[i-1] : null; + const nextPhase = i < phases.length - 1 ? phases[i+1] : null; + + const content = generateSequentialPhase({ + phaseNumber: i + 1, + phaseId: phase.id, + phaseName: phase.name, + phaseDescription: phase.description || `Execute ${phase.name}`, + input: prevPhase ? prevPhase.output : "user input", + output: phase.output, + nextPhase: nextPhase ? nextPhase.id : null, + config: config + }); + + Write(`${skillDir}/phases/${phase.id}.md`, content); + } +} + +function generateSequentialPhase(params) { + return `# Phase ${params.phaseNumber}: ${params.phaseName} + +${params.phaseDescription} + +## Objective + +- 主要目标描述 +- 具体任务列表 + +## Input + +- 依赖: \`${params.input}\` +- 配置: \`{workDir}/skill-config.json\` + +## Execution Steps + +### Step 1: 准备工作 + +\`\`\`javascript +// 读取上一阶段产出 +${params.phaseNumber > 1 ? + `const prevOutput = JSON.parse(Read(\`\${workDir}/${params.input}\`));` : + `// 首阶段,直接从配置开始`} +\`\`\` + +### Step 2: 核心处理 + +\`\`\`javascript +// TODO: 实现核心逻辑 +const result = { + // 处理结果 +}; +\`\`\` + +### Step 3: 输出结果 + +\`\`\`javascript +Write(\`\${workDir}/${params.output}\`, JSON.stringify(result, null, 2)); +\`\`\` + +## Output + +- **File**: \`${params.output}\` +- **Format**: ${params.output.endsWith('.json') ? 'JSON' : 'Markdown'} + +## Quality Checklist + +- [ ] 输入数据验证通过 +- [ ] 核心逻辑执行成功 +- [ ] 输出格式正确 + +${params.nextPhase ? + `## Next Phase\n\n→ [Phase ${params.phaseNumber + 1}: ${params.nextPhase}](${params.nextPhase}.md)` : + `## Completion\n\n此为最后阶段,输出最终产物。`} +`; +} +``` + +### Step 3: Autonomous 模式 - 生成编排器 + +```javascript +if (config.execution_mode === 'autonomous' || config.execution_mode === 'hybrid') { + + // 生成状态 Schema + const stateSchema = generateStateSchema(config); + Write(`${skillDir}/phases/state-schema.md`, stateSchema); + + // 生成编排器 + const orchestrator = generateOrchestrator(config); + Write(`${skillDir}/phases/orchestrator.md`, orchestrator); + + // 生成动作文件 + for (const action of config.autonomous_config.actions) { + const actionContent = generateAction(action, config); + Write(`${skillDir}/phases/actions/${action.id}.md`, actionContent); + } +} + +function generateStateSchema(config) { + return `# State Schema + +## 状态文件 + +位置: \`{workDir}/state.json\` + +## 结构定义 + +\`\`\`typescript +interface ${toPascalCase(config.skill_name)}State { + // 元信息 + skill_name: "${config.skill_name}"; + started_at: string; + updated_at: string; + + // 执行状态 + status: 'pending' | 'running' | 'completed' | 'failed'; + current_action: string | null; + completed_actions: string[]; + + // 业务数据 +${config.autonomous_config.state_schema?.fields?.map(f => + ` ${f.name}: ${f.type}; // ${f.description}` +).join('\n') || ' context: Record;'} + + // 错误追踪 + errors: Array<{ + action: string; + message: string; + timestamp: string; + }>; + error_count: number; +} +\`\`\` + +## 初始状态 + +\`\`\`json +{ + "skill_name": "${config.skill_name}", + "started_at": "", + "updated_at": "", + "status": "pending", + "current_action": null, + "completed_actions": [], +${config.autonomous_config.state_schema?.fields?.map(f => + ` "${f.name}": ${getDefaultValue(f.type)}` +).join(',\n') || ' "context": {}'} + "errors": [], + "error_count": 0 +} +\`\`\` + +## 状态转换规则 + +| 当前状态 | 触发条件 | 目标状态 | +|----------|----------|----------| +| pending | 首次执行 | running | +| running | 动作完成 | running | +| running | 所有任务完成 | completed | +| running | 错误超限 | failed | +`; +} + +function generateOrchestrator(config) { + const actions = config.autonomous_config.actions; + + return `# Orchestrator + +## Role + +根据当前状态选择并执行下一个动作。 + +## State Reading + +\`\`\`javascript +const state = JSON.parse(Read(\`\${workDir}/state.json\`)); +\`\`\` + +## Decision Logic + +\`\`\`javascript +function selectNextAction(state) { + // 1. 检查终止条件 +${config.autonomous_config.termination_conditions?.map(c => + ` if (${getTerminationCheck(c)}) return null;` +).join('\n') || ' if (state.status === "completed") return null;'} + + // 2. 错误检查 + if (state.error_count >= 3) return 'action-abort'; + + // 3. 根据状态选择动作 +${actions.map(a => + ` if (${getPreconditionCheck(a)}) return '${a.id}';` +).join('\n')} + + // 4. 默认: 完成 + return 'action-complete'; +} +\`\`\` + +## Execution Loop + +\`\`\`javascript +async function runOrchestrator() { + while (true) { + // 读取状态 + const state = JSON.parse(Read(\`\${workDir}/state.json\`)); + + // 选择动作 + const actionId = selectNextAction(state); + if (!actionId) { + console.log("任务完成或终止"); + break; + } + + // 更新当前动作 + state.current_action = actionId; + state.updated_at = new Date().toISOString(); + Write(\`\${workDir}/state.json\`, JSON.stringify(state, null, 2)); + + // 执行动作 + try { + const result = await executeAction(actionId, state); + + // 更新状态 + state.completed_actions.push(actionId); + state.current_action = null; + Object.assign(state, result.stateUpdates); + + } catch (error) { + state.errors.push({ + action: actionId, + message: error.message, + timestamp: new Date().toISOString() + }); + state.error_count++; + } + + Write(\`\${workDir}/state.json\`, JSON.stringify(state, null, 2)); + } +} +\`\`\` + +## Action Catalog + +| Action | Purpose | Preconditions | +|--------|---------|---------------| +${actions.map(a => + `| [${a.id}](actions/${a.id}.md) | ${a.description || a.name} | ${a.preconditions?.join(', ') || '-'} |` +).join('\n')} + +## Termination Conditions + +${config.autonomous_config.termination_conditions?.map(c => `- ${c}`).join('\n') || '- status === "completed"'} +`; +} + +function generateAction(action, config) { + return `# Action: ${action.name} + +${action.description || '执行 ' + action.name + ' 操作'} + +## Purpose + +${action.description || 'TODO: 描述此动作的目的'} + +## Preconditions + +${action.preconditions?.map(p => `- [ ] ${p}`).join('\n') || '- [ ] 无特殊前置条件'} + +## Execution + +\`\`\`javascript +async function execute(state) { + // TODO: 实现动作逻辑 + + // 1. 读取必要数据 + + // 2. 执行核心逻辑 + + // 3. 返回状态更新 + return { + stateUpdates: { + // 更新的状态字段 + } + }; +} +\`\`\` + +## State Updates + +\`\`\`javascript +return { + completed_actions: [...state.completed_actions, '${action.id}'], + // 其他状态更新 +${action.effects?.map(e => ` // Effect: ${e}`).join('\n') || ''} +}; +\`\`\` + +## Error Handling + +| 错误类型 | 处理方式 | +|----------|----------| +| 数据验证失败 | 返回错误,不更新状态 | +| 执行异常 | 记录错误,增加 error_count | + +## Next Actions (Hints) + +- 成功时: 由编排器根据状态决定 +- 失败时: 重试或 \`action-abort\` +`; +} +``` + +### Step 4: 辅助函数 + +```javascript +function toPascalCase(str) { + return str.split('-').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(''); +} + +function getDefaultValue(type) { + if (type.endsWith('[]')) return '[]'; + if (type === 'number') return '0'; + if (type === 'boolean') return 'false'; + if (type === 'string') return '""'; + return '{}'; +} + +function getTerminationCheck(condition) { + const checks = { + 'user_exit': 'state.status === "user_exit"', + 'error_limit': 'state.error_count >= 3', + 'task_completed': 'state.status === "completed"' + }; + return checks[condition] || `state.${condition}`; +} + +function getPreconditionCheck(action) { + if (!action.preconditions?.length) return 'true'; + return action.preconditions.map(p => `state.${p}`).join(' && '); +} +``` + +## Output + +### Sequential 模式 + +- `phases/01-{step}.md` +- `phases/02-{step}.md` +- ... + +### Autonomous 模式 + +- `phases/orchestrator.md` +- `phases/state-schema.md` +- `phases/actions/action-{name}.md` (多个) + +## Next Phase + +→ [Phase 4: Specs & Templates](04-specs-templates.md) diff --git a/.claude/skills/skill-generator/phases/04-specs-templates.md b/.claude/skills/skill-generator/phases/04-specs-templates.md new file mode 100644 index 00000000..27756f50 --- /dev/null +++ b/.claude/skills/skill-generator/phases/04-specs-templates.md @@ -0,0 +1,328 @@ +# Phase 4: Specs & Templates Generation + +生成规范文件和模板文件。 + +## Objective + +- 生成领域规范 (`specs/{domain}-requirements.md`) +- 生成质量标准 (`specs/quality-standards.md`) +- 生成 Agent 模板 (`templates/agent-base.md`) +- Autonomous 模式额外生成动作目录 (`specs/action-catalog.md`) + +## Input + +- 依赖: `skill-config.json`, SKILL.md, phases/*.md + +## Execution Steps + +### Step 1: 生成领域规范 + +```javascript +const config = JSON.parse(Read(`${workDir}/skill-config.json`)); +const skillDir = `.claude/skills/${config.skill_name}`; + +const domainRequirements = `# ${config.display_name} Requirements + +${config.description} + +## When to Use + +| Phase | Usage | Reference | +|-------|-------|-----------| +${config.execution_mode === 'sequential' ? + config.sequential_config.phases.map((p, i) => + `| Phase ${i+1} | ${p.name} | ${p.id}.md |` + ).join('\n') : + `| Orchestrator | 动作选择 | orchestrator.md | +| Actions | 动作执行 | actions/*.md |`} + +--- + +## Domain Requirements + +### 功能要求 + +- [ ] 要求1: TODO +- [ ] 要求2: TODO +- [ ] 要求3: TODO + +### 输出要求 + +- [ ] 格式: ${config.output.format} +- [ ] 位置: ${config.output.location} +- [ ] 命名: ${config.output.filename_pattern} + +### 质量要求 + +- [ ] 完整性: 所有必需内容存在 +- [ ] 一致性: 术语和格式统一 +- [ ] 准确性: 内容基于实际分析 + +## Validation Function + +\`\`\`javascript +function validate${toPascalCase(config.skill_name)}(output) { + const checks = [ + // TODO: 添加验证规则 + { name: "格式正确", pass: output.format === "${config.output.format}" }, + { name: "内容完整", pass: output.content?.length > 0 } + ]; + + return { + passed: checks.filter(c => c.pass).length, + total: checks.length, + details: checks + }; +} +\`\`\` + +## Error Handling + +| Error | Recovery | +|-------|----------| +| 输入数据缺失 | 返回明确错误信息 | +| 处理超时 | 缩小范围,重试 | +| 输出验证失败 | 记录问题,人工审核 | +`; + +Write(`${skillDir}/specs/${config.skill_name}-requirements.md`, domainRequirements); +``` + +### Step 2: 生成质量标准 + +```javascript +const qualityStandards = `# Quality Standards + +${config.display_name} 的质量评估标准。 + +## Quality Dimensions + +### 1. Completeness (完整性) - 25% + +| 要求 | 权重 | 检查方式 | +|------|------|----------| +| 所有必需输出存在 | 10 | 文件检查 | +| 内容覆盖完整 | 10 | 内容分析 | +| 无占位符残留 | 5 | 文本搜索 | + +### 2. Consistency (一致性) - 25% + +| 方面 | 检查 | +|------|------| +| 术语 | 同一概念使用相同术语 | +| 格式 | 标题层级、代码块格式一致 | +| 风格 | 语气和表达方式统一 | + +### 3. Accuracy (准确性) - 25% + +| 要求 | 说明 | +|------|------| +| 数据正确 | 引用和数据无错误 | +| 逻辑正确 | 流程和关系描述准确 | +| 代码正确 | 代码示例可运行 | + +### 4. Usability (可用性) - 25% + +| 指标 | 目标 | +|------|------| +| 可读性 | 结构清晰,易于理解 | +| 可导航 | 目录和链接正确 | +| 可操作 | 步骤明确,可执行 | + +## Quality Gates + +| Gate | Threshold | Action | +|------|-----------|--------| +| Pass | ≥ 80% | 输出最终产物 | +| Review | 60-79% | 处理警告后继续 | +| Fail | < 60% | 必须修复 | + +## Issue Classification + +### Errors (Must Fix) + +- 必需输出缺失 +- 数据错误 +- 代码不可运行 + +### Warnings (Should Fix) + +- 格式不一致 +- 内容深度不足 +- 缺少示例 + +### Info (Nice to Have) + +- 优化建议 +- 增强机会 + +## Automated Checks + +\`\`\`javascript +function runQualityChecks(workDir) { + const results = { + completeness: checkCompleteness(workDir), + consistency: checkConsistency(workDir), + accuracy: checkAccuracy(workDir), + usability: checkUsability(workDir) + }; + + results.overall = ( + results.completeness * 0.25 + + results.consistency * 0.25 + + results.accuracy * 0.25 + + results.usability * 0.25 + ); + + return { + score: results.overall, + gate: results.overall >= 80 ? 'pass' : + results.overall >= 60 ? 'review' : 'fail', + details: results + }; +} +\`\`\` +`; + +Write(`${skillDir}/specs/quality-standards.md`, qualityStandards); +``` + +### Step 3: 生成 Agent 模板 + +```javascript +const agentBase = `# Agent Base Template + +${config.display_name} 的 Agent 基础模板。 + +## 通用 Prompt 结构 + +\`\`\` +[ROLE] 你是{角色},专注于{职责}。 + +[PROJECT CONTEXT] +Skill: ${config.skill_name} +目标: ${config.description} + +[TASK] +{任务描述} +- 输出: {output_path} +- 格式: ${config.output.format} + +[CONSTRAINTS] +- 约束1 +- 约束2 + +[OUTPUT_FORMAT] +1. 执行任务 +2. 返回 JSON 简要信息 + +[QUALITY_CHECKLIST] +- [ ] 输出格式正确 +- [ ] 内容完整无遗漏 +- [ ] 无占位符残留 +\`\`\` + +## 变量说明 + +| 变量 | 来源 | 示例 | +|------|------|------| +| {workDir} | 运行时 | .workflow/.scratchpad/${config.skill_name}-xxx | +| {output_path} | 配置 | ${config.output.location}/${config.output.filename_pattern} | + +## 返回格式 + +\`\`\`typescript +interface AgentReturn { + status: "completed" | "partial" | "failed"; + output_file: string; + summary: string; // Max 50 chars + stats?: { + items_processed?: number; + errors?: number; + }; +} +\`\`\` + +## 角色定义参考 + +${config.execution_mode === 'sequential' ? + config.sequential_config.phases.map((p, i) => + `- **Phase ${i+1} Agent**: ${p.name} 专家` + ).join('\n') : + config.autonomous_config.actions.map(a => + `- **${a.name} Agent**: ${a.description || a.name + ' 执行者'}` + ).join('\n')} +`; + +Write(`${skillDir}/templates/agent-base.md`, agentBase); +``` + +### Step 4: Autonomous 模式 - 动作目录 + +```javascript +if (config.execution_mode === 'autonomous' || config.execution_mode === 'hybrid') { + const actionCatalog = `# Action Catalog + +${config.display_name} 的可用动作目录。 + +## Available Actions + +| Action | Purpose | Preconditions | Effects | +|--------|---------|---------------|---------| +${config.autonomous_config.actions.map(a => + `| [${a.id}](../phases/actions/${a.id}.md) | ${a.description || a.name} | ${a.preconditions?.join(', ') || '-'} | ${a.effects?.join(', ') || '-'} |` +).join('\n')} + +## Action Dependencies + +\`\`\`mermaid +graph TD +${config.autonomous_config.actions.map((a, i, arr) => { + if (i === 0) return ` ${a.id.replace(/-/g, '_')}[${a.name}]`; + const prev = arr[i-1]; + return ` ${prev.id.replace(/-/g, '_')} --> ${a.id.replace(/-/g, '_')}[${a.name}]`; +}).join('\n')} +\`\`\` + +## State Transitions + +| From State | Action | To State | +|------------|--------|----------| +| pending | action-init | running | +${config.autonomous_config.actions.slice(1).map(a => + `| running | ${a.id} | running |` +).join('\n')} +| running | action-complete | completed | +| running | action-abort | failed | + +## Selection Priority + +当多个动作的前置条件都满足时,按以下优先级选择: + +${config.autonomous_config.actions.map((a, i) => + `${i + 1}. \`${a.id}\` - ${a.name}` +).join('\n')} +`; + + Write(`${skillDir}/specs/action-catalog.md`, actionCatalog); +} +``` + +### Step 5: 辅助函数 + +```javascript +function toPascalCase(str) { + return str.split('-').map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(''); +} +``` + +## Output + +- `specs/{skill-name}-requirements.md` - 领域规范 +- `specs/quality-standards.md` - 质量标准 +- `specs/action-catalog.md` - 动作目录 (Autonomous 模式) +- `templates/agent-base.md` - Agent 模板 + +## Next Phase + +→ [Phase 5: Validation](05-validation.md) diff --git a/.claude/skills/skill-generator/phases/05-validation.md b/.claude/skills/skill-generator/phases/05-validation.md new file mode 100644 index 00000000..07fb637b --- /dev/null +++ b/.claude/skills/skill-generator/phases/05-validation.md @@ -0,0 +1,334 @@ +# Phase 5: Validation & Documentation + +验证生成的 Skill 完整性并生成使用说明。 + +## Objective + +- 验证所有必需文件存在 +- 检查文件内容完整性 +- 生成 README.md 使用说明 +- 输出验证报告 + +## Input + +- 依赖: 所有前序阶段产出 +- 生成的 Skill 目录 + +## Execution Steps + +### Step 1: 文件完整性检查 + +```javascript +const config = JSON.parse(Read(`${workDir}/skill-config.json`)); +const skillDir = `.claude/skills/${config.skill_name}`; + +const requiredFiles = { + common: [ + 'SKILL.md', + `specs/${config.skill_name}-requirements.md`, + 'specs/quality-standards.md', + 'templates/agent-base.md' + ], + sequential: config.sequential_config?.phases?.map(p => `phases/${p.id}.md`) || [], + autonomous: [ + 'phases/orchestrator.md', + 'phases/state-schema.md', + 'specs/action-catalog.md', + ...(config.autonomous_config?.actions?.map(a => `phases/actions/${a.id}.md`) || []) + ] +}; + +const filesToCheck = [ + ...requiredFiles.common, + ...(config.execution_mode === 'sequential' ? requiredFiles.sequential : requiredFiles.autonomous) +]; + +const fileCheckResults = filesToCheck.map(file => { + const fullPath = `${skillDir}/${file}`; + try { + const content = Read(fullPath); + return { + file: file, + exists: true, + size: content.length, + hasContent: content.length > 100, + hasTodo: content.includes('TODO') + }; + } catch (e) { + return { + file: file, + exists: false, + size: 0, + hasContent: false, + hasTodo: false + }; + } +}); +``` + +### Step 2: 内容质量检查 + +```javascript +const contentChecks = []; + +// 检查 SKILL.md +const skillMd = Read(`${skillDir}/SKILL.md`); +contentChecks.push({ + file: 'SKILL.md', + checks: [ + { name: 'Front Matter', pass: skillMd.startsWith('---') }, + { name: 'Architecture', pass: skillMd.includes('## Architecture') }, + { name: 'Execution Flow', pass: skillMd.includes('## Execution Flow') }, + { name: 'References', pass: skillMd.includes('## Reference Documents') } + ] +}); + +// 检查 Phase 文件 +const phaseFiles = Glob(`${skillDir}/phases/*.md`); +for (const phaseFile of phaseFiles) { + if (phaseFile.includes('/actions/')) continue; // 单独检查 + + const content = Read(phaseFile); + contentChecks.push({ + file: phaseFile.replace(skillDir + '/', ''), + checks: [ + { name: 'Objective', pass: content.includes('## Objective') }, + { name: 'Execution', pass: content.includes('## Execution') || content.includes('## Execution Steps') }, + { name: 'Output', pass: content.includes('## Output') }, + { name: 'Code Blocks', pass: content.includes('```') } + ] + }); +} + +// 检查 Specs 文件 +const specFiles = Glob(`${skillDir}/specs/*.md`); +for (const specFile of specFiles) { + const content = Read(specFile); + contentChecks.push({ + file: specFile.replace(skillDir + '/', ''), + checks: [ + { name: 'Has Content', pass: content.length > 200 }, + { name: 'Has Structure', pass: content.includes('##') }, + { name: 'No Empty Sections', pass: !content.match(/##[^#]+\n\n##/) } + ] + }); +} +``` + +### Step 3: 生成验证报告 + +```javascript +const report = { + skill_name: config.skill_name, + execution_mode: config.execution_mode, + generated_at: new Date().toISOString(), + + file_checks: { + total: fileCheckResults.length, + existing: fileCheckResults.filter(f => f.exists).length, + with_content: fileCheckResults.filter(f => f.hasContent).length, + with_todos: fileCheckResults.filter(f => f.hasTodo).length, + details: fileCheckResults + }, + + content_checks: { + files_checked: contentChecks.length, + all_passed: contentChecks.every(c => c.checks.every(ch => ch.pass)), + details: contentChecks + }, + + summary: { + status: calculateOverallStatus(fileCheckResults, contentChecks), + issues: collectIssues(fileCheckResults, contentChecks), + recommendations: generateRecommendations(fileCheckResults, contentChecks) + } +}; + +Write(`${workDir}/validation-report.json`, JSON.stringify(report, null, 2)); + +function calculateOverallStatus(fileResults, contentResults) { + const allFilesExist = fileResults.every(f => f.exists); + const allContentPassed = contentResults.every(c => c.checks.every(ch => ch.pass)); + + if (allFilesExist && allContentPassed) return 'PASS'; + if (allFilesExist) return 'REVIEW'; + return 'FAIL'; +} + +function collectIssues(fileResults, contentResults) { + const issues = []; + + fileResults.filter(f => !f.exists).forEach(f => { + issues.push({ type: 'ERROR', message: `文件缺失: ${f.file}` }); + }); + + fileResults.filter(f => f.hasTodo).forEach(f => { + issues.push({ type: 'WARNING', message: `包含 TODO: ${f.file}` }); + }); + + contentResults.forEach(c => { + c.checks.filter(ch => !ch.pass).forEach(ch => { + issues.push({ type: 'WARNING', message: `${c.file}: 缺少 ${ch.name}` }); + }); + }); + + return issues; +} + +function generateRecommendations(fileResults, contentResults) { + const recommendations = []; + + if (fileResults.some(f => f.hasTodo)) { + recommendations.push('替换所有 TODO 占位符为实际内容'); + } + + contentResults.forEach(c => { + if (c.checks.some(ch => !ch.pass)) { + recommendations.push(`完善 ${c.file} 的结构`); + } + }); + + return recommendations; +} +``` + +### Step 4: 生成 README.md + +```javascript +const readme = `# ${config.display_name} + +${config.description} + +## Quick Start + +### 触发词 + +${config.triggers.map(t => `- "${t}"`).join('\n')} + +### 执行模式 + +**${config.execution_mode === 'sequential' ? 'Sequential (顺序)' : 'Autonomous (自主)'}** + +${config.execution_mode === 'sequential' ? + `阶段按固定顺序执行:\n${config.sequential_config.phases.map((p, i) => + `${i + 1}. ${p.name}` + ).join('\n')}` : + `动作由编排器动态选择:\n${config.autonomous_config.actions.map(a => + `- ${a.name}: ${a.description || ''}` + ).join('\n')}`} + +## Usage + +\`\`\` +# 直接触发 +用户: ${config.triggers[0]} + +# 或使用 Skill 名称 +用户: /skill ${config.skill_name} +\`\`\` + +## Output + +- **格式**: ${config.output.format} +- **位置**: \`${config.output.location}\` +- **文件名**: \`${config.output.filename_pattern}\` + +## Directory Structure + +\`\`\` +.claude/skills/${config.skill_name}/ +├── SKILL.md # 入口文件 +├── phases/ # 执行阶段 +${config.execution_mode === 'sequential' ? + config.sequential_config.phases.map(p => `│ ├── ${p.id}.md`).join('\n') : + `│ ├── orchestrator.md +│ ├── state-schema.md +│ └── actions/ +${config.autonomous_config.actions.map(a => `│ ├── ${a.id}.md`).join('\n')}`} +├── specs/ # 规范文件 +│ ├── ${config.skill_name}-requirements.md +│ ├── quality-standards.md +${config.execution_mode === 'autonomous' ? '│ └── action-catalog.md' : ''} +└── templates/ # 模板文件 + └── agent-base.md +\`\`\` + +## Customization + +### 修改执行逻辑 + +编辑 \`phases/\` 目录下的阶段文件。 + +### 调整质量标准 + +编辑 \`specs/quality-standards.md\`。 + +### 添加新${config.execution_mode === 'sequential' ? '阶段' : '动作'} + +${config.execution_mode === 'sequential' ? + `1. 在 \`phases/\` 创建新的阶段文件 (如 \`03.5-new-step.md\`) +2. 更新 SKILL.md 的执行流程` : + `1. 在 \`phases/actions/\` 创建新的动作文件 +2. 更新 \`specs/action-catalog.md\` +3. 在 \`phases/orchestrator.md\` 添加选择逻辑`} + +## Related Documents + +- [设计规范](../_shared/SKILL-DESIGN-SPEC.md) +- [执行模式规范](specs/../../../skill-generator/specs/execution-modes.md) + +--- + +*Generated by skill-generator v1.0* +`; + +Write(`${skillDir}/README.md`, readme); +``` + +### Step 5: 输出最终结果 + +```javascript +const finalResult = { + skill_name: config.skill_name, + skill_path: skillDir, + execution_mode: config.execution_mode, + + generated_files: [ + 'SKILL.md', + 'README.md', + ...filesToCheck + ], + + validation: report.summary, + + next_steps: [ + '1. 审阅生成的文件结构', + '2. 替换 TODO 占位符', + '3. 根据实际需求调整阶段逻辑', + '4. 测试 Skill 执行流程', + '5. 更新触发词和描述' + ] +}; + +console.log('=== Skill 生成完成 ==='); +console.log(`路径: ${skillDir}`); +console.log(`模式: ${config.execution_mode}`); +console.log(`状态: ${report.summary.status}`); +console.log(''); +console.log('下一步:'); +finalResult.next_steps.forEach(s => console.log(s)); +``` + +## Output + +- `{workDir}/validation-report.json` - 验证报告 +- `{skillDir}/README.md` - 使用说明 + +## Completion + +Skill 生成流程完成。用户可以: + +1. 查看生成的 Skill 目录 +2. 根据验证报告修复问题 +3. 自定义执行逻辑 +4. 测试 Skill 功能 diff --git a/.claude/skills/skill-generator/specs/execution-modes.md b/.claude/skills/skill-generator/specs/execution-modes.md new file mode 100644 index 00000000..7e8d3e69 --- /dev/null +++ b/.claude/skills/skill-generator/specs/execution-modes.md @@ -0,0 +1,396 @@ +# Execution Modes Specification + +两种 Skill 执行模式的详细规范定义。 + +--- + +## 模式概览 + +| 特性 | Sequential (顺序) | Autonomous (自主) | +|------|-------------------|-------------------| +| 执行顺序 | 固定(数字前缀) | 动态(编排器决策) | +| 阶段依赖 | 强依赖 | 弱依赖/无依赖 | +| 状态管理 | 隐式(阶段产出) | 显式(状态文件) | +| 适用场景 | 流水线任务 | 交互式任务 | +| 复杂度 | 低 | 中-高 | +| 可扩展性 | 插入子阶段 | 添加新动作 | + +--- + +## Mode 1: Sequential (顺序模式) + +### 定义 + +阶段按固定顺序线性执行,每个阶段的输出作为下一阶段的输入。 + +### 目录结构 + +``` +phases/ +├── 01-{first-step}.md +├── 02-{second-step}.md +├── 02.5-{sub-step}.md # 可选:子阶段 +├── 03-{third-step}.md +└── ... +``` + +### 执行流程 + +``` +┌─────────┐ ┌─────────┐ ┌─────────┐ +│Phase 01 │────▶│Phase 02 │────▶│Phase 03 │────▶ ... +└─────────┘ └─────────┘ └─────────┘ + │ │ │ + ▼ ▼ ▼ + output1.json output2.md output3.md +``` + +### Phase 文件规范 + +```markdown +# Phase N: {阶段名称} + +{一句话描述} + +## Objective + +{详细目标} + +## Input + +- 依赖: {上一阶段产出} +- 配置: {配置文件} + +## Execution Steps + +### Step 1: {步骤} +{执行代码或说明} + +### Step 2: {步骤} +{执行代码或说明} + +## Output + +- **File**: `{输出文件}` +- **Format**: {JSON/Markdown} + +## Next Phase + +→ [Phase N+1: xxx](0N+1-xxx.md) +``` + +### 适用场景 + +- **文档生成**: 收集 → 分析 → 组装 → 优化 +- **代码分析**: 扫描 → 解析 → 报告 +- **数据处理**: 提取 → 转换 → 加载 + +### 优点 + +- 逻辑清晰,易于理解 +- 调试简单,可逐阶段验证 +- 输出可预测 + +### 缺点 + +- 灵活性低 +- 难以处理分支逻辑 +- 用户交互受限 + +--- + +## Mode 2: Autonomous (自主模式) + +### 定义 + +无固定执行顺序,由编排器 (Orchestrator) 根据当前状态动态选择下一个动作。 + +### 目录结构 + +``` +phases/ +├── orchestrator.md # 编排器:核心决策逻辑 +├── state-schema.md # 状态结构定义 +└── actions/ # 独立动作(无顺序) + ├── action-{a}.md + ├── action-{b}.md + ├── action-{c}.md + └── ... +``` + +### 核心组件 + +#### 1. Orchestrator (编排器) + +```markdown +# Orchestrator + +## Role + +根据当前状态选择并执行下一个动作。 + +## State Reading + +读取状态文件: `{workDir}/state.json` + +## Decision Logic + +```javascript +function selectNextAction(state) { + // 1. 检查终止条件 + if (state.status === 'completed') return null; + if (state.error_count > MAX_RETRIES) return 'action-abort'; + + // 2. 根据状态选择动作 + if (!state.initialized) return 'action-init'; + if (state.pending_items.length > 0) return 'action-process'; + if (state.needs_review) return 'action-review'; + + // 3. 默认动作 + return 'action-complete'; +} +``` + +## Execution Loop + +``` +while (true) { + state = readState(); + action = selectNextAction(state); + if (!action) break; + + result = executeAction(action, state); + updateState(result); +} +``` +``` + +#### 2. State Schema (状态结构) + +```markdown +# State Schema + +## 状态文件 + +位置: `{workDir}/state.json` + +## 结构定义 + +```typescript +interface SkillState { + // 元信息 + skill_name: string; + started_at: string; + updated_at: string; + + // 执行状态 + status: 'pending' | 'running' | 'completed' | 'failed'; + current_action: string | null; + completed_actions: string[]; + + // 业务数据 + context: Record; + pending_items: any[]; + results: Record; + + // 错误追踪 + errors: Array<{ + action: string; + message: string; + timestamp: string; + }>; + error_count: number; +} +``` + +## 初始状态 + +```json +{ + "skill_name": "{skill-name}", + "started_at": "{ISO8601}", + "updated_at": "{ISO8601}", + "status": "pending", + "current_action": null, + "completed_actions": [], + "context": {}, + "pending_items": [], + "results": {}, + "errors": [], + "error_count": 0 +} +``` +``` + +#### 3. Action (动作) + +```markdown +# Action: {action-name} + +## Purpose + +{动作目的} + +## Preconditions + +- [ ] 条件1 +- [ ] 条件2 + +## Execution + +{执行逻辑} + +## State Updates + +```javascript +return { + completed_actions: [...state.completed_actions, 'action-name'], + results: { + ...state.results, + action_name: { /* 结果 */ } + }, + // 其他状态更新 +}; +``` + +## Next Actions (Hints) + +- 成功时: `action-{next}` +- 失败时: `action-retry` 或 `action-abort` +``` + +### 执行流程 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Orchestrator Loop │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ +│ │ │ Read │────▶│ Select │────▶│ Execute │ │ │ +│ │ │ State │ │ Action │ │ Action │ │ │ +│ │ └──────────┘ └──────────┘ └──────────┘ │ │ +│ │ ▲ │ │ │ +│ │ │ ▼ │ │ +│ │ │ ┌──────────┐ │ │ +│ │ └───────────│ Update │◀────────────────────────┘ │ +│ │ │ State │ │ +│ │ └──────────┘ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────┐ │ +│ │ Termination? │ │ +│ │ - completed │ │ +│ │ - max_retries │ │ +│ │ - user_abort │ │ +│ └──────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 动作目录 (Action Catalog) + +在 `specs/action-catalog.md` 中定义: + +```markdown +# Action Catalog + +## Available Actions + +| Action | Purpose | Preconditions | Effects | +|--------|---------|---------------|---------| +| action-init | 初始化状态 | status=pending | status=running | +| action-process | 处理待办项 | pending_items.length>0 | pending_items-- | +| action-review | 用户审核 | needs_review=true | needs_review=false | +| action-complete | 完成任务 | pending_items.length=0 | status=completed | +| action-abort | 中止任务 | error_count>MAX | status=failed | + +## Action Dependencies Graph + +```mermaid +graph TD + INIT[action-init] --> PROCESS[action-process] + PROCESS --> PROCESS + PROCESS --> REVIEW[action-review] + REVIEW --> PROCESS + REVIEW --> COMPLETE[action-complete] + PROCESS --> ABORT[action-abort] +``` +``` + +### 适用场景 + +- **交互式任务**: 问答、对话、表单填写 +- **状态机任务**: Issue 管理、工作流审批 +- **探索式任务**: 调试、诊断、搜索 + +### 优点 + +- 高度灵活,适应动态需求 +- 支持复杂分支逻辑 +- 易于扩展新动作 + +### 缺点 + +- 复杂度高 +- 状态管理开销 +- 调试难度大 + +--- + +## 模式选择指南 + +### 决策流程 + +``` +用户需求分析 + │ + ▼ +┌────────────────────────────┐ +│ 阶段间是否有强依赖关系? │ +└────────────────────────────┘ + │ + ├── 是 → Sequential + │ + └── 否 → 继续判断 + │ + ▼ + ┌────────────────────────────┐ + │ 是否需要动态响应用户意图? │ + └────────────────────────────┘ + │ + ├── 是 → Autonomous + │ + └── 否 → Sequential +``` + +### 快速判断表 + +| 问题 | Sequential | Autonomous | +|------|------------|------------| +| 输出结构是否固定? | ✓ | ✗ | +| 是否需要用户多轮交互? | ✗ | ✓ | +| 阶段是否可以跳过/重复? | ✗ | ✓ | +| 是否有复杂分支逻辑? | ✗ | ✓ | +| 调试是否需要简单? | ✓ | ✗ | + +--- + +## 混合模式 + +某些复杂 Skill 可能需要混合使用两种模式: + +``` +phases/ +├── 01-init.md # Sequential: 初始化 +├── 02-orchestrator.md # Autonomous: 核心交互循环 +│ └── actions/ +│ ├── action-a.md +│ └── action-b.md +└── 03-finalize.md # Sequential: 收尾 +``` + +**适用场景**: +- 初始化和收尾固定,中间交互灵活 +- 多阶段任务,某阶段需要动态决策 diff --git a/.claude/skills/skill-generator/specs/skill-requirements.md b/.claude/skills/skill-generator/specs/skill-requirements.md new file mode 100644 index 00000000..c37573fd --- /dev/null +++ b/.claude/skills/skill-generator/specs/skill-requirements.md @@ -0,0 +1,344 @@ +# Skill Requirements Specification + +新 Skill 创建的需求收集规范。 + +--- + +## 必需信息 + +### 1. 基本信息 + +| 字段 | 类型 | 必需 | 说明 | +|------|------|------|------| +| `skill_name` | string | ✓ | Skill 标识符(小写-连字符) | +| `display_name` | string | ✓ | 显示名称 | +| `description` | string | ✓ | 一句话描述 | +| `triggers` | string[] | ✓ | 触发关键词列表 | + +### 2. 执行模式 + +| 字段 | 类型 | 必需 | 说明 | +|------|------|------|------| +| `execution_mode` | enum | ✓ | `sequential` \| `autonomous` | +| `phase_count` | number | 条件 | Sequential 模式下的阶段数 | +| `action_count` | number | 条件 | Autonomous 模式下的动作数 | + +### 3. 工具依赖 + +| 字段 | 类型 | 必需 | 说明 | +|------|------|------|------| +| `allowed_tools` | string[] | ✓ | 允许使用的工具列表 | +| `mcp_tools` | string[] | 可选 | 需要的 MCP 工具 | + +### 4. 输出配置 + +| 字段 | 类型 | 必需 | 说明 | +|------|------|------|------| +| `output_format` | enum | ✓ | `markdown` \| `html` \| `json` | +| `output_location` | string | ✓ | 输出目录模式 | + +--- + +## 配置文件结构 + +```typescript +interface SkillConfig { + // 基本信息 + skill_name: string; // "my-skill" + display_name: string; // "My Skill" + description: string; // "一句话描述" + triggers: string[]; // ["keyword1", "keyword2"] + + // 执行模式 + execution_mode: 'sequential' | 'autonomous'; + + // Sequential 模式配置 + sequential_config?: { + phases: Array<{ + id: string; // "01-init" + name: string; // "Initialization" + description: string; // "收集初始配置" + input: string[]; // 输入依赖 + output: string; // 输出文件 + }>; + }; + + // Autonomous 模式配置 + autonomous_config?: { + state_schema: { + fields: Array<{ + name: string; + type: string; + description: string; + }>; + }; + actions: Array<{ + id: string; // "action-init" + name: string; // "Initialize" + description: string; // "初始化状态" + preconditions: string[]; // 前置条件 + effects: string[]; // 执行效果 + }>; + termination_conditions: string[]; + }; + + // 工具依赖 + allowed_tools: string[]; // ["Task", "Read", "Write", ...] + mcp_tools?: string[]; // ["mcp__chrome__*"] + + // 输出配置 + output: { + format: 'markdown' | 'html' | 'json'; + location: string; // ".workflow/.scratchpad/{skill}-{timestamp}" + filename_pattern: string; // "{name}-output.{ext}" + }; + + // 质量配置 + quality?: { + dimensions: string[]; // ["completeness", "consistency", ...] + pass_threshold: number; // 80 + }; + + // 元数据 + created_at: string; + version: string; +} +``` + +--- + +## 需求收集问题 + +### Phase 1: 基本信息 + +```javascript +AskUserQuestion({ + questions: [ + { + question: "Skill 的名称是什么?(英文,小写-连字符格式)", + header: "Skill 名称", + multiSelect: false, + options: [ + { label: "自动生成", description: "根据描述自动生成名称" }, + { label: "手动输入", description: "输入自定义名称" } + ] + }, + { + question: "Skill 的主要用途是什么?", + header: "用途类型", + multiSelect: false, + options: [ + { label: "文档生成", description: "生成 Markdown/HTML 文档" }, + { label: "代码分析", description: "分析代码结构、质量、安全" }, + { label: "交互管理", description: "管理 Issue、任务、工作流" }, + { label: "数据处理", description: "ETL、转换、报告生成" }, + { label: "自定义", description: "其他用途" } + ] + } + ] +}); +``` + +### Phase 2: 执行模式 + +```javascript +AskUserQuestion({ + questions: [ + { + question: "选择执行模式:", + header: "执行模式", + multiSelect: false, + options: [ + { + label: "Sequential (顺序)", + description: "阶段按固定顺序执行,适合流水线任务(推荐)" + }, + { + label: "Autonomous (自主)", + description: "动态选择执行路径,适合交互式任务" + }, + { + label: "Hybrid (混合)", + description: "初始化和收尾固定,中间交互灵活" + } + ] + } + ] +}); +``` + +### Phase 3: 阶段/动作定义 + +#### Sequential 模式 + +```javascript +AskUserQuestion({ + questions: [ + { + question: "需要多少个执行阶段?", + header: "阶段数量", + multiSelect: false, + options: [ + { label: "3 阶段", description: "简单: 收集 → 处理 → 输出" }, + { label: "5 阶段", description: "标准: 收集 → 探索 → 分析 → 组装 → 验证" }, + { label: "7 阶段", description: "完整: 包含并行处理和迭代优化" }, + { label: "自定义", description: "手动指定阶段" } + ] + } + ] +}); +``` + +#### Autonomous 模式 + +```javascript +AskUserQuestion({ + questions: [ + { + question: "核心动作有哪些?", + header: "动作定义", + multiSelect: true, + options: [ + { label: "初始化 (init)", description: "设置初始状态" }, + { label: "列表 (list)", description: "显示当前项目" }, + { label: "创建 (create)", description: "创建新项目" }, + { label: "编辑 (edit)", description: "修改现有项目" }, + { label: "删除 (delete)", description: "删除项目" }, + { label: "完成 (complete)", description: "完成任务" } + ] + } + ] +}); +``` + +### Phase 4: 工具依赖 + +```javascript +AskUserQuestion({ + questions: [ + { + question: "需要哪些工具?", + header: "工具选择", + multiSelect: true, + options: [ + { label: "基础工具", description: "Task, Read, Write, Glob, Grep, Bash" }, + { label: "用户交互", description: "AskUserQuestion" }, + { label: "Chrome 截图", description: "mcp__chrome__*" }, + { label: "外部搜索", description: "mcp__exa__search" } + ] + } + ] +}); +``` + +--- + +## 验证规则 + +### 名称验证 + +```javascript +function validateSkillName(name) { + const rules = [ + { test: /^[a-z][a-z0-9-]*$/, msg: "必须以小写字母开头,只包含小写字母、数字、连字符" }, + { test: /^.{3,30}$/, msg: "长度 3-30 字符" }, + { test: /^(?!.*--)/, msg: "不能有连续连字符" }, + { test: /[^-]$/, msg: "不能以连字符结尾" } + ]; + + for (const rule of rules) { + if (!rule.test.test(name)) { + return { valid: false, error: rule.msg }; + } + } + return { valid: true }; +} +``` + +### 配置验证 + +```javascript +function validateSkillConfig(config) { + const errors = []; + + // 必需字段 + if (!config.skill_name) errors.push("缺少 skill_name"); + if (!config.description) errors.push("缺少 description"); + if (!config.execution_mode) errors.push("缺少 execution_mode"); + + // 模式特定验证 + if (config.execution_mode === 'sequential') { + if (!config.sequential_config?.phases?.length) { + errors.push("Sequential 模式需要定义 phases"); + } + } else if (config.execution_mode === 'autonomous') { + if (!config.autonomous_config?.actions?.length) { + errors.push("Autonomous 模式需要定义 actions"); + } + } + + return { valid: errors.length === 0, errors }; +} +``` + +--- + +## 示例配置 + +### Sequential 模式示例 + +```json +{ + "skill_name": "api-docs-generator", + "display_name": "API Docs Generator", + "description": "Generate API documentation from source code", + "triggers": ["generate api docs", "api documentation"], + "execution_mode": "sequential", + "sequential_config": { + "phases": [ + { "id": "01-scan", "name": "Code Scanning", "output": "endpoints.json" }, + { "id": "02-parse", "name": "Schema Parsing", "output": "schemas.json" }, + { "id": "03-generate", "name": "Doc Generation", "output": "api-docs.md" } + ] + }, + "allowed_tools": ["Task", "Read", "Write", "Glob", "Grep", "Bash"], + "output": { + "format": "markdown", + "location": ".workflow/.scratchpad/api-docs-{timestamp}", + "filename_pattern": "{name}-api-docs.md" + } +} +``` + +### Autonomous 模式示例 + +```json +{ + "skill_name": "task-manager", + "display_name": "Task Manager", + "description": "Interactive task management with CRUD operations", + "triggers": ["manage tasks", "task list", "create task"], + "execution_mode": "autonomous", + "autonomous_config": { + "state_schema": { + "fields": [ + { "name": "tasks", "type": "Task[]", "description": "任务列表" }, + { "name": "current_view", "type": "string", "description": "当前视图" } + ] + }, + "actions": [ + { "id": "action-list", "name": "List Tasks", "preconditions": [], "effects": ["显示任务列表"] }, + { "id": "action-create", "name": "Create Task", "preconditions": [], "effects": ["添加新任务"] }, + { "id": "action-edit", "name": "Edit Task", "preconditions": ["task_selected"], "effects": ["更新任务"] }, + { "id": "action-delete", "name": "Delete Task", "preconditions": ["task_selected"], "effects": ["删除任务"] } + ], + "termination_conditions": ["user_exit", "error_limit"] + }, + "allowed_tools": ["Task", "AskUserQuestion", "Read", "Write"], + "output": { + "format": "json", + "location": ".workflow/.scratchpad/tasks", + "filename_pattern": "tasks.json" + } +} +``` diff --git a/.claude/skills/skill-generator/templates/autonomous-action.md b/.claude/skills/skill-generator/templates/autonomous-action.md new file mode 100644 index 00000000..1c85ef84 --- /dev/null +++ b/.claude/skills/skill-generator/templates/autonomous-action.md @@ -0,0 +1,506 @@ +# Autonomous Action Template + +自主模式动作文件的模板。 + +## 模板结构 + +```markdown +# Action: {{action_name}} + +{{action_description}} + +## Purpose + +{{purpose}} + +## Preconditions + +{{preconditions_list}} + +## Execution + +\`\`\`javascript +async function execute(state) { + {{execution_code}} +} +\`\`\` + +## State Updates + +\`\`\`javascript +return { + stateUpdates: { + {{state_updates}} + } +}; +\`\`\` + +## Error Handling + +| Error Type | Recovery | +|------------|----------| +{{error_handling_table}} + +## Next Actions (Hints) + +{{next_actions_hints}} +``` + +## 变量说明 + +| 变量 | 说明 | +|------|------| +| `{{action_name}}` | 动作名称 | +| `{{action_description}}` | 动作描述 | +| `{{purpose}}` | 详细目的 | +| `{{preconditions_list}}` | 前置条件列表 | +| `{{execution_code}}` | 执行代码 | +| `{{state_updates}}` | 状态更新 | +| `{{error_handling_table}}` | 错误处理表格 | +| `{{next_actions_hints}}` | 后续动作提示 | + +## 动作类型模板 + +### 1. 初始化动作 (Init) + +```markdown +# Action: Initialize + +初始化 Skill 执行状态。 + +## Purpose + +设置初始状态,准备执行环境。 + +## Preconditions + +- [ ] state.status === 'pending' + +## Execution + +\`\`\`javascript +async function execute(state) { + // 1. 创建工作目录 + Bash(\`mkdir -p "\${workDir}"\`); + + // 2. 初始化数据 + const initialData = { + items: [], + metadata: {} + }; + + // 3. 返回状态更新 + return { + stateUpdates: { + status: 'running', + context: initialData + } + }; +} +\`\`\` + +## State Updates + +\`\`\`javascript +return { + stateUpdates: { + status: 'running', + started_at: new Date().toISOString(), + context: { /* 初始数据 */ } + } +}; +\`\`\` + +## Next Actions + +- 成功: 进入主处理循环 +- 失败: action-abort +``` + +### 2. 列表动作 (List) + +```markdown +# Action: List Items + +显示当前项目列表。 + +## Purpose + +展示所有项目供用户查看和选择。 + +## Preconditions + +- [ ] state.status === 'running' + +## Execution + +\`\`\`javascript +async function execute(state) { + const items = state.context.items || []; + + if (items.length === 0) { + console.log('暂无项目'); + } else { + console.log('项目列表:'); + items.forEach((item, i) => { + console.log(\`\${i + 1}. \${item.name} - \${item.status}\`); + }); + } + + return { + stateUpdates: { + last_action: 'list', + current_view: 'list' + } + }; +} +\`\`\` + +## State Updates + +\`\`\`javascript +return { + stateUpdates: { + current_view: 'list', + last_viewed_at: new Date().toISOString() + } +}; +\`\`\` + +## Next Actions + +- 用户选择创建: action-create +- 用户选择编辑: action-edit +- 用户退出: action-complete +``` + +### 3. 创建动作 (Create) + +```markdown +# Action: Create Item + +创建新项目。 + +## Purpose + +引导用户创建新项目。 + +## Preconditions + +- [ ] state.status === 'running' + +## Execution + +\`\`\`javascript +async function execute(state) { + // 1. 收集信息 + const input = await AskUserQuestion({ + questions: [{ + question: "请输入项目名称:", + header: "名称", + multiSelect: false, + options: [ + { label: "手动输入", description: "输入自定义名称" } + ] + }] + }); + + // 2. 创建项目 + const newItem = { + id: Date.now().toString(), + name: input["名称"], + status: 'pending', + created_at: new Date().toISOString() + }; + + // 3. 返回状态更新 + return { + stateUpdates: { + context: { + ...state.context, + items: [...(state.context.items || []), newItem] + }, + last_created_id: newItem.id + } + }; +} +\`\`\` + +## State Updates + +\`\`\`javascript +return { + stateUpdates: { + 'context.items': [...items, newItem], + last_action: 'create', + last_created_id: newItem.id + } +}; +\`\`\` + +## Next Actions + +- 继续创建: action-create +- 返回列表: action-list +``` + +### 4. 编辑动作 (Edit) + +```markdown +# Action: Edit Item + +编辑现有项目。 + +## Purpose + +修改已存在的项目。 + +## Preconditions + +- [ ] state.status === 'running' +- [ ] state.selected_item_id !== null + +## Execution + +\`\`\`javascript +async function execute(state) { + const itemId = state.selected_item_id; + const items = state.context.items || []; + const item = items.find(i => i.id === itemId); + + if (!item) { + throw new Error(\`Item not found: \${itemId}\`); + } + + // 1. 显示当前值 + console.log(\`当前名称: \${item.name}\`); + + // 2. 收集新值 + const input = await AskUserQuestion({ + questions: [{ + question: "请输入新名称(留空保持不变):", + header: "新名称", + multiSelect: false, + options: [ + { label: "保持不变", description: \`当前: \${item.name}\` }, + { label: "手动输入", description: "输入新名称" } + ] + }] + }); + + // 3. 更新项目 + const updatedItems = items.map(i => + i.id === itemId + ? { ...i, name: input["新名称"] || i.name, updated_at: new Date().toISOString() } + : i + ); + + return { + stateUpdates: { + context: { ...state.context, items: updatedItems }, + selected_item_id: null + } + }; +} +\`\`\` + +## State Updates + +\`\`\`javascript +return { + stateUpdates: { + 'context.items': updatedItems, + selected_item_id: null, + last_action: 'edit' + } +}; +\`\`\` + +## Next Actions + +- 返回列表: action-list +``` + +### 5. 删除动作 (Delete) + +```markdown +# Action: Delete Item + +删除项目。 + +## Purpose + +从列表中移除项目。 + +## Preconditions + +- [ ] state.status === 'running' +- [ ] state.selected_item_id !== null + +## Execution + +\`\`\`javascript +async function execute(state) { + const itemId = state.selected_item_id; + const items = state.context.items || []; + + // 1. 确认删除 + const confirm = await AskUserQuestion({ + questions: [{ + question: "确认删除此项目?", + header: "确认", + multiSelect: false, + options: [ + { label: "确认删除", description: "不可恢复" }, + { label: "取消", description: "返回列表" } + ] + }] + }); + + if (confirm["确认"] === "取消") { + return { stateUpdates: { selected_item_id: null } }; + } + + // 2. 执行删除 + const updatedItems = items.filter(i => i.id !== itemId); + + return { + stateUpdates: { + context: { ...state.context, items: updatedItems }, + selected_item_id: null + } + }; +} +\`\`\` + +## State Updates + +\`\`\`javascript +return { + stateUpdates: { + 'context.items': filteredItems, + selected_item_id: null, + last_action: 'delete' + } +}; +\`\`\` + +## Next Actions + +- 返回列表: action-list +``` + +### 6. 完成动作 (Complete) + +```markdown +# Action: Complete + +完成任务并退出。 + +## Purpose + +保存最终状态,结束 Skill 执行。 + +## Preconditions + +- [ ] state.status === 'running' + +## Execution + +\`\`\`javascript +async function execute(state) { + // 1. 保存最终数据 + Write(\`\${workDir}/final-output.json\`, JSON.stringify(state.context, null, 2)); + + // 2. 生成摘要 + const summary = { + total_items: state.context.items?.length || 0, + duration: Date.now() - new Date(state.started_at).getTime(), + actions_executed: state.completed_actions.length + }; + + console.log('任务完成!'); + console.log(\`处理项目: \${summary.total_items}\`); + console.log(\`执行动作: \${summary.actions_executed}\`); + + return { + stateUpdates: { + status: 'completed', + summary: summary + } + }; +} +\`\`\` + +## State Updates + +\`\`\`javascript +return { + stateUpdates: { + status: 'completed', + completed_at: new Date().toISOString(), + summary: { /* 统计信息 */ } + } +}; +\`\`\` + +## Next Actions + +- 无(终止状态) +``` + +## 生成函数 + +```javascript +function generateAction(actionConfig, skillConfig) { + return `# Action: ${actionConfig.name} + +${actionConfig.description || `执行 ${actionConfig.name} 操作`} + +## Purpose + +${actionConfig.purpose || 'TODO: 描述此动作的详细目的'} + +## Preconditions + +${actionConfig.preconditions?.map(p => `- [ ] ${p}`).join('\n') || '- [ ] 无特殊前置条件'} + +## Execution + +\`\`\`javascript +async function execute(state) { + // TODO: 实现动作逻辑 + + return { + stateUpdates: { + completed_actions: [...state.completed_actions, '${actionConfig.id}'] + } + }; +} +\`\`\` + +## State Updates + +\`\`\`javascript +return { + stateUpdates: { + // TODO: 定义状态更新 +${actionConfig.effects?.map(e => ` // Effect: ${e}`).join('\n') || ''} + } +}; +\`\`\` + +## Error Handling + +| Error Type | Recovery | +|------------|----------| +| 数据验证失败 | 返回错误,不更新状态 | +| 执行异常 | 记录错误,增加 error_count | + +## Next Actions (Hints) + +- 成功: 由编排器根据状态决定 +- 失败: 重试或 action-abort +`; +} +``` diff --git a/.claude/skills/skill-generator/templates/autonomous-orchestrator.md b/.claude/skills/skill-generator/templates/autonomous-orchestrator.md new file mode 100644 index 00000000..4b8544f7 --- /dev/null +++ b/.claude/skills/skill-generator/templates/autonomous-orchestrator.md @@ -0,0 +1,276 @@ +# Autonomous Orchestrator Template + +自主模式编排器的模板。 + +## 模板结构 + +```markdown +# Orchestrator + +## Role + +根据当前状态选择并执行下一个动作。 + +## State Management + +### 读取状态 + +\`\`\`javascript +const state = JSON.parse(Read(`${workDir}/state.json`)); +\`\`\` + +### 更新状态 + +\`\`\`javascript +function updateState(updates) { + const state = JSON.parse(Read(`${workDir}/state.json`)); + const newState = { + ...state, + ...updates, + updated_at: new Date().toISOString() + }; + Write(`${workDir}/state.json`, JSON.stringify(newState, null, 2)); + return newState; +} +\`\`\` + +## Decision Logic + +\`\`\`javascript +function selectNextAction(state) { + // 1. 终止条件检查 + {{termination_checks}} + + // 2. 错误限制检查 + if (state.error_count >= 3) { + return 'action-abort'; + } + + // 3. 动作选择逻辑 + {{action_selection_logic}} + + // 4. 默认完成 + return 'action-complete'; +} +\`\`\` + +## Execution Loop + +\`\`\`javascript +async function runOrchestrator() { + console.log('=== Orchestrator Started ==='); + + let iteration = 0; + const MAX_ITERATIONS = 100; + + while (iteration < MAX_ITERATIONS) { + iteration++; + + // 1. 读取当前状态 + const state = JSON.parse(Read(`${workDir}/state.json`)); + console.log(`[Iteration ${iteration}] Status: ${state.status}`); + + // 2. 选择下一个动作 + const actionId = selectNextAction(state); + + if (!actionId) { + console.log('No action selected, terminating.'); + break; + } + + console.log(`[Iteration ${iteration}] Executing: ${actionId}`); + + // 3. 更新状态:当前动作 + updateState({ current_action: actionId }); + + // 4. 执行动作 + try { + const actionPrompt = Read(`phases/actions/${actionId}.md`); + + const result = await Task({ + subagent_type: 'universal-executor', + run_in_background: false, + prompt: \` +[STATE] +\${JSON.stringify(state, null, 2)} + +[ACTION] +\${actionPrompt} + +[RETURN] +Return JSON with stateUpdates field. +\` + }); + + const actionResult = JSON.parse(result); + + // 5. 更新状态:动作完成 + updateState({ + current_action: null, + completed_actions: [...state.completed_actions, actionId], + ...actionResult.stateUpdates + }); + + } catch (error) { + // 错误处理 + updateState({ + current_action: null, + errors: [...state.errors, { + action: actionId, + message: error.message, + timestamp: new Date().toISOString() + }], + error_count: state.error_count + 1 + }); + } + } + + console.log('=== Orchestrator Finished ==='); +} +\`\`\` + +## Action Catalog + +| Action | Purpose | Preconditions | +|--------|---------|---------------| +{{action_catalog_table}} + +## Termination Conditions + +{{termination_conditions_list}} + +## Error Recovery + +| Error Type | Recovery Strategy | +|------------|-------------------| +| 动作执行失败 | 重试最多 3 次 | +| 状态不一致 | 回滚到上一个稳定状态 | +| 用户中止 | 保存当前状态,允许恢复 | +``` + +## 变量说明 + +| 变量 | 说明 | +|------|------| +| `{{termination_checks}}` | 终止条件检查代码 | +| `{{action_selection_logic}}` | 动作选择逻辑代码 | +| `{{action_catalog_table}}` | 动作目录表格 | +| `{{termination_conditions_list}}` | 终止条件列表 | + +## 生成函数 + +```javascript +function generateOrchestrator(config) { + const actions = config.autonomous_config.actions; + const terminations = config.autonomous_config.termination_conditions || []; + + // 生成终止条件检查 + const terminationChecks = terminations.map(t => { + const checks = { + 'user_exit': 'if (state.status === "user_exit") return null;', + 'error_limit': 'if (state.error_count >= 3) return "action-abort";', + 'task_completed': 'if (state.status === "completed") return null;', + 'max_iterations': 'if (state.iteration_count >= 100) return "action-abort";' + }; + return checks[t] || `if (state.${t}) return null;`; + }).join('\n '); + + // 生成动作选择逻辑 + const actionSelectionLogic = actions.map(action => { + if (!action.preconditions?.length) { + return `// ${action.name}: 无前置条件,需要手动添加选择逻辑`; + } + const conditions = action.preconditions.map(p => `state.${p}`).join(' && '); + return `if (${conditions}) return '${action.id}';`; + }).join('\n '); + + // 生成动作目录表格 + const actionCatalogTable = actions.map(a => + `| [${a.id}](actions/${a.id}.md) | ${a.description || a.name} | ${a.preconditions?.join(', ') || '-'} |` + ).join('\n'); + + // 生成终止条件列表 + const terminationConditionsList = terminations.map(t => `- ${t}`).join('\n'); + + return template + .replace('{{termination_checks}}', terminationChecks) + .replace('{{action_selection_logic}}', actionSelectionLogic) + .replace('{{action_catalog_table}}', actionCatalogTable) + .replace('{{termination_conditions_list}}', terminationConditionsList); +} +``` + +## 编排策略 + +### 1. 优先级策略 + +按预定义优先级选择动作: + +```javascript +const PRIORITY = ['action-init', 'action-process', 'action-review', 'action-complete']; + +function selectByPriority(state, availableActions) { + for (const actionId of PRIORITY) { + if (availableActions.includes(actionId) && checkPreconditions(actionId, state)) { + return actionId; + } + } + return null; +} +``` + +### 2. 用户驱动策略 + +询问用户选择下一个动作: + +```javascript +async function selectByUser(state, availableActions) { + const response = await AskUserQuestion({ + questions: [{ + question: "选择下一个操作:", + header: "操作", + multiSelect: false, + options: availableActions.map(a => ({ + label: a.name, + description: a.description + })) + }] + }); + + return availableActions.find(a => a.name === response["操作"])?.id; +} +``` + +### 3. 状态驱动策略 + +完全基于状态自动决策: + +```javascript +function selectByState(state) { + // 初始化 + if (state.status === 'pending') return 'action-init'; + + // 有待处理项 + if (state.pending_items?.length > 0) return 'action-process'; + + // 需要审核 + if (state.needs_review) return 'action-review'; + + // 完成 + return 'action-complete'; +} +``` + +## 状态机示例 + +```mermaid +stateDiagram-v2 + [*] --> pending + pending --> running: action-init + running --> running: action-process + running --> running: action-review + running --> completed: action-complete + running --> failed: action-abort + completed --> [*] + failed --> [*] +``` diff --git a/.claude/skills/skill-generator/templates/sequential-phase.md b/.claude/skills/skill-generator/templates/sequential-phase.md new file mode 100644 index 00000000..3a19649f --- /dev/null +++ b/.claude/skills/skill-generator/templates/sequential-phase.md @@ -0,0 +1,393 @@ +# Sequential Phase Template + +顺序模式 Phase 文件的模板。 + +## 模板结构 + +```markdown +# Phase {{phase_number}}: {{phase_name}} + +{{phase_description}} + +## Objective + +{{objectives}} + +## Input + +- 依赖: `{{input_dependency}}` +- 配置: `{workDir}/skill-config.json` + +## Execution Steps + +### Step 1: {{step_1_name}} + +\`\`\`javascript +{{step_1_code}} +\`\`\` + +### Step 2: {{step_2_name}} + +\`\`\`javascript +{{step_2_code}} +\`\`\` + +### Step 3: {{step_3_name}} + +\`\`\`javascript +{{step_3_code}} +\`\`\` + +## Output + +- **File**: `{{output_file}}` +- **Format**: {{output_format}} + +## Quality Checklist + +{{quality_checklist}} + +## Next Phase + +{{next_phase_link}} +``` + +## 变量说明 + +| 变量 | 说明 | +|------|------| +| `{{phase_number}}` | 阶段序号 (1, 2, 3...) | +| `{{phase_name}}` | 阶段名称 | +| `{{phase_description}}` | 一句话描述 | +| `{{objectives}}` | 目标列表 | +| `{{input_dependency}}` | 输入依赖文件 | +| `{{step_N_name}}` | 步骤名称 | +| `{{step_N_code}}` | 步骤代码 | +| `{{output_file}}` | 输出文件名 | +| `{{output_format}}` | 输出格式 | +| `{{quality_checklist}}` | 质量检查项 | +| `{{next_phase_link}}` | 下一阶段链接 | + +## Phase 类型模板 + +### 1. 收集型 Phase (Collection) + +```markdown +# Phase 1: Requirements Collection + +收集用户需求和项目配置。 + +## Objective + +- 收集用户输入 +- 自动检测项目信息 +- 生成配置文件 + +## Execution Steps + +### Step 1: 用户交互 + +\`\`\`javascript +const userInput = await AskUserQuestion({ + questions: [ + { + question: "请选择...", + header: "选项", + multiSelect: false, + options: [ + { label: "选项A", description: "..." }, + { label: "选项B", description: "..." } + ] + } + ] +}); +\`\`\` + +### Step 2: 自动检测 + +\`\`\`javascript +// 检测项目信息 +const packageJson = JSON.parse(Read('package.json')); +const projectName = packageJson.name; +\`\`\` + +### Step 3: 生成配置 + +\`\`\`javascript +const config = { + name: projectName, + userChoice: userInput["选项"], + // ... +}; + +Write(`${workDir}/config.json`, JSON.stringify(config, null, 2)); +\`\`\` + +## Output + +- **File**: `config.json` +- **Format**: JSON +``` + +### 2. 分析型 Phase (Analysis) + +```markdown +# Phase 2: Deep Analysis + +深度分析代码结构。 + +## Objective + +- 扫描代码文件 +- 提取关键信息 +- 生成分析报告 + +## Execution Steps + +### Step 1: 文件扫描 + +\`\`\`javascript +const files = Glob('src/**/*.ts'); +\`\`\` + +### Step 2: 内容分析 + +\`\`\`javascript +const analysisResults = []; +for (const file of files) { + const content = Read(file); + // 分析逻辑 + analysisResults.push({ file, /* 分析结果 */ }); +} +\`\`\` + +### Step 3: 生成报告 + +\`\`\`javascript +Write(`${workDir}/analysis.json`, JSON.stringify(analysisResults, null, 2)); +\`\`\` + +## Output + +- **File**: `analysis.json` +- **Format**: JSON +``` + +### 3. 并行型 Phase (Parallel) + +```markdown +# Phase 3: Parallel Processing + +并行处理多个子任务。 + +## Objective + +- 启动多个 Agent 并行执行 +- 收集各 Agent 结果 +- 合并输出 + +## Execution Steps + +### Step 1: 准备任务 + +\`\`\`javascript +const tasks = [ + { id: 'task-a', prompt: '...' }, + { id: 'task-b', prompt: '...' }, + { id: 'task-c', prompt: '...' } +]; +\`\`\` + +### Step 2: 并行执行 + +\`\`\`javascript +const results = await Promise.all( + tasks.map(task => + Task({ + subagent_type: 'universal-executor', + run_in_background: false, + prompt: task.prompt + }) + ) +); +\`\`\` + +### Step 3: 合并结果 + +\`\`\`javascript +const merged = results.map((r, i) => ({ + task_id: tasks[i].id, + result: JSON.parse(r) +})); + +Write(`${workDir}/parallel-results.json`, JSON.stringify(merged, null, 2)); +\`\`\` + +## Output + +- **File**: `parallel-results.json` +- **Format**: JSON +``` + +### 4. 组装型 Phase (Assembly) + +```markdown +# Phase 4: Document Assembly + +组装最终输出文档。 + +## Objective + +- 读取各阶段产出 +- 合并内容 +- 生成最终文档 + +## Execution Steps + +### Step 1: 读取产出 + +\`\`\`javascript +const config = JSON.parse(Read(`${workDir}/config.json`)); +const analysis = JSON.parse(Read(`${workDir}/analysis.json`)); +const sections = Glob(`${workDir}/sections/*.md`).map(f => Read(f)); +\`\`\` + +### Step 2: 组装内容 + +\`\`\`javascript +const document = \` +# \${config.name} + +## 概述 +\${config.description} + +## 详细内容 +\${sections.join('\\n\\n')} +\`; +\`\`\` + +### Step 3: 写入文件 + +\`\`\`javascript +Write(`${workDir}/${config.name}-output.md`, document); +\`\`\` + +## Output + +- **File**: `{name}-output.md` +- **Format**: Markdown +``` + +### 5. 验证型 Phase (Validation) + +```markdown +# Phase 5: Validation + +验证输出质量。 + +## Objective + +- 检查输出完整性 +- 验证内容质量 +- 生成验证报告 + +## Execution Steps + +### Step 1: 完整性检查 + +\`\`\`javascript +const outputFile = `${workDir}/${config.name}-output.md`; +const content = Read(outputFile); +const completeness = { + hasTitle: content.includes('# '), + hasSections: content.match(/## /g)?.length >= 3, + hasContent: content.length > 500 +}; +\`\`\` + +### Step 2: 质量评估 + +\`\`\`javascript +const quality = { + completeness: Object.values(completeness).filter(v => v).length / 3 * 100, + // 其他维度... +}; +\`\`\` + +### Step 3: 生成报告 + +\`\`\`javascript +const report = { + status: quality.completeness >= 80 ? 'PASS' : 'REVIEW', + scores: quality, + issues: [] +}; + +Write(`${workDir}/validation-report.json`, JSON.stringify(report, null, 2)); +\`\`\` + +## Output + +- **File**: `validation-report.json` +- **Format**: JSON +``` + +## 生成函数 + +```javascript +function generateSequentialPhase(phaseConfig, index, phases, skillConfig) { + const prevPhase = index > 0 ? phases[index - 1] : null; + const nextPhase = index < phases.length - 1 ? phases[index + 1] : null; + + return `# Phase ${index + 1}: ${phaseConfig.name} + +${phaseConfig.description || `执行 ${phaseConfig.name}`} + +## Objective + +- ${phaseConfig.objectives?.join('\n- ') || 'TODO: 定义目标'} + +## Input + +- 依赖: \`${prevPhase ? prevPhase.output : 'user input'}\` +- 配置: \`{workDir}/skill-config.json\` + +## Execution Steps + +### Step 1: 准备 + +\`\`\`javascript +${prevPhase ? + `const prevOutput = JSON.parse(Read(\`\${workDir}/${prevPhase.output}\`));` : + '// 首阶段,从配置开始'} +\`\`\` + +### Step 2: 处理 + +\`\`\`javascript +// TODO: 实现核心逻辑 +\`\`\` + +### Step 3: 输出 + +\`\`\`javascript +Write(\`\${workDir}/${phaseConfig.output}\`, JSON.stringify(result, null, 2)); +\`\`\` + +## Output + +- **File**: \`${phaseConfig.output}\` +- **Format**: ${phaseConfig.output.endsWith('.json') ? 'JSON' : 'Markdown'} + +## Quality Checklist + +- [ ] 输入验证通过 +- [ ] 核心逻辑执行成功 +- [ ] 输出格式正确 + +${nextPhase ? + `## Next Phase\n\n→ [Phase ${index + 2}: ${nextPhase.name}](${nextPhase.id}.md)` : + '## Completion\n\n此为最后阶段。'} +`; +} +``` diff --git a/.claude/skills/skill-generator/templates/skill-md.md b/.claude/skills/skill-generator/templates/skill-md.md new file mode 100644 index 00000000..63fe1e66 --- /dev/null +++ b/.claude/skills/skill-generator/templates/skill-md.md @@ -0,0 +1,144 @@ +# SKILL.md Template + +用于生成新 Skill 入口文件的模板。 + +## 模板结构 + +```markdown +--- +name: {{skill_name}} +description: {{description}}. Triggers on {{triggers}}. +allowed-tools: {{allowed_tools}} +--- + +# {{display_name}} + +{{description}} + +## Architecture Overview + +\`\`\` +{{architecture_diagram}} +\`\`\` + +## Key Design Principles + +{{design_principles}} + +## Execution Flow + +{{execution_flow}} + +## Directory Setup + +\`\`\`javascript +const timestamp = new Date().toISOString().slice(0,19).replace(/[-:T]/g, ''); +const workDir = `{{output_location}}`; + +Bash(`mkdir -p "${workDir}"`); +{{additional_dirs}} +\`\`\` + +## Output Structure + +\`\`\` +{{output_structure}} +\`\`\` + +## Reference Documents + +{{reference_table}} +``` + +## 变量说明 + +| 变量 | 类型 | 来源 | +|------|------|------| +| `{{skill_name}}` | string | config.skill_name | +| `{{display_name}}` | string | config.display_name | +| `{{description}}` | string | config.description | +| `{{triggers}}` | string | config.triggers.join(", ") | +| `{{allowed_tools}}` | string | config.allowed_tools.join(", ") | +| `{{architecture_diagram}}` | string | 根据 execution_mode 生成 | +| `{{design_principles}}` | string | 根据 execution_mode 生成 | +| `{{execution_flow}}` | string | 根据 phases/actions 生成 | +| `{{output_location}}` | string | config.output.location | +| `{{additional_dirs}}` | string | 根据 execution_mode 生成 | +| `{{output_structure}}` | string | 根据配置生成 | +| `{{reference_table}}` | string | 根据文件列表生成 | + +## 生成函数 + +```javascript +function generateSkillMd(config) { + const template = Read('templates/skill-md.md'); + + return template + .replace(/\{\{skill_name\}\}/g, config.skill_name) + .replace(/\{\{display_name\}\}/g, config.display_name) + .replace(/\{\{description\}\}/g, config.description) + .replace(/\{\{triggers\}\}/g, config.triggers.map(t => `"${t}"`).join(", ")) + .replace(/\{\{allowed_tools\}\}/g, config.allowed_tools.join(", ")) + .replace(/\{\{architecture_diagram\}\}/g, generateArchitecture(config)) + .replace(/\{\{design_principles\}\}/g, generatePrinciples(config)) + .replace(/\{\{execution_flow\}\}/g, generateFlow(config)) + .replace(/\{\{output_location\}\}/g, config.output.location) + .replace(/\{\{additional_dirs\}\}/g, generateAdditionalDirs(config)) + .replace(/\{\{output_structure\}\}/g, generateOutputStructure(config)) + .replace(/\{\{reference_table\}\}/g, generateReferenceTable(config)); +} +``` + +## Sequential 模式示例 + +```markdown +--- +name: api-docs-generator +description: Generate API documentation from source code. Triggers on "generate api docs", "api documentation". +allowed-tools: Task, Read, Write, Glob, Grep, Bash +--- + +# API Docs Generator + +Generate API documentation from source code. + +## Architecture Overview + +\`\`\` +┌─────────────────────────────────────────────────────────────────┐ +│ Phase 1: Scanning → endpoints.json │ +│ ↓ │ +│ Phase 2: Parsing → schemas.json │ +│ ↓ │ +│ Phase 3: Generation → api-docs.md │ +└─────────────────────────────────────────────────────────────────┘ +\`\`\` +``` + +## Autonomous 模式示例 + +```markdown +--- +name: task-manager +description: Interactive task management with CRUD operations. Triggers on "manage tasks", "task list". +allowed-tools: Task, AskUserQuestion, Read, Write +--- + +# Task Manager + +Interactive task management with CRUD operations. + +## Architecture Overview + +\`\`\` +┌─────────────────────────────────────────────────────────────────┐ +│ Orchestrator (状态驱动决策) │ +└───────────────┬─────────────────────────────────────────────────┘ + │ + ┌───────────┼───────────┬───────────┐ + ↓ ↓ ↓ ↓ +┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ +│ List │ │Create │ │ Edit │ │Delete │ +└───────┘ └───────┘ └───────┘ └───────┘ +\`\`\` +``` diff --git a/codex-lens/src/codexlens/cli/commands.py b/codex-lens/src/codexlens/cli/commands.py index 8f3660a9..fdb864ed 100644 --- a/codex-lens/src/codexlens/cli/commands.py +++ b/codex-lens/src/codexlens/cli/commands.py @@ -439,6 +439,11 @@ def search( "--weights", "-w", help="RRF weights as key=value pairs (e.g., 'splade=0.4,vector=0.6' or 'fts=0.4,vector=0.6'). Default: auto-detect based on available backends." ), + cascade_strategy: Optional[str] = typer.Option( + None, + "--cascade-strategy", + help="Cascade search strategy: 'binary' (fast binary+dense) or 'hybrid' (FTS+cross-encoder). Only used with --method cascade." + ), # Hidden deprecated parameter for backward compatibility mode: Optional[str] = typer.Option(None, "--mode", hidden=True, help="[DEPRECATED] Use --method instead."), json_mode: bool = typer.Option(False, "--json", help="Output JSON response."), @@ -488,9 +493,12 @@ def search( # SPLADE sparse neural search codexlens search "user login flow" --method splade - # Fast cascade retrieval for large codebases + # Fast cascade retrieval for large codebases (binary strategy) codexlens search "authentication" --method cascade + # Cascade with cross-encoder reranking (hybrid strategy) + codexlens search "authentication" --method cascade --cascade-strategy hybrid + # Hybrid with custom weights codexlens search "authentication" --method hybrid --weights splade=0.5,vector=0.5 """ @@ -540,6 +548,20 @@ def search( console.print(f"[dim]Valid methods: {', '.join(valid_methods)}[/dim]") raise typer.Exit(code=1) + # Validate cascade_strategy if provided + if cascade_strategy is not None: + valid_strategies = ["binary", "hybrid"] + if cascade_strategy not in valid_strategies: + if json_mode: + print_json(success=False, error=f"Invalid cascade strategy: {cascade_strategy}. Must be one of: {', '.join(valid_strategies)}") + else: + console.print(f"[red]Invalid cascade strategy:[/red] {cascade_strategy}") + console.print(f"[dim]Valid strategies: {', '.join(valid_strategies)}[/dim]") + raise typer.Exit(code=1) + # Warn if using cascade_strategy with non-cascade method + if actual_method != "cascade" and not json_mode: + console.print(f"[yellow]Warning: --cascade-strategy is only effective with --method cascade[/yellow]") + # Parse custom weights if provided hybrid_weights = None if weights: @@ -671,7 +693,7 @@ def search( else: # Dispatch to cascade_search for cascade method if actual_method == "cascade": - result = engine.cascade_search(query, search_path, k=limit, options=options) + result = engine.cascade_search(query, search_path, k=limit, options=options, strategy=cascade_strategy) else: result = engine.search(query, search_path, options) results_list = [ diff --git a/codex-lens/src/codexlens/config.py b/codex-lens/src/codexlens/config.py index a56aab67..46660aa7 100644 --- a/codex-lens/src/codexlens/config.py +++ b/codex-lens/src/codexlens/config.py @@ -271,6 +271,11 @@ class Config: "model": self.reranker_model, "top_k": self.reranker_top_k, }, + "cascade": { + "strategy": self.cascade_strategy, + "coarse_k": self.cascade_coarse_k, + "fine_k": self.cascade_fine_k, + }, } with open(self.settings_path, "w", encoding="utf-8") as f: json.dump(settings, f, indent=2) @@ -338,6 +343,23 @@ class Config: self.reranker_model = reranker["model"] if "top_k" in reranker: self.reranker_top_k = reranker["top_k"] + + # Load cascade settings + cascade = settings.get("cascade", {}) + if "strategy" in cascade: + strategy = cascade["strategy"] + if strategy in {"binary", "hybrid"}: + self.cascade_strategy = strategy + else: + log.warning( + "Invalid cascade strategy in %s: %r (expected 'binary' or 'hybrid')", + self.settings_path, + strategy, + ) + if "coarse_k" in cascade: + self.cascade_coarse_k = cascade["coarse_k"] + if "fine_k" in cascade: + self.cascade_fine_k = cascade["fine_k"] except Exception as exc: log.warning( "Failed to load settings from %s (%s): %s", diff --git a/codex-lens/src/codexlens/search/chain_search.py b/codex-lens/src/codexlens/search/chain_search.py index b131b582..f62166f0 100644 --- a/codex-lens/src/codexlens/search/chain_search.py +++ b/codex-lens/src/codexlens/search/chain_search.py @@ -797,7 +797,7 @@ class ChainSearchEngine: k: int = 10, coarse_k: int = 100, options: Optional[SearchOptions] = None, - strategy: Literal["binary", "hybrid"] = "binary", + strategy: Optional[Literal["binary", "hybrid"]] = None, ) -> ChainSearchResult: """Unified cascade search entry point with strategy selection. @@ -805,9 +805,9 @@ class ChainSearchEngine: - "binary": Uses binary vector coarse ranking + dense fine ranking (faster) - "hybrid": Uses FTS+SPLADE+Vector coarse ranking + cross-encoder reranking (original) - The strategy can be configured via: - 1. The `strategy` parameter (highest priority) - 2. Config `cascade_strategy` setting + The strategy is determined with the following priority: + 1. The `strategy` parameter (e.g., from CLI --cascade-strategy option) + 2. Config `cascade_strategy` setting from settings.json 3. Default: "binary" Args: @@ -816,7 +816,7 @@ class ChainSearchEngine: k: Number of final results to return (default 10) coarse_k: Number of coarse candidates from first stage (default 100) options: Search configuration (uses defaults if None) - strategy: Cascade strategy - "binary" or "hybrid" (default "binary") + strategy: Cascade strategy - "binary" or "hybrid". Overrides config if provided. Returns: ChainSearchResult with reranked results and statistics @@ -828,14 +828,18 @@ class ChainSearchEngine: >>> # Use hybrid cascade (original behavior) >>> result = engine.cascade_search("auth", Path("D:/project"), strategy="hybrid") """ - # Check config for strategy override + # Strategy priority: parameter > config > default effective_strategy = strategy - if self._config is not None: - config_strategy = getattr(self._config, "cascade_strategy", None) - if config_strategy in ("binary", "hybrid"): - # Only use config if no explicit strategy was passed - # (we can't detect if strategy was explicitly passed vs default) - effective_strategy = config_strategy + if effective_strategy is None: + # Not passed via parameter, check config + if self._config is not None: + config_strategy = getattr(self._config, "cascade_strategy", None) + if config_strategy in ("binary", "hybrid"): + effective_strategy = config_strategy + + # If still not set, apply default + if effective_strategy not in ("binary", "hybrid"): + effective_strategy = "binary" if effective_strategy == "binary": return self.binary_cascade_search(query, source_path, k, coarse_k, options) diff --git a/compare_search.py b/compare_search.py new file mode 100644 index 00000000..7d8c34c5 --- /dev/null +++ b/compare_search.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +"""Compare search results: Hybrid vs Cascade with Reranker.""" +import subprocess +import sys +import os +import re +import json + +os.chdir(r"D:\dongdiankaifa9\hydro_generator_module") +query = "热网络计算" + +ansi_escape = re.compile(r'\x1b\[[0-9;]*m') + +def run_search(method: str) -> dict: + """Run search and return parsed result dict.""" + cmd = [sys.executable, "-m", "codexlens", "search", query, + "--method", method, "--limit", "10", "--json"] + result = subprocess.run(cmd, capture_output=True, text=True, encoding="utf-8") + + # Strip ANSI codes + output = ansi_escape.sub('', result.stdout + result.stderr) + + # Find and parse JSON (properly handle nested structures) + start = output.find('{') + if start < 0: + return {"success": False, "error": "No JSON found"} + + # Count braces properly, handling strings + in_string = False + escaped = False + depth = 0 + end_idx = start + + for i, c in enumerate(output[start:]): + if escaped: + escaped = False + continue + if c == '\\': + escaped = True + continue + if c == '"' and not escaped: + in_string = not in_string + continue + if not in_string: + if c == '{': + depth += 1 + elif c == '}': + depth -= 1 + if depth == 0: + end_idx = start + i + 1 + break + + try: + return json.loads(output[start:end_idx]) + except Exception as e: + return {"success": False, "error": str(e)} + +print("=" * 75) +print(f"搜索对比: Hybrid vs Cascade") +print(f"查询: {query}") +print("=" * 75) + +# Hybrid search (no cross-encoder reranking) +print("\n[1] Hybrid 搜索 (无 Cross-Encoder Reranker):") +print("-" * 75) +hybrid_result = run_search("hybrid") +hybrid_files = [] +if hybrid_result.get("success"): + results = hybrid_result.get("result", {}).get("results", [])[:10] + for i, r in enumerate(results, 1): + name = os.path.basename(r.get("path", "")) + score = r.get("score", 0) + hybrid_files.append(name) + print(f"{i:2}. {name:<45} score={score:.4f}") +else: + print("搜索失败:", hybrid_result.get("error")) + +# Cascade search (with cross-encoder reranking when strategy=hybrid) +print("\n[2] Cascade 搜索 (使用 Cross-Encoder Reranker):") +print("-" * 75) +cascade_result = run_search("cascade") +cascade_files = [] +if cascade_result.get("success"): + results = cascade_result.get("result", {}).get("results", [])[:10] + for i, r in enumerate(results, 1): + name = os.path.basename(r.get("path", "")) + score = r.get("score", 0) + cascade_files.append(name) + print(f"{i:2}. {name:<45} score={score:.4f}") +else: + print("搜索失败:", cascade_result.get("error")) + +# Compare ranking changes +print("\n[3] 排名变化分析:") +print("-" * 75) +changes = [] +for i, name in enumerate(cascade_files): + if name in hybrid_files: + old_pos = hybrid_files.index(name) + 1 + new_pos = i + 1 + if old_pos != new_pos: + direction = "↑" if new_pos < old_pos else "↓" + changes.append(f" {name}: #{old_pos} → #{new_pos} {direction}") + else: + changes.append(f" {name}: NEW (不在 Hybrid 前10)") + +if changes: + print("Reranker 排序变化:") + for c in changes: + print(c) +else: + print("排序相同 (无变化)") + +print("\n" + "=" * 75) +print("配置说明:") +print("- Hybrid: FTS + Vector 融合 (无二次精排)") +print("- Cascade: 粗筛 + Cross-Encoder Reranker 精排") +print("- Reranker: Qwen/Qwen3-Reranker-8B via SiliconFlow API") +print("=" * 75)