rbin-task-flow 1.2.0 → 1.4.0
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.
- package/.cursor/rules/git_control.mdc +6 -5
- package/.cursor/rules/task_estimate.mdc +10 -6
- package/.cursor/rules/task_execution.mdc +12 -5
- package/.cursor/rules/task_generation.mdc +29 -27
- package/.cursor/rules/task_refactor.mdc +20 -9
- package/.cursor/rules/task_report.mdc +10 -5
- package/.cursor/rules/task_review.mdc +20 -7
- package/.cursor/rules/task_work.mdc +25 -18
- package/.cursor/settings.json +1 -3
- package/.model-versions.json +1 -17
- package/.task-flow/README.md +43 -21
- package/.task-flow/contexts/example.png.txt +29 -0
- package/.task-flow/tasks.input.txt +6 -5
- package/CLAUDE.md +17 -7
- package/README.md +41 -82
- package/bin/cli.js +12 -12
- package/lib/estimate.js +72 -47
- package/lib/install.js +6 -47
- package/lib/report.js +41 -22
- package/lib/utils.js +16 -1
- package/lib/version.js +0 -4
- package/package.json +5 -8
- package/.gemini/settings.json +0 -5
- package/.task-flow/screens/example.png.txt +0 -23
- package/GEMINI.md +0 -32
package/lib/install.js
CHANGED
|
@@ -39,7 +39,6 @@ async function installInProject(targetPath, options = {}) {
|
|
|
39
39
|
const dirs = [
|
|
40
40
|
'.cursor/rules',
|
|
41
41
|
'.claude',
|
|
42
|
-
'.gemini',
|
|
43
42
|
'.task-flow'
|
|
44
43
|
];
|
|
45
44
|
|
|
@@ -111,26 +110,6 @@ async function copyConfigs(targetPath) {
|
|
|
111
110
|
showSuccess('Claude instructions');
|
|
112
111
|
}
|
|
113
112
|
|
|
114
|
-
const geminiSettingsPath = path.join(TEMPLATE_DIR, '.gemini/settings.json');
|
|
115
|
-
if (fs.existsSync(geminiSettingsPath)) {
|
|
116
|
-
await fs.copy(
|
|
117
|
-
geminiSettingsPath,
|
|
118
|
-
path.join(targetPath, '.gemini/settings.json'),
|
|
119
|
-
{ overwrite: true }
|
|
120
|
-
);
|
|
121
|
-
showSuccess('Gemini settings');
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const geminiInstructionsPath = path.join(TEMPLATE_DIR, 'GEMINI.md');
|
|
125
|
-
if (fs.existsSync(geminiInstructionsPath)) {
|
|
126
|
-
await fs.copy(
|
|
127
|
-
geminiInstructionsPath,
|
|
128
|
-
path.join(targetPath, 'GEMINI.md'),
|
|
129
|
-
{ overwrite: true }
|
|
130
|
-
);
|
|
131
|
-
showSuccess('Gemini instructions');
|
|
132
|
-
}
|
|
133
|
-
|
|
134
113
|
await copyTaskFlow(targetPath);
|
|
135
114
|
}
|
|
136
115
|
|
|
@@ -143,16 +122,16 @@ async function copyTaskFlow(targetPath) {
|
|
|
143
122
|
showSuccess('Task Flow directory');
|
|
144
123
|
showInfo('Note: .internal/tasks.json and .internal/status.json are NOT overwritten (your data is safe)');
|
|
145
124
|
|
|
146
|
-
const
|
|
147
|
-
await fs.ensureDir(
|
|
148
|
-
showSuccess('
|
|
125
|
+
const contextsDest = path.join(taskFlowDest, 'contexts');
|
|
126
|
+
await fs.ensureDir(contextsDest);
|
|
127
|
+
showSuccess('Contexts directory (.task-flow/contexts/)');
|
|
149
128
|
|
|
150
129
|
const docsDest = path.join(taskFlowDest, 'docs');
|
|
151
130
|
await fs.ensureDir(docsDest);
|
|
152
131
|
showSuccess('Documentation directory (.task-flow/docs/)');
|
|
153
132
|
|
|
154
|
-
const exampleSrc = path.join(taskFlowSrc, '
|
|
155
|
-
const exampleDest = path.join(
|
|
133
|
+
const exampleSrc = path.join(taskFlowSrc, 'contexts/example.png.txt');
|
|
134
|
+
const exampleDest = path.join(contextsDest, 'example.png.txt');
|
|
156
135
|
if (fs.existsSync(exampleSrc) && !fs.existsSync(exampleDest)) {
|
|
157
136
|
await fs.copy(exampleSrc, exampleDest);
|
|
158
137
|
}
|
|
@@ -186,11 +165,9 @@ async function updateGitignore(targetPath) {
|
|
|
186
165
|
|
|
187
166
|
const entries = [
|
|
188
167
|
'.claude/',
|
|
189
|
-
'.gemini/',
|
|
190
168
|
'.cursor/',
|
|
191
169
|
'.task-flow/',
|
|
192
|
-
'CLAUDE.md'
|
|
193
|
-
'GEMINI.md'
|
|
170
|
+
'CLAUDE.md'
|
|
194
171
|
];
|
|
195
172
|
|
|
196
173
|
for (const entry of entries) {
|
|
@@ -246,24 +223,6 @@ async function showModelVersions(targetPath) {
|
|
|
246
223
|
}
|
|
247
224
|
}
|
|
248
225
|
|
|
249
|
-
const geminiSettingsPath = path.join(targetPath, '.gemini/settings.json');
|
|
250
|
-
if (fs.existsSync(geminiSettingsPath)) {
|
|
251
|
-
try {
|
|
252
|
-
const settings = await fs.readJSON(geminiSettingsPath);
|
|
253
|
-
if (settings.model) {
|
|
254
|
-
const modelName = typeof settings.model === 'string'
|
|
255
|
-
? settings.model
|
|
256
|
-
: settings.model.name || 'Default (recommended)';
|
|
257
|
-
console.log(chalk.blue('Gemini:'), chalk.yellow(modelName));
|
|
258
|
-
hasModels = true;
|
|
259
|
-
} else {
|
|
260
|
-
console.log(chalk.blue('Gemini:'), chalk.yellow('Default (recommended)'));
|
|
261
|
-
hasModels = true;
|
|
262
|
-
}
|
|
263
|
-
} catch (error) {
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
226
|
if (!hasModels) {
|
|
268
227
|
console.log(chalk.yellow('No model versions configured yet'));
|
|
269
228
|
}
|
package/lib/report.js
CHANGED
|
@@ -2,8 +2,9 @@ const fs = require('fs-extra');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const chalk = require('chalk');
|
|
4
4
|
const { execSync } = require('child_process');
|
|
5
|
+
const { parseTaskIds } = require('./utils');
|
|
5
6
|
|
|
6
|
-
async function generateReport(
|
|
7
|
+
async function generateReport(taskIdsInput, targetPath = process.cwd()) {
|
|
7
8
|
const tasksPath = path.join(targetPath, '.task-flow/.internal/tasks.json');
|
|
8
9
|
const statusPath = path.join(targetPath, '.task-flow/.internal/status.json');
|
|
9
10
|
const docsDir = path.join(targetPath, '.task-flow/docs');
|
|
@@ -22,36 +23,54 @@ async function generateReport(taskId, targetPath = process.cwd()) {
|
|
|
22
23
|
const tasksData = await fs.readJSON(tasksPath);
|
|
23
24
|
const statusData = await fs.readJSON(statusPath);
|
|
24
25
|
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
if (
|
|
28
|
-
console.log(chalk.red(
|
|
26
|
+
const taskIds = parseTaskIds(taskIdsInput, tasksData.tasks);
|
|
27
|
+
|
|
28
|
+
if (taskIds.length === 0) {
|
|
29
|
+
console.log(chalk.red('❌ No valid task IDs provided.'));
|
|
29
30
|
return;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (!taskStatus) {
|
|
35
|
-
console.log(chalk.yellow(`⚠️ Task ${taskId} has no status information.`));
|
|
36
|
-
}
|
|
33
|
+
await fs.ensureDir(docsDir);
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
? Object.values(taskStatus.subtasks).every(status => status === 'done')
|
|
41
|
-
: false;
|
|
35
|
+
let successCount = 0;
|
|
36
|
+
let errorCount = 0;
|
|
42
37
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
38
|
+
for (const taskId of taskIds) {
|
|
39
|
+
const task = tasksData.tasks.find(t => t.id === taskId);
|
|
46
40
|
|
|
47
|
-
|
|
41
|
+
if (!task) {
|
|
42
|
+
console.log(chalk.red(`❌ Task ${taskId} not found.`));
|
|
43
|
+
errorCount++;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
const taskStatus = statusData.tasks[taskId.toString()];
|
|
48
|
+
|
|
49
|
+
if (!taskStatus) {
|
|
50
|
+
console.log(chalk.yellow(`⚠️ Task ${taskId} has no status information.`));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const isCompleted = taskStatus && taskStatus.status === 'done';
|
|
54
|
+
const allSubtasksDone = taskStatus && taskStatus.subtasks
|
|
55
|
+
? Object.values(taskStatus.subtasks).every(status => status === 'done')
|
|
56
|
+
: false;
|
|
57
|
+
|
|
58
|
+
if (!isCompleted && !allSubtasksDone) {
|
|
59
|
+
console.log(chalk.yellow(`⚠️ Task ${taskId} is not completed. Generating partial report...`));
|
|
60
|
+
}
|
|
51
61
|
|
|
52
|
-
|
|
62
|
+
const reportContent = await buildReport(task, taskStatus, targetPath);
|
|
63
|
+
const reportPath = path.join(docsDir, `task-${taskId}-implementation.md`);
|
|
53
64
|
|
|
54
|
-
|
|
65
|
+
await fs.writeFile(reportPath, reportContent, 'utf8');
|
|
66
|
+
|
|
67
|
+
console.log(chalk.green(`✅ Report generated: ${reportPath}`));
|
|
68
|
+
successCount++;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (taskIds.length > 1) {
|
|
72
|
+
console.log(chalk.cyan(`\n📊 Generated ${successCount} report(s), ${errorCount} error(s)`));
|
|
73
|
+
}
|
|
55
74
|
|
|
56
75
|
} catch (error) {
|
|
57
76
|
console.error(chalk.red('Error generating report:'), error.message);
|
package/lib/utils.js
CHANGED
|
@@ -35,11 +35,26 @@ function showNextSteps(targetPath) {
|
|
|
35
35
|
console.log(chalk.blue('\n See'), chalk.yellow('.task-flow/README.md'), chalk.blue('for all available commands\n'));
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
function parseTaskIds(input, allTasks = []) {
|
|
39
|
+
if (!input || input.trim().toLowerCase() === 'all') {
|
|
40
|
+
return allTasks.map(t => t.id);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const ids = input.split(',')
|
|
44
|
+
.map(id => id.trim())
|
|
45
|
+
.filter(id => id.length > 0)
|
|
46
|
+
.map(id => parseInt(id))
|
|
47
|
+
.filter(id => !isNaN(id));
|
|
48
|
+
|
|
49
|
+
return ids;
|
|
50
|
+
}
|
|
51
|
+
|
|
38
52
|
module.exports = {
|
|
39
53
|
showHeader,
|
|
40
54
|
showSuccess,
|
|
41
55
|
showError,
|
|
42
56
|
showWarning,
|
|
43
57
|
showInfo,
|
|
44
|
-
showNextSteps
|
|
58
|
+
showNextSteps,
|
|
59
|
+
parseTaskIds
|
|
45
60
|
};
|
package/lib/version.js
CHANGED
|
@@ -43,10 +43,6 @@ async function checkVersionUpdates() {
|
|
|
43
43
|
await checkModelVersion('Cursor', versions.cursor, '.cursor/settings.json', rl);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
if (versions.gemini) {
|
|
47
|
-
await checkModelVersion('Gemini', versions.gemini, '.gemini/settings.json', rl);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
46
|
rl.close();
|
|
51
47
|
|
|
52
48
|
console.log(chalk.green('\n✅ Version check completed!\n'));
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rbin-task-flow",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "AI-powered task management for Claude
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "AI-powered task management for Claude and Cursor",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"rbin-task-flow": "
|
|
8
|
-
"task-flow": "
|
|
7
|
+
"rbin-task-flow": "bin/cli.js",
|
|
8
|
+
"task-flow": "bin/cli.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"test": "echo \"No tests yet\"",
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
"ai",
|
|
17
17
|
"claude",
|
|
18
18
|
"cursor",
|
|
19
|
-
"gemini",
|
|
20
19
|
"cli",
|
|
21
20
|
"task-management",
|
|
22
21
|
"ai-powered"
|
|
@@ -25,17 +24,15 @@
|
|
|
25
24
|
"license": "MIT",
|
|
26
25
|
"repository": {
|
|
27
26
|
"type": "git",
|
|
28
|
-
"url": "https://github.com/rbinoliveira/rbin-task-flow.git"
|
|
27
|
+
"url": "git+https://github.com/rbinoliveira/rbin-task-flow.git"
|
|
29
28
|
},
|
|
30
29
|
"files": [
|
|
31
30
|
"bin/",
|
|
32
31
|
".cursor/",
|
|
33
32
|
".claude/",
|
|
34
|
-
".gemini/",
|
|
35
33
|
".task-flow/",
|
|
36
34
|
".model-versions.json",
|
|
37
35
|
"CLAUDE.md",
|
|
38
|
-
"GEMINI.md",
|
|
39
36
|
"lib/"
|
|
40
37
|
],
|
|
41
38
|
"preferGlobal": true,
|
package/.gemini/settings.json
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# Example Screenshot
|
|
2
|
-
|
|
3
|
-
This is a placeholder file. Replace this file with a real screenshot (PNG or JPG).
|
|
4
|
-
|
|
5
|
-
## How to add screenshots:
|
|
6
|
-
|
|
7
|
-
1. Add your image files (.png or .jpg) to this folder
|
|
8
|
-
2. Use descriptive names in kebab-case
|
|
9
|
-
3. RBIN Task Flow will automatically detect and reference the screenshots
|
|
10
|
-
|
|
11
|
-
## Example names:
|
|
12
|
-
|
|
13
|
-
- `login_recover_signup.png`
|
|
14
|
-
- `dashboard.png`
|
|
15
|
-
- `patient.png`
|
|
16
|
-
- `patient_profile.png`
|
|
17
|
-
- `prescriptions.png`
|
|
18
|
-
- `medicine.png`
|
|
19
|
-
|
|
20
|
-
## Reference in tasks:
|
|
21
|
-
|
|
22
|
-
To reference a specific screenshot in a task, use:
|
|
23
|
-
`task-flow-screen filename.png`
|
package/GEMINI.md
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Gemini Instructions
|
|
2
|
-
|
|
3
|
-
## Development Rules
|
|
4
|
-
|
|
5
|
-
All development rules are automatically loaded from `.cursor/rules/` directory. These rules include:
|
|
6
|
-
- Cursor rules formatting guidelines
|
|
7
|
-
- Self-improvement processes
|
|
8
|
-
- Code commenting standards
|
|
9
|
-
- Commit practices
|
|
10
|
-
- Git command control
|
|
11
|
-
- Task execution management with RBIN Task Flow
|
|
12
|
-
|
|
13
|
-
## RBIN Task Flow
|
|
14
|
-
|
|
15
|
-
This project uses RBIN Task Flow for task management:
|
|
16
|
-
- **Task Definition**: Edit `.task-flow/tasks.input.txt` using simple format: `- Task description`
|
|
17
|
-
- **AI Commands**: Use AI-powered commands for task management:
|
|
18
|
-
- `task-flow: sync` - Synchronize tasks from tasks.input.txt
|
|
19
|
-
- `task-flow: run next X` - Work on next X subtasks
|
|
20
|
-
- `task-flow: run task X` - Execute all pending subtasks of task X
|
|
21
|
-
- `task-flow: status` - View current task status
|
|
22
|
-
- `task-flow: review` - Review completed tasks
|
|
23
|
-
- `task-flow: think` - Analyze code and suggest new tasks
|
|
24
|
-
- `task-flow: refactor` - Refactor code from current commit
|
|
25
|
-
- `task-flow: estimate task X` - Estimate time for task X based on subtasks and experience level
|
|
26
|
-
- `task-flow: report task X` - Generate implementation report for completed task X
|
|
27
|
-
- **Files**:
|
|
28
|
-
- `.task-flow/tasks.input.txt` - Define your tasks here
|
|
29
|
-
- `.task-flow/tasks.status.md` - Auto-generated status (DO NOT EDIT manually)
|
|
30
|
-
- `.task-flow/.internal/` - Internal system files (ignore)
|
|
31
|
-
|
|
32
|
-
Follow all rules defined in `.cursor/rules/` for consistent development practices.
|