mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-21 19:08:17 +08:00
feat: enhance workflow-tune skill with reference document extraction and intent matching improvements
This commit is contained in:
@@ -117,35 +117,42 @@ $ARGUMENTS → Parse:
|
|||||||
2. Contains pipe "|" → Format 1 (inline commands)
|
2. Contains pipe "|" → Format 1 (inline commands)
|
||||||
3. Matches skill-name pattern → Format 2 (comma-separated skills)
|
3. Matches skill-name pattern → Format 2 (comma-separated skills)
|
||||||
4. Everything else → Format 4 (natural language → semantic decomposition)
|
4. Everything else → Format 4 (natural language → semantic decomposition)
|
||||||
|
4a. Contains file path? → Read file as reference doc, extract workflow steps via LLM
|
||||||
|
4b. Pure intent text → Direct intent-verb matching (intentMap)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Format 4: Semantic Decomposition (Natural Language)
|
### Format 4: Semantic Decomposition (Natural Language)
|
||||||
|
|
||||||
When input is free-text (e.g., "分析 src 目录代码质量,做代码评审,然后修复高优先级问题"), the orchestrator:
|
When input is free-text (e.g., "分析 src 目录代码质量,做代码评审,然后修复高优先级问题"), the orchestrator:
|
||||||
|
|
||||||
|
#### 4a. Reference Document Mode (input contains file path)
|
||||||
|
|
||||||
|
When the input contains a file path (e.g., `d:\maestro2\guide\command-usage-guide.md 提取核心工作流`), the orchestrator:
|
||||||
|
|
||||||
|
1. **Detect File Path**: Extract file path from input via path pattern matching
|
||||||
|
2. **Read Reference Doc**: Read the file content as workflow reference material
|
||||||
|
3. **Extract Workflow via LLM**: Use Gemini to analyze the document + user intent, extract executable workflow steps
|
||||||
|
4. **Step Chain Generation**: LLM returns structured step chain with commands, tools, and execution order
|
||||||
|
5. **Command Doc + Confirmation**: Same as 4b below
|
||||||
|
|
||||||
|
#### 4b. Pure Intent Mode (no file path)
|
||||||
|
|
||||||
1. **Semantic Parse**: Identify intent verbs and targets → map to available skills/commands
|
1. **Semantic Parse**: Identify intent verbs and targets → map to available skills/commands
|
||||||
2. **Step Chain Generation**: Produce ordered step chain with tool/mode selection
|
2. **Step Chain Generation**: Produce ordered step chain with tool/mode selection
|
||||||
3. **Command Doc**: Generate formatted execution plan document
|
3. **Command Doc**: Generate formatted execution plan document
|
||||||
4. **User Confirmation**: Display plan, ask user to confirm/edit before execution
|
4. **User Confirmation**: Display plan, ask user to confirm/edit before execution
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Semantic decomposition uses intent-to-tool mapping
|
// ★ 4a: If input contains file path → read file, extract workflow via LLM
|
||||||
|
// Detect paths: Windows (D:\path\file.md), Unix (/path/file.md), relative (./file.md)
|
||||||
|
// Read file content → send to Gemini with user intent → get executable step chain
|
||||||
|
// See phases/01-setup.md Step 1.1b Mode 4a
|
||||||
|
|
||||||
|
// ★ 4b: Pure intent text → regex-based intent-to-tool mapping
|
||||||
const intentMap = {
|
const intentMap = {
|
||||||
// Analysis intents
|
|
||||||
'分析|analyze|审查|inspect|scan': { tool: 'gemini', mode: 'analysis', rule: 'analysis-analyze-code-patterns' },
|
'分析|analyze|审查|inspect|scan': { tool: 'gemini', mode: 'analysis', rule: 'analysis-analyze-code-patterns' },
|
||||||
'评审|review|code review': { tool: 'gemini', mode: 'analysis', rule: 'analysis-review-code-quality' },
|
'评审|review|code review': { tool: 'gemini', mode: 'analysis', rule: 'analysis-review-code-quality' },
|
||||||
'诊断|debug|排查|diagnose': { tool: 'gemini', mode: 'analysis', rule: 'analysis-diagnose-bug-root-cause' },
|
// ... (full map in phases/01-setup.md Step 1.1b Mode 4b)
|
||||||
'安全|security|漏洞': { tool: 'gemini', mode: 'analysis', rule: 'analysis-assess-security-risks' },
|
|
||||||
'性能|performance|perf': { tool: 'gemini', mode: 'analysis', rule: 'analysis-analyze-performance' },
|
|
||||||
'架构|architecture': { tool: 'gemini', mode: 'analysis', rule: 'analysis-review-architecture' },
|
|
||||||
// Write intents
|
|
||||||
'修复|fix|repair|解决': { tool: 'claude', mode: 'write', rule: 'development-debug-runtime-issues' },
|
|
||||||
'实现|implement|开发|create': { tool: 'claude', mode: 'write', rule: 'development-implement-feature' },
|
|
||||||
'重构|refactor': { tool: 'claude', mode: 'write', rule: 'development-refactor-codebase' },
|
|
||||||
'测试|test|generate test': { tool: 'claude', mode: 'write', rule: 'development-generate-tests' },
|
|
||||||
// Planning intents
|
|
||||||
'规划|plan|设计|design': { tool: 'gemini', mode: 'analysis', rule: 'planning-plan-architecture-design' },
|
|
||||||
'拆解|breakdown|分解': { tool: 'gemini', mode: 'analysis', rule: 'planning-breakdown-task-steps' },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Match input segments to intents, produce step chain
|
// Match input segments to intents, produce step chain
|
||||||
@@ -377,7 +384,8 @@ User Input (workflow steps / natural language + context)
|
|||||||
↓
|
↓
|
||||||
Phase 1: Setup
|
Phase 1: Setup
|
||||||
├─ [Format 1-3] Direct parse → steps[]
|
├─ [Format 1-3] Direct parse → steps[]
|
||||||
├─ [Format 4] Semantic decompose → steps[]
|
├─ [Format 4a] File path detected → Read doc → LLM extract → steps[]
|
||||||
|
├─ [Format 4b] Pure intent text → Regex intent matching → steps[]
|
||||||
↓
|
↓
|
||||||
Command Document (formatted plan)
|
Command Document (formatted plan)
|
||||||
↓
|
↓
|
||||||
|
|||||||
@@ -67,6 +67,26 @@ else if (/^[\w-]+(,[\w-]+)+/.test(args.split(/\s/)[0])) {
|
|||||||
else {
|
else {
|
||||||
inputFormat = 'natural-language';
|
inputFormat = 'natural-language';
|
||||||
naturalLanguageInput = args.replace(/--\w+\s+"[^"]*"/g, '').replace(/--\w+\s+\S+/g, '').replace(/-y|--yes/g, '').trim();
|
naturalLanguageInput = args.replace(/--\w+\s+"[^"]*"/g, '').replace(/--\w+\s+\S+/g, '').replace(/-y|--yes/g, '').trim();
|
||||||
|
|
||||||
|
// ★ 4a: Detect file paths in input (Windows absolute, Unix absolute, or relative paths)
|
||||||
|
const filePathPattern = /(?:[A-Za-z]:[\\\/][^\s,;,;、]+|\/[^\s,;,;、]+\.(?:md|txt|json|yaml|yml|toml)|\.\/?[^\s,;,;、]+\.(?:md|txt|json|yaml|yml|toml))/g;
|
||||||
|
const detectedPaths = naturalLanguageInput.match(filePathPattern) || [];
|
||||||
|
referenceDocContent = null;
|
||||||
|
referenceDocPath = null;
|
||||||
|
|
||||||
|
if (detectedPaths.length > 0) {
|
||||||
|
// Read first detected file as reference document
|
||||||
|
referenceDocPath = detectedPaths[0];
|
||||||
|
try {
|
||||||
|
referenceDocContent = Read(referenceDocPath);
|
||||||
|
// Remove file path from natural language input to get pure user intent
|
||||||
|
naturalLanguageInput = naturalLanguageInput.replace(referenceDocPath, '').trim();
|
||||||
|
} catch (e) {
|
||||||
|
// File not readable — fall through to 4b (pure intent mode)
|
||||||
|
referenceDocContent = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Steps will be populated in Step 1.1b
|
// Steps will be populated in Step 1.1b
|
||||||
steps = [];
|
steps = [];
|
||||||
}
|
}
|
||||||
@@ -102,10 +122,108 @@ if (!workflowContext) {
|
|||||||
|
|
||||||
> Skip this step if `inputFormat !== 'natural-language'`.
|
> Skip this step if `inputFormat !== 'natural-language'`.
|
||||||
|
|
||||||
Decompose natural language input into a structured step chain by identifying intent verbs and mapping them to available tools/skills.
|
Two sub-modes based on whether a reference document was detected in Step 1.1:
|
||||||
|
|
||||||
|
#### Mode 4a: Reference Document → LLM Extraction
|
||||||
|
|
||||||
|
When `referenceDocContent` is available, use Gemini to extract executable workflow steps from the document, guided by the user's intent text.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
if (inputFormat === 'natural-language') {
|
if (inputFormat === 'natural-language' && referenceDocContent) {
|
||||||
|
// ★ 4a: Extract workflow steps from reference document via LLM
|
||||||
|
const extractPrompt = `PURPOSE: Extract an executable workflow step chain from the reference document below, guided by the user's intent.
|
||||||
|
|
||||||
|
USER INTENT: ${naturalLanguageInput}
|
||||||
|
REFERENCE DOCUMENT PATH: ${referenceDocPath}
|
||||||
|
|
||||||
|
REFERENCE DOCUMENT CONTENT:
|
||||||
|
${referenceDocContent}
|
||||||
|
|
||||||
|
TASK:
|
||||||
|
1. Read the document and identify the workflow/process it describes (commands, steps, phases, procedures)
|
||||||
|
2. Filter by user intent — only extract the steps the user wants to test/tune
|
||||||
|
3. For each step, determine:
|
||||||
|
- The actual command to execute (shell command, CLI invocation, or skill name)
|
||||||
|
- The execution order and dependencies
|
||||||
|
- What tool to use (gemini/claude/codex/qwen) and mode (default: write)
|
||||||
|
4. Generate a step chain that can be directly executed
|
||||||
|
|
||||||
|
IMPORTANT:
|
||||||
|
- Extract REAL executable commands from the document, not analysis tasks about the document
|
||||||
|
- The user wants to RUN these workflow steps, not analyze the document itself
|
||||||
|
- If the document describes CLI commands like "maestro init", "maestro plan", etc., those are the steps to extract
|
||||||
|
- Preserve the original command syntax from the document
|
||||||
|
- Map each command to appropriate tool/mode for ccw cli execution, OR mark as 'command' type for direct shell execution
|
||||||
|
- Default mode to "write" — almost all steps produce output artifacts (files, reports, configs), even analysis steps need write permission to save results
|
||||||
|
|
||||||
|
EXPECTED OUTPUT (strict JSON, no markdown):
|
||||||
|
{
|
||||||
|
"workflow_name": "<descriptive name>",
|
||||||
|
"workflow_context": "<what this workflow achieves>",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"name": "<step name>",
|
||||||
|
"type": "command|ccw-cli|skill",
|
||||||
|
"command": "<the actual command to execute>",
|
||||||
|
"tool": "<gemini|claude|codex|qwen or null for shell commands>",
|
||||||
|
"mode": "<write (default) | analysis (read-only, rare) | null for shell commands>",
|
||||||
|
"rule": "<rule template or null>",
|
||||||
|
"original_text": "<source text from document>",
|
||||||
|
"expected_artifacts": ["<expected output files>"],
|
||||||
|
"success_criteria": "<what success looks like>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
CONSTRAINTS: Output ONLY valid JSON. Extract executable steps, NOT document analysis tasks.`;
|
||||||
|
|
||||||
|
Bash({
|
||||||
|
command: `ccw cli -p "${escapeForShell(extractPrompt)}" --tool gemini --mode analysis --rule universal-rigorous-style`,
|
||||||
|
run_in_background: true,
|
||||||
|
timeout: 300000
|
||||||
|
});
|
||||||
|
|
||||||
|
// STOP — wait for hook callback
|
||||||
|
// After callback: parse JSON response into steps[]
|
||||||
|
|
||||||
|
const extractOutput = /* CLI output from callback */;
|
||||||
|
const extractJsonMatch = extractOutput.match(/\{[\s\S]*\}/);
|
||||||
|
|
||||||
|
if (extractJsonMatch) {
|
||||||
|
try {
|
||||||
|
const extracted = JSON.parse(extractJsonMatch[0]);
|
||||||
|
workflowName = extracted.workflow_name || 'doc-workflow';
|
||||||
|
workflowContext = extracted.workflow_context || naturalLanguageInput;
|
||||||
|
steps = (extracted.steps || []).map((s, i) => ({
|
||||||
|
name: s.name || `step-${i + 1}`,
|
||||||
|
type: s.type || 'command',
|
||||||
|
command: s.command,
|
||||||
|
tool: s.tool || null,
|
||||||
|
mode: s.mode || null,
|
||||||
|
rule: s.rule || null,
|
||||||
|
original_text: s.original_text || '',
|
||||||
|
expected_artifacts: s.expected_artifacts || [],
|
||||||
|
success_criteria: s.success_criteria || ''
|
||||||
|
}));
|
||||||
|
} catch (e) {
|
||||||
|
// JSON parse failed — fall through to 4b intent matching
|
||||||
|
referenceDocContent = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (steps.length === 0) {
|
||||||
|
// Extraction produced no steps — fall through to 4b
|
||||||
|
referenceDocContent = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Mode 4b: Pure Intent → Regex Matching
|
||||||
|
|
||||||
|
When no reference document, or when 4a extraction failed, decompose by intent-verb matching.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
if (inputFormat === 'natural-language' && !referenceDocContent) {
|
||||||
// Intent-to-tool mapping (regex patterns → tool config)
|
// Intent-to-tool mapping (regex patterns → tool config)
|
||||||
const intentMap = [
|
const intentMap = [
|
||||||
{ pattern: /分析|analyze|审查|inspect|scan/i, name: 'analyze', tool: 'gemini', mode: 'analysis', rule: 'analysis-analyze-code-patterns' },
|
{ pattern: /分析|analyze|审查|inspect|scan/i, name: 'analyze', tool: 'gemini', mode: 'analysis', rule: 'analysis-analyze-code-patterns' },
|
||||||
@@ -190,12 +308,16 @@ if (inputFormat === 'natural-language') {
|
|||||||
s.name = `${s.name}-${nameCount[s.name]}`;
|
s.name = `${s.name}-${nameCount[s.name]}`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Set workflow context from the full natural language input
|
// Common: set workflow context and name for Format 4
|
||||||
|
if (inputFormat === 'natural-language') {
|
||||||
if (!workflowContext) {
|
if (!workflowContext) {
|
||||||
workflowContext = naturalLanguageInput;
|
workflowContext = naturalLanguageInput;
|
||||||
}
|
}
|
||||||
workflowName = 'nl-workflow'; // natural language derived
|
if (!workflowName || workflowName === 'unnamed-workflow') {
|
||||||
|
workflowName = referenceDocPath ? 'doc-workflow' : 'nl-workflow';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// Integration tests for HomePage data flows: stats + sessions loading concurrently
|
// Integration tests for HomePage data flows: stats + sessions loading concurrently
|
||||||
|
|
||||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||||
import { renderWithI18n, screen, waitFor } from '@/test/i18n';
|
import { renderWithI18n, waitFor } from '@/test/i18n';
|
||||||
import HomePage from '@/pages/HomePage';
|
import HomePage from '@/pages/HomePage';
|
||||||
|
|
||||||
// Mock hooks used by WorkflowTaskWidget
|
// Mock hooks used by WorkflowTaskWidget
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "claude-code-workflow",
|
"name": "claude-code-workflow",
|
||||||
"version": "7.2.10",
|
"version": "7.2.11",
|
||||||
"description": "JSON-driven multi-agent development framework with intelligent CLI orchestration (Gemini/Qwen/Codex), context-first architecture, and automated workflow execution",
|
"description": "JSON-driven multi-agent development framework with intelligent CLI orchestration (Gemini/Qwen/Codex), context-first architecture, and automated workflow execution",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "ccw/dist/index.js",
|
"main": "ccw/dist/index.js",
|
||||||
|
|||||||
Reference in New Issue
Block a user