ruvnet / ruvnet/ruflo

Bug: --no-chaining Flag Not Respected When Task Dependencies Present in worflow template files / npx claude-flow@alpha automation run-workflow

Open
#668 1 comment 0 reactions 0 assignees View on GitHub
already-fixed
Dominant language
TypeScript
Stars
72.7k
Forks
8.6k
Avg merge
2d 23h
Merged PRs (30d)
83

Description

## Summary
The `--no-chaining` flag in claude-flow automation workflows is completely ignored when tasks contain `depends` arrays, causing automatic stream chaining with 200-300% token usage overhead and cascade failures.

## Environment
- **Claude-Flow Version**: @alpha (latest as of 2025-08-18)
- **Node.js Version**: v20.19.2
- **Operating System**: Linux (WSL2)
- **Command**: `npx claude-flow@alpha automation run-workflow`

## Expected Behavior
When using `--no-chaining` flag, tasks should NOT pipe stdout between dependent tasks, regardless of `depends` field presence. Tasks should execute independently using only their assigned prompts.

## Actual Behavior
Despite `--no-chaining` flag, tasks with `depends` arrays automatically trigger stream chaining, causing:
1. Complete stdout from previous task piped to next task's stdin
2. 200-300% token usage increase due to full context streaming
3. "No messages returned" errors when piped content is malformed
4. Cascade failures through dependent task chains

## Steps to Reproduce

### 1. Create Test Workflow File
**File**: `test-workflow.json`
```json
{
"name": "No-Chaining Bug Test",
"description": "Test workflow to reproduce --no-chaining flag bug",
"version": "1.0.0",
"variables": {
"session_id": "test_${timestamp}"
},
"agents": [
{
"id": "agent1",
"type": "researcher",
"name": "First Agent"
},
{
"id": "agent2",
"type": "coordinator",
"name": "Second Agent"
}
],
"tasks": [
{
"id": "task1",
"name": "First Task",
"type": "research",
"description": "Simple first task",
"claudePrompt": "You are Agent 1. Simply respond: 'Task 1 completed successfully'. Do not include any additional output.",
"assignTo": "agent1",
"timeout": 60000
},
{
"id": "task2",
"name": "Second Task",
"type": "coordination",
"description": "Dependent second task",
"claudePrompt": "You are Agent 2. Respond: 'Task 2 completed successfully'. Do not reference any input.",
"assignTo": "agent2",
"depends": ["task1"],
"timeout": 60000
}
],
"settings": {
"maxConcurrency": 1,
"timeout": 300000,
"failurePolicy": "continue-on-error"
}
}
```

### 2. Execute With --no-chaining Flag
```bash
npx claude-flow@alpha automation run-workflow test-workflow.json \
--claude \
--non-interactive \
--output-format stream-json \
--no-chaining \
--max-concurrency 1 \
--timeout 300000
```

### 3. Observe Logs
**Expected Output** (correct behavior):
```
🚀 Starting: First Task
● First Task - Starting Execution
⎿ Simple first task
⎿ Agent: agent1

🚀 Starting: Second Task
● Second Task - Starting Execution
⎿ Dependent second task
⎿ Agent: agent2
```

**Actual Output** (bug behavior):
```
🚀 Starting: First Task
● First Task - Starting Execution
⎿ Simple first task
⎿ Agent: agent1

🚀 Starting: Second Task
● Second Task - Starting Execution
⎿ Dependent second task
⎿ Agent: agent2
🔗 Enabling stream chaining from task1 to task2
🔗 Chaining: Piping output from previous agent to Second Agent

❌ [Second Agent] Error: No messages returned
```

## Root Cause Analysis

### Code Location
**File**: `src/cli/simple-commands/automation-executor.js`
**Line**: 1151

### Problematic Code
```javascript
// Line 1151-1158
if (this.enableChaining && this.options.outputFormat === 'stream-json' && task.depends?.length > 0) {
// Get the output stream from the last dependency
const lastDependency = task.depends[task.depends.length - 1];
const dependencyStream = this.taskOutputStreams.get(lastDependency);
if (dependencyStream) {
console.log(` 🔗 Enabling stream chaining from ${lastDependency} to ${task.id}`);
chainOptions.inputStream = dependencyStream;
}
}
```

### Flag Parsing Analysis
The flag parsing works correctly:

1. **CLI Parsing**: `--no-chaining` sets `flags.chaining = false`
2. **runWorkflowCommand** (automation.js:292):
```javascript
enableChaining: options.chaining !== false // becomes: false !== false = false
```
3. **WorkflowExecutor Constructor** (automation-executor.js:50):
```javascript
this.enableChaining = options.enableChaining !== false; // becomes: false !== false = false
```

### The Bug
Despite `this.enableChaining = false`, the condition on line 1151 evaluates as:
- `this.enableChaining` = `false` ❌
- `this.options.outputFormat === 'stream-json'` = `true` ✅
- `task.depends?.length > 0` = `true` ✅

**However**, the logic `false && true && true = false` should prevent chaining, but it **still executes**. This suggests either:
1. The flag parsing chain is broken somewhere
2. There's another code path forcing chaining
3. The condition is being bypassed

## Impact Assessment

### Token Usage Impact
- **Without Dependencies**: ~5,000 tokens per workflow
- **With Stream Chaining**: ~15,000-20,000 tokens per workflow
- **Overhead**: 200-300% increase in token consumption
- **Cost Impact**: 2-3x increase in API costs

### Error Propagation
1. Task 1 completes successfully
2. Task 2 receives malformed stdin from Task 1's complete stdout
3. Claude CLI throws "No messages returned" error
4. Task 2 fails with exit code 1
5. Subsequent dependent tasks also fail in cascade

### Workflow Reliability
- **Success Rate with Dependencies**: ~33% (only first task succeeds)
- **Success Rate without Dependencies**: ~95% (all tasks independent)

## Workaround
Remove task dependencies and use memory-based coordination:

```json
{
"tasks": [
{
"id": "task1",
"claudePrompt": "Complete task and store result: npx claude-flow@alpha memory store session/task1/status 'completed'",
"assignTo": "agent1"
},
{
"id": "task2",
"claudePrompt": "Wait for task1: while true; do status=$(npx claude-flow@alpha memory retrieve session/task1/status 2>/dev/null || echo 'PENDING'); if [[ \"$status\" == \"completed\" ]]; then break; fi; sleep 5; done; echo 'Task 2 starting...'",
"assignTo": "agent2"
}
]
}
```

## Proposed Fix

### Option 1: Respect enableChaining Flag
```javascript
// Current (line 1151):
if (this.enableChaining && this.options.outputFormat === 'stream-json' && task.depends?.length > 0) {

// Fixed:
if (this.enableChaining && this.options.outputFormat === 'stream-json' && task.depends?.length > 0) {
```
*Note: This might already be correct. Need to investigate why it's not working.*

### Option 2: Add Explicit No-Chaining Check
```javascript
// More explicit fix:
if (this.enableChaining && !this.options.noChaining && this.options.outputFormat === 'stream-json' && task.depends?.length > 0) {
```

### Option 3: Debug Flag Parsing
Add debug logging to trace flag values:
```javascript
console.log(`DEBUG: enableChaining=${this.enableChaining}, noChaining=${this.options.noChaining}, outputFormat=${this.options.outputFormat}, depends=${task.depends?.length > 0}`);
```

## Additional Context

### Verification Command
The bug can be verified by searching for chaining messages:
```bash
npx claude-flow@alpha automation run-workflow test-workflow.json --no-chaining | grep -E "(Enabling stream chaining|Chaining:)"
```

**Expected**: No output (no chaining messages)
**Actual**: Shows chaining messages despite --no-chaining flag

### Related Code Files
- `src/cli/simple-commands/automation.js` - Flag parsing and WorkflowExecutor initialization
- `src/cli/simple-commands/automation-executor.js` - Stream chaining logic
- CLI argument parsing (need to investigate commander.js setup)

## Labels
`bug`, `automation`, `stream-chaining`, `flags`, `token-efficiency`, `workflow-execution`

Contributor guide

Open the contributing guide

Research direction

Start with src/cli/simple-commands/automation.js to trace --no-chaining into WorkflowExecutor, then inspect the chaining condition around line 1151 in src/cli/simple-commands/automation-executor.js. Reproduce with the provided test-workflow.json and verification command, tracing the flag values and any alternate chaining path. Done means --no-chaining produces no chaining messages and dependent tasks do not receive the previous task's stdout.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.