mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-05 01:50:27 +08:00
refactor: enhance conflict resolution command with modification suggestions for custom handling
This commit is contained in:
@@ -11,6 +11,17 @@ Orchestrates autonomous workflow execution through systematic task discovery, ag
|
||||
|
||||
**Resume Mode**: When called with `--resume-session` flag, skips discovery phase and directly enters TodoWrite generation and agent execution for the specified session.
|
||||
|
||||
## Performance Optimization Strategy
|
||||
|
||||
**Lazy Loading**: Task JSONs read **on-demand** during execution, not upfront. TODO_LIST.md + IMPL_PLAN.md provide metadata for planning.
|
||||
|
||||
| Metric | Before | After | Improvement |
|
||||
|--------|--------|-------|-------------|
|
||||
| **Initial Load** | All task JSONs (~2,300 lines) | TODO_LIST.md only (~650 lines) | **72% reduction** |
|
||||
| **Startup Time** | Seconds | Milliseconds | **~90% faster** |
|
||||
| **Memory** | All tasks | 1-2 tasks | **90% less** |
|
||||
| **Scalability** | 10-20 tasks | 100+ tasks | **5-10x** |
|
||||
|
||||
## Core Rules
|
||||
**Complete entire workflow autonomously without user interruption, using TodoWrite for comprehensive progress tracking.**
|
||||
**Execute all discovered pending tasks sequentially until workflow completion or blocking dependency.**
|
||||
@@ -63,40 +74,69 @@ Orchestrates autonomous workflow execution through systematic task discovery, ag
|
||||
### Phase 1: Discovery (Normal Mode Only)
|
||||
1. **Check Active Sessions**: Find `.workflow/.active-*` markers
|
||||
2. **Select Session**: If multiple found, prompt user selection
|
||||
3. **Load Session State**: Read `workflow-session.json` and `IMPL_PLAN.md`
|
||||
4. **Scan Tasks**: Analyze `.task/*.json` files for ready tasks
|
||||
3. **Load Session Metadata**: Read `workflow-session.json` ONLY (minimal context)
|
||||
4. **DO NOT read task JSONs yet** - defer until execution phase
|
||||
|
||||
**Note**: In resume mode, this phase is completely skipped.
|
||||
|
||||
### Phase 2: Analysis (Normal Mode Only)
|
||||
1. **Dependency Resolution**: Build execution order based on `depends_on`
|
||||
2. **Status Validation**: Filter tasks with `status: "pending"` and met dependencies
|
||||
3. **Agent Assignment**: Determine agent type from `meta.agent` or `meta.type`
|
||||
4. **Context Preparation**: Load dependency summaries and inherited context
|
||||
### Phase 2: Planning Document Analysis (Normal Mode Only)
|
||||
**Optimized to avoid reading all task JSONs upfront**
|
||||
|
||||
1. **Read IMPL_PLAN.md**: Understand overall strategy, task breakdown summary, dependencies
|
||||
2. **Read TODO_LIST.md**: Get current task statuses and execution progress
|
||||
3. **Extract Task Metadata**: Parse task IDs, titles, and dependency relationships from TODO_LIST.md
|
||||
4. **Build Execution Queue**: Determine ready tasks based on TODO_LIST.md status and dependencies
|
||||
|
||||
**Key Optimization**: Use IMPL_PLAN.md and TODO_LIST.md as primary sources instead of reading all task JSONs
|
||||
|
||||
**Note**: In resume mode, this phase is also skipped as session analysis was already completed by `/workflow:status`.
|
||||
|
||||
### Phase 3: Planning (Resume Mode Entry Point)
|
||||
### Phase 3: TodoWrite Generation (Resume Mode Entry Point)
|
||||
**This is where resume mode directly enters after skipping Phases 1 & 2**
|
||||
|
||||
1. **Create TodoWrite List**: Generate task list with status markers from session state
|
||||
2. **Mark Initial Status**: Set first pending task as `in_progress`
|
||||
1. **Create TodoWrite List**: Generate task list from TODO_LIST.md (not from task JSONs)
|
||||
- Parse TODO_LIST.md to extract all tasks with current statuses
|
||||
- Identify first pending task with met dependencies
|
||||
- Generate comprehensive TodoWrite covering entire workflow
|
||||
2. **Mark Initial Status**: Set first ready task as `in_progress` in TodoWrite
|
||||
3. **Prepare Session Context**: Inject workflow paths for agent use (using provided session-id)
|
||||
4. **Prepare Complete Task JSON**: Include pre_analysis and flow control steps for agent consumption
|
||||
5. **Validate Prerequisites**: Ensure all required context is available from existing session
|
||||
4. **Validate Prerequisites**: Ensure IMPL_PLAN.md and TODO_LIST.md exist and are valid
|
||||
|
||||
**Resume Mode Behavior**:
|
||||
- Load existing session state directly from `.workflow/{session-id}/`
|
||||
- Use session's task files and summaries without discovery
|
||||
- Generate TodoWrite from current session progress
|
||||
- Proceed immediately to agent execution
|
||||
- Load existing TODO_LIST.md directly from `.workflow/{session-id}/`
|
||||
- Extract current progress from TODO_LIST.md
|
||||
- Generate TodoWrite from TODO_LIST.md state
|
||||
- Proceed immediately to agent execution (Phase 4)
|
||||
|
||||
### Phase 4: Execution
|
||||
1. **Pass Task with Flow Control**: Include complete task JSON with `pre_analysis` steps for agent execution
|
||||
2. **Launch Agent**: Invoke specialized agent with complete context including flow control steps
|
||||
3. **Monitor Progress**: Track agent execution and handle errors without user interruption
|
||||
4. **Collect Results**: Gather implementation results and outputs
|
||||
5. **Continue Workflow**: Automatically proceed to next pending task until completion
|
||||
### Phase 4: Execution (Lazy Task Loading)
|
||||
**Key Optimization**: Read task JSON **only when needed** for execution
|
||||
|
||||
1. **Identify Next Task**: From TodoWrite, get the next `in_progress` task ID
|
||||
2. **Load Task JSON on Demand**: Read `.task/{task-id}.json` for current task ONLY
|
||||
3. **Validate Task Structure**: Ensure all 5 required fields exist (id, title, status, meta, context, flow_control)
|
||||
4. **Pass Task with Flow Control**: Include complete task JSON with `pre_analysis` steps for agent execution
|
||||
5. **Launch Agent**: Invoke specialized agent with complete context including flow control steps
|
||||
6. **Monitor Progress**: Track agent execution and handle errors without user interruption
|
||||
7. **Collect Results**: Gather implementation results and outputs
|
||||
8. **Update TODO_LIST.md**: Mark current task as completed in TODO_LIST.md
|
||||
9. **Continue Workflow**: Identify next pending task from TODO_LIST.md and repeat from step 1
|
||||
|
||||
**Execution Loop Pattern**:
|
||||
```
|
||||
while (TODO_LIST.md has pending tasks) {
|
||||
next_task_id = getTodoWriteInProgressTask()
|
||||
task_json = Read(.workflow/{session}/.task/{next_task_id}.json) // Lazy load
|
||||
executeTaskWithAgent(task_json)
|
||||
updateTodoListMarkCompleted(next_task_id)
|
||||
advanceTodoWriteToNextTask()
|
||||
}
|
||||
```
|
||||
|
||||
**Benefits**:
|
||||
- Reduces initial context loading by ~90%
|
||||
- Only reads task JSON when actually executing
|
||||
- Scales better for workflows with many tasks
|
||||
- Faster startup time for workflow execution
|
||||
|
||||
### Phase 5: Completion
|
||||
1. **Update Task Status**: Mark completed tasks in JSON files
|
||||
@@ -108,27 +148,33 @@ Orchestrates autonomous workflow execution through systematic task discovery, ag
|
||||
|
||||
## Task Discovery & Queue Building
|
||||
|
||||
### Session Discovery Process (Normal Mode)
|
||||
### Session Discovery Process (Normal Mode - Optimized)
|
||||
```
|
||||
├── Check for .active-* markers in .workflow/
|
||||
├── If multiple active sessions found → Prompt user to select
|
||||
├── Locate selected session's workflow folder
|
||||
├── Load selected session's workflow-session.json and IMPL_PLAN.md
|
||||
├── Scan selected session's .task/ directory for task JSON files
|
||||
├── Analyze task statuses and dependencies for selected session only
|
||||
└── Build execution queue of ready tasks from selected session
|
||||
├── Load session metadata: workflow-session.json (minimal context)
|
||||
├── Read IMPL_PLAN.md (strategy overview and task summary)
|
||||
├── Read TODO_LIST.md (current task statuses and dependencies)
|
||||
├── Parse TODO_LIST.md to extract task metadata (NO JSON loading)
|
||||
├── Build execution queue from TODO_LIST.md
|
||||
└── Generate TodoWrite from TODO_LIST.md state
|
||||
```
|
||||
|
||||
### Resume Mode Process (--resume-session flag)
|
||||
**Key Change**: Task JSONs are NOT loaded during discovery - they are loaded lazily during execution
|
||||
|
||||
### Resume Mode Process (--resume-session flag - Optimized)
|
||||
```
|
||||
├── Use provided session-id directly (skip discovery)
|
||||
├── Validate .workflow/{session-id}/ directory exists
|
||||
├── Load session's workflow-session.json and IMPL_PLAN.md directly
|
||||
├── Scan session's .task/ directory for task JSON files
|
||||
├── Use existing task statuses and dependencies (no re-analysis needed)
|
||||
└── Build execution queue from session state (prioritize pending/in-progress tasks)
|
||||
├── Read TODO_LIST.md for current progress
|
||||
├── Parse TODO_LIST.md to extract task IDs and statuses
|
||||
├── Generate TodoWrite from TODO_LIST.md (prioritize in-progress/pending tasks)
|
||||
└── Enter Phase 4 (Execution) with lazy task JSON loading
|
||||
```
|
||||
|
||||
**Key Change**: Completely skip IMPL_PLAN.md and task JSON loading - use TODO_LIST.md only
|
||||
|
||||
### Task Status Logic
|
||||
```
|
||||
pending + dependencies_met → executable
|
||||
@@ -141,52 +187,72 @@ blocked → skip until dependencies clear
|
||||
### Parallel Execution Algorithm
|
||||
**Core principle**: Execute independent tasks concurrently in batches based on dependency graph.
|
||||
|
||||
#### Algorithm Steps
|
||||
#### Algorithm Steps (Optimized with Lazy Loading)
|
||||
```javascript
|
||||
function executeBatchWorkflow(sessionId) {
|
||||
// 1. Build dependency graph from task JSONs
|
||||
const graph = buildDependencyGraph(`.workflow/${sessionId}/.task/*.json`);
|
||||
// 1. Build dependency graph from TODO_LIST.md (NOT task JSONs)
|
||||
const graph = buildDependencyGraphFromTodoList(`.workflow/${sessionId}/TODO_LIST.md`);
|
||||
|
||||
// 2. Process batches until graph is empty
|
||||
while (!graph.isEmpty()) {
|
||||
// 3. Identify current batch (tasks with in-degree = 0)
|
||||
const batch = graph.getNodesWithInDegreeZero();
|
||||
|
||||
// 4. Check for parallel execution opportunities
|
||||
const parallelGroups = groupByExecutionGroup(batch);
|
||||
// 4. Load task JSONs ONLY for current batch (lazy loading)
|
||||
const batchTaskJsons = batch.map(taskId =>
|
||||
Read(`.workflow/${sessionId}/.task/${taskId}.json`)
|
||||
);
|
||||
|
||||
// 5. Execute batch concurrently
|
||||
// 5. Check for parallel execution opportunities
|
||||
const parallelGroups = groupByExecutionGroup(batchTaskJsons);
|
||||
|
||||
// 6. Execute batch concurrently
|
||||
await Promise.all(
|
||||
parallelGroups.map(group => executeBatch(group))
|
||||
);
|
||||
|
||||
// 6. Update graph: remove completed tasks and their edges
|
||||
// 7. Update graph: remove completed tasks and their edges
|
||||
graph.removeNodes(batch);
|
||||
|
||||
// 7. Update TodoWrite to reflect completed batch
|
||||
// 8. Update TODO_LIST.md and TodoWrite to reflect completed batch
|
||||
updateTodoListAfterBatch(batch);
|
||||
updateTodoWriteAfterBatch(batch);
|
||||
}
|
||||
|
||||
// 8. All tasks complete - auto-complete session
|
||||
// 9. All tasks complete - auto-complete session
|
||||
SlashCommand("/workflow:session:complete");
|
||||
}
|
||||
|
||||
function buildDependencyGraph(taskFiles) {
|
||||
const tasks = loadAllTaskJSONs(taskFiles);
|
||||
function buildDependencyGraphFromTodoList(todoListPath) {
|
||||
const todoContent = Read(todoListPath);
|
||||
const tasks = parseTodoListTasks(todoContent);
|
||||
const graph = new DirectedGraph();
|
||||
|
||||
tasks.forEach(task => {
|
||||
graph.addNode(task.id, task);
|
||||
|
||||
// Add edges for dependencies
|
||||
task.context.depends_on?.forEach(depId => {
|
||||
graph.addEdge(depId, task.id); // Edge from dependency to task
|
||||
});
|
||||
graph.addNode(task.id, { id: task.id, title: task.title, status: task.status });
|
||||
task.dependencies?.forEach(depId => graph.addEdge(depId, task.id));
|
||||
});
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
function parseTodoListTasks(todoContent) {
|
||||
// Parse: - [ ] **IMPL-001**: Task title → [📋](./.task/IMPL-001.json)
|
||||
const taskPattern = /- \[([ x])\] \*\*([A-Z]+-\d+(?:\.\d+)?)\*\*: (.+?) →/g;
|
||||
const tasks = [];
|
||||
let match;
|
||||
|
||||
while ((match = taskPattern.exec(todoContent)) !== null) {
|
||||
tasks.push({
|
||||
status: match[1] === 'x' ? 'completed' : 'pending',
|
||||
id: match[2],
|
||||
title: match[3]
|
||||
});
|
||||
}
|
||||
|
||||
return tasks;
|
||||
}
|
||||
|
||||
function groupByExecutionGroup(tasks) {
|
||||
const groups = {};
|
||||
|
||||
@@ -338,11 +404,12 @@ TodoWrite({
|
||||
- **Workflow Completion Check**: When all tasks marked `completed`, auto-call `/workflow:session:complete`
|
||||
|
||||
#### TODO_LIST.md Update Timing
|
||||
- **Before Agent Launch**: Update TODO_LIST.md to mark task as `in_progress` (⚠️)
|
||||
- **After Task Complete**: Update TODO_LIST.md to mark as `completed` (✅), advance to next
|
||||
- **On Error**: Keep as `in_progress` in TODO_LIST.md, add error note
|
||||
- **Workflow Complete**: When all tasks completed, call `/workflow:session:complete`
|
||||
- **Session End**: Sync all TODO_LIST.md statuses with JSON task files
|
||||
**Single source of truth for task status** - enables lazy loading by providing task metadata without reading JSONs
|
||||
|
||||
- **Before Agent Launch**: Mark task as `in_progress` (⚠️)
|
||||
- **After Task Complete**: Mark as `completed` (✅), advance to next
|
||||
- **On Error**: Keep as `in_progress`, add error note
|
||||
- **Workflow Complete**: Call `/workflow:session:complete`
|
||||
|
||||
### 3. Agent Context Management
|
||||
**Comprehensive context preparation** for autonomous agent execution:
|
||||
@@ -423,7 +490,7 @@ Task(subagent_type="{meta.agent}",
|
||||
3. **Implement Solution**: Follow `flow_control.implementation_approach` using accumulated context
|
||||
4. **Complete Task**:
|
||||
- Update task status: `jq '.status = \"completed\"' {session.task_json_path} > temp.json && mv temp.json {session.task_json_path}`
|
||||
- Update TODO list: {session.todo_list_path}
|
||||
- Update TODO_LIST.md: Mark task as [x] completed in {session.todo_list_path}
|
||||
- Generate summary: {session.summaries_dir}/{task.id}-summary.md
|
||||
- Check workflow completion and call `/workflow:session:complete` if all tasks done
|
||||
|
||||
|
||||
@@ -166,7 +166,12 @@ Task(subagent_type="cli-execution-agent", prompt=`
|
||||
"modifications": [...]
|
||||
}
|
||||
],
|
||||
"recommended": 0
|
||||
"recommended": 0,
|
||||
"modification_suggestions": [
|
||||
"建议1:具体的修改方向或注意事项",
|
||||
"建议2:可能需要考虑的边界情况",
|
||||
"建议3:相关的最佳实践或模式"
|
||||
]
|
||||
}
|
||||
],
|
||||
"summary": {
|
||||
@@ -186,12 +191,15 @@ Task(subagent_type="cli-execution-agent", prompt=`
|
||||
- section: Markdown heading for context (helps locate position)
|
||||
- Minimum 2 strategies per conflict, max 4
|
||||
- All text in Chinese for user-facing fields (brief, name, pros, cons)
|
||||
- modification_suggestions: 2-5 actionable suggestions for custom handling (Chinese)
|
||||
|
||||
Quality Standards:
|
||||
- Each strategy must have actionable modifications
|
||||
- old_content must be precise enough for Edit tool matching
|
||||
- new_content preserves markdown formatting and structure
|
||||
- Recommended strategy (index) based on lowest complexity + risk
|
||||
- modification_suggestions must be specific, actionable, and context-aware
|
||||
- Each suggestion should address a specific aspect (compatibility, migration, testing, etc.)
|
||||
`)
|
||||
```
|
||||
|
||||
@@ -238,10 +246,19 @@ for (const [batchIdx, batch] of batches.entries()) {
|
||||
console.log(` 复杂度: ${strategy.complexity} | 风险: ${strategy.risk} | 工作量: ${strategy.effort}`);
|
||||
});
|
||||
|
||||
// Add skip option
|
||||
const skipLetter = String.fromCharCode(97 + conflict.strategies.length);
|
||||
console.log(`${skipLetter}) 跳过此冲突`);
|
||||
console.log(` 说明:稍后手动处理,不应用任何修改\n`);
|
||||
// Add custom option
|
||||
const customLetter = String.fromCharCode(97 + conflict.strategies.length);
|
||||
console.log(`${customLetter}) 自定义修改`);
|
||||
console.log(` 说明:根据修改建议自行处理,不应用预设策略`);
|
||||
|
||||
// Show modification suggestions
|
||||
if (conflict.modification_suggestions && conflict.modification_suggestions.length > 0) {
|
||||
console.log(` 修改建议:`);
|
||||
conflict.modification_suggestions.forEach(suggestion => {
|
||||
console.log(` - ${suggestion}`);
|
||||
});
|
||||
}
|
||||
console.log();
|
||||
});
|
||||
|
||||
console.log(`请回答 (格式: 1a 2b 3c...):`);
|
||||
@@ -253,38 +270,51 @@ for (const [batchIdx, batch] of batches.entries()) {
|
||||
const answers = parseUserAnswers(userInput, batch);
|
||||
}
|
||||
|
||||
// 3. Build selected strategies
|
||||
const selectedStrategies = answers.filter(a => !a.isSkip).map(a => a.strategy);
|
||||
// 3. Build selected strategies (exclude custom selections)
|
||||
const selectedStrategies = answers.filter(a => !a.isCustom).map(a => a.strategy);
|
||||
const customConflicts = answers.filter(a => a.isCustom).map(a => ({
|
||||
id: a.conflict.id,
|
||||
brief: a.conflict.brief,
|
||||
suggestions: a.conflict.modification_suggestions
|
||||
}));
|
||||
```
|
||||
|
||||
**Text Output Example**:
|
||||
```markdown
|
||||
===== 冲突解决 (第 1/1 轮) =====
|
||||
|
||||
【问题1 - 认证系统】CON-001: 现有认证系统与计划不兼容
|
||||
【问题1 - Architecture】CON-001: 现有认证系统与计划不兼容
|
||||
a) 渐进式迁移
|
||||
说明:保留现有系统,逐步迁移到新方案
|
||||
复杂度: Medium | 风险: Low | 工作量: 3-5天
|
||||
b) 完全重写
|
||||
说明:废弃旧系统,从零实现新认证
|
||||
复杂度: High | 风险: Medium | 工作量: 7-10天
|
||||
c) 跳过此冲突
|
||||
说明:稍后手动处理,不应用任何修改
|
||||
c) 自定义修改
|
||||
说明:根据修改建议自行处理,不应用预设策略
|
||||
修改建议:
|
||||
- 评估现有认证系统的兼容性,考虑是否可以通过适配器模式桥接
|
||||
- 检查JWT token格式和验证逻辑是否需要调整
|
||||
- 确保用户会话管理与新架构保持一致
|
||||
|
||||
【问题2 - 数据库】CON-002: 数据库 schema 冲突
|
||||
【问题2 - Data】CON-002: 数据库 schema 冲突
|
||||
a) 添加迁移脚本
|
||||
说明:创建数据库迁移脚本处理 schema 变更
|
||||
复杂度: Low | 风险: Low | 工作量: 1-2天
|
||||
b) 跳过此冲突
|
||||
说明:稍后手动处理,不应用任何修改
|
||||
b) 自定义修改
|
||||
说明:根据修改建议自行处理,不应用预设策略
|
||||
修改建议:
|
||||
- 检查现有表结构是否支持新增字段,避免破坏性变更
|
||||
- 考虑使用数据库版本控制工具(如Flyway或Liquibase)
|
||||
- 准备数据迁移和回滚策略
|
||||
|
||||
请回答 (格式: 1a 2b):
|
||||
```
|
||||
|
||||
**User Input Examples**:
|
||||
- `1a 2a` → Conflict 1: 渐进式迁移, Conflict 2: 添加迁移脚本
|
||||
- `1b 2b` → Conflict 1: 完全重写, Conflict 2: 跳过
|
||||
- `1c 2c` → Both skipped
|
||||
- `1b 2b` → Conflict 1: 完全重写, Conflict 2: 自定义修改
|
||||
- `1c 2c` → Both choose custom modification (user handles manually with suggestions)
|
||||
|
||||
### Phase 4: Apply Modifications
|
||||
|
||||
@@ -316,11 +346,25 @@ contextPackage.conflict_detection.resolved_conflicts = conflicts.map(c => c.id);
|
||||
contextPackage.conflict_detection.resolved_at = new Date().toISOString();
|
||||
Write(contextPath, JSON.stringify(contextPackage, null, 2));
|
||||
|
||||
// 4. Return summary
|
||||
// 4. Output custom conflict summary (if any)
|
||||
if (customConflicts.length > 0) {
|
||||
console.log("\n===== 需要自定义处理的冲突 =====\n");
|
||||
customConflicts.forEach(conflict => {
|
||||
console.log(`【${conflict.id}】${conflict.brief}`);
|
||||
console.log("修改建议:");
|
||||
conflict.suggestions.forEach(suggestion => {
|
||||
console.log(` - ${suggestion}`);
|
||||
});
|
||||
console.log();
|
||||
});
|
||||
}
|
||||
|
||||
// 5. Return summary
|
||||
return {
|
||||
resolved: modifications.length,
|
||||
skipped: selectedStrategies.filter(s => s === "skip").length,
|
||||
modified_files: [...new Set(modifications.map(m => m.file))]
|
||||
custom: customConflicts.length,
|
||||
modified_files: [...new Set(modifications.map(m => m.file))],
|
||||
custom_conflicts: customConflicts
|
||||
};
|
||||
```
|
||||
|
||||
@@ -397,21 +441,23 @@ If Edit tool fails mid-application:
|
||||
|
||||
**User Interaction**:
|
||||
- Text-based strategy selection (max 10 conflicts per round)
|
||||
- Each conflict: 2-4 strategy options + "跳过" option
|
||||
- Each conflict: 2-4 strategy options + "自定义修改" option (with suggestions)
|
||||
|
||||
### Success Criteria
|
||||
```
|
||||
✓ CLI analysis returns valid JSON structure
|
||||
✓ Conflicts presented in batches (max 10 per round)
|
||||
✓ Min 2 strategies per conflict with modifications
|
||||
✓ Text output displays all conflicts correctly
|
||||
✓ Each conflict includes 2-5 modification_suggestions
|
||||
✓ Text output displays all conflicts correctly with suggestions
|
||||
✓ User selections captured and processed
|
||||
✓ Edit tool applies modifications successfully
|
||||
✓ Custom conflicts displayed with suggestions for manual handling
|
||||
✓ guidance-specification.md updated with resolved conflicts
|
||||
✓ Role analyses (*.md) updated with resolved conflicts
|
||||
✓ context-package.json marked as "resolved"
|
||||
✓ No CONFLICT_RESOLUTION.md file generated
|
||||
✓ Modification summary returned to user
|
||||
✓ Modification summary includes custom conflict count
|
||||
✓ Agent log saved to .workflow/{session_id}/.chat/
|
||||
✓ Error handling robust (validate/retry/degrade)
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user