Skip to content

fix: resolve path resolution and context gathering errors across multiple commands#954

Merged
Crunchyman-ralph merged 2 commits intoeyaltoledano:nextfrom
ben-vargas:fix/next-command-paths
Jul 11, 2025
Merged

fix: resolve path resolution and context gathering errors across multiple commands#954
Crunchyman-ralph merged 2 commits intoeyaltoledano:nextfrom
ben-vargas:fix/next-command-paths

Conversation

@ben-vargas
Copy link
Contributor

Summary

This PR fixes critical path resolution issues and context gathering errors that were preventing multiple commands from functioning properly. The fixes ensure commands can create their output files without requiring them to exist first, and properly handle context gathering results across the codebase.

Problem Description

1. Path Resolution Issues

Commands like parse-prd and analyze-complexity were failing with "override path does not exist" errors because they required their output files to exist before they could create them - a classic catch-22 situation.

2. Context Gathering Errors

Multiple commands were failing with "Parameter 'gatheredContext' expected string, got object" errors due to incorrect handling of the contextGatherer.gather() return value.

3. Prompt Variant Errors

The analyze-complexity command was attempting to load a non-existent 'research' variant, causing runtime failures.

Changes Made

1. scripts/modules/commands.js

parse-prd Command (Lines 808, 828-835, 919-921)

// Before:
.option('-o, --output <file>', 'Output file path', TASKMASTER_TASKS_FILE)
// After:
.option('-o, --output <file>', 'Output file path')

Why: The default value in the option definition meant options.output was ALWAYS populated, making our conditional check if (options.output) always true.

// Before:
taskMaster = initTaskMaster({
    prdPath: file || options.input || true,
    tasksPath: options.output || true
});

// After:
const initOptions = {
    prdPath: file || options.input || true
};
if (options.output) {
    initOptions.tasksPath = options.output;
}
taskMaster = initTaskMaster(initOptions);

Why: Only include tasksPath when explicitly specified by the user, allowing the command to work without requiring the output file to exist.

// Added null handling:
const outputPath = taskMaster.getTasksPath() || 
    path.join(taskMaster.getProjectRoot(), TASKMASTER_TASKS_FILE);

Why: Provides a fallback when getTasksPath() returns null, ensuring the command can always determine where to write output.

analyze-complexity Command (Lines 1637-1640, 1673-1680, 1695-1696)

Similar changes as parse-prd:

  • Removed default value from output option
  • Conditional inclusion of complexityReportPath in initTaskMaster
  • Added null handling for report path

2. scripts/modules/task-manager/analyze-task-complexity.js

Context Gathering Fix (Line 243)

// Before:
gatheredContext = contextResult;
// After:
gatheredContext = contextResult.context || '';

Why: contextGatherer.gather() returns an object with multiple properties, not just a string. We need to extract the context property.

Prompt Variant Fix (Lines 409-413)

// Before:
const variantKey = useResearch ? 'research' : 'default';
const { systemPrompt, userPrompt: prompt } = await promptManager.loadPrompt(
    'analyze-complexity',
    promptParams,
    variantKey
);

// After:
const { systemPrompt, userPrompt: prompt } = await promptManager.loadPrompt(
    'analyze-complexity',
    promptParams,
    'default'
);

Why: The analyze-complexity prompt only has a 'default' variant. The conditional logic for research mode is handled within the prompt template itself using handlebars conditions.

3. Context Gathering Fixes in Multiple Files

Fixed the same context gathering issue in:

  • scripts/modules/task-manager/expand-task.js (Line 372)
  • scripts/modules/task-manager/update-task-by-id.js (Line 349)
  • scripts/modules/task-manager/update-subtask-by-id.js (Line 164)
  • scripts/modules/task-manager/update-tasks.js (Line 303)

All changed from:

gatheredContext = contextResult;

To:

gatheredContext = contextResult.context || '';

