mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-12 02:37:45 +08:00
feat: 更新工具列表,支持 .ccw 目录的安装和升级,调整相关路径
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: ccw-loop-b
|
name: ccw-loop-b
|
||||||
description: Hybrid orchestrator pattern for iterative development. Coordinator + specialized workers with batch wait, parallel split, and two-phase clarification. Triggers on "ccw-loop-b".
|
description: Hybrid orchestrator pattern for iterative development. Coordinator + specialized workers with batch wait, parallel split, and two-phase clarification. Triggers on "ccw-loop-b".
|
||||||
allowed-tools: Task, AskUserQuestion, TodoWrite, Read, Write, Edit, Bash, Glob, Grep
|
allowed-tools: spawn_agent, wait, send_input, close_agent, AskUserQuestion, Read, Write, Edit, Bash, Glob, Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# CCW Loop-B - Hybrid Orchestrator Pattern
|
# CCW Loop-B - Hybrid Orchestrator Pattern
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: ccw-loop
|
name: ccw-loop
|
||||||
description: Stateless iterative development loop with single-agent deep interaction. Supports develop, debug, validate phases with file-based state tracking. Triggers on "ccw-loop", "dev loop", "development loop", "开发循环", "迭代开发".
|
description: Stateless iterative development loop with single-agent deep interaction. Supports develop, debug, validate phases with file-based state tracking. Triggers on "ccw-loop", "dev loop", "development loop", "开发循环", "迭代开发".
|
||||||
allowed-tools: Task, AskUserQuestion, TodoWrite, Read, Write, Edit, Bash, Glob, Grep
|
allowed-tools: spawn_agent, wait, send_input, close_agent, AskUserQuestion, Read, Write, Edit, Bash, Glob, Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# CCW Loop - Stateless Iterative Development Workflow
|
# CCW Loop - Stateless Iterative Development Workflow
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: parallel-dev-cycle
|
name: parallel-dev-cycle
|
||||||
description: Multi-agent parallel development cycle with requirement analysis, exploration planning, code development, and validation. Supports continuous iteration with markdown progress documentation. Triggers on "parallel-dev-cycle".
|
description: Multi-agent parallel development cycle with requirement analysis, exploration planning, code development, and validation. Supports continuous iteration with markdown progress documentation. Triggers on "parallel-dev-cycle".
|
||||||
allowed-tools: Task, AskUserQuestion, TodoWrite, Read, Write, Edit, Bash, Glob, Grep
|
allowed-tools: spawn_agent, wait, send_input, close_agent, AskUserQuestion, Read, Write, Edit, Bash, Glob, Grep
|
||||||
---
|
---
|
||||||
|
|
||||||
# Parallel Dev Cycle
|
# Parallel Dev Cycle
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Lite Plan produces an implementation plan and an `executionContext`, then hands
|
|||||||
|
|
||||||
## Key Design Principles
|
## Key Design Principles
|
||||||
|
|
||||||
1. **Shared Execution**: Lite Plan produces `executionContext` consumed by Phase 4 (Lite Execute)
|
1. **Shared Execution**: Lite Plan produces `executionContext` consumed by Phase 2 (Lite Execute)
|
||||||
2. **Progressive Phase Loading**: Only load phase docs when about to execute
|
2. **Progressive Phase Loading**: Only load phase docs when about to execute
|
||||||
3. **Auto-Continue**: After the plan is confirmed ("Allow"), automatically load execution phase
|
3. **Auto-Continue**: After the plan is confirmed ("Allow"), automatically load execution phase
|
||||||
4. **Default Auto Mode**: When `--yes`, skip confirmations and auto-approve the plan
|
4. **Default Auto Mode**: When `--yes`, skip confirmations and auto-approve the plan
|
||||||
@@ -49,7 +49,7 @@ $workflow-lite-plan-execute "docs/todo.md"
|
|||||||
| Phase | Document | Purpose |
|
| Phase | Document | Purpose |
|
||||||
|-------|----------|---------|
|
|-------|----------|---------|
|
||||||
| 1 | `phases/01-lite-plan.md` | Lightweight planning with exploration, clarification, plan generation, and confirmation |
|
| 1 | `phases/01-lite-plan.md` | Lightweight planning with exploration, clarification, plan generation, and confirmation |
|
||||||
| 4 | `phases/04-lite-execute.md` | Shared execution engine: task grouping, batch execution, optional code review |
|
| 2 | `phases/02-lite-execute.md` | Shared execution engine: task grouping, batch execution, optional code review |
|
||||||
|
|
||||||
## Orchestrator Logic
|
## Orchestrator Logic
|
||||||
|
|
||||||
@@ -81,14 +81,14 @@ if (executionContext?.userSelection?.confirmation !== 'Allow' && !autoYes) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase 4: Lite Execute
|
// Phase 2: Lite Execute
|
||||||
Read('phases/04-lite-execute.md')
|
Read('phases/02-lite-execute.md')
|
||||||
// Execute execution phase with executionContext from Phase 1
|
// Execute execution phase with executionContext from Phase 1
|
||||||
```
|
```
|
||||||
|
|
||||||
## executionContext Contract (High Level)
|
## executionContext Contract (High Level)
|
||||||
|
|
||||||
`executionContext` is the only contract between Phase 1 and Phase 4.
|
`executionContext` is the only contract between Phase 1 and Phase 2.
|
||||||
|
|
||||||
Required (minimum) fields:
|
Required (minimum) fields:
|
||||||
```javascript
|
```javascript
|
||||||
@@ -110,7 +110,7 @@ Initialization:
|
|||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
{"content": "Lite Plan - Planning", "status": "in_progress", "activeForm": "Planning"},
|
{"content": "Lite Plan - Planning", "status": "in_progress", "activeForm": "Planning"},
|
||||||
{"content": "Execution (Phase 4)", "status": "pending", "activeForm": "Executing tasks"}
|
{"content": "Execution (Phase 2)", "status": "pending", "activeForm": "Executing tasks"}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -118,14 +118,14 @@ After planning completes:
|
|||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
{"content": "Lite Plan - Planning", "status": "completed", "activeForm": "Planning"},
|
{"content": "Lite Plan - Planning", "status": "completed", "activeForm": "Planning"},
|
||||||
{"content": "Execution (Phase 4)", "status": "in_progress", "activeForm": "Executing tasks"}
|
{"content": "Execution (Phase 2)", "status": "in_progress", "activeForm": "Executing tasks"}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Core Rules
|
## Core Rules
|
||||||
|
|
||||||
1. **Planning phase NEVER modifies project code** - it may write planning artifacts, but all implementation is delegated to Phase 4
|
1. **Planning phase NEVER modifies project code** - it may write planning artifacts, but all implementation is delegated to Phase 2
|
||||||
2. **Phase 4 runs only after confirmation** - execute only when confirmation is "Allow" (or `--yes` auto mode)
|
2. **Phase 2 runs only after confirmation** - execute only when confirmation is "Allow" (or `--yes` auto mode)
|
||||||
3. **executionContext is the contract** between planning and execution phases
|
3. **executionContext is the contract** between planning and execution phases
|
||||||
4. **Progressive loading**: Read phase doc only when about to execute
|
4. **Progressive loading**: Read phase doc only when about to execute
|
||||||
5. **File-path detection**: Treat input as a file path only if the path exists; do not infer from file extensions
|
5. **File-path detection**: Treat input as a file path only if the path exists; do not infer from file extensions
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const __filename = fileURLToPath(import.meta.url);
|
|||||||
const __dirname = dirname(__filename);
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
// Source directories to install (includes .codex with prompts folder)
|
// Source directories to install (includes .codex with prompts folder)
|
||||||
const SOURCE_DIRS = ['.claude', '.codex', '.gemini', '.qwen'];
|
const SOURCE_DIRS = ['.claude', '.codex', '.gemini', '.qwen', '.ccw'];
|
||||||
|
|
||||||
// Subdirectories that should always be installed to global (~/.claude/)
|
// Subdirectories that should always be installed to global (~/.claude/)
|
||||||
const GLOBAL_SUBDIRS = ['workflows', 'scripts', 'templates'];
|
const GLOBAL_SUBDIRS = ['workflows', 'scripts', 'templates'];
|
||||||
@@ -380,7 +380,10 @@ export async function installCommand(options: InstallOptions): Promise<void> {
|
|||||||
|
|
||||||
for (const dir of availableDirs) {
|
for (const dir of availableDirs) {
|
||||||
const srcPath = join(sourceDir, dir);
|
const srcPath = join(sourceDir, dir);
|
||||||
const destPath = join(installPath, dir);
|
|
||||||
|
// .ccw always installs to global ~/.ccw/ regardless of mode
|
||||||
|
const destBase = (mode === 'Path' && dir === '.ccw') ? homedir() : installPath;
|
||||||
|
const destPath = join(destBase, dir);
|
||||||
|
|
||||||
spinner.text = `Installing ${dir}...`;
|
spinner.text = `Installing ${dir}...`;
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const __filename = fileURLToPath(import.meta.url);
|
|||||||
const __dirname = dirname(__filename);
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
// Source directories to install
|
// Source directories to install
|
||||||
const SOURCE_DIRS = ['.claude', '.codex', '.gemini', '.qwen'];
|
const SOURCE_DIRS = ['.claude', '.codex', '.gemini', '.qwen', '.ccw'];
|
||||||
|
|
||||||
// Subdirectories that should always be installed to global (~/.claude/)
|
// Subdirectories that should always be installed to global (~/.claude/)
|
||||||
const GLOBAL_SUBDIRS = ['workflows', 'scripts', 'templates'];
|
const GLOBAL_SUBDIRS = ['workflows', 'scripts', 'templates'];
|
||||||
@@ -268,7 +268,10 @@ async function performUpgrade(manifest: any, sourceDir: string, version: string)
|
|||||||
// Copy each directory
|
// Copy each directory
|
||||||
for (const dir of availableDirs) {
|
for (const dir of availableDirs) {
|
||||||
const srcPath = join(sourceDir, dir);
|
const srcPath = join(sourceDir, dir);
|
||||||
const destPath = join(installPath, dir);
|
|
||||||
|
// .ccw always upgrades to global ~/.ccw/ regardless of mode
|
||||||
|
const destBase = (mode === 'Path' && dir === '.ccw') ? homedir() : installPath;
|
||||||
|
const destPath = join(destBase, dir);
|
||||||
|
|
||||||
// For Path mode on .claude, exclude global subdirs (they're already installed to global)
|
// For Path mode on .claude, exclude global subdirs (they're already installed to global)
|
||||||
const excludeDirs = (mode === 'Path' && dir === '.claude') ? GLOBAL_SUBDIRS : [];
|
const excludeDirs = (mode === 'Path' && dir === '.claude') ? GLOBAL_SUBDIRS : [];
|
||||||
|
|||||||
@@ -117,6 +117,70 @@ export async function handleCcwRoutes(ctx: RouteContext): Promise<boolean> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// API: CCW Install (non-interactive)
|
||||||
|
if (pathname === '/api/ccw/install' && req.method === 'POST') {
|
||||||
|
handlePostRequest(req, res, async (body) => {
|
||||||
|
const { mode = 'Global', path: installPath, force = true } = body as { mode?: string; path?: string; force?: boolean };
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { spawn } = await import('child_process');
|
||||||
|
|
||||||
|
const args = ['install', '--mode', mode, '--force'];
|
||||||
|
if (mode === 'Path' && installPath) {
|
||||||
|
args.push('--path', installPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
const installProcess = spawn('ccw', args, {
|
||||||
|
shell: true,
|
||||||
|
stdio: ['ignore', 'pipe', 'pipe']
|
||||||
|
});
|
||||||
|
|
||||||
|
let stdout = '';
|
||||||
|
let stderr = '';
|
||||||
|
|
||||||
|
installProcess.stdout?.on('data', (data: Buffer) => {
|
||||||
|
const chunk = data.toString();
|
||||||
|
stdout += chunk;
|
||||||
|
broadcastToClients({
|
||||||
|
type: 'CCW_INSTALL_OUTPUT',
|
||||||
|
payload: { data: chunk }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
installProcess.stderr?.on('data', (data: Buffer) => {
|
||||||
|
stderr += data.toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
installProcess.on('close', (code: number | null) => {
|
||||||
|
if (code === 0) {
|
||||||
|
broadcastToClients({
|
||||||
|
type: 'CCW_INSTALL_COMPLETED',
|
||||||
|
payload: { success: true, mode }
|
||||||
|
});
|
||||||
|
resolve({ success: true, message: 'Installation completed', mode, output: stdout });
|
||||||
|
} else {
|
||||||
|
resolve({ success: false, error: stderr || 'Installation failed', output: stdout, status: 500 });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
installProcess.on('error', (err: Error) => {
|
||||||
|
resolve({ success: false, error: err.message, status: 500 });
|
||||||
|
});
|
||||||
|
|
||||||
|
// Timeout after 2 minutes
|
||||||
|
setTimeout(() => {
|
||||||
|
installProcess.kill();
|
||||||
|
resolve({ success: false, error: 'Installation timed out', status: 504 });
|
||||||
|
}, 120000);
|
||||||
|
});
|
||||||
|
} catch (err: unknown) {
|
||||||
|
return { success: false, error: err instanceof Error ? err.message : String(err), status: 500 };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// API: CCW Upgrade
|
// API: CCW Upgrade
|
||||||
if (pathname === '/api/ccw/upgrade' && req.method === 'POST') {
|
if (pathname === '/api/ccw/upgrade' && req.method === 'POST') {
|
||||||
handlePostRequest(req, res, async (body) => {
|
handlePostRequest(req, res, async (body) => {
|
||||||
|
|||||||
@@ -943,7 +943,7 @@ export async function handleClaudeRoutes(ctx: RouteContext): Promise<boolean> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find guidelines file path - always use user-level path
|
// Find guidelines file path - always use user-level path
|
||||||
const userGuidelinesPath = join(homedir(), '.claude', 'workflows', 'chinese-response.md');
|
const userGuidelinesPath = join(homedir(), '.ccw', 'workflows', 'chinese-response.md');
|
||||||
|
|
||||||
if (existsSync(userGuidelinesPath)) {
|
if (existsSync(userGuidelinesPath)) {
|
||||||
guidelinesPath = userGuidelinesPath;
|
guidelinesPath = userGuidelinesPath;
|
||||||
@@ -979,7 +979,7 @@ export async function handleClaudeRoutes(ctx: RouteContext): Promise<boolean> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Find guidelines file path - always use user-level path with ~ shorthand
|
// Find guidelines file path - always use user-level path with ~ shorthand
|
||||||
const userGuidelinesPath = join(homedir(), '.claude', 'workflows', 'chinese-response.md');
|
const userGuidelinesPath = join(homedir(), '.ccw', 'workflows', 'chinese-response.md');
|
||||||
|
|
||||||
if (!existsSync(userGuidelinesPath)) {
|
if (!existsSync(userGuidelinesPath)) {
|
||||||
return { error: 'Chinese response guidelines file not found at ~/.ccw/workflows/chinese-response.md', status: 404 };
|
return { error: 'Chinese response guidelines file not found at ~/.ccw/workflows/chinese-response.md', status: 404 };
|
||||||
@@ -1107,7 +1107,7 @@ export async function handleClaudeRoutes(ctx: RouteContext): Promise<boolean> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find guidelines file path
|
// Find guidelines file path
|
||||||
const userGuidelinesPath = join(homedir(), '.claude', 'workflows', 'cli-tools-usage.md');
|
const userGuidelinesPath = join(homedir(), '.ccw', 'workflows', 'cli-tools-usage.md');
|
||||||
|
|
||||||
if (existsSync(userGuidelinesPath)) {
|
if (existsSync(userGuidelinesPath)) {
|
||||||
guidelinesPath = userGuidelinesPath;
|
guidelinesPath = userGuidelinesPath;
|
||||||
@@ -1172,7 +1172,7 @@ export async function handleClaudeRoutes(ctx: RouteContext): Promise<boolean> {
|
|||||||
if (content) content += '\n';
|
if (content) content += '\n';
|
||||||
|
|
||||||
// Read and add updated section
|
// Read and add updated section
|
||||||
const cliToolsUsagePath = join(homedir(), '.claude', 'workflows', 'cli-tools-usage.md');
|
const cliToolsUsagePath = join(homedir(), '.ccw', 'workflows', 'cli-tools-usage.md');
|
||||||
let cliToolsUsageContent = '';
|
let cliToolsUsageContent = '';
|
||||||
if (existsSync(cliToolsUsagePath)) {
|
if (existsSync(cliToolsUsagePath)) {
|
||||||
cliToolsUsageContent = readFileSync(cliToolsUsagePath, 'utf8');
|
cliToolsUsageContent = readFileSync(cliToolsUsagePath, 'utf8');
|
||||||
@@ -1208,7 +1208,7 @@ export async function handleClaudeRoutes(ctx: RouteContext): Promise<boolean> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read cli-tools-usage.md content
|
// Read cli-tools-usage.md content
|
||||||
const cliToolsUsagePath = join(homedir(), '.claude', 'workflows', 'cli-tools-usage.md');
|
const cliToolsUsagePath = join(homedir(), '.ccw', 'workflows', 'cli-tools-usage.md');
|
||||||
let cliToolsUsageContent = '';
|
let cliToolsUsageContent = '';
|
||||||
if (existsSync(cliToolsUsagePath)) {
|
if (existsSync(cliToolsUsagePath)) {
|
||||||
cliToolsUsageContent = readFileSync(cliToolsUsagePath, 'utf8');
|
cliToolsUsageContent = readFileSync(cliToolsUsagePath, 'utf8');
|
||||||
@@ -1266,7 +1266,7 @@ export async function handleClaudeRoutes(ctx: RouteContext): Promise<boolean> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find guidelines file path - always use user-level path
|
// Find guidelines file path - always use user-level path
|
||||||
const userGuidelinesPath = join(homedir(), '.claude', 'workflows', 'windows-platform.md');
|
const userGuidelinesPath = join(homedir(), '.ccw', 'workflows', 'windows-platform.md');
|
||||||
|
|
||||||
if (existsSync(userGuidelinesPath)) {
|
if (existsSync(userGuidelinesPath)) {
|
||||||
guidelinesPath = userGuidelinesPath;
|
guidelinesPath = userGuidelinesPath;
|
||||||
@@ -1301,7 +1301,7 @@ export async function handleClaudeRoutes(ctx: RouteContext): Promise<boolean> {
|
|||||||
const userClaudeDir = join(homedir(), '.claude');
|
const userClaudeDir = join(homedir(), '.claude');
|
||||||
|
|
||||||
// Find guidelines file path - always use user-level path with ~ shorthand
|
// Find guidelines file path - always use user-level path with ~ shorthand
|
||||||
const userGuidelinesPath = join(homedir(), '.claude', 'workflows', 'windows-platform.md');
|
const userGuidelinesPath = join(homedir(), '.ccw', 'workflows', 'windows-platform.md');
|
||||||
|
|
||||||
if (!existsSync(userGuidelinesPath)) {
|
if (!existsSync(userGuidelinesPath)) {
|
||||||
return { error: 'Windows platform guidelines file not found at ~/.ccw/workflows/windows-platform.md', status: 404 };
|
return { error: 'Windows platform guidelines file not found at ~/.ccw/workflows/windows-platform.md', status: 404 };
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ function checkCcwInstallStatus(): {
|
|||||||
missingFiles: string[];
|
missingFiles: string[];
|
||||||
installPath: string;
|
installPath: string;
|
||||||
} {
|
} {
|
||||||
const claudeDir = join(homedir(), '.claude');
|
const ccwDir = join(homedir(), '.ccw');
|
||||||
const workflowsDir = join(claudeDir, 'workflows');
|
const workflowsDir = join(ccwDir, 'workflows');
|
||||||
|
|
||||||
// Required workflow files for full functionality
|
// Required workflow files for full functionality
|
||||||
const requiredFiles = [
|
const requiredFiles = [
|
||||||
|
|||||||
@@ -948,10 +948,10 @@ export function updateCodeIndexMcp(
|
|||||||
// Only update global CLAUDE.md (consistent with Chinese response / Windows platform)
|
// Only update global CLAUDE.md (consistent with Chinese response / Windows platform)
|
||||||
const globalClaudeMdPath = path.join(os.homedir(), '.claude', 'CLAUDE.md');
|
const globalClaudeMdPath = path.join(os.homedir(), '.claude', 'CLAUDE.md');
|
||||||
|
|
||||||
// Define patterns for all formats
|
// Define patterns for all formats (match both old .claude and new .ccw paths)
|
||||||
const codexlensPattern = /@~\/\.claude\/workflows\/context-tools\.md/g;
|
const codexlensPattern = /@~\/\.(?:claude|ccw)\/workflows\/context-tools\.md/g;
|
||||||
const acePattern = /@~\/\.claude\/workflows\/context-tools-ace\.md/g;
|
const acePattern = /@~\/\.(?:claude|ccw)\/workflows\/context-tools-ace\.md/g;
|
||||||
const nonePattern = /@~\/\.claude\/workflows\/context-tools-none\.md/g;
|
const nonePattern = /@~\/\.(?:claude|ccw)\/workflows\/context-tools-none\.md/g;
|
||||||
|
|
||||||
// Determine target file based on provider
|
// Determine target file based on provider
|
||||||
const targetFile = provider === 'ace'
|
const targetFile = provider === 'ace'
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export interface TemplateIndex {
|
|||||||
// Constants
|
// Constants
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
const TEMPLATES_BASE_DIR = join(homedir(), '.claude', 'workflows', 'cli-templates');
|
const TEMPLATES_BASE_DIR = join(homedir(), '.ccw', 'workflows', 'cli-templates');
|
||||||
const PROMPTS_DIR = join(TEMPLATES_BASE_DIR, 'prompts');
|
const PROMPTS_DIR = join(TEMPLATES_BASE_DIR, 'prompts');
|
||||||
const PROTOCOLS_DIR = join(TEMPLATES_BASE_DIR, 'protocols');
|
const PROTOCOLS_DIR = join(TEMPLATES_BASE_DIR, 'protocols');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user