diff --git a/ccw/src/core/routes/claude-routes.ts b/ccw/src/core/routes/claude-routes.ts index 36adcec2..8561a382 100644 --- a/ccw/src/core/routes/claude-routes.ts +++ b/ccw/src/core/routes/claude-routes.ts @@ -314,7 +314,7 @@ TASK: • Analyze module's purpose and responsibilities • Document public APIs MODE: analysis CONTEXT: @${modulePath}/**/* | Memory: Project conventions from .claude/CLAUDE.md EXPECTED: Module-level CLAUDE.md with: - Module purpose (1-2 sentences) - Key files and their roles - Public API documentation - Integration points - Testing approach -RULES: $(cat ~/.claude/workflows/cli-templates/prompts/planning/02-design-component-spec.txt) | Module-level perspective only | Concrete examples | analysis=READ-ONLY`; +RULES: $PROTO $TMPL | Module-level perspective only | Concrete examples | analysis=READ-ONLY`; } else { // User/Project level prompt const contextPath = level === 'user' ? '~/.claude' : '.claude'; @@ -323,7 +323,7 @@ TASK: • Analyze ${level} configuration and conventions • Identify common pat MODE: analysis CONTEXT: @${contextPath}/**/* EXPECTED: Updated CLAUDE.md content with: - Preserved existing sections - New insights appended to relevant sections - Timestamp header - Focus on ${level}-level concerns -RULES: $(cat ~/.claude/workflows/cli-templates/prompts/analysis/02-analyze-code-patterns.txt) | Maintain existing CLAUDE.md structure | Focus on actionable rules | analysis=READ-ONLY`; +RULES: $PROTO $TMPL | Maintain existing CLAUDE.md structure | Focus on actionable rules | analysis=READ-ONLY`; } } @@ -559,6 +559,7 @@ export async function handleClaudeRoutes(ctx: RouteContext): Promise { // Import CLI executor and content formatter const { executeCliTool } = await import('../../tools/cli-executor.js'); const { SmartContentFormatter } = await import('../../tools/cli-output-converter.js'); + const { loadProtocol, loadTemplate } = await import('../../tools/template-discovery.js'); // Determine file path based on level let filePath: string; @@ -617,6 +618,15 @@ export async function handleClaudeRoutes(ctx: RouteContext): Promise { }); }; + // Build rulesEnv for $PROTO and $TMPL injection + const templateName = level === 'module' + ? 'planning-design-component-spec' + : 'analysis-analyze-code-patterns'; + const rulesEnv = { + PROTO: loadProtocol('analysis'), + TMPL: loadTemplate(templateName) + }; + const startTime = Date.now(); const result = await executeCliTool({ tool: tool === 'qwen' ? 'qwen' : 'gemini', @@ -627,7 +637,8 @@ export async function handleClaudeRoutes(ctx: RouteContext): Promise { timeout: 600000, // 10 minutes stream: false, category: 'internal', - id: syncId + id: syncId, + rulesEnv }, (unit) => { // CliOutputUnit handler: use SmartContentFormatter for intelligent formatting (never returns null) const content = SmartContentFormatter.format(unit.content, unit.type); diff --git a/ccw/src/core/routes/rules-routes.ts b/ccw/src/core/routes/rules-routes.ts index 95b4bdbb..03ccd5c4 100644 --- a/ccw/src/core/routes/rules-routes.ts +++ b/ccw/src/core/routes/rules-routes.ts @@ -7,6 +7,7 @@ import { join } from 'path'; import { homedir } from 'os'; import { executeCliTool } from '../../tools/cli-executor.js'; import { SmartContentFormatter } from '../../tools/cli-output-converter.js'; +import { loadProtocol, loadTemplate } from '../../tools/template-discovery.js'; import type { RouteContext } from './types.js'; interface ParsedRuleFrontmatter { @@ -445,7 +446,7 @@ FILE NAME: ${fileName} ${subdirectory ? `SUBDIRECTORY: ${subdirectory}` : ''} ${reviewInstruction} -RULES: $(cat ~/.claude/workflows/cli-templates/prompts/universal/00-universal-rigorous-style.txt) | Generate ONLY the rule content in markdown | No additional commentary | Do NOT use any tools | Output raw markdown text directly | write=CREATE`; +RULES: $PROTO $TMPL | Generate ONLY the rule content in markdown | No additional commentary | Do NOT use any tools | Output raw markdown text directly | write=CREATE`; } /** @@ -516,7 +517,7 @@ FILE NAME: ${fileName} ${subdirectory ? `SUBDIRECTORY: ${subdirectory}` : ''} INFERRED CATEGORY: ${context.category} -RULES: $(cat ~/.claude/workflows/cli-templates/prompts/analysis/02-analyze-code-patterns.txt) | Extract REAL patterns from code | Include actual code snippets as examples | Do NOT use any tools | Output raw markdown text directly | analysis=READ-ONLY`; +RULES: $PROTO $TMPL | Extract REAL patterns from code | Include actual code snippets as examples | Do NOT use any tools | Output raw markdown text directly | analysis=READ-ONLY`; } /** @@ -567,7 +568,7 @@ EXPECTED OUTPUT: - If the original is already high quality, return it unchanged - Preserve any frontmatter (---paths---) if present -RULES: $(cat ~/.claude/workflows/cli-templates/prompts/universal/00-universal-rigorous-style.txt) | Output ONLY improved markdown content | No additional text | Do NOT use any tools | Output raw markdown text directly | write=CREATE`; +RULES: $PROTO $TMPL | Output ONLY improved markdown content | No additional text | Do NOT use any tools | Output raw markdown text directly | write=CREATE`; } /** @@ -628,7 +629,7 @@ async function generateRuleViaCLI(params: RuleGenerateParams): Promise t !== 'cli-wrapper'), type: 'cli-wrapper' }; - console.log(`[claude-cli-tools] Migrated cli-wrapper "${ep.name}" to tools`); + debugLog(`[claude-cli-tools] Migrated cli-wrapper "${ep.name}" to tools`); } } else { // Pure API endpoint becomes a tool with type: 'api-endpoint' @@ -332,7 +344,7 @@ function migrateConfig(config: any, projectDir: string): ClaudeCliToolsConfig { type: 'api-endpoint', id: ep.id // Store endpoint ID for settings lookup }; - console.log(`[claude-cli-tools] Migrated API endpoint "${ep.name}" to tools`); + debugLog(`[claude-cli-tools] Migrated API endpoint "${ep.name}" to tools`); } } } @@ -347,7 +359,7 @@ function migrateConfig(config: any, projectDir: string): ClaudeCliToolsConfig { type: 'api-endpoint', id: ep.id // Store endpoint ID for settings lookup }; - console.log(`[claude-cli-tools] Migrated API endpoint "${ep.name}" to tools`); + debugLog(`[claude-cli-tools] Migrated API endpoint "${ep.name}" to tools`); } } @@ -375,7 +387,7 @@ export function ensureClaudeCliTools(projectDir: string, createInProject: boolea } // Config doesn't exist - create in global directory only - console.log('[claude-cli-tools] Config not found, creating default cli-tools.json in ~/.claude'); + debugLog('[claude-cli-tools] Config not found, creating default cli-tools.json in ~/.claude'); const defaultConfig: ClaudeCliToolsConfig = { ...DEFAULT_TOOLS_CONFIG }; @@ -387,7 +399,7 @@ export function ensureClaudeCliTools(projectDir: string, createInProject: boolea const globalPath = getGlobalConfigPath(); try { fs.writeFileSync(globalPath, JSON.stringify(defaultConfig, null, 2), 'utf-8'); - console.log(`[claude-cli-tools] Created default config at: ${globalPath}`); + debugLog(`[claude-cli-tools] Created default config at: ${globalPath}`); return { ...defaultConfig, _source: 'global' }; } catch (err) { console.error('[claude-cli-tools] Failed to create global config:', err); @@ -438,13 +450,13 @@ export function loadClaudeCliTools(projectDir: string): ClaudeCliToolsConfig & { if (needsSave) { try { saveClaudeCliTools(projectDir, config); - console.log(`[claude-cli-tools] Saved migrated config to: ${resolved.path}`); + debugLog(`[claude-cli-tools] Saved migrated config to: ${resolved.path}`); } catch (err) { console.warn('[claude-cli-tools] Failed to save migrated config:', err); } } - console.log(`[claude-cli-tools] Loaded tools config from ${resolved.source}: ${resolved.path}`); + debugLog(`[claude-cli-tools] Loaded tools config from ${resolved.source}: ${resolved.path}`); return config; } catch (err) { console.error('[claude-cli-tools] Error loading tools config:', err); @@ -468,7 +480,7 @@ export function saveClaudeCliTools(projectDir: string, config: ClaudeCliToolsCon try { fs.writeFileSync(configPath, JSON.stringify(configToSave, null, 2), 'utf-8'); - console.log(`[claude-cli-tools] Saved tools config to: ${configPath}`); + debugLog(`[claude-cli-tools] Saved tools config to: ${configPath}`); } catch (err) { console.error('[claude-cli-tools] Error saving tools config:', err); throw new Error(`Failed to save CLI tools config: ${err}`); @@ -504,7 +516,7 @@ export function loadClaudeCliSettings(projectDir: string): ClaudeCliSettingsConf _source: resolved.source }; - console.log(`[claude-cli-tools] Loaded settings from ${resolved.source}: ${resolved.path}`); + debugLog(`[claude-cli-tools] Loaded settings from ${resolved.source}: ${resolved.path}`); return config; } catch (err) { console.error('[claude-cli-tools] Error loading settings:', err); @@ -528,7 +540,7 @@ export function saveClaudeCliSettings(projectDir: string, config: ClaudeCliSetti try { fs.writeFileSync(settingsPath, JSON.stringify(configToSave, null, 2), 'utf-8'); - console.log(`[claude-cli-tools] Saved settings to: ${settingsPath}`); + debugLog(`[claude-cli-tools] Saved settings to: ${settingsPath}`); } catch (err) { console.error('[claude-cli-tools] Error saving settings:', err); throw new Error(`Failed to save CLI settings: ${err}`); @@ -744,7 +756,7 @@ export function updateCodeIndexMcp( 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)`); + debugLog(`[claude-cli-tools] Updated project CLAUDE.md to use ${provider} (no global CLAUDE.md found)`); } } else { // Update global CLAUDE.md (primary target) @@ -756,7 +768,7 @@ export function updateCodeIndexMcp( content = content.replace(nonePattern, targetFile); fs.writeFileSync(globalClaudeMdPath, content, 'utf-8'); - console.log(`[claude-cli-tools] Updated global CLAUDE.md to use ${provider}`); + debugLog(`[claude-cli-tools] Updated global CLAUDE.md to use ${provider}`); } return { success: true, settings }; diff --git a/ccw/src/tools/cli-executor-core.ts b/ccw/src/tools/cli-executor-core.ts index 3738c6b3..87c6fad7 100644 --- a/ccw/src/tools/cli-executor-core.ts +++ b/ccw/src/tools/cli-executor-core.ts @@ -1149,7 +1149,7 @@ async function executeCliTool( duration_ms: duration, output: newTurnOutput, parsedOutput: flattenOutputUnits(allOutputUnits, { - excludeTypes: ['stderr', 'progress', 'metadata', 'system'] + excludeTypes: ['stderr', 'progress', 'metadata', 'system', 'tool_call'] }) };