feat: Implement UX improvement pipeline with role specifications and task management

- Added role specifications for explorer, implementer, scanner, tester, and diagnoser.
- Created dispatch and monitor commands for orchestrating task execution.
- Defined team configuration for the UX improvement pipeline, including roles and responsibilities.
- Established structured task descriptions for scanning, diagnosing, designing, implementing, and testing UI components.
- Introduced caching mechanisms for exploration results and context accumulation for implementer tasks.
- Enhanced error handling and validation processes across roles.
This commit is contained in:
catlog22
2026-03-05 16:42:56 +08:00
parent f6c7c14042
commit 3d92478772
18 changed files with 2039 additions and 122 deletions

View File

@@ -16,6 +16,7 @@ import {
XCircle,
Loader2,
Info,
FolderOpen,
} from 'lucide-react';
import {
Dialog,
@@ -31,6 +32,7 @@ import { Textarea } from '@/components/ui/Textarea';
import { Label } from '@/components/ui/Label';
import { validateSkillImport, createSkill } from '@/lib/api';
import { useWorkflowStore, selectProjectPath } from '@/stores/workflowStore';
import { FloatingFileBrowser } from '@/components/terminal-dashboard/FloatingFileBrowser';
import { cn } from '@/lib/utils';
export interface SkillCreateDialogProps {
@@ -58,7 +60,6 @@ export function SkillCreateDialog({ open, onOpenChange, onCreated, cliType = 'cl
// Import mode state
const [sourcePath, setSourcePath] = useState('');
const [customName, setCustomName] = useState('');
const [validationResult, setValidationResult] = useState<ValidationResult | null>(null);
const [isValidating, setIsValidating] = useState(false);
@@ -68,16 +69,19 @@ export function SkillCreateDialog({ open, onOpenChange, onCreated, cliType = 'cl
const [isCreating, setIsCreating] = useState(false);
// File browser state
const [isFileBrowserOpen, setIsFileBrowserOpen] = useState(false);
const resetState = useCallback(() => {
setMode('import');
setLocation('project');
setSourcePath('');
setCustomName('');
setValidationResult(null);
setIsValidating(false);
setSkillName('');
setDescription('');
setIsCreating(false);
setIsFileBrowserOpen(false);
}, []);
const handleOpenChange = useCallback((open: boolean) => {
@@ -122,7 +126,7 @@ export function SkillCreateDialog({ open, onOpenChange, onCreated, cliType = 'cl
mode,
location,
sourcePath: mode === 'import' ? sourcePath.trim() : undefined,
skillName: mode === 'import' ? (customName.trim() || undefined) : skillName.trim(),
skillName: mode === 'cli-generate' ? skillName.trim() : undefined,
description: mode === 'cli-generate' ? description.trim() : undefined,
generationType: mode === 'cli-generate' ? 'description' : undefined,
projectPath,
@@ -142,7 +146,7 @@ export function SkillCreateDialog({ open, onOpenChange, onCreated, cliType = 'cl
} finally {
setIsCreating(false);
}
}, [mode, location, sourcePath, customName, skillName, description, validationResult, projectPath, handleOpenChange, onCreated, formatMessage]);
}, [mode, location, sourcePath, skillName, description, validationResult, projectPath, handleOpenChange, onCreated, formatMessage]);
const canCreate = mode === 'import'
? sourcePath.trim() && validationResult?.valid && !isCreating
@@ -250,32 +254,30 @@ export function SkillCreateDialog({ open, onOpenChange, onCreated, cliType = 'cl
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="sourcePath">{formatMessage({ id: 'skills.create.sourcePath' })}</Label>
<Input
id="sourcePath"
value={sourcePath}
onChange={(e) => {
setSourcePath(e.target.value);
setValidationResult(null);
}}
placeholder={formatMessage({ id: 'skills.create.sourcePathPlaceholder' })}
className="font-mono text-sm"
/>
<div className="flex gap-2">
<Input
id="sourcePath"
value={sourcePath}
onChange={(e) => {
setSourcePath(e.target.value);
setValidationResult(null);
}}
placeholder={formatMessage({ id: 'skills.create.sourcePathPlaceholder' })}
className="font-mono text-sm flex-1"
/>
<Button
type="button"
variant="outline"
size="icon"
onClick={() => setIsFileBrowserOpen(true)}
title={formatMessage({ id: 'skills.create.browseFolder' })}
>
<FolderOpen className="w-4 h-4" />
</Button>
</div>
<p className="text-xs text-muted-foreground">{formatMessage({ id: 'skills.create.sourcePathHint' })}</p>
</div>
<div className="space-y-2">
<Label htmlFor="customName">
{formatMessage({ id: 'skills.create.customName' })}
<span className="text-muted-foreground ml-1">({formatMessage({ id: 'skills.create.customNameHint' })})</span>
</Label>
<Input
id="customName"
value={customName}
onChange={(e) => setCustomName(e.target.value)}
placeholder={formatMessage({ id: 'skills.create.customNamePlaceholder' })}
/>
</div>
{/* Validation Result */}
{isValidating && (
<div className="flex items-center gap-2 p-3 bg-muted/50 rounded-lg">
@@ -401,6 +403,19 @@ export function SkillCreateDialog({ open, onOpenChange, onCreated, cliType = 'cl
</Button>
</DialogFooter>
</DialogContent>
{/* File Browser for selecting source folder */}
<FloatingFileBrowser
isOpen={isFileBrowserOpen}
onClose={() => setIsFileBrowserOpen(false)}
rootPath={projectPath}
onInsertPath={(path) => {
setSourcePath(path);
setValidationResult(null);
setIsFileBrowserOpen(false);
}}
initialSelectedPath={sourcePath || null}
/>
</Dialog>
);
}

View File

@@ -1340,11 +1340,30 @@ async function executeCliTool(
export const schema: ToolSchema = {
name: 'cli_executor',
description: `Execute external CLI tools (gemini/qwen/codex) with unified interface.
Modes:
- analysis: Read-only operations (default)
- write: File modifications allowed
- auto: Full autonomous operations (codex only)
- review: Code review mode (codex uses 'codex review' subcommand, others accept but no operation change)`,
**Required Parameters:**
**tool** (string): CLI tool to execute - "gemini" | "qwen" | "codex".
**prompt** (string): Prompt to send to the CLI tool.
**Optional Parameters:**
*mode* (string): Execution mode (default: "analysis").
- "analysis": Read-only operations, no file modifications.
- "write": File modifications allowed.
- "auto": Full autonomous operations (codex only).
- "review": Code review mode (codex uses 'codex review' subcommand).
*model* (string): Model override (tool-specific, e.g., "gemini-2.5-pro").
*cd* (string): Working directory for execution.
*includeDirs* (string): Additional directories (comma-separated).
**Examples:**
cli_executor(tool="gemini", prompt="Analyze the auth module")
cli_executor(tool="gemini", prompt="Fix the bug", mode="write")
cli_executor(tool="codex", prompt="Review changes", mode="review")
cli_executor(tool="qwen", prompt="Implement feature", mode="write", cd="src/auth")
**Mode-Tool Compatibility:**
- gemini/qwen: analysis, write
- codex: analysis, write, auto, review`,
inputSchema: {
type: 'object',
properties: {

View File

@@ -588,27 +588,60 @@ async function execute(params: Params): Promise<OperationResult> {
// Tool schema for MCP
export const schema: ToolSchema = {
name: 'core_memory',
description: `Core memory management for strategic context.
description: `Core memory management for strategic context. Choose an operation and provide its required parameters.
Usage:
core_memory(operation="list") # List all memories
core_memory(operation="list", tags=["auth","api"]) # List memories with specific tags
core_memory(operation="import", text="important context") # Import text as new memory
core_memory(operation="export", id="CMEM-xxx") # Export memory as plain text
core_memory(operation="summary", id="CMEM-xxx") # Generate AI summary
core_memory(operation="embed", source_id="CMEM-xxx") # Generate embeddings for memory
core_memory(operation="search", query="authentication") # Search memories semantically
core_memory(operation="embed_status") # Check embedding status
core_memory(operation="extract") # Trigger batch memory extraction (V2)
core_memory(operation="extract_status") # Check extraction pipeline status
core_memory(operation="consolidate") # Trigger memory consolidation (V2)
core_memory(operation="consolidate_status") # Check consolidation status
core_memory(operation="jobs") # List all V2 pipeline jobs
**Operations & Required Parameters:**
Path parameter (highest priority):
core_memory(operation="list", path="/path/to/project") # Use specific project path
* **list**: List all memories.
* *limit* (number): Max results (default: 100).
* *tags* (array): Filter by tags (AND logic).
* *path* (string): Project path (overrides auto-detection).
Memory IDs use format: CMEM-YYYYMMDD-HHMMSS`,
* **import**: Import text as new memory.
* **text** (string, **REQUIRED**): Content to import.
* *path* (string): Project path.
* **export**: Export memory as plain text.
* **id** (string, **REQUIRED**): Memory ID (e.g., CMEM-20260305-120000).
* *path* (string): Project path.
* **summary**: Generate AI summary for a memory.
* **id** (string, **REQUIRED**): Memory ID.
* *tool* (string): AI tool for summary ("gemini" or "qwen", default: "gemini").
* *path* (string): Project path.
* **search**: Search memories semantically.
* **query** (string, **REQUIRED**): Search query.
* *top_k* (number): Max results (default: 10).
* *min_score* (number): Min similarity score (default: 0.3).
* *source_type* (string): Filter by type ("core_memory" | "workflow" | "cli_history").
* *path* (string): Project path.
* **embed**: Generate embeddings for memory chunks.
* *source_id* (string): Specific memory to embed (optional, embeds all if omitted).
* *batch_size* (number): Batch size (default: 8).
* *force* (boolean): Force re-embedding (default: false).
* *path* (string): Project path.
* **embed_status**: Check embedding status. (No required params)
* **extract**: Trigger batch memory extraction (V2, fire-and-forget).
* *max_sessions* (number): Max sessions to process.
* *path* (string): Project path.
* **extract_status**: Check extraction pipeline status. (No required params)
* **consolidate**: Trigger memory consolidation (V2, fire-and-forget).
* *path* (string): Project path.
* **consolidate_status**: Check consolidation status. (No required params)
* **jobs**: List all V2 pipeline jobs.
* *kind* (string): Filter by job kind (e.g., "extraction", "consolidation").
* *status_filter* (string): Filter by status ("pending" | "running" | "done" | "error").
* *path* (string): Project path.
**Memory ID Format:** CMEM-YYYYMMDD-HHMMSS (e.g., CMEM-20260305-143022)`,
inputSchema: {
type: 'object',
properties: {

View File

@@ -454,32 +454,37 @@ function executeLineMode(content: string, params: LineModeParams): LineModeResul
// Tool schema for MCP
export const schema: ToolSchema = {
name: 'edit_file',
description: `Edit file using two modes: "update" for text replacement (default) and "line" for line-based operations.
description: `Edit file using ONE of two modes. Provide parameters for only ONE mode - mixing modes causes validation error.
**Update Mode** (default):
- Use oldText/newText for single replacement OR edits for multiple replacements
- Parameters: oldText, newText, replaceAll, dryRun
- Cannot use line mode parameters (operation, line, end_line, text)
- Validation: oldText/newText and edits are mutually exclusive
**Mode 1: update** (default) - Text replacement
**path** (string, **REQUIRED**): File path to edit.
**oldText** (string, **REQUIRED** if not using edits): Text to find and replace.
**newText** (string, **REQUIRED** if using oldText): Replacement text.
* OR use **edits** (array) for multiple replacements: [{oldText:"a", newText:"b"}, ...]
*replaceAll* (boolean): Replace all occurrences (default: false).
*dryRun* (boolean): Preview diff without modifying (default: false).
**Line Mode**:
- Use for precise line-based operations
- Parameters: operation (insert_before/insert_after/replace/delete), line, end_line, text, dryRun
- Cannot use update mode parameters (oldText, newText, edits, replaceAll)
Example:
edit_file(path="file.ts", oldText="old", newText="new")
edit_file(path="file.ts", edits=[{oldText:"a", newText:"b"}])
edit_file(path="file.ts", oldText="x", newText="y", replaceAll=true)
Usage (update mode - single replacement):
edit_file(path="f.js", oldText="old", newText="new")
**Mode 2: line** - Line-based operations
**path** (string, **REQUIRED**): File path to edit.
**operation** (string, **REQUIRED**): "insert_before" | "insert_after" | "replace" | "delete".
**line** (number, **REQUIRED**): 1-based line number.
*text* (string): Content for insert/replace operations.
*end_line* (number): End line for range operations (replace/delete).
*dryRun* (boolean): Preview diff without modifying (default: false).
Usage (update mode - multiple replacements):
edit_file(path="f.js", edits=[{oldText:"a",newText:"b"},{oldText:"c",newText:"d"}])
Example:
edit_file(path="file.ts", mode="line", operation="insert_after", line=10, text="new line")
edit_file(path="file.ts", mode="line", operation="delete", line=5, end_line=8)
Usage (line mode):
edit_file(path="f.js", mode="line", operation="insert_after", line=10, text="new line")
edit_file(path="f.js", mode="line", operation="delete", line=5, end_line=8)
Options: dryRun=true (preview diff), replaceAll=true (update mode only)
**Important**: Each mode only accepts its own parameters. Providing parameters from both modes will cause a validation error.`,
**⚠️ MUTUAL EXCLUSIVITY:**
- update mode: Use ONLY oldText/newText OR edits, plus replaceAll, dryRun
- line mode: Use ONLY operation, line, end_line, text, dryRun
- DO NOT mix parameters from both modes`,
inputSchema: {
type: 'object',
properties: {

View File

@@ -1022,15 +1022,51 @@ async function execute(params: Params): Promise<any> {
export const schema: ToolSchema = {
name: 'session_manager',
description: `Workflow session management.
description: `Workflow session management. Choose an operation and provide its required parameters.
Usage:
session_manager(operation="init", type="workflow", description="...")
session_manager(operation="list", location="active|archived|both")
session_manager(operation="read", sessionId="WFS-xxx", contentType="plan|task|summary")
session_manager(operation="write", sessionId="WFS-xxx", contentType="plan", content={...})
session_manager(operation="archive", sessionId="WFS-xxx")
session_manager(operation="stats", sessionId="WFS-xxx")`,
**Operations & Required Parameters:**
* **init**: Initialize a new workflow session.
* **metadata** (object, **REQUIRED**): Session metadata with project, type, description.
* Returns: New session ID.
* **list**: List workflow sessions.
* *location* (string): Filter by "active" | "archived" | "both" (default: "both").
* *include_metadata* (boolean): Include session metadata (default: false).
* **read**: Read content from a session file.
* **session_id** (string, **REQUIRED**): Session ID (e.g., WFS-my-session).
* **content_type** (string, **REQUIRED**): Type to read - "plan" | "task" | "summary" | "session" | "process" | "chat" | "brainstorm" | "review-dim" | "review-iter" | "review-fix" | "todo" | "context".
* *path_params* (object): Dynamic path parameters (task_id, filename, dimension, iteration).
* **write**: Write content to a session file.
* **session_id** (string, **REQUIRED**): Session ID.
* **content_type** (string, **REQUIRED**): Type to write (see read operation).
* **content** (object, **REQUIRED**): Content to write (object for JSON, string for text).
* *path_params* (object): Dynamic path parameters.
* **update**: Update existing content.
* **session_id** (string, **REQUIRED**): Session ID.
* **content_type** (string, **REQUIRED**): Type to update.
* **content** (object, **REQUIRED**): Updated content.
* *path_params* (object): Dynamic path parameters.
* **archive**: Archive a completed session.
* **session_id** (string, **REQUIRED**): Session ID.
* *update_status* (boolean): Mark status as completed (default: true).
* **mkdir**: Create session directories.
* **session_id** (string, **REQUIRED**): Session ID.
* **dirs** (array, **REQUIRED**): Directory paths to create.
* **delete**: Delete a file within a session.
* **session_id** (string, **REQUIRED**): Session ID.
* **file_path** (string, **REQUIRED**): Relative file path to delete.
* **stats**: Get session statistics.
* **session_id** (string, **REQUIRED**): Session ID.
**Session ID Format:** WFS-{name}-{date} (e.g., WFS-my-project-2026-03-05)`,
inputSchema: {
type: 'object',
properties: {

View File

@@ -2032,38 +2032,46 @@ async function executePriorityFallbackMode(params: Params): Promise<SearchResult
// Tool schema for MCP
export const schema: ToolSchema = {
name: 'smart_search',
description: `Unified code search tool with content search, file discovery, and semantic search capabilities.
description: `Unified code search tool. Choose an action and provide its required parameters.
**Actions:**
- search: Search file content (default)
- find_files: Find files by path/name pattern (glob matching)
- init: Create FTS index (incremental - skips existing)
- init_force: Force full rebuild (delete and recreate index)
- status: Check index status
- update: Incremental index update (for changed files)
- watch: Start file watcher for automatic updates
**Actions & Required Parameters:**
**Content Search (action="search"):**
smart_search(query="authentication logic") # fuzzy mode (default) - FTS + ripgrep fusion
smart_search(query="MyClass", mode="fuzzy") # fuzzy mode - fast hybrid search
smart_search(query="how to auth", mode="semantic") # semantic mode - dense + reranker
* **search** (default): Search file content.
* **query** (string, **REQUIRED**): Content to search for.
* *mode* (string): 'fuzzy' (default, FTS+ripgrep) or 'semantic' (dense+reranker).
* *limit* (number): Max results (default: 20).
* *path* (string): Directory to search (default: current).
* *contextLines* (number): Context lines around matches (default: 0).
* *regex* (boolean): Use regex matching (default: true).
* *caseSensitive* (boolean): Case-sensitive search (default: true).
**File Discovery (action="find_files"):**
smart_search(action="find_files", pattern="*.ts") # find all TypeScript files
smart_search(action="find_files", pattern="src/**/*.js") # recursive glob pattern
smart_search(action="find_files", pattern="test_*.py") # find test files
smart_search(action="find_files", pattern="*.tsx", offset=20, limit=10) # pagination
* **find_files**: Find files by path/name pattern.
* **pattern** (string, **REQUIRED**): Glob pattern (e.g., "*.ts", "src/**/*.js").
* *limit* (number): Max results (default: 20).
* *offset* (number): Pagination offset (default: 0).
* *includeHidden* (boolean): Include hidden files (default: false).
**Index Maintenance:**
smart_search(action="update", path="/project") # incremental index update
smart_search(action="watch", path="/project") # start file watcher
smart_search(action="watch", debounce=2000) # custom debounce interval
* **init**: Create FTS index (incremental, skips existing).
* *path* (string): Directory to index (default: current).
* *languages* (array): Languages to index (e.g., ["javascript", "typescript"]).
**Pagination:** All actions support offset/limit for paginated results:
smart_search(query="auth", limit=10, offset=0) # first page
smart_search(query="auth", limit=10, offset=10) # second page
* **init_force**: Force full rebuild (delete and recreate index).
* *path* (string): Directory to index (default: current).
**Modes:** fuzzy (FTS + ripgrep fusion, default), semantic (dense + reranker)`,
* **status**: Check index status. (No required params)
* **update**: Incremental index update.
* *path* (string): Directory to update (default: current).
* **watch**: Start file watcher for auto-updates.
* *path* (string): Directory to watch (default: current).
**Examples:**
smart_search(query="authentication logic") # Content search (default action)
smart_search(query="MyClass", mode="semantic") # Semantic search
smart_search(action="find_files", pattern="*.ts") # Find TypeScript files
smart_search(action="init", path="/project") # Initialize index
smart_search(query="auth", limit=10, offset=0) # Paginated search`,
inputSchema: {
type: 'object',
properties: {

View File

@@ -234,27 +234,55 @@ function resolveTeamId(params: Params): string | null {
export const schema: ToolSchema = {
name: 'team_msg',
description: `Team message bus - persistent JSONL log for Agent Team communication.
description: `Team message bus - persistent JSONL log for Agent Team communication. Choose an operation and provide its required parameters.
Directory Structure (NEW):
.workflow/.team/{session-id}/.msg/messages.jsonl
**Storage Location:** .workflow/.team/{session-id}/.msg/messages.jsonl
Directory Structure (LEGACY):
.workflow/.team-msg/{team-name}/messages.jsonl
**Operations & Required Parameters:**
Operations:
team_msg(operation="log", session_id="TLS-xxx", from="planner", type="plan_ready", data={ref: "plan.json"})
team_msg(operation="log", session_id="TLS-xxx", from="coordinator", type="state_update", data={pipeline_mode: "full"})
team_msg(operation="broadcast", session_id="TLS-xxx", from="coordinator", type="shutdown")
team_msg(operation="get_state", session_id="TLS-xxx", role="researcher")
team_msg(operation="read", session_id="TLS-xxx", id="MSG-003")
team_msg(operation="list", session_id="TLS-xxx", from="tester", last=5)
team_msg(operation="status", session_id="TLS-xxx")
team_msg(operation="delete", session_id="TLS-xxx", id="MSG-003")
team_msg(operation="clear", session_id="TLS-xxx")
* **log**: Append a message to the log.
* **session_id** (string, **REQUIRED**): Session ID (e.g., TLS-my-project-2026-02-27).
* **from** (string, **REQUIRED**): Sender role name (e.g., "planner", "coordinator").
* *to* (string): Recipient role (default: "coordinator").
* *type* (string): Message type (default: "message").
* *summary* (string): One-line summary (auto-generated if omitted).
* *data* (object): Structured data payload. Use data.ref for file paths.
Defaults: to="coordinator", summary=auto-generated if omitted, type="message"
Message types: plan_ready, plan_approved, plan_revision, task_unblocked, impl_complete, impl_progress, test_result, review_result, fix_required, error, shutdown, state_update`,
* **broadcast**: Send message to all team members.
* **session_id** (string, **REQUIRED**): Session ID.
* **from** (string, **REQUIRED**): Sender role name.
* *type* (string): Message type (e.g., "shutdown").
* *summary* (string): One-line summary.
* *data* (object): Structured data payload.
* **read**: Read a specific message by ID.
* **session_id** (string, **REQUIRED**): Session ID.
* **id** (string, **REQUIRED**): Message ID (e.g., "MSG-003").
* **list**: List recent messages.
* **session_id** (string, **REQUIRED**): Session ID.
* *last* (number): Number of messages to show (default: 20, max: 100).
* *from* (string): Filter by sender role.
* *to* (string): Filter by recipient role.
* *type* (string): Filter by message type.
* **status**: Summarize team member activity.
* **session_id** (string, **REQUIRED**): Session ID.
* **get_state**: Get state for a specific role.
* **session_id** (string, **REQUIRED**): Session ID.
* *role* (string): Role name to query (omit for all roles).
* **delete**: Delete a message by ID.
* **session_id** (string, **REQUIRED**): Session ID.
* **id** (string, **REQUIRED**): Message ID to delete.
* **clear**: Clear all messages for a session.
* **session_id** (string, **REQUIRED**): Session ID.
**Common Message Types:** plan_ready, plan_approved, plan_revision, task_unblocked, impl_complete, impl_progress, test_result, review_result, fix_required, error, shutdown, state_update
**Session ID Format:** TLS-{name}-{date} (e.g., TLS-my-project-2026-02-27)`,
inputSchema: {
type: 'object',
properties: {