rbin-task-flow 1.19.1 → 1.19.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,52 +10,52 @@ alwaysApply: true
10
10
  - **ALL TASKS**: `task-flow: estimate all` → Estimate all tasks
11
11
  - When user says "task-flow: estimate X", "estimate X", "estimate X,Y", "estimate all", or "how long will task X take":
12
12
  - **READ**: `.task-flow/.internal/tasks.json` to get task details
13
- - **CALCULATE**: Time estimate based on number of subtasks and developer experience level
13
+ - **CALCULATE**: Time estimate based on task level, complexity signals, and developer experience level
14
14
  - **DISPLAY**: Show time estimate with intervals for 3 experience levels (junior, mid, senior)
15
- - **FORMAT**: Show estimates in hours with ranges (e.g., "10-14 hours" for mid-level)
15
+ - **FORMAT**: Show estimates in hours with ranges (e.g., "10-14 hours" for intermediate)
16
16
 
17
17
  - **Estimation Rules:**
18
- 1. **Base Calculation**: Count total number of subtasks in the task
19
- 2. **Experience Levels**:
18
+ 1. **Base Analysis**: Evaluate the task title and subtasks to infer real task level
19
+ 2. **Experience Levels** (use internally; display "Intermediate" not "Mid-level" to user):
20
20
  - **Junior** (0-2 years): Base time × 1.5 multiplier
21
- - **Mid-level** (3-5 years): Base time × 1.0 multiplier (baseline)
21
+ - **Intermediate** (3-5 years): Base time × 1.0 multiplier (baseline)
22
22
  - **Senior** (6+ years): Base time × 0.7 multiplier
23
- 3. **Time per Subtask**:
24
- - Simple subtask: 1-2 hours (mid-level baseline)
25
- - Medium subtask: 2-4 hours (mid-level baseline)
26
- - Complex subtask: 4-6 hours (mid-level baseline)
27
- 4. **Default Assumption**: Average 2-3 hours per subtask for mid-level (baseline)
28
- 5. **Range Calculation**:
29
- - Lower bound: (subtasks × 2) × multiplier
30
- - Upper bound: (subtasks × 3) × multiplier
23
+ 3. **Task Level Heuristics**:
24
+ - **Low**: localized change, clear requirement, low ambiguity, low regression risk
25
+ - **Medium**: multi-file implementation, moderate ambiguity, moderate validation needs
26
+ - **High**: architectural, cross-cutting, migration, security, performance, or high-risk change
27
+ 4. **Subtask count is only one signal**: use it to inform scope, but never as the sole estimate driver
28
+ 5. **Intermediate baseline per subtask**:
29
+ - Low-level task: 1.5-2.5 hours
30
+ - Medium-level task: 2.5-4 hours
31
+ - High-level task: 4-6.5 hours
32
+ 6. **Risk and scope adjustment**:
33
+ - Increase estimate when the task mentions integrations, migrations, refactors, security, performance, billing, or architecture work
34
+ 7. **Range Calculation**:
35
+ - Lower bound: (subtasks × baseline lower) × risk factor × experience multiplier
36
+ - Upper bound: (subtasks × baseline upper) × risk factor × experience multiplier
31
37
  - Round to nearest hour
32
38
 
33
39
  - **Estimation Formula:**
34
40
  ```
35
- Base hours per subtask: 2-3 hours (mid-level)
36
-
37
- Junior (0-2 years):
38
- Lower: (subtasks × 2) × 1.5
39
- Upper: (subtasks × 3) × 1.5
40
-
41
- Mid-level (3-5 years):
42
- Lower: subtasks × 2
43
- Upper: subtasks × 3
44
-
45
- Senior (6+ years):
46
- Lower: (subtasks × 2) × 0.7
47
- Upper: (subtasks × 3) × 0.7
41
+ 1. Infer task level: low, medium, or high
42
+ 2. Choose intermediate baseline per subtask from task level
43
+ 3. Apply risk/scope multiplier when complexity indicators exist
44
+ 4. Apply experience multiplier:
45
+ Junior: × 1.5
46
+ Intermediate: × 1.0
47
+ Senior: × 0.7
48
48
  ```