Why This Approach Over "|| false"

The original PATH-FIXES.md suggested using || false to make paths optional:

tasksPath: options.file || false

Our approach is superior because:

  1. Clearer Intent: We only include parameters that are actually needed, rather than passing boolean flags that initTaskMaster must interpret.

  2. Avoids Boolean Confusion: The boolean approach (true = required, false = optional) is not intuitive and prone to errors.

  3. More Explicit: The code clearly shows "only use this path if the user provided it" rather than relying on boolean interpretation.

  4. Aligns with Best Practices: The PATH-FIXES.md itself identified "Boolean Parameters Are Dangerous" in its lessons learned.

  5. Cleaner API: By not including unnecessary parameters, we keep the initTaskMaster calls cleaner and more maintainable.

Testing

All commands now work properly:

  • tm parse-prd creates tasks.json without requiring it to exist
  • tm analyze-complexity creates the report file without requiring it to exist
  • tm expand --all properly expands tasks with context gathering
  • All update commands work with proper context handling

Impact

This PR fixes critical functionality issues that were preventing normal use of the task-master CLI. The changes are backward compatible and only affect the internal handling of paths and context data.

…ty commands

This commit fixes critical path resolution regressions where commands were requiring files they create to already exist.

## Changes Made:

### 1. parse-prd Command (Lines 808, 828-835, 919-921)
**Problem**: Command required tasks.json to exist before it could create it (catch-22)
**Root Cause**: Default value in option definition meant options.output was always set
**Fixes**:
- Removed default value from --output option definition (line 808)
- Modified initTaskMaster to only include tasksPath when explicitly specified
- Added null handling for output path with fallback to default location

### 2. analyze-complexity Command (Lines 1637-1640, 1673-1680, 1695-1696)
**Problem**: Command required complexity report file to exist before creating it
**Root Cause**: Default value in option definition meant options.output was always set
**Fixes**:
- Removed default value from --output option definition (lines 1637-1640)
- Modified initTaskMaster to only include complexityReportPath when explicitly specified
- Added null handling for report path with fallback to default location

## Technical Details:

The core issue was that Commander.js option definitions with default values always populate the options object, making conditional checks like `if (options.output)` always true. By removing default values from option definitions, we ensure paths are only included in initTaskMaster when users explicitly provide them.

This approach is cleaner than using boolean flags (true/false) for required/optional, as it eliminates the path entirely when not needed, letting initTaskMaster use its default behavior.

## Testing:
- parse-prd now works on fresh projects without existing tasks.json
- analyze-complexity creates report file without requiring it to exist
- Commands maintain backward compatibility when paths are explicitly provided

Fixes issues reported in PATH-FIXES.md and extends the solution to other affected commands.
@changeset-bot
Copy link

changeset-bot bot commented Jul 10, 2025

⚠️ No Changeset found

Latest commit: a886833

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@ben-vargas
Copy link
Contributor Author

CI Fix: Updated test mock to match implementation

During CI testing, discovered that the expand-task test was failing because the ContextGatherer mock was returning the wrong format. The test expected a string but the actual implementation (after our fixes) returns an object with a context property.

Changes made:

  • Updated ContextGatherer mock to return { context: 'Mock project context from files' } instead of just the string
  • Added missing FuzzyTaskSearch mock that the module imports

This ensures the test accurately reflects the actual implementation behavior after our context gathering fixes.

Commit: f7337c8

Copy link
Collaborator

@Crunchyman-ralph Crunchyman-ralph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, but have small nitpicks

