feat: Implement multi-phase project analysis workflow with Mermaid diagram generation and CPCC compliance documentation

- Phase 3: Added Mermaid diagram generation for system architecture, function modules, algorithms, class diagrams, sequence diagrams, and error flows.
- Phase 4: Assembled analysis and diagrams into a structured CPCC-compliant document with section templates and figure numbering.
- Phase 5: Developed compliance review process with iterative refinement based on analysis findings and user feedback.
- Added CPCC compliance requirements and quality standards for project analysis reports.
- Established a comprehensive project analysis skill with detailed execution flow and report types.
- Enhanced error handling and recovery mechanisms throughout the analysis phases.
This commit is contained in:
catlog22
2025-12-26 11:44:29 +08:00
parent f14c3299bc
commit 89f6ac6804
25 changed files with 5018 additions and 34 deletions

View File

@@ -5,7 +5,7 @@ argument-hint: "[--dry-run] [\"focus area\"]"
allowed-tools: TodoWrite(*), Task(*), AskUserQuestion(*), Read(*), Glob(*), Bash(*), Write(*)
---
# Clean Command (/clean)
# Clean Command (/workflow:clean)
## Overview
@@ -20,9 +20,9 @@ Intelligent cleanup command that explores the codebase to identify the developme
## Usage
```bash
/clean # Full intelligent cleanup (explore → analyze → confirm → execute)
/clean --dry-run # Explore and analyze only, no execution
/clean "auth module" # Focus cleanup on specific area
/workflow:clean # Full intelligent cleanup (explore → analyze → confirm → execute)
/workflow:clean --dry-run # Explore and analyze only, no execution
/workflow:clean "auth module" # Focus cleanup on specific area
```
## Execution Process
@@ -321,7 +321,7 @@ if (flags.includes('--dry-run')) {
**Dry-run mode**: No changes made.
Manifest saved to: ${sessionFolder}/cleanup-manifest.json
To execute cleanup: /clean
To execute cleanup: /workflow:clean
`)
return
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,584 @@
# Mermaid Utilities Library
Shared utilities for generating and validating Mermaid diagrams across all analysis skills.
## Sanitization Functions
### sanitizeId
Convert any text to a valid Mermaid node ID.
```javascript
/**
* Sanitize text to valid Mermaid node ID
* - Only alphanumeric and underscore allowed
* - Cannot start with number
* - Truncates to 50 chars max
*
* @param {string} text - Input text
* @returns {string} - Valid Mermaid ID
*/
function sanitizeId(text) {
if (!text) return '_empty';
return text
.replace(/[^a-zA-Z0-9_\u4e00-\u9fa5]/g, '_') // Allow Chinese chars
.replace(/^[0-9]/, '_$&') // Prefix number with _
.replace(/_+/g, '_') // Collapse multiple _
.substring(0, 50); // Limit length
}
// Examples:
// sanitizeId("User-Service") → "User_Service"
// sanitizeId("3rdParty") → "_3rdParty"
// sanitizeId("用户服务") → "用户服务"
```
### escapeLabel
Escape special characters for Mermaid labels.
```javascript
/**
* Escape special characters in Mermaid labels
* Uses HTML entity encoding for problematic chars
*
* @param {string} text - Label text
* @returns {string} - Escaped label
*/
function escapeLabel(text) {
if (!text) return '';
return text
.replace(/"/g, "'") // Avoid quote issues
.replace(/\(/g, '#40;') // (
.replace(/\)/g, '#41;') // )
.replace(/\{/g, '#123;') // {
.replace(/\}/g, '#125;') // }
.replace(/\[/g, '#91;') // [
.replace(/\]/g, '#93;') // ]
.replace(/</g, '#60;') // <
.replace(/>/g, '#62;') // >
.replace(/\|/g, '#124;') // |
.substring(0, 80); // Limit length
}
// Examples:
// escapeLabel("Process(data)") → "Process#40;data#41;"
// escapeLabel("Check {valid?}") → "Check #123;valid?#125;"
```
### sanitizeType
Sanitize type names for class diagrams.
```javascript
/**
* Sanitize type names for Mermaid classDiagram
* Removes generics syntax that causes issues
*
* @param {string} type - Type name
* @returns {string} - Sanitized type
*/
function sanitizeType(type) {
if (!type) return 'any';
return type
.replace(/<[^>]*>/g, '') // Remove generics <T>
.replace(/\|/g, ' or ') // Union types
.replace(/&/g, ' and ') // Intersection types
.replace(/\[\]/g, 'Array') // Array notation
.substring(0, 30);
}
// Examples:
// sanitizeType("Array<string>") → "Array"
// sanitizeType("string | number") → "string or number"
```
## Diagram Generation Functions
### generateFlowchartNode
Generate a flowchart node with proper shape.
```javascript
/**
* Generate flowchart node with shape
*
* @param {string} id - Node ID
* @param {string} label - Display label
* @param {string} type - Node type: start|end|process|decision|io|subroutine
* @returns {string} - Mermaid node definition
*/
function generateFlowchartNode(id, label, type = 'process') {
const safeId = sanitizeId(id);
const safeLabel = escapeLabel(label);
const shapes = {
start: `${safeId}(["${safeLabel}"])`, // Stadium shape
end: `${safeId}(["${safeLabel}"])`, // Stadium shape
process: `${safeId}["${safeLabel}"]`, // Rectangle
decision: `${safeId}{"${safeLabel}"}`, // Diamond
io: `${safeId}[/"${safeLabel}"/]`, // Parallelogram
subroutine: `${safeId}[["${safeLabel}"]]`, // Subroutine
database: `${safeId}[("${safeLabel}")]`, // Cylinder
manual: `${safeId}[/"${safeLabel}"\\]` // Trapezoid
};
return shapes[type] || shapes.process;
}
```
### generateFlowchartEdge
Generate a flowchart edge with optional label.
```javascript
/**
* Generate flowchart edge
*
* @param {string} from - Source node ID
* @param {string} to - Target node ID
* @param {string} label - Edge label (optional)
* @param {string} style - Edge style: solid|dashed|thick
* @returns {string} - Mermaid edge definition
*/
function generateFlowchartEdge(from, to, label = '', style = 'solid') {
const safeFrom = sanitizeId(from);
const safeTo = sanitizeId(to);
const safeLabel = label ? `|"${escapeLabel(label)}"|` : '';
const arrows = {
solid: '-->',
dashed: '-.->',
thick: '==>'
};
const arrow = arrows[style] || arrows.solid;
return ` ${safeFrom} ${arrow}${safeLabel} ${safeTo}`;
}
```
### generateAlgorithmFlowchart (Enhanced)
Generate algorithm flowchart with branch/loop support.
```javascript
/**
* Generate algorithm flowchart with decision support
*
* @param {Object} algorithm - Algorithm definition
* - name: Algorithm name
* - inputs: [{name, type}]
* - outputs: [{name, type}]
* - steps: [{id, description, type, next: [id], conditions: [text]}]
* @returns {string} - Complete Mermaid flowchart
*/
function generateAlgorithmFlowchart(algorithm) {
let mermaid = 'flowchart TD\n';
// Start node
mermaid += ` START(["开始: ${escapeLabel(algorithm.name)}"])\n`;
// Input node (if has inputs)
if (algorithm.inputs?.length > 0) {
const inputList = algorithm.inputs.map(i => `${i.name}: ${i.type}`).join(', ');
mermaid += ` INPUT[/"输入: ${escapeLabel(inputList)}"/]\n`;
mermaid += ` START --> INPUT\n`;
}
// Process nodes
const steps = algorithm.steps || [];
for (const step of steps) {
const nodeId = sanitizeId(step.id || `STEP_${step.step_num}`);
if (step.type === 'decision') {
mermaid += ` ${nodeId}{"${escapeLabel(step.description)}"}\n`;
} else if (step.type === 'io') {
mermaid += ` ${nodeId}[/"${escapeLabel(step.description)}"/]\n`;
} else if (step.type === 'loop_start') {
mermaid += ` ${nodeId}[["循环: ${escapeLabel(step.description)}"]]\n`;
} else {
mermaid += ` ${nodeId}["${escapeLabel(step.description)}"]\n`;
}
}
// Output node
const outputDesc = algorithm.outputs?.map(o => o.name).join(', ') || '结果';
mermaid += ` OUTPUT[/"输出: ${escapeLabel(outputDesc)}"/]\n`;
mermaid += ` END_(["结束"])\n`;
// Connect first step to input/start
if (steps.length > 0) {
const firstStep = sanitizeId(steps[0].id || 'STEP_1');
if (algorithm.inputs?.length > 0) {
mermaid += ` INPUT --> ${firstStep}\n`;
} else {
mermaid += ` START --> ${firstStep}\n`;
}
}
// Connect steps based on next array
for (const step of steps) {
const nodeId = sanitizeId(step.id || `STEP_${step.step_num}`);
if (step.next && step.next.length > 0) {
step.next.forEach((nextId, index) => {
const safeNextId = sanitizeId(nextId);
const condition = step.conditions?.[index];
if (condition) {
mermaid += ` ${nodeId} -->|"${escapeLabel(condition)}"| ${safeNextId}\n`;
} else {
mermaid += ` ${nodeId} --> ${safeNextId}\n`;
}
});
} else if (!step.type?.includes('end')) {
// Default: connect to next step or output
const stepIndex = steps.indexOf(step);
if (stepIndex < steps.length - 1) {
const nextStep = sanitizeId(steps[stepIndex + 1].id || `STEP_${stepIndex + 2}`);
mermaid += ` ${nodeId} --> ${nextStep}\n`;
} else {
mermaid += ` ${nodeId} --> OUTPUT\n`;
}
}
}
// Connect output to end
mermaid += ` OUTPUT --> END_\n`;
return mermaid;
}
```
## Diagram Validation
### validateMermaidSyntax
Comprehensive Mermaid syntax validation.
```javascript
/**
* Validate Mermaid diagram syntax
*
* @param {string} content - Mermaid diagram content
* @returns {Object} - {valid: boolean, issues: string[]}
*/
function validateMermaidSyntax(content) {
const issues = [];
// Check 1: Diagram type declaration
if (!content.match(/^(graph|flowchart|classDiagram|sequenceDiagram|stateDiagram|erDiagram|gantt|pie|mindmap)/m)) {
issues.push('Missing diagram type declaration');
}
// Check 2: Undefined values
if (content.includes('undefined') || content.includes('null')) {
issues.push('Contains undefined/null values');
}
// Check 3: Invalid arrow syntax
if (content.match(/-->\s*-->/)) {
issues.push('Double arrow syntax error');
}
// Check 4: Unescaped special characters in labels
const labelMatches = content.match(/\["[^"]*[(){}[\]<>][^"]*"\]/g);
if (labelMatches?.some(m => !m.includes('#'))) {
issues.push('Unescaped special characters in labels');
}
// Check 5: Node ID starts with number
if (content.match(/\n\s*[0-9][a-zA-Z0-9_]*[\[\({]/)) {
issues.push('Node ID cannot start with number');
}
// Check 6: Nested subgraph syntax error
if (content.match(/subgraph\s+\S+\s*\n[^e]*subgraph/)) {
// This is actually valid, only flag if brackets don't match
const subgraphCount = (content.match(/subgraph/g) || []).length;
const endCount = (content.match(/\bend\b/g) || []).length;
if (subgraphCount > endCount) {
issues.push('Unbalanced subgraph/end blocks');
}
}
// Check 7: Invalid arrow type for diagram type
const diagramType = content.match(/^(graph|flowchart|classDiagram|sequenceDiagram)/m)?.[1];
if (diagramType === 'classDiagram' && content.includes('-->|')) {
issues.push('Invalid edge label syntax for classDiagram');
}
// Check 8: Empty node labels
if (content.match(/\[""\]|\{\}|\(\)/)) {
issues.push('Empty node labels detected');
}
// Check 9: Reserved keywords as IDs
const reserved = ['end', 'graph', 'subgraph', 'direction', 'class', 'click'];
for (const keyword of reserved) {
const pattern = new RegExp(`\\n\\s*${keyword}\\s*[\\[\\(\\{]`, 'i');
if (content.match(pattern)) {
issues.push(`Reserved keyword "${keyword}" used as node ID`);
}
}
// Check 10: Line length (Mermaid has issues with very long lines)
const lines = content.split('\n');
for (let i = 0; i < lines.length; i++) {
if (lines[i].length > 500) {
issues.push(`Line ${i + 1} exceeds 500 characters`);
}
}
return {
valid: issues.length === 0,
issues
};
}
```
### validateDiagramDirectory
Validate all diagrams in a directory.
```javascript
/**
* Validate all Mermaid diagrams in directory
*
* @param {string} diagramDir - Path to diagrams directory
* @returns {Object[]} - Array of {file, valid, issues}
*/
function validateDiagramDirectory(diagramDir) {
const files = Glob(`${diagramDir}/*.mmd`);
const results = [];
for (const file of files) {
const content = Read(file);
const validation = validateMermaidSyntax(content);
results.push({
file: file.split('/').pop(),
path: file,
valid: validation.valid,
issues: validation.issues,
lines: content.split('\n').length
});
}
return results;
}
```
## Class Diagram Utilities
### generateClassDiagram
Generate class diagram with relationships.
```javascript
/**
* Generate class diagram from analysis data
*
* @param {Object} analysis - Data structure analysis
* - entities: [{name, type, properties, methods}]
* - relationships: [{from, to, type, label}]
* @param {Object} options - Generation options
* - maxClasses: Max classes to include (default: 15)
* - maxProperties: Max properties per class (default: 8)
* - maxMethods: Max methods per class (default: 6)
* @returns {string} - Mermaid classDiagram
*/
function generateClassDiagram(analysis, options = {}) {
const maxClasses = options.maxClasses || 15;
const maxProperties = options.maxProperties || 8;
const maxMethods = options.maxMethods || 6;
let mermaid = 'classDiagram\n';
const entities = (analysis.entities || []).slice(0, maxClasses);
// Generate classes
for (const entity of entities) {
const className = sanitizeId(entity.name);
mermaid += ` class ${className} {\n`;
// Properties
for (const prop of (entity.properties || []).slice(0, maxProperties)) {
const vis = {public: '+', private: '-', protected: '#'}[prop.visibility] || '+';
const type = sanitizeType(prop.type);
mermaid += ` ${vis}${type} ${prop.name}\n`;
}
// Methods
for (const method of (entity.methods || []).slice(0, maxMethods)) {
const vis = {public: '+', private: '-', protected: '#'}[method.visibility] || '+';
const params = (method.params || []).map(p => p.name).join(', ');
const returnType = sanitizeType(method.returnType || 'void');
mermaid += ` ${vis}${method.name}(${params}) ${returnType}\n`;
}
mermaid += ' }\n';
// Add stereotype if applicable
if (entity.type === 'interface') {
mermaid += ` <<interface>> ${className}\n`;
} else if (entity.type === 'abstract') {
mermaid += ` <<abstract>> ${className}\n`;
}
}
// Generate relationships
const arrows = {
inheritance: '--|>',
implementation: '..|>',
composition: '*--',
aggregation: 'o--',
association: '-->',
dependency: '..>'
};
for (const rel of (analysis.relationships || [])) {
const from = sanitizeId(rel.from);
const to = sanitizeId(rel.to);
const arrow = arrows[rel.type] || '-->';
const label = rel.label ? ` : ${escapeLabel(rel.label)}` : '';
// Only include if both entities exist
if (entities.some(e => sanitizeId(e.name) === from) &&
entities.some(e => sanitizeId(e.name) === to)) {
mermaid += ` ${from} ${arrow} ${to}${label}\n`;
}
}
return mermaid;
}
```
## Sequence Diagram Utilities
### generateSequenceDiagram
Generate sequence diagram from scenario.
```javascript
/**
* Generate sequence diagram from scenario
*
* @param {Object} scenario - Sequence scenario
* - name: Scenario name
* - actors: [{id, name, type}]
* - messages: [{from, to, description, type}]
* - blocks: [{type, condition, messages}]
* @returns {string} - Mermaid sequenceDiagram
*/
function generateSequenceDiagram(scenario) {
let mermaid = 'sequenceDiagram\n';
// Title
if (scenario.name) {
mermaid += ` title ${escapeLabel(scenario.name)}\n`;
}
// Participants
for (const actor of scenario.actors || []) {
const actorType = actor.type === 'external' ? 'actor' : 'participant';
mermaid += ` ${actorType} ${sanitizeId(actor.id)} as ${escapeLabel(actor.name)}\n`;
}
mermaid += '\n';
// Messages
for (const msg of scenario.messages || []) {
const from = sanitizeId(msg.from);
const to = sanitizeId(msg.to);
const desc = escapeLabel(msg.description);
let arrow;
switch (msg.type) {
case 'async': arrow = '->>'; break;
case 'response': arrow = '-->>'; break;
case 'create': arrow = '->>+'; break;
case 'destroy': arrow = '->>-'; break;
case 'self': arrow = '->>'; break;
default: arrow = '->>';
}
mermaid += ` ${from}${arrow}${to}: ${desc}\n`;
// Activation
if (msg.activate) {
mermaid += ` activate ${to}\n`;
}
if (msg.deactivate) {
mermaid += ` deactivate ${from}\n`;
}
// Notes
if (msg.note) {
mermaid += ` Note over ${to}: ${escapeLabel(msg.note)}\n`;
}
}
// Blocks (loops, alt, opt)
for (const block of scenario.blocks || []) {
switch (block.type) {
case 'loop':
mermaid += ` loop ${escapeLabel(block.condition)}\n`;
break;
case 'alt':
mermaid += ` alt ${escapeLabel(block.condition)}\n`;
break;
case 'opt':
mermaid += ` opt ${escapeLabel(block.condition)}\n`;
break;
}
for (const m of block.messages || []) {
mermaid += ` ${sanitizeId(m.from)}->>${sanitizeId(m.to)}: ${escapeLabel(m.description)}\n`;
}
mermaid += ' end\n';
}
return mermaid;
}
```
## Usage Examples
### Example 1: Algorithm with Branches
```javascript
const algorithm = {
name: "用户认证流程",
inputs: [{name: "credentials", type: "Object"}],
outputs: [{name: "token", type: "JWT"}],
steps: [
{id: "validate", description: "验证输入格式", type: "process"},
{id: "check_user", description: "用户是否存在?", type: "decision",
next: ["verify_pwd", "error_user"], conditions: ["是", "否"]},
{id: "verify_pwd", description: "验证密码", type: "process"},
{id: "pwd_ok", description: "密码正确?", type: "decision",
next: ["gen_token", "error_pwd"], conditions: ["是", "否"]},
{id: "gen_token", description: "生成 JWT Token", type: "process"},
{id: "error_user", description: "返回用户不存在", type: "io"},
{id: "error_pwd", description: "返回密码错误", type: "io"}
]
};
const flowchart = generateAlgorithmFlowchart(algorithm);
```
### Example 2: Validate Before Output
```javascript
const diagram = generateClassDiagram(analysis);
const validation = validateMermaidSyntax(diagram);
if (!validation.valid) {
console.log("Diagram has issues:", validation.issues);
// Fix issues or regenerate
} else {
Write(`${outputDir}/class-diagram.mmd`, diagram);
}
```

View File

@@ -0,0 +1,95 @@
---
name: copyright-docs
description: Generate software copyright design specification documents compliant with China Copyright Protection Center (CPCC) standards. Creates complete design documents with Mermaid diagrams based on source code analysis. Use for software copyright registration, generating design specification, creating CPCC-compliant documents, or documenting software for intellectual property protection. Triggers on "软件著作权", "设计说明书", "版权登记", "CPCC", "软著申请".
allowed-tools: Task, AskUserQuestion, Read, Bash, Glob, Grep, Write
---
# Software Copyright Documentation Skill
Generate CPCC-compliant software design specification documents (软件设计说明书) through multi-phase code analysis.
## Execution Flow
```
┌─────────────────────────────────────────────────────────────────┐
│ Phase 1: Metadata Collection │
│ → Read: phases/01-metadata-collection.md │
│ → Collect: software name, version, category, scope │
├─────────────────────────────────────────────────────────────────┤
│ Phase 2: Deep Code Analysis │
│ → Read: phases/02-deep-analysis.md │
│ → Launch: 6 parallel agents (architecture, functions, │
│ algorithms, data_structures, interfaces, exceptions) │
├─────────────────────────────────────────────────────────────────┤
│ Phase 3: Diagram Generation │
│ → Read: phases/03-diagram-generation.md │
│ → Reference: ../_shared/mermaid-utils.md │
│ → Generate: Mermaid diagrams for all 7 sections │
├─────────────────────────────────────────────────────────────────┤
│ Phase 4: Document Assembly │
│ → Read: phases/04-document-assembly.md │
│ → Reference: specs/cpcc-requirements.md │
│ → Assemble: 7-section CPCC-compliant document │
├─────────────────────────────────────────────────────────────────┤
│ Phase 5: Compliance Review & Refinement │
│ → Read: phases/05-compliance-refinement.md │
│ → Reference: specs/cpcc-requirements.md (Compliance Checklist) │
│ → Validate: run CPCC compliance checks before each iteration │
│ → Loop: discovery-driven questions until all checks pass │
└─────────────────────────────────────────────────────────────────┘
```
## Document Sections (7 Required)
| Section | Title | Diagram |
|---------|-------|---------|
| 1 | 软件概述 | - |
| 2 | 系统架构图 | graph TD |
| 3 | 功能模块设计 | flowchart TD |
| 4 | 核心算法与流程 | flowchart TD |
| 5 | 数据结构设计 | classDiagram |
| 6 | 接口设计 | sequenceDiagram |
| 7 | 异常处理设计 | flowchart TD |
## Directory Setup
```bash
timestamp=$(date +%Y%m%d-%H%M%S)
dir=".workflow/.scratchpad/copyright-$timestamp"
mkdir -p "$dir/diagrams" "$dir/iterations"
echo "$dir"
```
## Reference Documents
| Document | Purpose |
|----------|---------|
| [phases/01-metadata-collection.md](phases/01-metadata-collection.md) | Software info collection |
| [phases/02-deep-analysis.md](phases/02-deep-analysis.md) | 6-agent parallel analysis |
| [phases/03-diagram-generation.md](phases/03-diagram-generation.md) | Mermaid diagram generation |
| [phases/04-document-assembly.md](phases/04-document-assembly.md) | Document structure assembly |
| [phases/05-compliance-refinement.md](phases/05-compliance-refinement.md) | Iterative refinement loop |
| [specs/cpcc-requirements.md](specs/cpcc-requirements.md) | CPCC compliance checklist |
| [../_shared/mermaid-utils.md](../_shared/mermaid-utils.md) | Shared Mermaid utilities |
## Output Structure
```
.workflow/.scratchpad/copyright-{timestamp}/
├── project-metadata.json
├── analysis-architecture.json
├── analysis-functions.json
├── analysis-algorithms.json
├── analysis-data_structures.json
├── analysis-interfaces.json
├── analysis-exceptions.json
├── diagrams/
│ ├── manifest.json
│ ├── architecture.mmd
│ ├── functions.mmd
│ ├── class-diagram.mmd
│ ├── algorithm-*.mmd
│ └── sequence-*.mmd
├── iterations/
└── {软件名称}-软件设计说明书.md
```

View File

@@ -0,0 +1,78 @@
# Phase 1: Metadata Collection
Collect software metadata for document header and context.
## Execution
### Step 1: Software Name & Version
```javascript
AskUserQuestion({
questions: [{
question: "请输入软件名称(将显示在文档页眉):",
header: "软件名称",
multiSelect: false,
options: [
{label: "自动检测", description: "从 package.json 或项目配置读取"},
{label: "手动输入", description: "输入自定义名称"}
]
}]
})
```
### Step 2: Software Category
```javascript
AskUserQuestion({
questions: [{
question: "软件属于哪种类型?",
header: "软件类型",
multiSelect: false,
options: [
{label: "命令行工具 (CLI)", description: "重点描述命令、参数"},
{label: "后端服务/API", description: "重点描述端点、协议"},
{label: "SDK/库", description: "重点描述接口、集成"},
{label: "数据处理系统", description: "重点描述数据流、转换"},
{label: "自动化脚本", description: "重点描述工作流、触发器"}
]
}]
})
```
### Step 3: Scope Definition
```javascript
AskUserQuestion({
questions: [{
question: "分析范围是什么?",
header: "分析范围",
multiSelect: false,
options: [
{label: "整个项目", description: "分析全部源代码"},
{label: "指定目录", description: "仅分析 src/ 或其他目录"},
{label: "自定义路径", description: "手动指定路径"}
]
}]
})
```
## Output
Save metadata to `project-metadata.json`:
```json
{
"software_name": "智能数据分析系统",
"version": "V1.0.0",
"category": "后端服务/API",
"scope_path": "src/",
"tech_stack": {
"language": "TypeScript",
"runtime": "Node.js 18+",
"framework": "Express.js",
"dependencies": ["mongoose", "redis", "bull"]
},
"entry_points": ["src/index.ts", "src/cli.ts"],
"main_modules": ["auth", "data", "api", "worker"]
}
```

View File

@@ -0,0 +1,138 @@
# Phase 2: Deep Code Analysis
Launch 6 parallel agents for multi-dimensional code analysis.
## Execution
### Analysis Dimensions
| Agent | Dimension | Analysis Focus | Output Section |
|-------|-----------|----------------|----------------|
| 1 | architecture | 分层、模块、依赖 | Section 2 |
| 2 | functions | 功能、工作流、交互 | Section 3 |
| 3 | algorithms | 核心逻辑、复杂度、流程 | Section 4 |
| 4 | data_structures | 实体、属性、关系 | Section 5 |
| 5 | interfaces | API、参数、响应 | Section 6 |
| 6 | exceptions | 错误类型、处理、恢复 | Section 7 |
### Agent Prompts
**Architecture Analysis:**
```javascript
Task({
subagent_type: "cli-explore-agent",
prompt: `
## 分析目标
分析项目的系统架构,为"系统架构图"章节提供数据。
## 分析内容
1. 分层结构识别代码的分层Controller/Service/Repository
2. 模块边界:各模块的职责范围和边界
3. 依赖关系:模块间的依赖方向和类型
4. 核心组件:系统的核心组件及其作用
5. 数据流向:数据在各层之间的流动路径
## 输出格式
{
"layers": [{name, components, responsibility}],
"modules": [{name, path, responsibility, dependencies}],
"data_flow": [{from, to, data_type, description}],
"core_components": [{name, type, responsibility}]
}
`
})
```
**Function Analysis:**
```javascript
prompt = `
## 分析目标
分析项目的功能模块,为"功能模块设计"章节提供数据。
## 输出格式
{
"feature_list": [{id, name, description, module, entry_file}],
"feature_groups": [{group_name, features: []}],
"feature_hierarchy": {root: {children: [...]}},
"interactions": [{caller, callee, trigger, description}],
"key_workflows": [{name, steps: [], files_involved}]
}
`
```
**Algorithm Analysis:**
```javascript
prompt = `
## 分析目标
分析项目的核心算法和业务逻辑,为"核心算法与流程"章节提供数据。
## 输出格式
{
"algorithms": [{
name, file, line, description, complexity,
inputs: [{name, type, description}],
outputs: [{name, type, description}],
steps: [{step_num, description, type, next, conditions}]
}],
"complex_functions": [{name, file, cyclomatic_complexity}]
}
`
```
**Data Structure Analysis:**
```javascript
prompt = `
## 分析目标
分析项目的数据结构,为"数据结构设计"章节提供数据。
## 输出格式
{
"entities": [{
name, file, type,
properties: [{name, type, visibility, description}],
methods: [{name, params, return_type, visibility}]
}],
"relationships": [{from, to, type, cardinality, description}],
"enums": [{name, values: [{name, value, description}]}]
}
`
```
**Interface Analysis:**
```javascript
prompt = `
## 分析目标
分析项目的接口设计,为"接口设计"章节提供数据。
## 输出格式
{
"apis": [{
name, path, method, description,
parameters: [{name, type, required, description}],
response: {type, schema, description},
category
}],
"protocols": [{name, type, description}]
}
`
```
**Exception Analysis:**
```javascript
prompt = `
## 分析目标
分析项目的异常处理机制,为"异常处理设计"章节提供数据。
## 输出格式
{
"exception_types": [{name, parent, code, message, file}],
"error_codes": [{code, message, severity, category}],
"handling_patterns": [{pattern, locations: [], description}],
"recovery_strategies": [{strategy, trigger, action, files}]
}
`
```
## Output
Save each analysis to `analysis-{dimension}.json`.

View File

@@ -0,0 +1,147 @@
# Phase 3: Mermaid Diagram Generation
Generate Mermaid diagrams for each document section.
> **Reference**: See [mermaid-utils.md](../../_shared/mermaid-utils.md) for utility functions.
## Execution
### Diagram Mapping
| Section | Diagram Type | Format | File |
|---------|--------------|--------|------|
| 2. 系统架构图 | Architecture | graph TD | architecture.mmd |
| 3. 功能模块设计 | Function Tree | flowchart TD | functions.mmd |
| 4. 核心算法与流程 | Algorithm Flow | flowchart TD | algorithm-*.mmd |
| 5. 数据结构设计 | Class Diagram | classDiagram | class-diagram.mmd |
| 6. 接口设计 | Sequence | sequenceDiagram | sequence-*.mmd |
| 7. 异常处理设计 | Error Flow | flowchart TD | exception-flow.mmd |
### Section 2: System Architecture
```javascript
function generateArchitectureDiagram(analysis) {
let mermaid = 'graph TD\n';
for (const layer of analysis.layers) {
mermaid += ` subgraph ${sanitizeId(layer.name)}["${escapeLabel(layer.name)}"]\n`;
for (const comp of layer.components) {
mermaid += ` ${sanitizeId(comp)}["${escapeLabel(comp)}"]\n`;
}
mermaid += ' end\n';
}
for (const flow of analysis.data_flow) {
mermaid += ` ${sanitizeId(flow.from)} -->|"${escapeLabel(flow.description)}"| ${sanitizeId(flow.to)}\n`;
}
return mermaid;
}
```
### Section 3: Function Modules
```javascript
function generateFunctionDiagram(analysis, softwareName) {
let mermaid = 'flowchart TD\n';
mermaid += ` ROOT["${escapeLabel(softwareName)}"]\n`;
for (const group of analysis.feature_groups) {
mermaid += ` subgraph ${sanitizeId(group.group_name)}["${escapeLabel(group.group_name)}"]\n`;
for (const feature of group.features) {
mermaid += ` ${sanitizeId(feature.id)}["${escapeLabel(feature.name)}"]\n`;
}
mermaid += ' end\n';
mermaid += ` ROOT --> ${sanitizeId(group.group_name)}\n`;
}
return mermaid;
}
```
### Section 4: Algorithm Flowchart (with branches)
```javascript
// Uses generateAlgorithmFlowchart from _shared/mermaid-utils.md
// Supports: type (process/decision/io), next, conditions
const flowchart = generateAlgorithmFlowchart({
name: algorithm.name,
inputs: algorithm.inputs,
outputs: algorithm.outputs,
steps: algorithm.steps // Each step can have type, next, conditions
});
```
### Section 5: Class Diagram
```javascript
function generateClassDiagram(analysis) {
let mermaid = 'classDiagram\n';
for (const entity of analysis.entities) {
mermaid += ` class ${sanitizeId(entity.name)} {\n`;
for (const prop of entity.properties) {
const vis = {public: '+', private: '-', protected: '#'}[prop.visibility] || '+';
mermaid += ` ${vis}${sanitizeType(prop.type)} ${prop.name}\n`;
}
for (const method of entity.methods) {
const vis = {public: '+', private: '-', protected: '#'}[method.visibility] || '+';
mermaid += ` ${vis}${method.name}(${method.params}) ${sanitizeType(method.return_type)}\n`;
}
mermaid += ' }\n';
}
const arrows = {
inheritance: '--|>',
composition: '*--',
aggregation: 'o--',
association: '-->'
};
for (const rel of analysis.relationships) {
const arrow = arrows[rel.type] || '-->';
mermaid += ` ${sanitizeId(rel.from)} ${arrow} ${sanitizeId(rel.to)} : ${escapeLabel(rel.description)}\n`;
}
return mermaid;
}
```
### Section 6: Sequence Diagram
```javascript
function generateSequenceDiagram(scenario) {
let mermaid = 'sequenceDiagram\n';
for (const actor of scenario.actors) {
mermaid += ` participant ${sanitizeId(actor.id)} as ${escapeLabel(actor.name)}\n`;
}
for (const msg of scenario.messages) {
const arrow = msg.type === 'async' ? '-)' : '->>';
mermaid += ` ${sanitizeId(msg.from)}${arrow}${sanitizeId(msg.to)}: ${escapeLabel(msg.description)}\n`;
}
return mermaid;
}
```
### Validation
```javascript
// Validate all generated diagrams
const results = validateDiagramDirectory(`${outputDir}/diagrams`);
const failed = results.filter(r => !r.valid);
if (failed.length > 0) {
// Regenerate failed diagrams with stricter escaping
for (const f of failed) {
regenerateWithFixes(f.file, f.issues);
}
}
```
## Output
Save diagrams to `diagrams/` with `manifest.json`.

View File

@@ -0,0 +1,128 @@
# Phase 4: Document Assembly
Assemble all analysis and diagrams into CPCC-compliant document.
## Execution
### Document Structure (7 Sections)
```markdown
<!-- 页眉:{软件名称} - 版本号:{版本号} -->
<!-- 注:最终文档页码位于每页右上角 -->
## 1. 软件概述
### 1.1 软件背景与用途
### 1.2 开发目标与特点
### 1.3 运行环境与技术架构
## 2. 系统架构图
图2-1 系统架构图
(Mermaid graph TD)
## 3. 功能模块设计
图3-1 功能模块结构图
(Mermaid flowchart TD)
## 4. 核心算法与流程
图4-1 {算法名称}流程图
(Mermaid flowchart TD)
## 5. 数据结构设计
图5-1 数据结构类图
(Mermaid classDiagram)
## 6. 接口设计
图6-1 接口调用时序图
(Mermaid sequenceDiagram)
## 7. 异常处理设计
图7-1 异常处理流程图
(Mermaid flowchart TD)
```
### Section Templates
**Section 1: 软件概述**
```markdown
## 1. 软件概述
### 1.1 软件背景与用途
${software_name}是一款${category}软件,主要用于${inferred_purpose}。
本软件基于${tech_stack.language}语言开发,采用${tech_stack.framework}实现核心功能。
### 1.2 开发目标与特点
**开发目标**
${objectives}
**技术特点**
${features}
### 1.3 运行环境与技术架构
**运行环境**
- 操作系统:${os}
- 运行时:${runtime}
- 依赖环境:${dependencies}
**技术架构**
- 架构模式:${architecture_pattern}
- 核心框架:${framework}
```
**Section 2-7: Pattern**
```markdown
## {N}. {章节标题}
本章节展示${software_name}的{描述}。
\`\`\`mermaid
${diagram_content}
\`\`\`
**图{N}-1 {图表标题}**
### {子标题}
{详细说明}
```
### Figure Numbering
| Section | Figure Number | Title |
|---------|---------------|-------|
| 2 | 图2-1 | 系统架构图 |
| 3 | 图3-1 | 功能模块结构图 |
| 4 | 图4-1, 图4-2... | {算法名称}流程图 |
| 5 | 图5-1 | 数据结构类图 |
| 6 | 图6-1, 图6-2... | {接口名称}时序图 |
| 7 | 图7-1 | 异常处理流程图 |
### Assembly Code
```javascript
function assembleDocument(metadata, analyses, diagrams) {
let doc = '';
// Header
doc += `<!-- 页眉:${metadata.software_name} - 版本号:${metadata.version} -->\n`;
doc += `<!-- 注:最终文档页码位于每页右上角 -->\n\n`;
// Generate each section
doc += generateSection1(metadata, analyses.architecture);
doc += generateSection2(analyses.architecture, diagrams.architecture);
doc += generateSection3(analyses.functions, diagrams.functions, metadata.software_name);
doc += generateSection4(analyses.algorithms, diagrams.algorithms);
doc += generateSection5(analyses.data_structures, diagrams.class);
doc += generateSection6(analyses.interfaces, diagrams.sequences);
doc += generateSection7(analyses.exceptions, diagrams.exception_flow);
return doc;
}
```
## Output
Generate `{软件名称}-软件设计说明书.md`.

View File

@@ -0,0 +1,192 @@
# Phase 5: Compliance Review & Iterative Refinement
Discovery-driven refinement loop until CPCC compliance is met.
## Execution
### Step 1: Extract Compliance Issues
```javascript
function extractComplianceIssues(validationResult, deepAnalysis) {
return {
// Missing or incomplete sections
missingSections: validationResult.details
.filter(d => !d.pass)
.map(d => ({
section: d.name,
severity: 'critical',
suggestion: `需要补充 ${d.name} 相关内容`
})),
// Features with weak descriptions (< 50 chars)
weakDescriptions: (deepAnalysis.functions?.feature_list || [])
.filter(f => !f.description || f.description.length < 50)
.map(f => ({
feature: f.name,
current: f.description || '(无描述)',
severity: 'warning'
})),
// Complex algorithms without detailed flowcharts
complexAlgorithms: (deepAnalysis.algorithms?.algorithms || [])
.filter(a => (a.complexity || 0) > 10 && (a.steps?.length || 0) < 5)
.map(a => ({
algorithm: a.name,
complexity: a.complexity,
file: a.file,
severity: 'warning'
})),
// Data relationships without descriptions
incompleteRelationships: (deepAnalysis.data_structures?.relationships || [])
.filter(r => !r.description)
.map(r => ({from: r.from, to: r.to, severity: 'info'})),
// Diagram validation issues
diagramIssues: (deepAnalysis.diagrams?.validation || [])
.filter(d => !d.valid)
.map(d => ({file: d.file, issues: d.issues, severity: 'critical'}))
};
}
```
### Step 2: Build Dynamic Questions
```javascript
function buildComplianceQuestions(issues) {
const questions = [];
if (issues.missingSections.length > 0) {
questions.push({
question: `发现 ${issues.missingSections.length} 个章节内容不完整,需要补充哪些?`,
header: "章节补充",
multiSelect: true,
options: issues.missingSections.slice(0, 4).map(s => ({
label: s.section,
description: s.suggestion
}))
});
}
if (issues.weakDescriptions.length > 0) {
questions.push({
question: `以下 ${issues.weakDescriptions.length} 个功能描述过于简短,请选择需要详细说明的:`,
header: "功能描述",
multiSelect: true,
options: issues.weakDescriptions.slice(0, 4).map(f => ({
label: f.feature,
description: `当前:${f.current.substring(0, 30)}...`
}))
});
}
if (issues.complexAlgorithms.length > 0) {
questions.push({
question: `发现 ${issues.complexAlgorithms.length} 个复杂算法缺少详细流程图,是否生成?`,
header: "算法详解",
multiSelect: false,
options: [
{label: "全部生成 (推荐)", description: "为所有复杂算法生成含分支/循环的流程图"},
{label: "仅最复杂的", description: `仅为 ${issues.complexAlgorithms[0]?.algorithm} 生成`},
{label: "跳过", description: "保持当前简单流程图"}
]
});
}
questions.push({
question: "如何处理当前文档?",
header: "操作",
multiSelect: false,
options: [
{label: "应用修改并继续", description: "应用上述选择,继续检查"},
{label: "完成文档", description: "当前文档满足要求,生成最终版本"},
{label: "重新分析", description: "使用不同配置重新分析代码"}
]
});
return questions.slice(0, 4);
}
```
### Step 3: Apply Updates
```javascript
async function applyComplianceUpdates(responses, issues, analyses, outputDir) {
const updates = [];
if (responses['章节补充']) {
for (const section of responses['章节补充']) {
const sectionAnalysis = await Task({
subagent_type: "cli-explore-agent",
prompt: `深入分析 ${section.section} 所需内容...`
});
updates.push({type: 'section_supplement', section: section.section, data: sectionAnalysis});
}
}
if (responses['算法详解'] === '全部生成 (推荐)') {
for (const algo of issues.complexAlgorithms) {
const detailedSteps = await analyzeAlgorithmInDepth(algo, analyses);
const flowchart = generateAlgorithmFlowchart({
name: algo.algorithm,
inputs: detailedSteps.inputs,
outputs: detailedSteps.outputs,
steps: detailedSteps.steps
});
Write(`${outputDir}/diagrams/algorithm-${sanitizeId(algo.algorithm)}-detailed.mmd`, flowchart);
updates.push({type: 'algorithm_flowchart', algorithm: algo.algorithm});
}
}
return updates;
}
```
### Step 4: Iteration Loop
```javascript
async function runComplianceLoop(documentPath, analyses, metadata, outputDir) {
let iteration = 0;
const maxIterations = 5;
while (iteration < maxIterations) {
iteration++;
// Validate current document
const document = Read(documentPath);
const validation = validateCPCCCompliance(document, analyses);
// Extract issues
const issues = extractComplianceIssues(validation, analyses);
const totalIssues = Object.values(issues).flat().length;
if (totalIssues === 0) {
console.log("✅ 所有检查通过,文档符合 CPCC 要求");
break;
}
// Ask user
const questions = buildComplianceQuestions(issues);
const responses = await AskUserQuestion({questions});
if (responses['操作'] === '完成文档') break;
if (responses['操作'] === '重新分析') return {action: 'restart'};
// Apply updates
const updates = await applyComplianceUpdates(responses, issues, analyses, outputDir);
// Regenerate document
const updatedDocument = regenerateDocument(document, updates, analyses);
Write(documentPath, updatedDocument);
// Archive iteration
Write(`${outputDir}/iterations/v${iteration}.md`, document);
}
return {action: 'finalized', iterations: iteration};
}
```
## Output
Final compliant document + iteration history in `iterations/`.

View File

@@ -0,0 +1,121 @@
# CPCC Compliance Requirements
China Copyright Protection Center (CPCC) requirements for software design specification.
## When to Use
| Phase | Usage | Section |
|-------|-------|---------|
| Phase 4 | Check document structure before assembly | Document Requirements, Mandatory Sections |
| Phase 4 | Apply correct figure numbering | Figure Numbering Convention |
| Phase 5 | Validate before each iteration | Validation Function |
| Phase 5 | Handle failures during refinement | Error Handling |
---
## Document Requirements
### Format
- [ ] 页眉包含软件名称和版本号
- [ ] 页码位于右上角说明
- [ ] 每页不少于30行文字图表页除外
- [ ] A4纵向排版文字从左至右
### Mandatory Sections (7 章节)
- [ ] 1. 软件概述
- [ ] 2. 系统架构图
- [ ] 3. 功能模块设计
- [ ] 4. 核心算法与流程
- [ ] 5. 数据结构设计
- [ ] 6. 接口设计
- [ ] 7. 异常处理设计
### Content Requirements
- [ ] 所有内容基于代码分析
- [ ] 无臆测或未来计划
- [ ] 无原始指令性文字
- [ ] Mermaid 语法正确
- [ ] 图表编号和说明完整
## Validation Function
```javascript
function validateCPCCCompliance(document, analyses) {
const checks = [
{name: "软件概述完整性", pass: document.includes("## 1. 软件概述")},
{name: "系统架构图存在", pass: document.includes("图2-1 系统架构图")},
{name: "功能模块设计完整", pass: document.includes("## 3. 功能模块设计")},
{name: "核心算法描述", pass: document.includes("## 4. 核心算法与流程")},
{name: "数据结构设计", pass: document.includes("## 5. 数据结构设计")},
{name: "接口设计说明", pass: document.includes("## 6. 接口设计")},
{name: "异常处理设计", pass: document.includes("## 7. 异常处理设计")},
{name: "Mermaid图表语法", pass: !document.includes("mermaid error")},
{name: "页眉信息", pass: document.includes("页眉")},
{name: "页码说明", pass: document.includes("页码")}
];
return {
passed: checks.filter(c => c.pass).length,
total: checks.length,
details: checks
};
}
```
## Software Categories
| Category | Document Focus |
|----------|----------------|
| 命令行工具 (CLI) | 命令、参数、使用流程 |
| 后端服务/API | 端点、协议、数据流 |
| SDK/库 | 接口、集成、使用示例 |
| 数据处理系统 | 数据流、转换、ETL |
| 自动化脚本 | 工作流、触发器、调度 |
## Figure Numbering Convention
| Section | Figure | Title |
|---------|--------|-------|
| 2 | 图2-1 | 系统架构图 |
| 3 | 图3-1 | 功能模块结构图 |
| 4 | 图4-N | {算法名称}流程图 |
| 5 | 图5-1 | 数据结构类图 |
| 6 | 图6-N | {接口名称}时序图 |
| 7 | 图7-1 | 异常处理流程图 |
## Error Handling
| Error | Recovery |
|-------|----------|
| Analysis timeout | Reduce scope, retry |
| Missing section data | Re-run targeted agent |
| Diagram validation fails | Regenerate with fixes |
| User abandons iteration | Save progress, allow resume |
---
## Integration with Phases
**Phase 4 - Document Assembly**:
```javascript
// Before assembling document
const docChecks = [
{check: "页眉格式", value: `<!-- 页眉:${metadata.software_name} - 版本号:${metadata.version} -->`},
{check: "页码说明", value: `<!-- 注:最终文档页码位于每页右上角 -->`}
];
// Apply figure numbering from convention table
const figureNumbers = getFigureNumbers(sectionIndex);
```
**Phase 5 - Compliance Refinement**:
```javascript
// In 05-compliance-refinement.md
const validation = validateCPCCCompliance(document, analyses);
if (validation.passed < validation.total) {
// Failed checks become discovery questions
const failedChecks = validation.details.filter(d => !d.pass);
discoveries.complianceIssues = failedChecks;
}
```

View File

@@ -0,0 +1,89 @@
---
name: project-analyze
description: Multi-phase iterative project analysis with Mermaid diagrams. Generates architecture reports, design reports, method analysis reports. Use when analyzing codebases, understanding project structure, reviewing architecture, exploring design patterns, or documenting system components. Triggers on "analyze project", "architecture report", "design analysis", "code structure", "system overview".
allowed-tools: Task, AskUserQuestion, Read, Bash, Glob, Grep, Write
---
# Project Analysis Skill
Generate comprehensive project analysis reports through multi-phase iterative workflow.
## Execution Flow
```
┌─────────────────────────────────────────────────────────────────┐
│ Phase 1: Requirements Discovery │
│ → Read: phases/01-requirements-discovery.md │
│ → Collect: report type, depth level, scope │
├─────────────────────────────────────────────────────────────────┤
│ Phase 2: Project Exploration │
│ → Read: phases/02-project-exploration.md │
│ → Launch: parallel cli-explore-agents │
├─────────────────────────────────────────────────────────────────┤
│ Phase 3: Deep Analysis │
│ → Read: phases/03-deep-analysis.md │
│ → Execute: Gemini CLI with exploration context │
├─────────────────────────────────────────────────────────────────┤
│ Phase 3.5: Diagram Generation │
│ → Read: phases/03.5-diagram-generation.md │
│ → Reference: ../_shared/mermaid-utils.md │
│ → Generate: Mermaid diagrams based on report type │
├─────────────────────────────────────────────────────────────────┤
│ Phase 4: Report Generation │
│ → Read: phases/04-report-generation.md │
│ → Reference: specs/quality-standards.md (Report Requirements) │
│ → Assemble: Markdown report with embedded diagrams │
├─────────────────────────────────────────────────────────────────┤
│ Phase 5: Iterative Refinement │
│ → Read: phases/05-iterative-refinement.md │
│ → Reference: specs/quality-standards.md (Quality Gates) │
│ → Validate: run quality checks before each iteration │
│ → Loop: discovery-driven questions until all gates pass │
└─────────────────────────────────────────────────────────────────┘
```
## Report Types
| Type | Output | Focus |
|------|--------|-------|
| `architecture` | ARCHITECTURE-REPORT.md | System structure, modules, dependencies |
| `design` | DESIGN-REPORT.md | Patterns, classes, interfaces |
| `methods` | METHODS-REPORT.md | Algorithms, critical paths, APIs |
| `comprehensive` | COMPREHENSIVE-REPORT.md | All above combined |
## Directory Setup
```bash
timestamp=$(date +%Y%m%d-%H%M%S)
dir=".workflow/.scratchpad/analyze-$timestamp"
mkdir -p "$dir/diagrams" "$dir/iterations"
echo "$dir"
```
## Reference Documents
| Document | Purpose |
|----------|---------|
| [phases/01-requirements-discovery.md](phases/01-requirements-discovery.md) | User interaction, config collection |
| [phases/02-project-exploration.md](phases/02-project-exploration.md) | Parallel agent exploration |
| [phases/03-deep-analysis.md](phases/03-deep-analysis.md) | Gemini CLI analysis |
| [phases/03.5-diagram-generation.md](phases/03.5-diagram-generation.md) | Mermaid diagram generation |
| [phases/04-report-generation.md](phases/04-report-generation.md) | Report assembly |
| [phases/05-iterative-refinement.md](phases/05-iterative-refinement.md) | Discovery-driven refinement |
| [specs/quality-standards.md](specs/quality-standards.md) | Quality gates, error handling |
| [../_shared/mermaid-utils.md](../_shared/mermaid-utils.md) | Shared Mermaid utilities |
## Output Structure
```
.workflow/.scratchpad/analyze-{timestamp}/
├── analysis-config.json
├── exploration-*.json
├── deep-analysis.json
├── diagrams/
│ ├── manifest.json
│ ├── validation.json
│ └── *.mmd
├── {TYPE}-REPORT.md
└── iterations/
```

View File

@@ -0,0 +1,79 @@
# Phase 1: Requirements Discovery
Collect user requirements before analysis begins.
## Execution
### Step 1: Report Type Selection
```javascript
AskUserQuestion({
questions: [{
question: "What type of project analysis report would you like?",
header: "Report Type",
multiSelect: false,
options: [
{label: "Architecture (Recommended)", description: "System structure, module relationships, layer analysis, dependency graph"},
{label: "Design", description: "Design patterns, class relationships, component interactions, abstraction analysis"},
{label: "Methods", description: "Key algorithms, critical code paths, core function explanations with examples"},
{label: "Comprehensive", description: "All above combined into a complete project analysis"}
]
}]
})
```
### Step 2: Depth Level Selection
```javascript
AskUserQuestion({
questions: [{
question: "What depth level do you need?",
header: "Depth",
multiSelect: false,
options: [
{label: "Overview", description: "High-level understanding, suitable for onboarding"},
{label: "Detailed", description: "In-depth analysis with code examples"},
{label: "Deep-Dive", description: "Exhaustive analysis with implementation details"}
]
}]
})
```
### Step 3: Scope Definition
```javascript
AskUserQuestion({
questions: [{
question: "What scope should the analysis cover?",
header: "Scope",
multiSelect: false,
options: [
{label: "Full Project", description: "Analyze entire codebase"},
{label: "Specific Module", description: "Focus on a specific module or directory"},
{label: "Custom Path", description: "Specify custom path pattern"}
]
}]
})
```
## Focus Areas Mapping
| Report Type | Focus Areas |
|-------------|-------------|
| Architecture | Layer Structure, Module Dependencies, Entry Points, Data Flow |
| Design | Design Patterns, Class Relationships, Interface Contracts, State Management |
| Methods | Core Algorithms, Critical Paths, Public APIs, Complex Logic |
| Comprehensive | All above combined |
## Output
Save configuration to `analysis-config.json`:
```json
{
"type": "architecture|design|methods|comprehensive",
"depth": "overview|detailed|deep-dive",
"scope": "**/*|src/**/*|custom",
"focus_areas": ["..."]
}
```

View File

@@ -0,0 +1,74 @@
# Phase 2: Project Exploration
Launch parallel exploration agents based on report type.
## Execution
### Step 1: Map Exploration Angles
```javascript
const angleMapping = {
architecture: ["Layer Structure", "Module Dependencies", "Entry Points", "Data Flow"],
design: ["Design Patterns", "Class Relationships", "Interface Contracts", "State Management"],
methods: ["Core Algorithms", "Critical Paths", "Public APIs", "Complex Logic"],
comprehensive: ["Layer Structure", "Design Patterns", "Core Algorithms", "Data Flow"]
};
const angles = angleMapping[config.type];
```
### Step 2: Launch Parallel Agents
For each angle, launch an exploration agent:
```javascript
Task({
subagent_type: "cli-explore-agent",
description: `Explore: ${angle}`,
prompt: `
## Exploration Objective
Execute **${angle}** exploration for project analysis report.
## Context
- **Angle**: ${angle}
- **Report Type**: ${config.type}
- **Depth**: ${config.depth}
- **Scope**: ${config.scope}
## Exploration Protocol
1. Structural Discovery (get_modules_by_depth, rg, glob)
2. Pattern Recognition (conventions, naming, organization)
3. Relationship Mapping (dependencies, integration points)
## Output Format
{
"angle": "${angle}",
"findings": {
"structure": [...],
"patterns": [...],
"relationships": [...],
"key_files": [{path, relevance, rationale}]
},
"insights": [...]
}
`
})
```
### Step 3: Aggregate Results
Merge all exploration results into unified findings:
```javascript
const aggregatedFindings = {
structure: [], // from all angles
patterns: [], // from all angles
relationships: [], // from all angles
key_files: [], // deduplicated
insights: [] // prioritized
};
```
## Output
Save exploration results to `exploration-{angle}.json` files.

View File

@@ -0,0 +1,58 @@
# Phase 3: Deep Analysis
Execute deep analysis using Gemini CLI with exploration context.
## Execution
### Step 1: Prepare CLI Prompt
```bash
ccw cli -p "
PURPOSE: Generate ${type} analysis report for project
TASK:
• Analyze project structure and patterns from ${type} perspective
• Focus on: ${focus_areas}
• Depth level: ${depth}
• Key files: ${key_files}
MODE: analysis
CONTEXT: @**/* | Exploration results
EXPECTED:
- Structured analysis
- Code references (file:line format)
- Mermaid diagram data
- Actionable insights
RULES: $(cat ~/.claude/workflows/cli-templates/protocols/analysis-protocol.md)
" --tool gemini --mode analysis
```
### Step 2: Parse Analysis Results
Extract structured data from CLI response:
```javascript
const deepAnalysis = {
findings: [], // Analyzed findings with confidence scores
patterns: [], // Identified patterns with consistency scores
dependencies: [], // Dependency relationships
recommendations: [], // Prioritized recommendations
sections: [], // Report section data
diagram_data: {} // Data for diagram generation
};
```
### Step 3: Validate Analysis Quality
Check analysis completeness:
```javascript
const qualityChecks = {
has_executive_summary: Boolean,
focus_areas_covered: config.focus_areas.every(area => analysis.covers(area)),
code_references_valid: analysis.references.every(ref => fileExists(ref)),
insights_actionable: analysis.insights.filter(i => i.actionable).length > 0
};
```
## Output
Save analysis results to `deep-analysis.json`.

View File

@@ -0,0 +1,86 @@
# Phase 3.5: Diagram Generation
Generate Mermaid diagrams based on report type and analysis data.
> **Reference**: See [mermaid-utils.md](../../_shared/mermaid-utils.md) for utility functions.
## Execution
### Step 1: Determine Required Diagrams
```javascript
const diagramRequirements = {
architecture: [
{type: 'architecture', format: 'graph TD', file: 'architecture.mmd'},
{type: 'layers', format: 'graph TD', file: 'layers.mmd'},
{type: 'dependencies', format: 'graph LR', file: 'dependencies.mmd'},
{type: 'dataflow', format: 'flowchart LR', file: 'dataflow.mmd'}
],
design: [
{type: 'class', format: 'classDiagram', file: 'class-diagram.mmd'},
{type: 'components', format: 'graph TD', file: 'components.mmd'},
{type: 'patterns', format: 'graph TD', file: 'patterns.mmd'},
{type: 'state', format: 'stateDiagram-v2', file: 'state.mmd'}
],
methods: [
{type: 'algorithm', format: 'flowchart TD', file: 'algorithm-*.mmd'},
{type: 'sequence', format: 'sequenceDiagram', file: 'sequence-*.mmd'},
{type: 'critical_path', format: 'flowchart LR', file: 'critical-path.mmd'},
{type: 'api', format: 'graph LR', file: 'api.mmd'}
],
comprehensive: [
{type: 'architecture', format: 'graph TD', file: 'architecture.mmd'},
{type: 'class', format: 'classDiagram', file: 'class-diagram.mmd'},
{type: 'sequence', format: 'sequenceDiagram', file: 'sequence-main.mmd'},
{type: 'dataflow', format: 'flowchart LR', file: 'dataflow.mmd'}
]
};
const required = diagramRequirements[config.type];
```
### Step 2: Generate Each Diagram
Use shared utilities from `../_shared/mermaid-utils.md`:
```javascript
// Import utilities
const { sanitizeId, escapeLabel, generateClassDiagram, generateSequenceDiagram, validateMermaidSyntax } = require('../_shared/mermaid-utils.md');
for (const diagram of required) {
const content = generateDiagram(diagram.type, diagram.format, analysisData);
Write(`${outputDir}/diagrams/${diagram.file}`, content);
}
```
### Step 3: Validate All Diagrams
```javascript
const validationResults = validateDiagramDirectory(`${outputDir}/diagrams`);
const failedDiagrams = validationResults.filter(r => !r.valid);
if (failedDiagrams.length > 0) {
// Regenerate failed diagrams
for (const failed of failedDiagrams) {
regenerateDiagram(failed.file, failed.issues);
}
}
```
### Step 4: Create Diagram Manifest
```javascript
Write(`${outputDir}/diagrams/manifest.json`, JSON.stringify({
generated_at: new Date().toISOString(),
diagrams: required.map(d => ({
type: d.type,
file: d.file,
format: d.format
})),
validation: validationResults
}, null, 2));
```
## Output
Save diagrams to `diagrams/` folder with `manifest.json`.

View File

@@ -0,0 +1,94 @@
# Phase 4: Report Generation
Assemble analysis and diagrams into structured Markdown report.
## Execution
### Step 1: Determine Report Sections
```javascript
const reportSections = {
architecture: [
"# Architecture Report",
"## Executive Summary",
"## System Overview",
"## Layer Analysis",
"## Module Dependencies",
"## Data Flow",
"## Entry Points & Critical Paths",
"## Dependency Graph",
"## Recommendations"
],
design: [
"# Design Report",
"## Executive Summary",
"## Design Patterns Used",
"## Class Relationships",
"## Interface Contracts",
"## State Management",
"## Component Diagrams",
"## Design Recommendations"
],
methods: [
"# Key Methods Report",
"## Executive Summary",
"## Core Algorithms",
"## Critical Code Paths",
"## Public API Reference",
"## Complex Logic Breakdown",
"## Sequence Diagrams",
"## Optimization Suggestions"
],
comprehensive: [
"# Comprehensive Project Analysis",
"## Executive Summary",
"## Architecture Overview",
"## Design Patterns & Principles",
"## Key Methods & Algorithms",
"## System Diagrams",
"## Recommendations & Next Steps"
]
};
const sections = reportSections[config.type];
```
### Step 2: Generate Report Content
```javascript
let report = '';
for (const section of sections) {
report += section + '\n\n';
// Add section content from analysis
const sectionContent = generateSectionContent(section, deepAnalysis);
report += sectionContent + '\n\n';
// Embed relevant diagrams
const relatedDiagrams = findRelatedDiagrams(section, diagrams);
for (const diagram of relatedDiagrams) {
report += `\`\`\`mermaid\n${Read(diagram.path)}\n\`\`\`\n\n`;
}
}
```
### Step 3: Add Code References
Format all code references as `file:line`:
```javascript
// Example: src/auth/login.ts:42
const codeRef = `${finding.file}:${finding.line}`;
```
### Step 4: Write Report
```javascript
const reportFileName = `${config.type.toUpperCase()}-REPORT.md`;
Write(`${outputDir}/${reportFileName}`, report);
```
## Output
Generate `{TYPE}-REPORT.md` in output directory.

View File

@@ -0,0 +1,124 @@
# Phase 5: Iterative Refinement
Discovery-driven refinement based on analysis findings.
## Execution
### Step 1: Extract Discoveries
```javascript
function extractDiscoveries(deepAnalysis) {
return {
ambiguities: deepAnalysis.findings.filter(f => f.confidence < 0.7),
complexityHotspots: deepAnalysis.findings.filter(f => f.complexity === 'high'),
patternDeviations: deepAnalysis.patterns.filter(p => p.consistency < 0.8),
unclearDependencies: deepAnalysis.dependencies.filter(d => d.type === 'implicit'),
potentialIssues: deepAnalysis.recommendations.filter(r => r.priority === 'investigate'),
depthOpportunities: deepAnalysis.sections.filter(s => s.has_more_detail)
};
}
const discoveries = extractDiscoveries(deepAnalysis);
```
### Step 2: Build Dynamic Questions
Questions emerge from discoveries, NOT predetermined:
```javascript
function buildDynamicQuestions(discoveries, config) {
const questions = [];
if (discoveries.ambiguities.length > 0) {
questions.push({
question: `Analysis found ambiguity in "${discoveries.ambiguities[0].area}". Which interpretation is correct?`,
header: "Clarify",
options: discoveries.ambiguities[0].interpretations
});
}
if (discoveries.complexityHotspots.length > 0) {
questions.push({
question: `These areas have high complexity. Which would you like explained?`,
header: "Deep-Dive",
multiSelect: true,
options: discoveries.complexityHotspots.slice(0, 4).map(h => ({
label: h.name,
description: h.summary
}))
});
}
if (discoveries.patternDeviations.length > 0) {
questions.push({
question: `Found pattern deviations. Should these be highlighted in the report?`,
header: "Patterns",
options: [
{label: "Yes, include analysis", description: "Add section explaining deviations"},
{label: "No, skip", description: "Omit from report"}
]
});
}
// Always include action question
questions.push({
question: "How would you like to proceed?",
header: "Action",
options: [
{label: "Continue refining", description: "Address more discoveries"},
{label: "Finalize report", description: "Generate final output"},
{label: "Change scope", description: "Modify analysis scope"}
]
});
return questions.slice(0, 4); // Max 4 questions
}
```
### Step 3: Apply Refinements
```javascript
if (userAction === "Continue refining") {
// Apply selected refinements
for (const selection of userSelections) {
applyRefinement(selection, deepAnalysis, report);
}
// Save iteration
Write(`${outputDir}/iterations/iteration-${iterationCount}.json`, {
timestamp: new Date().toISOString(),
discoveries: discoveries,
selections: userSelections,
changes: appliedChanges
});
// Loop back to Step 1
iterationCount++;
goto Step1;
}
if (userAction === "Finalize report") {
// Proceed to final output
goto FinalizeReport;
}
```
### Step 4: Finalize Report
```javascript
// Add iteration history to report metadata
const finalReport = {
...report,
metadata: {
iterations: iterationCount,
refinements_applied: allRefinements,
final_discoveries: discoveries
}
};
Write(`${outputDir}/${config.type.toUpperCase()}-REPORT.md`, finalReport);
```
## Output
Updated report with refinements, saved iterations to `iterations/` folder.

View File

@@ -0,0 +1,115 @@
# Quality Standards
Quality gates and requirements for project analysis reports.
## When to Use
| Phase | Usage | Section |
|-------|-------|---------|
| Phase 4 | Check report structure before assembly | Report Requirements |
| Phase 5 | Validate before each iteration | Quality Gates |
| Phase 5 | Handle failures during refinement | Error Handling |
---
## Report Requirements
**Use in Phase 4**: Ensure report includes all required elements.
| Requirement | Check | How to Fix |
|-------------|-------|------------|
| Executive Summary | 3-5 key takeaways | Extract from analysis findings |
| Visual diagrams | Valid Mermaid syntax | Use `../_shared/mermaid-utils.md` |
| Code references | `file:line` format | Link to actual source locations |
| Recommendations | Actionable, specific | Derive from analysis insights |
| Consistent depth | Match user's depth level | Adjust detail per config.depth |
---
## Quality Gates
**Use in Phase 5**: Run these checks before asking user questions.
```javascript
function runQualityGates(report, config, diagrams) {
const gates = [
{
name: "focus_areas_covered",
check: () => config.focus_areas.every(area =>
report.toLowerCase().includes(area.toLowerCase())
),
fix: "Re-analyze missing focus areas"
},
{
name: "diagrams_valid",
check: () => diagrams.every(d => d.valid),
fix: "Regenerate failed diagrams with mermaid-utils"
},
{
name: "code_refs_accurate",
check: () => extractCodeRefs(report).every(ref => fileExists(ref)),
fix: "Update invalid file references"
},
{
name: "no_placeholders",
check: () => !report.includes('[TODO]') && !report.includes('[PLACEHOLDER]'),
fix: "Fill in all placeholder content"
},
{
name: "recommendations_specific",
check: () => !report.includes('consider') || report.includes('specifically'),
fix: "Make recommendations project-specific"
}
];
const results = gates.map(g => ({...g, passed: g.check()}));
const allPassed = results.every(r => r.passed);
return { allPassed, results };
}
```
**Integration with Phase 5**:
```javascript
// In 05-iterative-refinement.md
const { allPassed, results } = runQualityGates(report, config, diagrams);
if (allPassed) {
// All gates passed → ask user to confirm or finalize
} else {
// Gates failed → include failed gates in discovery questions
const failedGates = results.filter(r => !r.passed);
discoveries.qualityIssues = failedGates;
}
```
---
## Error Handling
**Use when**: Encountering errors during any phase.
| Error | Detection | Recovery |
|-------|-----------|----------|
| CLI timeout | Bash exits with timeout | Reduce scope via `config.scope`, retry |
| Exploration failure | Agent returns error | Fall back to `Read` + `Grep` directly |
| User abandons | User selects "cancel" | Save to `iterations/`, allow resume |
| Invalid scope path | Path doesn't exist | `AskUserQuestion` to correct path |
| Diagram validation fails | `validateMermaidSyntax` returns issues | Regenerate with stricter escaping |
**Recovery Flow**:
```javascript
try {
await executePhase(phase);
} catch (error) {
const recovery = ERROR_HANDLERS[error.type];
if (recovery) {
await recovery.action(error, config);
// Retry phase or continue
} else {
// Save progress and ask user
Write(`${outputDir}/error-state.json`, { phase, error, config });
AskUserQuestion({ question: "遇到错误,如何处理?", ... });
}
}
```

1
ccw/.gitignore vendored
View File

@@ -1,3 +1,4 @@
# TypeScript build output
dist/
.ace-tool/

View File

@@ -769,9 +769,9 @@ export async function handleCliRoutes(ctx: RouteContext): Promise<boolean> {
if (pathname === '/api/cli/code-index-mcp' && req.method === 'PUT') {
handlePostRequest(req, res, async (body: unknown) => {
try {
const { provider } = body as { provider: 'codexlens' | 'ace' };
if (!provider || !['codexlens', 'ace'].includes(provider)) {
return { error: 'Invalid provider. Must be "codexlens" or "ace"', status: 400 };
const { provider } = body as { provider: 'codexlens' | 'ace' | 'none' };
if (!provider || !['codexlens', 'ace', 'none'].includes(provider)) {
return { error: 'Invalid provider. Must be "codexlens", "ace", or "none"', status: 400 };
}
const result = updateCodeIndexMcp(initialPath, provider);

View File

@@ -21,9 +21,24 @@ let nativeResumeEnabled = localStorage.getItem('ccw-native-resume') !== 'false';
// Recursive Query settings (for hierarchical storage aggregation)
let recursiveQueryEnabled = localStorage.getItem('ccw-recursive-query') !== 'false'; // default true
// Code Index MCP provider (codexlens or ace)
// Code Index MCP provider (codexlens, ace, or none)
let codeIndexMcpProvider = 'codexlens';
// ========== Helper Functions ==========
/**
* Get the context-tools filename based on provider
*/
function getContextToolsFileName(provider) {
switch (provider) {
case 'ace':
return 'context-tools-ace.md';
case 'none':
return 'context-tools-none.md';
default:
return 'context-tools.md';
}
}
// ========== Initialization ==========
function initCliStatus() {
// Load all statuses in one call using aggregated endpoint
@@ -637,9 +652,17 @@ function renderCliStatus() {
onclick="setCodeIndexMcpProvider('ace')">
ACE
</button>
<button class="code-mcp-btn px-3 py-1.5 text-xs font-medium rounded-md transition-all ${codeIndexMcpProvider === 'none' ? 'bg-primary text-primary-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'}"
onclick="setCodeIndexMcpProvider('none')">
None
</button>
</div>
</div>
<p class="cli-setting-desc">Code search provider (updates CLAUDE.md context-tools reference)</p>
<p class="cli-setting-desc text-xs text-muted-foreground mt-1">
<i data-lucide="file-text" class="w-3 h-3 inline-block mr-1"></i>
Current: <code class="bg-muted px-1 rounded">${getContextToolsFileName(codeIndexMcpProvider)}</code>
</p>
</div>
</div>
</div>
@@ -775,7 +798,8 @@ async function setCodeIndexMcpProvider(provider) {
if (window.claudeCliToolsConfig && window.claudeCliToolsConfig.settings) {
window.claudeCliToolsConfig.settings.codeIndexMcp = provider;
}
showRefreshToast(`Code Index MCP switched to ${provider === 'ace' ? 'ACE (Augment)' : 'CodexLens'}`, 'success');
const providerName = provider === 'ace' ? 'ACE (Augment)' : provider === 'none' ? 'None (Built-in only)' : 'CodexLens';
showRefreshToast(`Code Index MCP switched to ${providerName}`, 'success');
// Re-render both CLI status and settings section
if (typeof renderCliStatus === 'function') renderCliStatus();
if (typeof renderCliSettingsSection === 'function') renderCliSettingsSection();

View File

@@ -996,9 +996,14 @@ function renderCliSettingsSection() {
'<select class="cli-setting-select" onchange="setCodeIndexMcpProvider(this.value)">' +
'<option value="codexlens"' + (codeIndexMcpProvider === 'codexlens' ? ' selected' : '') + '>CodexLens</option>' +
'<option value="ace"' + (codeIndexMcpProvider === 'ace' ? ' selected' : '') + '>ACE (Augment)</option>' +
'<option value="none"' + (codeIndexMcpProvider === 'none' ? ' selected' : '') + '>None (Built-in)</option>' +
'</select>' +
'</div>' +
'<p class="cli-setting-desc">' + t('cli.codeIndexMcpDesc') + '</p>' +
'<p class="cli-setting-desc text-xs text-muted-foreground">' +
'<i data-lucide="file-text" class="w-3 h-3 inline-block mr-1"></i>' +
'Current: <code class="bg-muted px-1 rounded">' + getContextToolsFileName(codeIndexMcpProvider) + '</code>' +
'</p>' +
'</div>' +
'</div>';

View File

@@ -70,7 +70,7 @@ async function renderCliHistoryView() {
: '';
historyHtml += '<div class="history-item' + (isSelected ? ' history-item-selected' : '') + '" ' +
'onclick="' + (isMultiSelectMode ? 'toggleExecutionSelection(\'' + exec.id + '\')' : 'showExecutionDetail(\'' + exec.id + (exec.sourceDir ? '\',\'' + escapeHtml(exec.sourceDir) : '') + '\')') + '">' +
'onclick="' + (isMultiSelectMode ? 'toggleExecutionSelection(\'' + exec.id + '\')' : 'showExecutionDetail(\'' + exec.id + '\', \'' + (exec.sourceDir || '').replace(/\'/g, "\\'") + '\')') + '">' +
checkboxHtml +
'<div class="history-item-main">' +
'<div class="history-item-header">' +
@@ -87,14 +87,17 @@ async function renderCliHistoryView() {
'<div class="history-item-meta">' +
'<span class="history-time"><i data-lucide="clock" class="w-3 h-3"></i> ' + timeAgo + '</span>' +
'<span class="history-duration"><i data-lucide="timer" class="w-3 h-3"></i> ' + duration + '</span>' +
'<span class="history-id"><i data-lucide="hash" class="w-3 h-3"></i> ' + exec.id.split('-')[0] + '</span>' +
'<span class="history-id" title="' + exec.id + '"><i data-lucide="hash" class="w-3 h-3"></i> ' + exec.id.substring(0, 13) + '...' + exec.id.split('-').pop() + '</span>' +
'</div>' +
'</div>' +
'<div class="history-item-actions">' +
'<button class="btn-icon" onclick="event.stopPropagation(); showExecutionDetail(\'' + exec.id + '\')" title="View Details">' +
'<button class="btn-icon" onclick="event.stopPropagation(); copyExecutionId(\'' + exec.id + '\')" title="Copy ID">' +
'<i data-lucide="copy" class="w-4 h-4"></i>' +
'</button>' +
'<button class="btn-icon" onclick="event.stopPropagation(); showExecutionDetail(\'' + exec.id + '\', \'' + (exec.sourceDir || '').replace(/'/g, "\\'") + '\')" title="View Details">' +
'<i data-lucide="eye" class="w-4 h-4"></i>' +
'</button>' +
'<button class="btn-icon btn-danger" onclick="event.stopPropagation(); confirmDeleteExecution(\'' + exec.id + (exec.sourceDir ? '\',\'' + escapeHtml(exec.sourceDir) : '') + '\')" title="Delete">' +
'<button class="btn-icon btn-danger" onclick="event.stopPropagation(); confirmDeleteExecution(\'' + exec.id + '\', \'' + (exec.sourceDir || '').replace(/'/g, "\\'") + '\')" title="Delete">' +
'<i data-lucide="trash-2" class="w-4 h-4"></i>' +
'</button>' +
'</div>' +

View File

@@ -42,7 +42,7 @@ export interface ClaudeCliToolsConfig {
nativeResume: boolean;
recursiveQuery: boolean;
cache: ClaudeCacheSettings;
codeIndexMcp: 'codexlens' | 'ace'; // Code Index MCP provider
codeIndexMcp: 'codexlens' | 'ace' | 'none'; // Code Index MCP provider
};
}
@@ -308,7 +308,7 @@ export function getClaudeCliToolsInfo(projectDir: string): {
*/
export function updateCodeIndexMcp(
projectDir: string,
provider: 'codexlens' | 'ace'
provider: 'codexlens' | 'ace' | 'none'
): { success: boolean; error?: string; config?: ClaudeCliToolsConfig } {
try {
// Update config
@@ -319,21 +319,28 @@ export function updateCodeIndexMcp(
// Only update global CLAUDE.md (consistent with Chinese response / Windows platform)
const globalClaudeMdPath = path.join(os.homedir(), '.claude', 'CLAUDE.md');
// Define patterns for all formats
const codexlensPattern = /@~\/\.claude\/workflows\/context-tools\.md/g;
const acePattern = /@~\/\.claude\/workflows\/context-tools-ace\.md/g;
const nonePattern = /@~\/\.claude\/workflows\/context-tools-none\.md/g;
// Determine target file based on provider
const targetFile = provider === 'ace'
? '@~/.claude/workflows/context-tools-ace.md'
: provider === 'none'
? '@~/.claude/workflows/context-tools-none.md'
: '@~/.claude/workflows/context-tools.md';
if (!fs.existsSync(globalClaudeMdPath)) {
// If global CLAUDE.md doesn't exist, check project-level
const projectClaudeMdPath = path.join(projectDir, '.claude', 'CLAUDE.md');
if (fs.existsSync(projectClaudeMdPath)) {
let content = fs.readFileSync(projectClaudeMdPath, 'utf-8');
// Define patterns for both formats
const codexlensPattern = /@~\/\.claude\/workflows\/context-tools\.md/g;
const acePattern = /@~\/\.claude\/workflows\/context-tools-ace\.md/g;
if (provider === 'ace') {
content = content.replace(codexlensPattern, '@~/.claude/workflows/context-tools-ace.md');
} else {
content = content.replace(acePattern, '@~/.claude/workflows/context-tools.md');
}
// Replace any existing pattern with the target
content = content.replace(codexlensPattern, targetFile);
content = content.replace(acePattern, targetFile);
content = content.replace(nonePattern, targetFile);
fs.writeFileSync(projectClaudeMdPath, content, 'utf-8');
console.log(`[claude-cli-tools] Updated project CLAUDE.md to use ${provider} (no global CLAUDE.md found)`);
@@ -342,14 +349,10 @@ export function updateCodeIndexMcp(
// Update global CLAUDE.md (primary target)
let content = fs.readFileSync(globalClaudeMdPath, 'utf-8');
const codexlensPattern = /@~\/\.claude\/workflows\/context-tools\.md/g;
const acePattern = /@~\/\.claude\/workflows\/context-tools-ace\.md/g;
if (provider === 'ace') {
content = content.replace(codexlensPattern, '@~/.claude/workflows/context-tools-ace.md');
} else {
content = content.replace(acePattern, '@~/.claude/workflows/context-tools.md');
}
// Replace any existing pattern with the target
content = content.replace(codexlensPattern, targetFile);
content = content.replace(acePattern, targetFile);
content = content.replace(nonePattern, targetFile);
fs.writeFileSync(globalClaudeMdPath, content, 'utf-8');
console.log(`[claude-cli-tools] Updated global CLAUDE.md to use ${provider}`);
@@ -365,7 +368,21 @@ export function updateCodeIndexMcp(
/**
* Get current Code Index MCP provider
*/
export function getCodeIndexMcp(projectDir: string): 'codexlens' | 'ace' {
export function getCodeIndexMcp(projectDir: string): 'codexlens' | 'ace' | 'none' {
const config = loadClaudeCliTools(projectDir);
return config.settings.codeIndexMcp || 'codexlens';
}
/**
* Get the context-tools file path based on provider
*/
export function getContextToolsPath(provider: 'codexlens' | 'ace' | 'none'): string {
switch (provider) {
case 'ace':
return 'context-tools-ace.md';
case 'none':
return 'context-tools-none.md';
default:
return 'context-tools.md';
}
}