49
49
 
50
50
  - **Display Format:**
51
51
  ```
52
52
  📊 Time Estimation for Task X: [Task Title]
53
53
 
54
- Based on [N] subtasks:
54
+ Based on [N] subtasks and task-level analysis:
55
55
 
56
- 👶 Junior (0-2 years): [X-Y] hours
57
- 👨‍💼 Mid-level (3-5 years): [X-Y] hours
58
- 👴 Senior (6+ years): [X-Y] hours
56
+ 👶 Junior (0-2 years): [X-Y] hours
57
+ 👨‍💼 Intermediate (3-5 years): [X-Y] hours
58
+ 👴 Senior (6+ years): [X-Y] hours
59
59
  ```
60
60
 
61
61
  - **Natural Language Phrases:**
@@ -72,15 +72,15 @@ alwaysApply: true
72
72
  ```
73
73
  User: "task-flow: estimate 1"
74
74
 
75
- Task 1 has 5 subtasks:
75
+ Task 1 has 5 subtasks and medium complexity signals:
76
76
 
77
77
  📊 Time Estimation for Task 1: Create authentication system
78
78
 
79
- Based on 5 subtasks:
79
+ Based on 5 subtasks and task-level analysis:
80
80
 
81
- 👶 Junior (0-2 years): 15-23 hours
82
- 👨‍💼 Mid-level (3-5 years): 10-15 hours
83
- 👴 Senior (6+ years): 7-11 hours
81
+ 👶 Junior (0-2 years): 15-23 hours
82
+ 👨‍💼 Intermediate (3-5 years): 10-15 hours
83
+ 👴 Senior (6+ years): 7-11 hours
84
84
  ```
85
85
 
86
86
  - **Integration:**
@@ -89,4 +89,4 @@ alwaysApply: true
89
89
  - Estimates are informational only (not stored)
90
90
 
91
91
  - **Principle:**
92
- > **Provide realistic time estimates based on task complexity (number of subtasks) and developer experience level. Show ranges to account for variability in implementation speed.**
92
+ > **Provide realistic time estimates based on real task level, scope, ambiguity, and risk. Subtask count informs scope, but must not be the sole estimation criterion.**
@@ -37,7 +37,7 @@ alwaysApply: true
37
37
  - `task-flow: report X` - Generate implementation report for task X (simplified - no "task" needed)
38
38
  - `task-flow: report X,Y` - Generate reports for multiple tasks (comma-separated)
39
39
  - `task-flow: report all` - Generate reports for all tasks
40
- - `task-flow: generate flow` - Populate tasks.flow.md with dependencies, estimated hours (mid-level dev, billing), and AI model recommendations
40
+ - `task-flow: generate flow` - Populate tasks.flow.md with dependencies, estimated hours, and AI model recommendations
41
41
 
42
42
  - **Workflow Example:**
43
43
  ```markdown
@@ -1,73 +1,91 @@
1
1
  ---
2
- description: Generate task flow with dependencies, estimated hours (billing), and AI model recommendations
2
+ description: Generate task flow with dependencies, estimated hours, and AI model recommendations
3
3
  globs: **/*
4
4
  alwaysApply: true
5
5
  ---
6
6
 
7
7
  - **Task Flow Generation - Dependencies, Hours & Model Recommendations:**
8
- - **FAST FORMAT**: `task-flow: generate flow` → Populate tasks.flow.md with dependencies, estimated hours, and model recommendations
8
+ - **FAST FORMAT**: `task-flow: generate flow` → Populate tasks.flow.md
9
9
  - When user says "task-flow: generate flow", "generate flow", "gerar flow", or "flow":
10
- - **READ**: `.task-flow/.internal/tasks.json` to get all tasks
11
- - **READ**: `.task-flow/.internal/status.json` (optional, for context)
12
- - **ANALYZE**: For each task, determine dependencies, estimated hours, and model recommendations
10
+ - **READ**: `.task-flow/.internal/tasks.json` and optionally `status.json`
11
+ - **SEARCH**: Current versions of GPT-5.x, Composer, Claude (Haiku, Sonnet) via web search
13
12
  - **WRITE**: Populate `.task-flow/tasks.flow.md` with the generated flow
14
- - **DO NOT**: Populate tasks.flow.md when running `task-flow: sync` — only when `task-flow: generate flow`
13
+ - **DO NOT**: Populate tasks.flow.md when running `task-flow: sync`
15
14
 
16
15
  - **Generation Process:**
17
- 1. **Search for current model versions** (quick web search): Codex, Composer (Cursor), Claude (Haiku, Sonnet, Opus). Use the latest available versions in recommendations.
18
- 2. Read all tasks from tasks.json (id, title, description, subtasks)
16
+ 1. **Search for current model versions** (web search): one GPT-5.x coding-capable model, Composer (Cursor), Claude Haiku, Claude Sonnet. Include version next to each model (e.g. "Claude Sonnet 4.6").
17
+ 2. Read tasks from tasks.json
19
18
  3. For each task, determine:
20
- - **Estimated hours** (dev mediano, cobrança ao cliente): Range in hours for mid-level developer (3-5 years). Formula: subtasks × 2 to subtasks × 3 hours (same as [task_estimate.mdc](mdc:.cursor/rules/task_estimate.mdc)). Round to nearest hour. Purpose: developer billing.
21
- - **Dependencies**: Which tasks (if any) must be completed first
22
- - Infer from task order, descriptions, subtask content
23
- - Task 1 typically has no dependencies
24
- - Task N may depend on 1..N-1 if it builds on their output
25
- - Use "none" or "nenhuma" when no dependencies
26
- - **Model recommendations** (in order, most to least indicated):
27
- - **Codex** (variants): include current version from web search
28
- - **Composer** (Cursor): include current version from web search
29
- - **Claude**: Haiku, Sonnet, Opus include current version from web search
30
- - **Effort**: low, medium, or high (based on subtask count, complexity)
31
- 4. Output format per task (simple, one line):
32
- - `task X - depende da task Y - X-Yh (dev mediano, cobrança) - model1 effort E, model2, model3 effort E`
33
- - Or: `task X - nenhuma dependência - X-Yh (dev mediano, cobrança) - model1 effort E, model2, model3 effort E`
19
+ - **Dependencies**: Which tasks must be completed first (or "—" if none)
20
+ - **Estimated hours** (for billing): infer from real task scope, ambiguity, dependencies, and validation needs. Subtask count informs scope, but do not use a fixed subtasks × hours formula. Do NOT show "dev mediano" or "mid-level".
21
+ - **3 model options** (in order of priority): one GPT-5.x model, one Composer, one Claude — always these 3. Include version and effort for each.
22
+ - **Model priority must be defined by AI judgment**, based on task nature, implementation risk, ambiguity, architecture impact, validation needs, and expected autonomy. Do not use a fixed ranking.
23
+ - **Effort** per model: low, medium, or high, defined by task level and difficulty. Do not infer effort from subtask count alone.
24
+ 4. **Claude**: Use only Haiku or Sonnet **never Opus**
25
+ 5. **Effort heuristics**:
26
+ - **low**: localized change, clear requirement, low ambiguity, low regression risk, limited validation
27
+ - **medium**: multi-file implementation, moderate ambiguity, moderate regression risk, requires broader validation
28
+ - **high**: architecture or cross-cutting change, high ambiguity, high regression risk, sequencing concerns, or deep investigation/refactor
29
+ 6. **Model heuristics**:
30
+ - **GPT-5.x**: prioritize when the task needs strong implementation, refactoring, debugging, or broader code reasoning
31
+ - **Composer**: prioritize when the task benefits from editor-native iteration, repo-wide navigation, and fast execution in the coding flow
32
+ - **Claude Haiku**: prioritize for simpler, well-bounded tasks with low effort
33
+ - **Claude Sonnet**: prioritize for tasks that need more synthesis, reasoning depth, or architectural analysis
34
+ - The first recommendation must reflect the best fit for that specific task, not a template order reused across all tasks
34
35
 
35
- - **Output Format for tasks.flow.md:**
36
+ - **Output Format (direct blocks per task):**
36
37
  ```markdown
37
38
  # Task Flow — Dependencies, Hours & Model Recommendations
38
39
 
39
40
  <!-- Populated by task-flow: generate flow. Do not edit manually. -->
40
- <!-- Horas: dev mediano (3-5 anos), uso para cobrança ao cliente -->
41
+ <!-- Horas: uso para cobrança ao cliente -->
41
42
 
42
- ## Tasks
43
+ ## Legenda
43
44
 
44
- task 1 - nenhuma dependência - 6-9h (dev mediano, cobrança) - codex effort medium, composer, claude sonnet effort medium
45
- task 2 - depende da task 1 - 8-12h (dev mediano, cobrança) - codex effort medium, composer, claude sonnet effort medium
46
- task 3 - depende da task 2 - 14-21h (dev mediano, cobrança) - codex effort high, composer, claude opus effort high
47
- ```
45
+ | Símbolo | Significado |
46
+ |---------|-------------|
47
+ | | Task concluída |
48
+ | ⚡ | Pode iniciar agora (deps satisfeitas) |
49
+ | 🔒 | Bloqueada por dependências |
50
+
51
+ **Esforço (Effort):** definido pelo nível e dificuldade real da task, não pela quantidade de subtasks
52
+ **Claude:** Haiku ou Sonnet — **não use Opus**
53
+
54
+ ## Tasks (blocos diretos por task)
48
55
 
49
- - **Model Recommendation Rules:**
50
- - **MUST list multiple models** in order (most to least indicated), not just one
51
- - **Order**: Codex first, then Composer, then Claude (unless task clearly favors another order)
52
- - **Consider**: Subtask count, description complexity, integration needs
53
- - **Effort**: low (1-3 subtasks), medium (4-6), high (7+ or complex)
54
- - **VERSIONS**: Do a quick web search for current Codex, Composer, Claude model versions before generating; include them in the output. If search fails or is unclear, use model names only.
56
+ ### Task 1 — [Título]
57
+ - **Depende de:**
58
+ - **Horas cobrança:** 10-15h
59
+ - **Modelos sugeridos** (ordem de prioridade):
60
+ 1. GPT-5.x [versão] effort medium
61
+ 2. Composer [versão] effort medium
62
+ 3. Claude Sonnet [versão] — effort medium
55
63
 
56
- - **Dependency Inference Rules:**
57
- - Sequential order: Task 2 often depends on 1, Task 3 on 2, etc.
58
- - Semantic analysis: If task mentions "using X from task Y" or similar, add dependency
59
- - Independent tasks: Can mark as "nenhuma dependência" or "none" to enable parallelization
64
+ ### Task 2 — [Título]
65
+ - **Depende de:** Task 1
66
+ - **Horas cobrança:** 10-15h
67
+ - **Modelos sugeridos** (ordem de prioridade):
68
+ 1. Composer [versão] — effort medium
69
+ 2. GPT-5.x [versão] — effort medium
70
+ 3. Claude Sonnet [versão] — effort medium
71
+
72
+ ### 🔒 Task 3 — [Título]
73
+ - **Depende de:** Task 2
74
+ - **Horas cobrança:** 8-12h
75
+ - **Modelos sugeridos** (ordem de prioridade):
76
+ 1. Claude Haiku [versão] — effort low
77
+ 2. GPT-5.x [versão] — effort low
78
+ 3. Composer [versão] — effort low
79
+ ```
60
80
 