const { systemPrompt, userPrompt: prompt } = await promptManager.loadPrompt(
'analyze-complexity',
promptParams,
variantKey
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we changing it here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code was looking for a separate 'research' prompt variant that doesn't exist. The --research functionality is actually built into the default prompt using template conditionals ({{#if useResearch}}), so we should always use the 'default' variant and pass useResearch as a parameter, which we already do correctly on line 406.

There's no need to pass useResearch in both promptParams and variantKey, especially if there is no 'research' variant defined.

Passing the variantKey causes the command to fail - probably a separate issue that should be better handled when a key is missing, but I'm trying to limit the scope of this PR and just get 'next' working again after all of these regression issues caused by recent merges.

The Prompt File Structure

The analyze-complexity.json prompt file only defines a 'default' variant (line 36). There is no 'research' variant defined.

How It Actually Works

Looking at line 38, the prompt uses a conditional template: {{#if useResearch}} Consider current best practices, common implementation patterns, and industry standards in your analysis.{{/if}}

This means the --research flag is handled within the default prompt by adding extra instructions when useResearch is true. It doesn't need a separate 'research' variant.

The Bug

The code was incorrectly trying to load a separate 'research' variant:

const variantKey = useResearch ? 'research' : 'default';

But since only 'default' exists, it should always use 'default' and let the prompt template handle the research mode internally.

The test was expecting gatheredContext to be a string, but the actual
implementation returns an object with a context property. Updated the
ContextGatherer mock to return the correct format and added missing
FuzzyTaskSearch mock.
@ben-vargas ben-vargas force-pushed the fix/next-command-paths branch from f7337c8 to a886833 Compare July 11, 2025 00:57
@Crunchyman-ralph Crunchyman-ralph merged commit 3e61d26 into eyaltoledano:next Jul 11, 2025
3 checks passed
@ben-vargas ben-vargas deleted the fix/next-command-paths branch July 13, 2025 01:46
stephanschielke pushed a commit to stephanschielke/cursor-task-master that referenced this pull request Aug 22, 2025
…iple commands (eyaltoledano#954)

* fix: resolve path resolution issues in parse-prd and analyze-complexity commands

This commit fixes critical path resolution regressions where commands were requiring files they create to already exist.

## Changes Made:

### 1. parse-prd Command (Lines 808, 828-835, 919-921)
**Problem**: Command required tasks.json to exist before it could create it (catch-22)
**Root Cause**: Default value in option definition meant options.output was always set
**Fixes**:
- Removed default value from --output option definition (line 808)
- Modified initTaskMaster to only include tasksPath when explicitly specified
- Added null handling for output path with fallback to default location

### 2. analyze-complexity Command (Lines 1637-1640, 1673-1680, 1695-1696)
**Problem**: Command required complexity report file to exist before creating it
**Root Cause**: Default value in option definition meant options.output was always set
**Fixes**:
- Removed default value from --output option definition (lines 1637-1640)
- Modified initTaskMaster to only include complexityReportPath when explicitly specified
- Added null handling for report path with fallback to default location

## Technical Details:

The core issue was that Commander.js option definitions with default values always populate the options object, making conditional checks like `if (options.output)` always true. By removing default values from option definitions, we ensure paths are only included in initTaskMaster when users explicitly provide them.

This approach is cleaner than using boolean flags (true/false) for required/optional, as it eliminates the path entirely when not needed, letting initTaskMaster use its default behavior.

## Testing:
- parse-prd now works on fresh projects without existing tasks.json
- analyze-complexity creates report file without requiring it to exist
- Commands maintain backward compatibility when paths are explicitly provided

Fixes issues reported in PATH-FIXES.md and extends the solution to other affected commands.

* fix: update expand-task test to match context gathering fix

The test was expecting gatheredContext to be a string, but the actual
implementation returns an object with a context property. Updated the
ContextGatherer mock to return the correct format and added missing
FuzzyTaskSearch mock.

---------

Co-authored-by: Ben Vargas <ben@example.com>
stephanschielke pushed a commit to stephanschielke/cursor-task-master that referenced this pull request Aug 22, 2025
…iple commands (eyaltoledano#954)

* fix: resolve path resolution issues in parse-prd and analyze-complexity commands

This commit fixes critical path resolution regressions where commands were requiring files they create to already exist.

## Changes Made:

### 1. parse-prd Command (Lines 808, 828-835, 919-921)
**Problem**: Command required tasks.json to exist before it could create it (catch-22)
**Root Cause**: Default value in option definition meant options.output was always set
**Fixes**:
- Removed default value from --output option definition (line 808)
- Modified initTaskMaster to only include tasksPath when explicitly specified
- Added null handling for output path with fallback to default location

### 2. analyze-complexity Command (Lines 1637-1640, 1673-1680, 1695-1696)
**Problem**: Command required complexity report file to exist before creating it
**Root Cause**: Default value in option definition meant options.output was always set
**Fixes**:
- Removed default value from --output option definition (lines 1637-1640)
- Modified initTaskMaster to only include complexityReportPath when explicitly specified
- Added null handling for report path with fallback to default location

## Technical Details:

The core issue was that Commander.js option definitions with default values always populate the options object, making conditional checks like `if (options.output)` always true. By removing default values from option definitions, we ensure paths are only included in initTaskMaster when users explicitly provide them.

This approach is cleaner than using boolean flags (true/false) for required/optional, as it eliminates the path entirely when not needed, letting initTaskMaster use its default behavior.

## Testing:
- parse-prd now works on fresh projects without existing tasks.json
- analyze-complexity creates report file without requiring it to exist
- Commands maintain backward compatibility when paths are explicitly provided

Fixes issues reported in PATH-FIXES.md and extends the solution to other affected commands.

* fix: update expand-task test to match context gathering fix

The test was expecting gatheredContext to be a string, but the actual
implementation returns an object with a context property. Updated the
ContextGatherer mock to return the correct format and added missing
FuzzyTaskSearch mock.

---------

Co-authored-by: Ben Vargas <ben@example.com>
sfc-gh-dflippo pushed a commit to sfc-gh-dflippo/task-master-ai that referenced this pull request Dec 4, 2025
…iple commands (eyaltoledano#954)

* fix: resolve path resolution issues in parse-prd and analyze-complexity commands

This commit fixes critical path resolution regressions where commands were requiring files they create to already exist.

## Changes Made:

### 1. parse-prd Command (Lines 808, 828-835, 919-921)
**Problem**: Command required tasks.json to exist before it could create it (catch-22)
**Root Cause**: Default value in option definition meant options.output was always set
**Fixes**:
- Removed default value from --output option definition (line 808)
- Modified initTaskMaster to only include tasksPath when explicitly specified
- Added null handling for output path with fallback to default location

### 2. analyze-complexity Command (Lines 1637-1640, 1673-1680, 1695-1696)
**Problem**: Command required complexity report file to exist before creating it
**Root Cause**: Default value in option definition meant options.output was always set
**Fixes**:
- Removed default value from --output option definition (lines 1637-1640)
- Modified initTaskMaster to only include complexityReportPath when explicitly specified
- Added null handling for report path with fallback to default location

## Technical Details:

The core issue was that Commander.js option definitions with default values always populate the options object, making conditional checks like `if (options.output)` always true. By removing default values from option definitions, we ensure paths are only included in initTaskMaster when users explicitly provide them.

This approach is cleaner than using boolean flags (true/false) for required/optional, as it eliminates the path entirely when not needed, letting initTaskMaster use its default behavior.

## Testing:
- parse-prd now works on fresh projects without existing tasks.json
- analyze-complexity creates report file without requiring it to exist
- Commands maintain backward compatibility when paths are explicitly provided

Fixes issues reported in PATH-FIXES.md and extends the solution to other affected commands.

* fix: update expand-task test to match context gathering fix

The test was expecting gatheredContext to be a string, but the actual
implementation returns an object with a context property. Updated the
ContextGatherer mock to return the correct format and added missing
FuzzyTaskSearch mock.

---------

Co-authored-by: Ben Vargas <ben@example.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants