@e0ipso/ai-task-manager 1.26.3 → 1.26.4
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/package.json +1 -1
- package/templates/ai-task-manager/config/scripts/check-task-dependencies.cjs +212 -274
- package/templates/ai-task-manager/config/scripts/find-root.cjs +10 -0
- package/templates/ai-task-manager/config/scripts/get-next-plan-id.cjs +22 -59
- package/templates/ai-task-manager/config/scripts/get-next-task-id.cjs +29 -48
- package/templates/ai-task-manager/config/scripts/shared-utils.cjs +332 -85
- package/templates/ai-task-manager/config/scripts/validate-plan-blueprint.cjs +80 -188
- package/templates/assistant/commands/tasks/create-plan.md +16 -4
- package/templates/assistant/commands/tasks/execute-blueprint.md +17 -4
- package/templates/assistant/commands/tasks/execute-task.md +16 -5
- package/templates/assistant/commands/tasks/full-workflow.md +20 -7
- package/templates/assistant/commands/tasks/generate-tasks.md +15 -2
- package/templates/assistant/commands/tasks/refine-plan.md +16 -5
|
@@ -2,245 +2,137 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
const
|
|
5
|
+
const sharedUtils = require('./shared-utils.cjs');
|
|
6
|
+
const {
|
|
7
|
+
findTaskManagerRoot,
|
|
8
|
+
findPlanById,
|
|
9
|
+
countTasks,
|
|
10
|
+
checkBlueprintExists,
|
|
11
|
+
getAllPlans,
|
|
12
|
+
validatePlanFile,
|
|
13
|
+
checkStandardRootShortcut,
|
|
14
|
+
resolvePlan
|
|
15
|
+
} = sharedUtils;
|
|
6
16
|
|
|
7
17
|
/**
|
|
8
18
|
* Error logging utility
|
|
19
|
+
* @private
|
|
9
20
|
* @param {string} message - Error message
|
|
10
21
|
* @param {...any} args - Additional arguments to log
|
|
11
22
|
*/
|
|
12
|
-
function
|
|
23
|
+
function _errorLog(message, ...args) {
|
|
13
24
|
console.error(`[ERROR] ${message}`, ...args);
|
|
14
25
|
}
|
|
15
26
|
|
|
16
|
-
/**
|
|
17
|
-
* Find plan file and directory for a given plan ID
|
|
18
|
-
* @param {string|number} planId - Plan ID to search for
|
|
19
|
-
* @returns {Object|null} Object with planFile and planDir, or null if not found
|
|
20
|
-
*/
|
|
21
|
-
function findPlanById(planId) {
|
|
22
|
-
const taskManagerRoot = findTaskManagerRoot();
|
|
23
|
-
|
|
24
|
-
if (!taskManagerRoot) {
|
|
25
|
-
errorLog('No .ai/task-manager directory found in current directory or any parent directory.');
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Convert planId to numeric for flexible matching (handles both "2" and "02")
|
|
30
|
-
const numericPlanId = parseInt(planId, 10);
|
|
31
|
-
|
|
32
|
-
if (isNaN(numericPlanId)) {
|
|
33
|
-
errorLog(`Invalid plan ID: ${planId}. Plan ID must be numeric.`);
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const plansDir = path.join(taskManagerRoot, 'plans');
|
|
38
|
-
const archiveDir = path.join(taskManagerRoot, 'archive');
|
|
39
|
-
|
|
40
|
-
// Search both plans and archive directories
|
|
41
|
-
for (const dir of [plansDir, archiveDir]) {
|
|
42
|
-
if (!fs.existsSync(dir)) {
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
48
|
-
|
|
49
|
-
for (const entry of entries) {
|
|
50
|
-
// Match directory pattern: [plan-id]--* (with flexible ID matching)
|
|
51
|
-
if (entry.isDirectory()) {
|
|
52
|
-
// Extract numeric ID from directory name, stripping leading zeros
|
|
53
|
-
const dirMatch = entry.name.match(/^0*(\d+)--/);
|
|
54
|
-
if (dirMatch && parseInt(dirMatch[1], 10) === numericPlanId) {
|
|
55
|
-
const planDirPath = path.join(dir, entry.name);
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
const planDirEntries = fs.readdirSync(planDirPath, { withFileTypes: true });
|
|
59
|
-
|
|
60
|
-
// Look for plan file: plan-[plan-id]--*.md (with flexible ID matching)
|
|
61
|
-
for (const planEntry of planDirEntries) {
|
|
62
|
-
if (planEntry.isFile()) {
|
|
63
|
-
// Extract numeric ID from filename, stripping leading zeros
|
|
64
|
-
const fileMatch = planEntry.name.match(/^plan-0*(\d+)--.*\.md$/);
|
|
65
|
-
if (fileMatch && parseInt(fileMatch[1], 10) === numericPlanId) {
|
|
66
|
-
const planFilePath = path.join(planDirPath, planEntry.name);
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
planFile: planFilePath,
|
|
70
|
-
planDir: planDirPath
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
} catch (err) {
|
|
76
|
-
errorLog(`Failed to read plan directory ${planDirPath}: ${err.message}`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
} catch (err) {
|
|
82
|
-
errorLog(`Failed to read directory ${dir}: ${err.message}`);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Count task files in a plan's tasks directory
|
|
91
|
-
* @param {string} planDir - Plan directory path
|
|
92
|
-
* @returns {number} Number of task files found
|
|
93
|
-
*/
|
|
94
|
-
function countTasks(planDir) {
|
|
95
|
-
const tasksDir = path.join(planDir, 'tasks');
|
|
96
|
-
|
|
97
|
-
if (!fs.existsSync(tasksDir)) {
|
|
98
|
-
return 0;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
const stats = fs.lstatSync(tasksDir);
|
|
103
|
-
if (!stats.isDirectory()) {
|
|
104
|
-
return 0;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const files = fs.readdirSync(tasksDir).filter(f => f.endsWith('.md'));
|
|
108
|
-
return files.length;
|
|
109
|
-
} catch (err) {
|
|
110
|
-
errorLog(`Failed to read tasks directory ${tasksDir}: ${err.message}`);
|
|
111
|
-
return 0;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Check if execution blueprint section exists in plan file
|
|
117
|
-
* @param {string} planFile - Path to plan file
|
|
118
|
-
* @returns {boolean} True if blueprint section exists, false otherwise
|
|
119
|
-
*/
|
|
120
|
-
function checkBlueprintExists(planFile) {
|
|
121
|
-
try {
|
|
122
|
-
const planContent = fs.readFileSync(planFile, 'utf8');
|
|
123
|
-
const blueprintExists = /^## Execution Blueprint/m.test(planContent);
|
|
124
|
-
return blueprintExists;
|
|
125
|
-
} catch (err) {
|
|
126
|
-
errorLog(`Failed to read plan file ${planFile}: ${err.message}`);
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
27
|
/**
|
|
132
28
|
* List available plans for error messaging
|
|
29
|
+
* @private
|
|
30
|
+
* @param {string} [taskManagerRoot] - Optional task manager root path
|
|
133
31
|
* @returns {string[]} Array of plan directory names
|
|
134
32
|
*/
|
|
135
|
-
function
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
for (const dir of [plansDir, archiveDir]) {
|
|
147
|
-
if (!fs.existsSync(dir)) {
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
try {
|
|
152
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
153
|
-
for (const entry of entries) {
|
|
154
|
-
if (entry.isDirectory() && entry.name.match(/^\d+--/)) {
|
|
155
|
-
plans.push(entry.name);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
} catch (err) {
|
|
159
|
-
// Silently continue
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return plans.sort((a, b) => {
|
|
164
|
-
const aId = parseInt(a.match(/^(\d+)--/)[1], 10);
|
|
165
|
-
const bId = parseInt(b.match(/^(\d+)--/)[1], 10);
|
|
166
|
-
return aId - bId;
|
|
167
|
-
});
|
|
33
|
+
function _listAvailablePlans(taskManagerRoot) {
|
|
34
|
+
const plans = getAllPlans(taskManagerRoot);
|
|
35
|
+
return plans
|
|
36
|
+
.map(p => p.name)
|
|
37
|
+
.sort((a, b) => {
|
|
38
|
+
const aIdMatch = a.match(/^(\d+)--/);
|
|
39
|
+
const bIdMatch = b.match(/^(\d+)--/);
|
|
40
|
+
if (!aIdMatch || !bIdMatch) return 0;
|
|
41
|
+
return parseInt(aIdMatch[1], 10) - parseInt(bIdMatch[1], 10);
|
|
42
|
+
});
|
|
168
43
|
}
|
|
169
44
|
|
|
170
45
|
/**
|
|
171
46
|
* Validate plan blueprint and output JSON or specific field
|
|
172
|
-
* @
|
|
173
|
-
* @param {string}
|
|
47
|
+
* @private
|
|
48
|
+
* @param {string|number} inputId - Plan ID or absolute path to validate
|
|
49
|
+
* @param {string} [fieldName] - Optional field name to extract (planFile, planDir, taskCount, blueprintExists, taskManagerRoot, planId)
|
|
50
|
+
* @param {string} [startPath] - Optional start path for finding task manager root
|
|
174
51
|
*/
|
|
175
|
-
function
|
|
176
|
-
if (!
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
52
|
+
function _validatePlanBlueprint(inputId, fieldName, startPath = process.cwd()) {
|
|
53
|
+
if (!inputId) {
|
|
54
|
+
_errorLog('Plan ID or absolute path is required');
|
|
55
|
+
_errorLog('');
|
|
56
|
+
_errorLog('Usage: node validate-plan-blueprint.cjs <plan-id-or-path> [field-name]');
|
|
57
|
+
_errorLog('');
|
|
58
|
+
_errorLog('Examples:');
|
|
59
|
+
_errorLog(' node validate-plan-blueprint.cjs 47 # Output full JSON');
|
|
60
|
+
_errorLog(' node validate-plan-blueprint.cjs /path/to/plan.md # Output full JSON for specific file');
|
|
61
|
+
_errorLog(' node validate-plan-blueprint.cjs 47 planFile # Output just the plan file path');
|
|
62
|
+
_errorLog(' node validate-plan-blueprint.cjs 47 blueprintExists # Output yes/no');
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check if input is numeric (allowing padded zeros) - if not a number or path, it's invalid
|
|
67
|
+
const numericInput = parseInt(inputId, 10);
|
|
68
|
+
const isNumeric = !isNaN(numericInput);
|
|
69
|
+
const isAbsolutePath = inputId.startsWith('/');
|
|
70
|
+
|
|
71
|
+
if (!isNumeric && !isAbsolutePath) {
|
|
72
|
+
_errorLog(`Invalid plan ID: "${inputId}" is not a valid number`);
|
|
187
73
|
process.exit(1);
|
|
188
74
|
}
|
|
189
75
|
|
|
190
|
-
const
|
|
76
|
+
const resolved = resolvePlan(inputId, startPath);
|
|
191
77
|
|
|
192
|
-
if (!
|
|
193
|
-
|
|
194
|
-
|
|
78
|
+
if (!resolved) {
|
|
79
|
+
_errorLog(`Plan ID ${inputId} not found or invalid`);
|
|
80
|
+
_errorLog('');
|
|
195
81
|
|
|
196
|
-
const
|
|
82
|
+
const tmRoot = findTaskManagerRoot(startPath);
|
|
83
|
+
const availablePlans = _listAvailablePlans(tmRoot);
|
|
197
84
|
if (availablePlans.length > 0) {
|
|
198
|
-
|
|
85
|
+
_errorLog('Available plans:');
|
|
199
86
|
availablePlans.forEach(plan => {
|
|
200
|
-
|
|
87
|
+
_errorLog(` ${plan}`);
|
|
201
88
|
});
|
|
202
|
-
} else {
|
|
203
|
-
errorLog('No plans found in .ai/task-manager/{plans,archive}/');
|
|
204
89
|
}
|
|
205
90
|
|
|
206
|
-
errorLog('');
|
|
207
|
-
errorLog('Please verify:');
|
|
208
|
-
errorLog(' 1. You are in the correct project directory');
|
|
209
|
-
errorLog(' 2. The plan exists in .ai/task-manager/plans/ or .ai/task-manager/archive/');
|
|
210
|
-
errorLog(' 3. The plan directory follows the naming pattern: [plan-id]--[name]');
|
|
211
|
-
errorLog(' 4. The plan file follows the naming pattern: plan-[plan-id]--[name].md');
|
|
212
91
|
process.exit(1);
|
|
213
92
|
}
|
|
214
93
|
|
|
215
|
-
const {
|
|
94
|
+
const {
|
|
95
|
+
planFile,
|
|
96
|
+
planDir,
|
|
97
|
+
taskManagerRoot,
|
|
98
|
+
planId
|
|
99
|
+
} = resolved;
|
|
100
|
+
|
|
216
101
|
const taskCount = countTasks(planDir);
|
|
217
102
|
const blueprintExists = checkBlueprintExists(planFile);
|
|
218
103
|
|
|
219
104
|
const result = {
|
|
220
105
|
planFile,
|
|
221
106
|
planDir,
|
|
107
|
+
taskManagerRoot,
|
|
108
|
+
planId,
|
|
222
109
|
taskCount,
|
|
223
110
|
blueprintExists: blueprintExists ? 'yes' : 'no'
|
|
224
111
|
};
|
|
225
112
|
|
|
226
113
|
// If field name is provided, output just that field
|
|
227
114
|
if (fieldName) {
|
|
228
|
-
const validFields = ['planFile', 'planDir', 'taskCount', 'blueprintExists'];
|
|
115
|
+
const validFields = ['planFile', 'planDir', 'taskCount', 'blueprintExists', 'taskManagerRoot', 'planId'];
|
|
229
116
|
if (!validFields.includes(fieldName)) {
|
|
230
|
-
|
|
231
|
-
|
|
117
|
+
_errorLog(`Invalid field name: ${fieldName}`);
|
|
118
|
+
_errorLog(`Valid fields: ${validFields.join(', ')}`);
|
|
232
119
|
process.exit(1);
|
|
233
120
|
}
|
|
234
121
|
// Use process.stdout.write to avoid util.inspect colorization
|
|
235
|
-
// Convert to string explicitly to ensure plain text output
|
|
236
122
|
process.stdout.write(String(result[fieldName]) + '\n');
|
|
237
123
|
} else {
|
|
238
|
-
// Output full JSON
|
|
124
|
+
// Output full JSON
|
|
239
125
|
console.log(JSON.stringify(result, null, 2));
|
|
240
126
|
}
|
|
241
127
|
}
|
|
242
128
|
|
|
243
129
|
// Main execution
|
|
244
|
-
|
|
245
|
-
const
|
|
246
|
-
|
|
130
|
+
if (require.main === module) {
|
|
131
|
+
const planId = process.argv[2];
|
|
132
|
+
const fieldName = process.argv[3];
|
|
133
|
+
_validatePlanBlueprint(planId, fieldName);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
module.exports = {
|
|
137
|
+
_validatePlanBlueprint
|
|
138
|
+
};
|
|
@@ -4,8 +4,8 @@ description: Create a comprehensive plan to accomplish the request from the user
|
|
|
4
4
|
---
|
|
5
5
|
# Comprehensive Plan Creation
|
|
6
6
|
|
|
7
|
-
You are a strategic planning specialist who creates actionable plan documents that balance comprehensive context with
|
|
8
|
-
disciplined scope control. Your role is to think hard to create detailed, actionable plans based on user input while
|
|
7
|
+
You are a strategic planning specialist who creates actionable plan documents that balance comprehensive context with
|
|
8
|
+
disciplined scope control. Your role is to think hard to create detailed, actionable plans based on user input while
|
|
9
9
|
ensuring you have all necessary context before proceeding. Use the plan-creator sub-agent for this if it is available.
|
|
10
10
|
|
|
11
11
|
## Assistant Configuration
|
|
@@ -132,10 +132,22 @@ The schema for this frontmatter is:
|
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
### Plan ID Generation
|
|
135
|
-
|
|
135
|
+
|
|
136
|
+
First, discover the task manager root directory:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
root=$(node -e 'const fs=require("fs"),path=require("path");const f=p=>{const t=path.join(p,".ai/task-manager");const m=path.join(t,".init-metadata.json");try{if(JSON.parse(fs.readFileSync(m)).version){console.log(path.resolve(t));process.exit(0)}}catch(e){};const d=path.dirname(p);if(d!==p)f(d)};f(process.cwd());process.exit(1)')
|
|
140
|
+
|
|
141
|
+
if [ -z "$root" ]; then
|
|
142
|
+
echo "Error: Could not find task manager root directory (.ai/task-manager)"
|
|
143
|
+
exit 1
|
|
144
|
+
fi
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Then execute this script to determine the plan ID:
|
|
136
148
|
|
|
137
149
|
```bash
|
|
138
|
-
node
|
|
150
|
+
next_id=$(node $root/config/scripts/get-next-plan-id.cjs)
|
|
139
151
|
```
|
|
140
152
|
|
|
141
153
|
**Key formatting:**
|
|
@@ -44,12 +44,25 @@ Before proceeding with execution, validate that tasks exist and the execution bl
|
|
|
44
44
|
|
|
45
45
|
**Validation Steps:**
|
|
46
46
|
|
|
47
|
+
First, discover the task manager root directory:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
root=$(node -e 'const fs=require("fs"),path=require("path");const f=p=>{const t=path.join(p,".ai/task-manager");const m=path.join(t,".init-metadata.json");try{if(JSON.parse(fs.readFileSync(m)).version){console.log(path.resolve(t));process.exit(0)}}catch(e){};const d=path.dirname(p);if(d!==p)f(d)};f(process.cwd());process.exit(1)')
|
|
51
|
+
|
|
52
|
+
if [ -z "$root" ]; then
|
|
53
|
+
echo "Error: Could not find task manager root directory (.ai/task-manager)"
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Then extract validation results:
|
|
59
|
+
|
|
47
60
|
```bash
|
|
48
61
|
# Extract validation results directly from script
|
|
49
|
-
plan_file=$(node
|
|
50
|
-
plan_dir=$(node
|
|
51
|
-
task_count=$(node
|
|
52
|
-
blueprint_exists=$(node
|
|
62
|
+
plan_file=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 planFile)
|
|
63
|
+
plan_dir=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 planDir)
|
|
64
|
+
task_count=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 taskCount)
|
|
65
|
+
blueprint_exists=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 blueprintExists)
|
|
53
66
|
```
|
|
54
67
|
|
|
55
68
|
4. **Automatic task generation**:
|
|
@@ -57,21 +57,32 @@ fi
|
|
|
57
57
|
|
|
58
58
|
## Execution Process
|
|
59
59
|
|
|
60
|
-
### 1.
|
|
60
|
+
### 1. Root Discovery and Plan Location
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
First, discover the task manager root directory:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
root=$(node -e 'const fs=require("fs"),path=require("path");const f=p=>{const t=path.join(p,".ai/task-manager");const m=path.join(t,".init-metadata.json");try{if(JSON.parse(fs.readFileSync(m)).version){console.log(path.resolve(t));process.exit(0)}}catch(e){};const d=path.dirname(p);if(d!==p)f(d)};f(process.cwd());process.exit(1)')
|
|
66
|
+
|
|
67
|
+
if [ -z "$root" ]; then
|
|
68
|
+
echo "Error: Could not find task manager root directory (.ai/task-manager)"
|
|
69
|
+
exit 1
|
|
70
|
+
fi
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Then locate the plan directory using the discovered root:
|
|
63
74
|
|
|
64
75
|
```bash
|
|
65
76
|
plan_id="$1"
|
|
66
77
|
task_id="$2"
|
|
67
78
|
|
|
68
79
|
# Find plan directory
|
|
69
|
-
plan_dir=$(find
|
|
80
|
+
plan_dir=$(find $root/{plans,archive} -type d -name "${plan_id}--*" 2>/dev/null | head -1)
|
|
70
81
|
|
|
71
82
|
if [ -z "$plan_dir" ]; then
|
|
72
83
|
echo "Error: Plan with ID ${plan_id} not found"
|
|
73
84
|
echo "Available plans:"
|
|
74
|
-
find
|
|
85
|
+
find $root/plans -name "*--*" -type d | head -5
|
|
75
86
|
exit 1
|
|
76
87
|
fi
|
|
77
88
|
|
|
@@ -147,7 +158,7 @@ Use the dependency checking script to validate all dependencies:
|
|
|
147
158
|
|
|
148
159
|
```bash
|
|
149
160
|
# Call the dependency checking script
|
|
150
|
-
if ! node
|
|
161
|
+
if ! node $root/config/scripts/check-task-dependencies.cjs "$plan_id" "$task_id"; then
|
|
151
162
|
echo ""
|
|
152
163
|
echo "Task execution blocked by unresolved dependencies."
|
|
153
164
|
echo "Please complete the required dependencies first."
|
|
@@ -145,9 +145,20 @@ created: 2025-09-01
|
|
|
145
145
|
|
|
146
146
|
#### Plan ID Generation
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
First, discover the task manager root directory:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
root=$(node -e 'const fs=require("fs"),path=require("path");const f=p=>{const t=path.join(p,".ai/task-manager");const m=path.join(t,".init-metadata.json");try{if(JSON.parse(fs.readFileSync(m)).version){console.log(path.resolve(t));process.exit(0)}}catch(e){};const d=path.dirname(p);if(d!==p)f(d)};f(process.cwd());process.exit(1)')
|
|
152
|
+
|
|
153
|
+
if [ -z "$root" ]; then
|
|
154
|
+
echo "Error: Could not find task manager root directory (.ai/task-manager)"
|
|
155
|
+
exit 1
|
|
156
|
+
fi
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Then auto-generate the next plan ID:
|
|
149
160
|
```bash
|
|
150
|
-
node
|
|
161
|
+
node $root/config/scripts/get-next-plan-id.cjs
|
|
151
162
|
```
|
|
152
163
|
|
|
153
164
|
**Key formatting:**
|
|
@@ -272,7 +283,7 @@ Use the task template in .ai/task-manager/config/templates/TASK_TEMPLATE.md
|
|
|
272
283
|
When creating tasks, you need to determine the next available task ID for the specified plan. Use this bash command to automatically generate the correct ID:
|
|
273
284
|
|
|
274
285
|
```bash
|
|
275
|
-
node
|
|
286
|
+
node $root/config/scripts/get-next-task-id.cjs [PLAN_ID from Step 1]
|
|
276
287
|
```
|
|
277
288
|
|
|
278
289
|
#### Step 4: POST_TASK_GENERATION_ALL hook
|
|
@@ -337,12 +348,14 @@ Before proceeding with execution, validate that tasks exist and the execution bl
|
|
|
337
348
|
|
|
338
349
|
**Validation Steps:**
|
|
339
350
|
|
|
351
|
+
Use the task manager root discovered in Step 1 to extract validation results:
|
|
352
|
+
|
|
340
353
|
```bash
|
|
341
354
|
# Extract validation results directly from script
|
|
342
|
-
plan_file=$(node
|
|
343
|
-
plan_dir=$(node
|
|
344
|
-
task_count=$(node
|
|
345
|
-
blueprint_exists=$(node
|
|
355
|
+
plan_file=$(node $root/config/scripts/validate-plan-blueprint.cjs [planId] planFile)
|
|
356
|
+
plan_dir=$(node $root/config/scripts/validate-plan-blueprint.cjs [planId] planDir)
|
|
357
|
+
task_count=$(node $root/config/scripts/validate-plan-blueprint.cjs [planId] taskCount)
|
|
358
|
+
blueprint_exists=$(node $root/config/scripts/validate-plan-blueprint.cjs [planId] blueprintExists)
|
|
346
359
|
```
|
|
347
360
|
|
|
348
361
|
If either `$task_count` is 0 or `$blueprint_exists` is "no":
|
|
@@ -38,9 +38,22 @@ Use your internal Todo task tool to track the following process:
|
|
|
38
38
|
|
|
39
39
|
- A plan document. Extract it with the following command.
|
|
40
40
|
|
|
41
|
+
First, discover the task manager root directory:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
root=$(node -e 'const fs=require("fs"),path=require("path");const f=p=>{const t=path.join(p,".ai/task-manager");const m=path.join(t,".init-metadata.json");try{if(JSON.parse(fs.readFileSync(m)).version){console.log(path.resolve(t));process.exit(0)}}catch(e){};const d=path.dirname(p);if(d!==p)f(d)};f(process.cwd());process.exit(1)')
|
|
45
|
+
|
|
46
|
+
if [ -z "$root" ]; then
|
|
47
|
+
echo "Error: Could not find task manager root directory (.ai/task-manager)"
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Then extract validation results:
|
|
53
|
+
|
|
41
54
|
```bash
|
|
42
55
|
# Extract validation results directly from script
|
|
43
|
-
plan_file=$(node
|
|
56
|
+
plan_file=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 planFile)
|
|
44
57
|
```
|
|
45
58
|
|
|
46
59
|
### Input Error Handling
|
|
@@ -243,7 +256,7 @@ Use the task template in .ai/task-manager/config/templates/TASK_TEMPLATE.md
|
|
|
243
256
|
When creating tasks, you need to determine the next available task ID for the specified plan. Use this bash command to automatically generate the correct ID:
|
|
244
257
|
|
|
245
258
|
```bash
|
|
246
|
-
node
|
|
259
|
+
node $root/config/scripts/get-next-task-id.cjs $1
|
|
247
260
|
```
|
|
248
261
|
|
|
249
262
|
### Validation Checklist
|
|
@@ -4,9 +4,9 @@ description: Review the plan with the provided ID, gather clarifications, and re
|
|
|
4
4
|
---
|
|
5
5
|
# Plan Review and Refinement
|
|
6
6
|
|
|
7
|
-
You are a strategic planning specialist who specializes in interrogating existing plans, uncovering blind spots, and
|
|
8
|
-
refining the document so that task generators receive the clearest possible instructions. Treat the current plan as the
|
|
9
|
-
work product of another assistant: your responsibility is to pressure test it, request any missing information from the
|
|
7
|
+
You are a strategic planning specialist who specializes in interrogating existing plans, uncovering blind spots, and
|
|
8
|
+
refining the document so that task generators receive the clearest possible instructions. Treat the current plan as the
|
|
9
|
+
work product of another assistant: your responsibility is to pressure test it, request any missing information from the
|
|
10
10
|
user, and update the plan with the refinements. Use the plan-creator sub-agent for this if it is available.
|
|
11
11
|
|
|
12
12
|
## Assistant Configuration
|
|
@@ -34,11 +34,22 @@ If the plan ID is missing, immediately stop and show an error explaining correct
|
|
|
34
34
|
|
|
35
35
|
### Plan Discovery and Validation
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
First, discover the task manager root directory:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
root=$(node -e 'const fs=require("fs"),path=require("path");const f=p=>{const t=path.join(p,".ai/task-manager");const m=path.join(t,".init-metadata.json");try{if(JSON.parse(fs.readFileSync(m)).version){console.log(path.resolve(t));process.exit(0)}}catch(e){};const d=path.dirname(p);if(d!==p)f(d)};f(process.cwd());process.exit(1)')
|
|
41
|
+
|
|
42
|
+
if [ -z "$root" ]; then
|
|
43
|
+
echo "Error: Could not find task manager root directory (.ai/task-manager)"
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then obtain the plan using the plan ID:
|
|
38
49
|
|
|
39
50
|
```bash
|
|
40
51
|
# Extract validation results directly from script
|
|
41
|
-
plan_file=$(node
|
|
52
|
+
plan_file=$(node $root/config/scripts/validate-plan-blueprint.cjs $1 planFile)
|
|
42
53
|
```
|
|
43
54
|
|
|
44
55
|
## Process Checklist
|