61
- - **Natural Language Phrases:**
62
- - **FAST FORMAT**: `task-flow: generate flow` or `task-flow generate flow`
63
- - "generate flow", "gerar flow", "flow", "gerar tasks.flow"
64
- - Any variation asking to generate/populate the task flow
81
+ - **Model Rules:**
82
+ - **3 models per task**: One GPT-5.x model, one Composer, one Claude — always in order of priority
83
+ - **Version required**: Include current version next to each model name (from web search)
84
+ - **Effort required**: low, medium, or high for each model
85
+ - **AI-defined ranking**: order models by best fit for the task, not by a fixed global priority
86
+ - **No Opus**: Claude = Haiku or Sonnet only
65
87
 
66
- - **Integration:**
67
- - Uses data from `.task-flow/.internal/tasks.json`
68
- - Writes to `.task-flow/tasks.flow.md` (created by `rbin-task-flow init`)
69
- - Does NOT run on `task-flow: sync` — only when user explicitly requests `task-flow: generate flow`
70
- - Works with [task_execution.mdc](mdc:.cursor/rules/task_execution.mdc) workflow
88
+ - **Natural Language:** "generate flow", "gerar flow", "flow"
71
89
 
72
90
  - **Principle:**
73
- > **Populate tasks.flow.md with dependencies (for parallelization), estimated hours for billing (dev mediano), and AI model recommendations in order. Enable users to decide which tasks can run in parallel, how many hours to charge the client, and which model/effort to use for each.**
91
+ > **Populate tasks.flow.md with direct blocks per task. Dependencies, hours, and 3 model options (GPT-5.x, Composer, Claude) with version and effort. Let AI define ranking and effort from task context. Never use Opus.**
@@ -95,10 +95,10 @@ Refactors code from specific task(s). Removes explanatory comments, improves cod
95
95
  - `task-flow: refactor all` → Refactors all tasks
96
96
 
97
97
  ### `task-flow: estimate X` (simplified syntax)
98
- Estimates time required to complete task(s) based on the number of subtasks and developer experience level.
98
+ Estimates time required to complete task(s) based on task level, scope, risk, and developer experience level. Subtask count informs scope, but is not the sole criterion.
99
99
 
100
100
  **Output includes:**
101
- - Time estimates for Junior (0-2 years), Mid-level (3-5 years), and Senior (6+ years) developers
101
+ - Time estimates for Junior (0-2 years), Intermediate (3-5 years), and Senior (6+ years) developers
102
102
  - Estimates in hours and business days
103
103
  - Recommendation for management with buffer
104
104
 
@@ -108,7 +108,7 @@ Estimates time required to complete task(s) based on the number of subtasks and
108
108
  - `task-flow: estimate all` → Shows time estimates for all tasks
109
109
 
110
110
  ### `task-flow: generate flow`
111
- Populates `tasks.flow.md` with: (1) task dependencies (for parallelization), (2) estimated hours, and (3) AI model recommendations (Codex, Composer, Claude) with effort levels. Run after `task-flow: sync` when you want to know which tasks can run in parallel and which model/effort to use.
111
+ Populates `tasks.flow.md` with: (1) task dependencies (for parallelization), (2) estimated hours, and (3) AI model recommendations (GPT-5.x, Composer, Claude) with effort levels. Model ranking and effort must be defined by the AI from task context, not from a fixed order or only from subtask count. Run after `task-flow: sync` when you want to know which tasks can run in parallel and which model/effort to use.
112
112
 
113
113
  ### `task-flow: report X` (simplified syntax)
114
114
  Generates a detailed implementation report for completed task(s) in Markdown format.
package/CLAUDE.md CHANGED
@@ -37,11 +37,11 @@ This project uses RBIN Task Flow for task management:
37
37
  - `task-flow: report X` - Generate implementation report for task X (simplified - no "task" needed)
38
38
  - `task-flow: report X,Y` - Generate reports for multiple tasks (comma-separated)
39
39
  - `task-flow: report all` - Generate reports for all tasks
40
- - `task-flow: generate flow` - Populate tasks.flow.md with dependencies, estimated hours (mid-level dev, billing), and AI model recommendations
40
+ - `task-flow: generate flow` - Populate tasks.flow.md with dependencies, estimated hours, and AI model recommendations
41
41
  - **Files**:
42
42
  - `.task-flow/tasks.input.txt` - Define your tasks here
43
43
  - `.task-flow/tasks.status.md` - Auto-generated status (DO NOT EDIT manually)
44
- - `.task-flow/tasks.flow.md` - Dependencies, estimated hours (mid-level dev, billing), and model recommendations (populated by `task-flow: generate flow`)
44
+ - `.task-flow/tasks.flow.md` - Dependencies, estimated hours, and model recommendations (populated by `task-flow: generate flow`)
45
45
  - `.task-flow/.internal/` - Internal system files (ignore)
46
46
 
47
47
  Follow all rules defined in `.cursor/rules/` for consistent development practices.
package/lib/estimate.js CHANGED
@@ -40,7 +40,8 @@ async function estimateTask(taskIdsInput, targetPath = process.cwd()) {
40
40
  continue;
41
41
  }
42
42
 
43
- const estimates = calculateEstimates(subtaskCount);
43
+ const analysis = analyzeTaskComplexity(task);
44
+ const estimates = calculateEstimates(analysis);
44
45
 
45
46
  if (taskIds.length > 1) {
46
47
  console.log('\n' + chalk.cyan('═'.repeat(70)));
@@ -51,11 +52,13 @@ async function estimateTask(taskIdsInput, targetPath = process.cwd()) {
51
52
  console.log(chalk.cyan('═'.repeat(70)) + '\n');
52
53
 
53
54
  console.log(chalk.blue.bold('Task:'), chalk.yellow(`#${taskId} - ${task.title}\n`));
54
- console.log(chalk.blue(`Complexity: ${chalk.yellow(subtaskCount)} subtasks\n`));
55
+ console.log(chalk.blue(`Complexity: ${chalk.yellow(analysis.level)} (${subtaskCount} subtasks)\n`));
55
56
 
56
57
  console.log(chalk.cyan('─'.repeat(70)));
57
58
  console.log(chalk.magenta.bold('Time Estimates by Experience Level:\n'));
58
59
 
60
+ console.log(chalk.gray(`Signals: ${analysis.signals.join(', ')}\n`));
61
+
59
62
  const juniorDays = Math.ceil(estimates.junior.upper / 8);
60
63
  const midDays = Math.ceil(estimates.mid.upper / 8);
61
64
  const seniorDays = Math.ceil(estimates.senior.upper / 8);
@@ -65,7 +68,7 @@ async function estimateTask(taskIdsInput, targetPath = process.cwd()) {
65
68
  console.log(chalk.white(' Days: '), chalk.yellow(`~${juniorDays} business day(s)`));
66
69
  console.log('');
67
70
 
68
- console.log(chalk.gray('👨‍💼 Mid-level Developer (3-5 years):'));
71
+ console.log(chalk.gray('👨‍💼 Intermediate (3-5 years):'));
69
72
  console.log(chalk.white(' Hours:'), chalk.yellow(`${estimates.mid.lower}-${estimates.mid.upper} hours`));
70
73
  console.log(chalk.white(' Days: '), chalk.yellow(`~${midDays} business day(s)`));
71
74
  console.log('');
@@ -77,7 +80,7 @@ async function estimateTask(taskIdsInput, targetPath = process.cwd()) {
77
80
 
78
81
  console.log(chalk.cyan('─'.repeat(70)));
79
82
  console.log(chalk.magenta.bold('Recommendation for Management:\n'));
80
- console.log(chalk.white(' Recommended estimate:'), chalk.yellow(`${estimates.mid.lower}-${estimates.mid.upper} hours`), chalk.gray('(mid-level baseline)'));
83
+ console.log(chalk.white(' Recommended estimate:'), chalk.yellow(`${estimates.mid.lower}-${estimates.mid.upper} hours`), chalk.gray('(3-5 years baseline)'));
81
84
  console.log(chalk.white(' Buffer recommended:'), chalk.yellow(`+20%`), chalk.gray('for unexpected issues'));
82
85
  console.log(chalk.white(' Total estimate:'), chalk.yellow(`${Math.round(estimates.mid.upper * 1.2)} hours`), chalk.gray(`(~${Math.ceil(estimates.mid.upper * 1.2 / 8)} business days)`));
83
86
  console.log('');
@@ -94,9 +97,16 @@ async function estimateTask(taskIdsInput, targetPath = process.cwd()) {
94
97
  }
95
98
  }
96
99
 
97
- function calculateEstimates(subtaskCount) {
98
- const baseLower = subtaskCount * 2;
99
- const baseUpper = subtaskCount * 3;
100
+ function calculateEstimates(analysis) {
101
+ const { subtaskCount, level, riskMultiplier } = analysis;
102
+ const levelRanges = {
103
+ low: { lower: 1.5, upper: 2.5 },
104
+ medium: { lower: 2.5, upper: 4 },
105
+ high: { lower: 4, upper: 6.5 }
106
+ };
107
+ const baseRange = levelRanges[level] || levelRanges.medium;
108
+ const baseLower = subtaskCount * baseRange.lower * riskMultiplier;
109
+ const baseUpper = subtaskCount * baseRange.upper * riskMultiplier;
100
110
 
101
111
  return {
102
112
  junior: {
@@ -114,4 +124,91 @@ function calculateEstimates(subtaskCount) {
114
124
  };
115
125
  }
116
126
 
127
+ function analyzeTaskComplexity(task) {
128
+ const subtasks = Array.isArray(task.subtasks) ? task.subtasks : [];
129
+ const subtaskCount = subtasks.length;
130
+ const content = buildTaskContent(task, subtasks);
131
+ const keywordScores = scoreKeywords(content);
132
+
133
+ let score = 0;
134
+
135
+ if (subtaskCount <= 2) score += 1;
136
+ else if (subtaskCount <= 5) score += 2;
137
+ else score += 3;
138
+
139
+ score += keywordScores.complexity;
140
+
141
+ let level = 'medium';
142
+ if (score <= 2) level = 'low';
143
+ else if (score >= 6) level = 'high';
144
+
145
+ const riskMultiplier = Math.max(1, 1 + keywordScores.risk * 0.08 + keywordScores.scope * 0.06);
146
+ const signals = [
147
+ `${subtaskCount} subtasks`,
148
+ `${level} task level`
149
+ ];
150
+
151
+ if (keywordScores.scope > 0) signals.push('multi-file or integration indicators');
152
+ if (keywordScores.risk > 0) signals.push('risk or validation indicators');
153
+ if (keywordScores.architecture > 0) signals.push('architecture/refactor indicators');
154
+ if (signals.length === 2) signals.push('no elevated complexity indicators');
155
+
156
+ return {
157
+ subtaskCount,
158
+ level,
159
+ riskMultiplier,
160
+ signals
161
+ };
162
+ }
163
+
164
+ function buildTaskContent(task, subtasks) {
165
+ const parts = [task.title, task.description];
166
+
167
+ for (const subtask of subtasks) {
168
+ if (typeof subtask === 'string') {
169
+ parts.push(subtask);
170
+ continue;
171
+ }
172
+
173
+ if (subtask && typeof subtask === 'object') {
174
+ parts.push(subtask.title, subtask.description);
175
+ }
176
+ }
177
+
178
+ return parts
179
+ .filter(Boolean)
180
+ .join(' ')
181
+ .toLowerCase();
182
+ }
183
+
184
+ function scoreKeywords(content) {
185
+ const architectureKeywords = [
186
+ 'architecture', 'arquitetura', 'refactor', 'refator', 'migrate', 'migra',
187
+ 'core', 'infra', 'foundation', 'sdk', 'abstraction'
188
+ ];
189
+ const scopeKeywords = [
190
+ 'integration', 'integracao', 'integrar', 'api', 'database', 'banco',
191
+ 'auth', 'oauth', 'deploy', 'pipeline', 'webhook', 'service', 'provider'
192
+ ];
193
+ const riskKeywords = [
194
+ 'critical', 'critico', 'security', 'seguranca', 'performance', 'perf',
195
+ 'bug', 'fix', 'regression', 'migration', 'compliance', 'billing', 'payment'
196
+ ];
197
+
198
+ const architecture = countMatches(content, architectureKeywords);
199
+ const scope = countMatches(content, scopeKeywords);
200
+ const risk = countMatches(content, riskKeywords);
201
+
202
+ return {
203
+ architecture,
204
+ scope,
205
+ risk,
206
+ complexity: architecture * 2 + scope + risk
207
+ };
208
+ }
209
+
210
+ function countMatches(content, keywords) {
211
+ return keywords.reduce((total, keyword) => total + (content.includes(keyword) ? 1 : 0), 0);
212
+ }
213
+
117
214
  module.exports = { estimateTask };
package/lib/install.js CHANGED
@@ -120,10 +120,10 @@ async function copyConfigs(targetPath, isUpdate = false) {
120
120
  showSuccess('Codex instructions (AGENTS.md)');
121
121
  }
122
122
 
123
- await copyTaskFlow(targetPath);
123
+ await copyTaskFlow(targetPath, isUpdate);
124
124
  }
125
125
 
126
- async function copyTaskFlow(targetPath) {
126
+ async function copyTaskFlow(targetPath, isUpdate = false) {
127
127
  const taskFlowSrc = path.join(TEMPLATE_DIR, '.task-flow');
128
128
  const taskFlowDest = path.join(targetPath, '.task-flow');
129
129
 
@@ -132,11 +132,24 @@ async function copyTaskFlow(targetPath) {
132
132
  const PROTECTED = [
133
133
  path.join(taskFlowDest, '.internal'),
134
134
  ];
135
+ const PRESERVED_ON_INIT = [
136
+ path.join(taskFlowDest, 'tasks.input.txt'),
137
+ path.join(taskFlowDest, 'tasks.status.md'),
138
+ path.join(taskFlowDest, 'tasks.flow.md'),
139
+ ];
135
140
 
136
141
  await fs.copy(taskFlowSrc, taskFlowDest, {
137
142
  overwrite: true,
138
- filter: (src) => {
139
- return !PROTECTED.some((p) => src.startsWith(p));
143
+ filter: (src, dest) => {
144
+ if (PROTECTED.some((p) => src.startsWith(p) || dest.startsWith(p))) {
145
+ return false;
146
+ }
147
+
148
+ if (!isUpdate && PRESERVED_ON_INIT.includes(dest) && fs.existsSync(dest)) {
149
+ return false;
150
+ }
151
+
152
+ return true;
140
153
  },
141
154
  });
142
155
 
@@ -148,14 +161,18 @@ async function copyTaskFlow(targetPath) {
148
161
  '# Task Flow — Dependencies, Hours & Model Recommendations',
149
162
  '',
150
163
  '<!-- Populated by task-flow: generate flow. Do not edit manually. -->',
151
- '<!-- Horas: dev mediano (3-5 anos), uso para cobrança ao cliente -->',
164
+ '<!-- Horas: uso para cobrança ao cliente -->',
152
165
  '',
153
166
  ].join('\n');
154
167
  await fs.writeFile(flowPath, flowStub);
155
168
  }
156
169
 
157
- showSuccess('Task Flow directory (overwritten)');
158
- showInfo('Protected: .internal/ (your task data is safe)');
170
+ showSuccess('Task Flow directory');
171
+ if (isUpdate) {
172
+ showInfo('Protected: .internal/ (your task data is safe)');
173
+ } else {
174
+ showInfo('Protected on init: .internal/, tasks.input.txt, tasks.status.md, tasks.flow.md');
175
+ }
159
176
  }
160
177
 
161
178
  async function updateGitignore(targetPath) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rbin-task-flow",
3
- "version": "1.19.1",
3
+ "version": "1.19.3",
4
4
  "description": "AI-powered task management for Claude and Cursor",
5
5
  "main": "index.js",
6
6
  "bin": {