fix: add complexity score to tm list and tm show#1270
Conversation
🦋 Changeset detectedLatest commit: 8335516 The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughAdds complexity-reporting: new report types and ComplexityReportManager, enriches loaded tasks with complexity data and reasoning, extends Task types/entity with new fields, surfaces numeric/colorized complexity in CLI UI, and removes complexity-based filtering from TaskService. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant CLI
participant FileStorage
participant ReportMgr as ComplexityReportManager
participant FS as Filesystem
CLI->>FileStorage: loadTasks(tag)
activate FileStorage
FileStorage->>FS: read tasks JSON
FS-->>FileStorage: tasks[]
FileStorage->>ReportMgr: getComplexityForTasks(taskIds, tag)
activate ReportMgr
alt cache miss
ReportMgr->>FS: read .taskmaster/reports/report[.tag].json
FS-->>ReportMgr: report or ENOENT
opt valid report
ReportMgr->>ReportMgr: cache report by tag
end
end
ReportMgr-->>FileStorage: Map(taskId -> {complexityScore,recommendedSubtasks,expansionPrompt,complexityReasoning})
FileStorage->>FileStorage: merge complexity fields into tasks
FileStorage-->>CLI: enriched tasks[]
deactivate ReportMgr
deactivate FileStorage
sequenceDiagram
autonumber
participant CLI as list.command
participant Tasks as tasks[]
participant UI as Components/Utils
CLI->>Tasks: compute nextTaskInfo via findNextTask
CLI->>Tasks: resolve nextTask by id
alt nextTask found
CLI->>UI: displayRecommendedNextTask({id,title,priority,status,dependencies,description,complexity})
UI->>UI: render complexity via getComplexityWithScore/getComplexityWithColor
else no nextTask
CLI->>UI: skip next-task section
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (3)
🧰 Additional context used🧠 Learnings (4)📓 Common learnings📚 Learning: 2025-07-18T17:14:29.399ZApplied to files:
📚 Learning: 2025-07-18T17:09:16.839ZApplied to files:
📚 Learning: 2025-07-18T17:16:32.622ZApplied to files:
🧬 Code graph analysis (3)apps/cli/src/ui/components/dashboard.component.ts (1)
apps/cli/src/utils/ui.ts (1)
apps/cli/src/ui/components/next-task.component.ts (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (6)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (14)
.changeset/whole-pigs-say.md(1 hunks)apps/cli/src/commands/list.command.ts(2 hunks)apps/cli/src/ui/components/dashboard.component.ts(2 hunks)apps/cli/src/ui/components/next-task.component.ts(3 hunks)apps/cli/src/ui/components/task-detail.component.ts(2 hunks)apps/cli/src/utils/ui.ts(2 hunks)packages/tm-core/src/entities/task.entity.ts(3 hunks)packages/tm-core/src/index.ts(1 hunks)packages/tm-core/src/reports/complexity-report-manager.ts(1 hunks)packages/tm-core/src/reports/index.ts(1 hunks)packages/tm-core/src/reports/types.ts(1 hunks)packages/tm-core/src/services/task-service.ts(0 hunks)packages/tm-core/src/storage/file-storage/file-storage.ts(4 hunks)packages/tm-core/src/types/index.ts(1 hunks)
💤 Files with no reviewable changes (1)
- packages/tm-core/src/services/task-service.ts
🧰 Additional context used
📓 Path-based instructions (2)
.changeset/*.md
📄 CodeRabbit inference engine (.cursor/rules/changeset.mdc)
.changeset/*.md: When runningnpm run changesetornpx changeset add, provide a concise summary of the changes for theCHANGELOG.mdin imperative mood, typically a single line, and not a detailed Git commit message.
The changeset summary should be user-facing, describing what changed in the released version that is relevant to users or consumers of the package.
Do not use your detailed Git commit message body as the changeset summary.
Files:
.changeset/whole-pigs-say.md
.changeset/*
📄 CodeRabbit inference engine (.cursor/rules/new_features.mdc)
Create appropriate changesets for new features, use semantic versioning, include tagged system information in release notes, and document breaking changes if any.
Files:
.changeset/whole-pigs-say.md
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.658Z
Learning: Use task-master complexity-report to view formatted complexity insights and recommendations
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Calculate and display completion statistics for the current tag, track both task and subtask completion, and use visual progress indicators.
Applied to files:
apps/cli/src/ui/components/dashboard.component.ts
📚 Learning: 2025-09-24T15:12:12.658Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.658Z
Learning: Use task-master complexity-report to view formatted complexity insights and recommendations
Applied to files:
packages/tm-core/src/reports/complexity-report-manager.tspackages/tm-core/src/reports/types.ts
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Use AI to generate detailed subtasks within the current tag context, considering complexity analysis for subtask counts and ensuring proper IDs for newly created subtasks.
Applied to files:
packages/tm-core/src/storage/file-storage/file-storage.ts
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Use consistent formatting for task files, include all task properties in text files, and format dependencies with status indicators.
Applied to files:
apps/cli/src/ui/components/task-detail.component.ts
🧬 Code graph analysis (8)
apps/cli/src/ui/components/dashboard.component.ts (1)
apps/cli/src/utils/ui.ts (1)
getComplexityWithScore(109-122)
apps/cli/src/utils/ui.ts (1)
tests/unit/ui.test.js (1)
chalk(17-17)
packages/tm-core/src/reports/complexity-report-manager.ts (2)
packages/tm-core/src/reports/index.ts (4)
ComplexityReportManager(5-5)ComplexityReport(7-7)TaskComplexityData(10-10)ComplexityAnalysis(9-9)packages/tm-core/src/reports/types.ts (3)
ComplexityReport(46-51)TaskComplexityData(56-65)ComplexityAnalysis(8-21)
apps/cli/src/ui/components/next-task.component.ts (1)
apps/cli/src/utils/ui.ts (1)
getComplexityWithScore(109-122)
packages/tm-core/src/reports/types.ts (2)
packages/tm-core/src/index.ts (4)
ComplexityAnalysis(70-70)ComplexityReportMetadata(69-69)ComplexityReport(68-68)TaskComplexityData(71-71)packages/tm-core/src/reports/index.ts (4)
ComplexityAnalysis(9-9)ComplexityReportMetadata(8-8)ComplexityReport(7-7)TaskComplexityData(10-10)
packages/tm-core/src/storage/file-storage/file-storage.ts (2)
packages/tm-core/src/reports/complexity-report-manager.ts (1)
ComplexityReportManager(21-185)packages/tm-core/src/types/index.ts (1)
Task(57-82)
apps/cli/src/commands/list.command.ts (1)
apps/cli/src/ui/components/next-task.component.ts (2)
getTaskDescription(125-141)displayRecommendedNextTask(27-120)
apps/cli/src/ui/components/task-detail.component.ts (1)
apps/cli/src/utils/ui.ts (1)
getComplexityWithColor(89-104)
🪛 markdownlint-cli2 (0.18.1)
.changeset/whole-pigs-say.md
5-5: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🔇 Additional comments (26)
.changeset/whole-pigs-say.md (1)
1-8: LGTM! Changeset follows conventions.The changeset correctly identifies the patch-level change and provides a clear, user-facing description of the complexity score display improvements.
Note: The static analysis hint about MD041 (first-line-heading) can be safely ignored here—changesets use YAML frontmatter (lines 1-3) by design, not a Markdown heading.
packages/tm-core/src/reports/types.ts (1)
56-65: LGTM! TaskComplexityData interface is well-designed.The optional fields align with the enrichment pattern used in storage and allow graceful degradation when complexity data is unavailable.
packages/tm-core/src/index.ts (1)
65-72: LGTM! Public API exports are properly structured.The new reports section follows the established pattern for module exports and makes the complexity reporting functionality accessible to consumers.
apps/cli/src/ui/components/next-task.component.ts (3)
9-9: LGTM! Import is correct.The
getComplexityWithScoreutility provides consistent complexity formatting across UI components.
21-21: LGTM! Type addition is appropriate.Adding
complexity?: numberto the display options interface enables numeric complexity rendering in the next task display.
87-90: LGTM! Complexity rendering is well-guarded.The
typeofcheck ensures the Complexity line only renders when a numeric value is available, preventing display of invalid or missing data.apps/cli/src/ui/components/dashboard.component.ts (2)
9-9: LGTM! Import is correct.Centralizing complexity formatting through
getComplexityWithScoreensures consistent presentation across the dashboard.
483-483: LGTM! Complexity formatting is properly delegated.The explicit type assertion and call to
getComplexityWithScoreprovide clear, consistent complexity display with proper fallback handling.apps/cli/src/utils/ui.ts (1)
344-349: LGTM! Table complexity display is properly guarded.The
typeofcheck and conditional rendering ensure complexity is only displayed when a numeric value is available, with a clear fallback for missing data.apps/cli/src/ui/components/task-detail.component.ts (2)
12-16: LGTM! Import is correct.Adding
getComplexityWithColorto the imports enables consistent complexity formatting in task details.
115-117: LGTM! Complexity rendering is properly guarded.The conditional rendering ensures complexity is displayed only when available as a numeric value, with a clear 'N/A' fallback.
packages/tm-core/src/storage/file-storage/file-storage.ts (4)
14-14: LGTM! Import is correct.The
ComplexityReportManagerimport enables complexity data enrichment during task loading.
23-29: LGTM! ComplexityReportManager initialization is correct.The manager is properly instantiated with the project root path, enabling per-tag report loading and caching.
93-104: LGTM! Task loading enrichment is well-structured.The enrichment call is properly placed after task extraction, providing a clean separation between storage deserialization and data augmentation. The updated docstring clearly communicates the enrichment behavior.
607-645: LGTM! Complexity enrichment implementation is efficient and robust.The implementation demonstrates several good practices:
- Efficient bulk loading: Uses
getComplexityForTasksto load all complexity data in a single operation rather than per-task lookups.- Graceful degradation: Returns tasks unchanged when no complexity data is available (line 625-627).
- Consistent ID handling: Uses
String(task.id)for lookups, matching thenormalizeTaskIdspattern.- Non-invasive enrichment: Only adds complexity fields when data exists; doesn't modify tasks unnecessarily.
The enrichment overhead is minimal thanks to report caching in
ComplexityReportManager.packages/tm-core/src/entities/task.entity.ts (2)
36-38: LGTM! Property declarations align with the Task interface.The three new optional properties (recommendedSubtasks, expansionPrompt, complexityReasoning) are correctly declared and match the expanded Task interface.
255-258: LGTM! Serialization includes all new complexity fields.The toJSON method correctly includes the three new optional properties, ensuring they are preserved when the entity is serialized.
packages/tm-core/src/types/index.ts (2)
75-82: LGTM! Task interface extended to support numeric complexity scores.The changes enable tasks to carry either enum-based complexity ('simple' | 'moderate' | 'complex' | 'very-complex') or numeric scores (1-10), along with additional analysis fields. This aligns with the new ComplexityReportManager functionality.
147-154: Verify removal of complexity filtering in TaskFilter.
- Confirm removal of
complexityfrom theTaskFilterinterface is intentional.- Verify no existing filters or codepaths rely on
TaskFilter.complexity.- Determine if range-based complexity filtering should be supported in future.
packages/tm-core/src/reports/index.ts (1)
1-11: LGTM! Clean public API for the reports module.This barrel export file provides a well-organized public interface for the reports module, exposing the ComplexityReportManager class and its associated types. The structure follows the pattern used by other modules in the codebase.
apps/cli/src/commands/list.command.ts (2)
284-289: LGTM! More efficient next-task resolution.The change to find the full task object from the existing tasks array (rather than re-reading it) is more efficient and ensures the complexity data from storage enrichment is preserved.
311-321: CastingnextTask.complexitytonumber | undefinedis safe; storage enrichment always converts it to a numeric score.packages/tm-core/src/reports/complexity-report-manager.ts (4)
32-36: LGTM! Path resolution handles tags correctly.The getReportPath method correctly computes the file path with an optional tag suffix, treating 'master' as the default tag without a suffix.
95-120: LGTM! Safe ID comparison using String() coercion.The getComplexityForTask method correctly handles both string and numeric task IDs by coercing to strings for comparison, and properly maps ComplexityAnalysis to TaskComplexityData.
126-157: LGTM! Efficient bulk retrieval with pre-built map.The getComplexityForTasks method efficiently handles multiple task lookups by building a map once and reusing it for all task IDs.
176-184: LGTM! Simple existence check.The hasReport method correctly checks for file existence without loading the file.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
packages/tm-core/src/reports/complexity-report-manager.ts (1)
42-90: Consider validating individual ComplexityAnalysis items.The
loadReportmethod validates the report structure (presence ofmetaandcomplexityAnalysisarray) but does not validate individual analysis objects within the array. Malformed analysis items (e.g., missingtaskId, non-numericcomplexityScore) could cause issues:
- In
getComplexityForTask(line 106),String(a.taskId)would coerceundefinedto"undefined", potentially causing false matches.- Accessing undefined fields (lines 115-118) would populate
TaskComplexityDatawithundefinedvalues, which is type-safe but may not be the intended behavior.Consider adding validation for each analysis item as suggested in the previous review:
// Validate basic structure if (!report.meta || !Array.isArray(report.complexityAnalysis)) { logger.warn( `Invalid complexity report structure at ${reportPath}, ignoring` ); return null; } + +// Validate individual analysis items +const isValidAnalysis = report.complexityAnalysis.every( + (a) => a.taskId !== undefined && + typeof a.complexityScore === 'number' && + typeof a.recommendedSubtasks === 'number' +); +if (!isValidAnalysis) { + logger.warn( + `Invalid complexity analysis items in ${reportPath}, ignoring` + ); + return null; +}
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
apps/cli/src/utils/ui.ts(3 hunks)packages/tm-core/src/reports/complexity-report-manager.ts(1 hunks)packages/tm-core/src/reports/types.ts(1 hunks)packages/tm-core/src/services/task-service.ts(0 hunks)
💤 Files with no reviewable changes (1)
- packages/tm-core/src/services/task-service.ts
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.658Z
Learning: Use task-master complexity-report to view formatted complexity insights and recommendations
📚 Learning: 2025-09-24T15:12:12.658Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: assets/.windsurfrules:0-0
Timestamp: 2025-09-24T15:12:12.658Z
Learning: Use task-master complexity-report to view formatted complexity insights and recommendations
Applied to files:
packages/tm-core/src/reports/types.ts
📚 Learning: 2025-07-18T08:29:52.384Z
Learnt from: mm-parthy
PR: eyaltoledano/claude-task-master#943
File: scripts/modules/task-manager/list-tasks.js:0-0
Timestamp: 2025-07-18T08:29:52.384Z
Learning: TODO comments about adding tag support to internal functions like readComplexityReport are obsolete in the boundary-first tag resolution pattern because report paths are already resolved at the CLI command boundary layer before reaching these functions.
Applied to files:
packages/tm-core/src/reports/complexity-report-manager.ts
🧬 Code graph analysis (3)
apps/cli/src/utils/ui.ts (1)
tests/unit/ui.test.js (1)
chalk(17-17)
packages/tm-core/src/reports/types.ts (2)
packages/tm-core/src/index.ts (4)
ComplexityAnalysis(70-70)ComplexityReportMetadata(69-69)ComplexityReport(68-68)TaskComplexityData(71-71)packages/tm-core/src/reports/index.ts (4)
ComplexityAnalysis(9-9)ComplexityReportMetadata(8-8)ComplexityReport(7-7)TaskComplexityData(10-10)
packages/tm-core/src/reports/complexity-report-manager.ts (1)
packages/tm-core/src/reports/types.ts (3)
ComplexityReport(46-51)TaskComplexityData(56-65)ComplexityAnalysis(8-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Test
🔇 Additional comments (11)
apps/cli/src/utils/ui.ts (3)
105-115: LGTM! Refactor successfully implemented.The function now correctly delegates threshold logic to
getComplexityLevel, eliminating code duplication while preserving the original string-parsing and NaN-handling behavior. This addresses the previous review comment.
117-127: LGTM! New function correctly implements the dashboard format.The function properly handles
number | undefined, delegates togetComplexityLevelfor consistent threshold logic, and provides the/10format appropriate for dashboard displays. The implementation aligns with the usage patterns described in the AI summary.
348-354: LGTM! Complexity rendering correctly updated.The table now conditionally displays numeric complexity scores using
getComplexityWithColor, which appropriately omits the "/10" suffix for table contexts. The type guard ensures runtime safety when complexity data may not be present.packages/tm-core/src/reports/types.ts (4)
8-21: LGTM! Past naming inconsistency has been resolved.The
ComplexityAnalysisinterface is well-structured and now usescomplexityReasoningconsistently withTaskComplexityData. The union typestring | numberfortaskIdprovides flexibility, and the manager code correctly coerces both to strings when matching.
26-41: LGTM!The metadata structure appropriately balances required and optional fields. Using
stringforgeneratedAtis suitable for JSON serialization and deserialization.
46-51: LGTM!The
ComplexityReportinterface correctly combines metadata and analysis data. Making both fields required aligns with the validation logic inComplexityReportManager.loadReport.
56-65: LGTM!The
TaskComplexityDatainterface appropriately makes all fields optional, as not every task will have complexity analysis data. The field names are now consistent withComplexityAnalysis, simplifying the mapping logic inComplexityReportManager.packages/tm-core/src/reports/complexity-report-manager.ts (4)
21-36: LGTM!The class structure, constructor, and private
getReportPathmethod are well-implemented. The tag-based path resolution correctly differentiates between the default 'master' tag and other tags.
95-120: LGTM!The method correctly handles taskId coercion for comparison and cleanly converts
ComplexityAnalysistoTaskComplexityData. The consistent field naming between the two types simplifies the mapping.
126-157: LGTM!The bulk lookup method efficiently uses a
Mapfor O(1) complexity lookups and correctly handles taskId coercion. The conversion logic is consistent withgetComplexityForTask.
175-183: LGTM!The
hasReportmethod correctly checks for file existence usingfs.accessand returns a boolean. The error handling appropriately treats any error as "file does not exist."
This PR was automatically generated to update documentation based on recent changes. Original commit: fix: add complexity score to tm list and tm show (#1270)\n\n\n Co-authored-by: Claude <claude-assistant@anthropic.com>
What type of PR is this?
Description
Related Issues
How to Test This
# Example commands or stepsExpected result:
Contributor Checklist
npm run changesetnpm testnpm run format-check(ornpm run formatto fix)Changelog Entry
For Maintainers
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Documentation