@e0ipso/ai-task-manager 1.3.0 → 1.5.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.
@@ -0,0 +1,332 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Script: check-task-dependencies.js
5
+ * Purpose: Check if a task has all of its dependencies resolved (completed)
6
+ * Usage: node check-task-dependencies.js <plan-id> <task-id>
7
+ * Returns: 0 if all dependencies are resolved, 1 if not
8
+ */
9
+
10
+ const fs = require('fs-extra');
11
+ const path = require('path');
12
+ const { execSync } = require('child_process');
13
+
14
+ // Chalk instance - loaded dynamically to handle ESM module
15
+ let chalkInstance = null;
16
+
17
+ // Initialize chalk instance dynamically
18
+ async function initChalk() {
19
+ if (chalkInstance) return chalkInstance;
20
+
21
+ try {
22
+ const { default: chalk } = await import('chalk');
23
+ chalkInstance = chalk;
24
+ } catch (_error) {
25
+ // Chalk not available, will fall back to plain console output
26
+ chalkInstance = null;
27
+ }
28
+
29
+ return chalkInstance;
30
+ }
31
+
32
+ // Color functions for output
33
+ const printError = (message, chalk) => {
34
+ const formattedMessage = chalk?.red(`ERROR: ${message}`) || `ERROR: ${message}`;
35
+ console.error(formattedMessage);
36
+ };
37
+
38
+ const printSuccess = (message, chalk) => {
39
+ const formattedMessage = chalk?.green(`✓ ${message}`) || `✓ ${message}`;
40
+ console.log(formattedMessage);
41
+ };
42
+
43
+ const printWarning = (message, chalk) => {
44
+ const formattedMessage = chalk?.yellow(`⚠ ${message}`) || `⚠ ${message}`;
45
+ console.log(formattedMessage);
46
+ };
47
+
48
+ const printInfo = (message) => {
49
+ console.log(message);
50
+ };
51
+
52
+ // Function to find plan directory
53
+ const findPlanDirectory = (planId) => {
54
+ try {
55
+ // Use find command similar to bash script
56
+ const findCommand = `find .ai/task-manager/plans .ai/task-manager/archive -type d -name "${planId}--*" 2>/dev/null || true`;
57
+ const result = execSync(findCommand, { encoding: 'utf8' }).trim();
58
+ const directories = result.split('\n').filter(dir => dir.length > 0);
59
+ return directories.length > 0 ? directories[0] : null;
60
+ } catch (error) {
61
+ return null;
62
+ }
63
+ };
64
+
65
+ // Function to find task file with padded/unpadded ID handling
66
+ const findTaskFile = (planDir, taskId) => {
67
+ const taskDir = path.join(planDir, 'tasks');
68
+
69
+ if (!fs.existsSync(taskDir)) {
70
+ return null;
71
+ }
72
+
73
+ // Try exact match first
74
+ let pattern = `${taskId}--*.md`;
75
+ let files = fs.readdirSync(taskDir).filter(file => {
76
+ const regex = new RegExp(`^${taskId}--.*\\.md$`);
77
+ return regex.test(file);
78
+ });
79
+
80
+ if (files.length > 0) {
81
+ return path.join(taskDir, files[0]);
82
+ }
83
+
84
+ // Try with zero-padding if direct match fails
85
+ const paddedTaskId = taskId.padStart(2, '0');
86
+ if (paddedTaskId !== taskId) {
87
+ pattern = `${paddedTaskId}--*.md`;
88
+ files = fs.readdirSync(taskDir).filter(file => {
89
+ const regex = new RegExp(`^${paddedTaskId}--.*\\.md$`);
90
+ return regex.test(file);
91
+ });
92
+
93
+ if (files.length > 0) {
94
+ return path.join(taskDir, files[0]);
95
+ }
96
+ }
97
+
98
+ // Try removing potential zero-padding from taskId
99
+ const unpaddedTaskId = taskId.replace(/^0+/, '') || '0';
100
+ if (unpaddedTaskId !== taskId) {
101
+ pattern = `${unpaddedTaskId}--*.md`;
102
+ files = fs.readdirSync(taskDir).filter(file => {
103
+ const regex = new RegExp(`^${unpaddedTaskId}--.*\\.md$`);
104
+ return regex.test(file);
105
+ });
106
+
107
+ if (files.length > 0) {
108
+ return path.join(taskDir, files[0]);
109
+ }
110
+
111
+ // Try with zero-padding of unpadded version
112
+ const repaddedTaskId = unpaddedTaskId.padStart(2, '0');
113
+ pattern = `${repaddedTaskId}--*.md`;
114
+ files = fs.readdirSync(taskDir).filter(file => {
115
+ const regex = new RegExp(`^${repaddedTaskId}--.*\\.md$`);
116
+ return regex.test(file);
117
+ });
118
+
119
+ if (files.length > 0) {
120
+ return path.join(taskDir, files[0]);
121
+ }
122
+ }
123
+
124
+ return null;
125
+ };
126
+
127
+ // Function to parse YAML frontmatter
128
+ const parseFrontmatter = (content) => {
129
+ const lines = content.split('\n');
130
+ let inFrontmatter = false;
131
+ let frontmatterEnd = false;
132
+ let delimiterCount = 0;
133
+ const frontmatterLines = [];
134
+
135
+ for (const line of lines) {
136
+ if (line.trim() === '---') {
137
+ delimiterCount++;
138
+ if (delimiterCount === 1) {
139
+ inFrontmatter = true;
140
+ continue;
141
+ } else if (delimiterCount === 2) {
142
+ frontmatterEnd = true;
143
+ break;
144
+ }
145
+ }
146
+
147
+ if (inFrontmatter && !frontmatterEnd) {
148
+ frontmatterLines.push(line);
149
+ }
150
+ }
151
+
152
+ return frontmatterLines.join('\n');
153
+ };
154
+
155
+ // Function to extract dependencies from frontmatter
156
+ const extractDependencies = (frontmatter) => {
157
+ const lines = frontmatter.split('\n');
158
+ const dependencies = [];
159
+ let inDependenciesSection = false;
160
+
161
+ for (let i = 0; i < lines.length; i++) {
162
+ const line = lines[i];
163
+
164
+ // Check for dependencies line
165
+ if (line.match(/^dependencies:/)) {
166
+ inDependenciesSection = true;
167
+
168
+ // Check if dependencies are on the same line (array syntax)
169
+ const arrayMatch = line.match(/\[(.*)\]/);
170
+ if (arrayMatch) {
171
+ const deps = arrayMatch[1]
172
+ .split(',')
173
+ .map(dep => dep.trim().replace(/['"]/g, ''))
174
+ .filter(dep => dep.length > 0);
175
+ dependencies.push(...deps);
176
+ inDependenciesSection = false;
177
+ }
178
+ continue;
179
+ }
180
+
181
+ // If we're in dependencies section and hit a non-indented line that's not a list item, exit
182
+ if (inDependenciesSection && line.match(/^[^ ]/) && !line.match(/^[ \t]*-/)) {
183
+ inDependenciesSection = false;
184
+ }
185
+
186
+ // Parse list format dependencies
187
+ if (inDependenciesSection && line.match(/^[ \t]*-/)) {
188
+ const dep = line.replace(/^[ \t]*-[ \t]*/, '').replace(/[ \t]*$/, '').replace(/['"]/g, '');
189
+ if (dep.length > 0) {
190
+ dependencies.push(dep);
191
+ }
192
+ }
193
+ }
194
+
195
+ return dependencies;
196
+ };
197
+
198
+ // Function to extract status from frontmatter
199
+ const extractStatus = (frontmatter) => {
200
+ const lines = frontmatter.split('\n');
201
+
202
+ for (const line of lines) {
203
+ if (line.match(/^status:/)) {
204
+ return line.replace(/^status:[ \t]*/, '').replace(/^["']/, '').replace(/["']$/, '').trim();
205
+ }
206
+ }
207
+
208
+ return null;
209
+ };
210
+
211
+ // Main function
212
+ const main = async () => {
213
+ // Initialize chalk
214
+ const chalk = await initChalk();
215
+
216
+ // Check arguments
217
+ if (process.argv.length !== 4) {
218
+ printError('Invalid number of arguments', chalk);
219
+ console.log('Usage: node check-task-dependencies.js <plan-id> <task-id>');
220
+ console.log('Example: node check-task-dependencies.js 16 03');
221
+ process.exit(1);
222
+ }
223
+
224
+ const planId = process.argv[2];
225
+ const taskId = process.argv[3];
226
+
227
+ // Find the plan directory
228
+ const planDir = findPlanDirectory(planId);
229
+
230
+ if (!planDir) {
231
+ printError(`Plan with ID ${planId} not found`, chalk);
232
+ process.exit(1);
233
+ }
234
+
235
+ printInfo(`Found plan directory: ${planDir}`);
236
+
237
+ // Find task file
238
+ const taskFile = findTaskFile(planDir, taskId);
239
+
240
+ if (!taskFile || !fs.existsSync(taskFile)) {
241
+ printError(`Task with ID ${taskId} not found in plan ${planId}`, chalk);
242
+ process.exit(1);
243
+ }
244
+
245
+ printInfo(`Checking task: ${path.basename(taskFile)}`);
246
+ console.log('');
247
+
248
+ // Read and parse task file
249
+ const taskContent = fs.readFileSync(taskFile, 'utf8');
250
+ const frontmatter = parseFrontmatter(taskContent);
251
+ const dependencies = extractDependencies(frontmatter);
252
+
253
+ // Check if there are any dependencies
254
+ if (dependencies.length === 0) {
255
+ printSuccess('Task has no dependencies - ready to execute!', chalk);
256
+ process.exit(0);
257
+ }
258
+
259
+ // Display dependencies
260
+ printInfo('Task dependencies found:');
261
+ dependencies.forEach(dep => {
262
+ console.log(` - Task ${dep}`);
263
+ });
264
+ console.log('');
265
+
266
+ // Check each dependency
267
+ let allResolved = true;
268
+ let unresolvedDeps = [];
269
+ let resolvedCount = 0;
270
+ const totalDeps = dependencies.length;
271
+
272
+ printInfo('Checking dependency status...');
273
+ console.log('');
274
+
275
+ for (const depId of dependencies) {
276
+ // Find dependency task file
277
+ const depFile = findTaskFile(planDir, depId);
278
+
279
+ if (!depFile || !fs.existsSync(depFile)) {
280
+ printError(`Dependency task ${depId} not found`, chalk);
281
+ allResolved = false;
282
+ unresolvedDeps.push(`${depId} (not found)`);
283
+ continue;
284
+ }
285
+
286
+ // Extract status from dependency task
287
+ const depContent = fs.readFileSync(depFile, 'utf8');
288
+ const depFrontmatter = parseFrontmatter(depContent);
289
+ const status = extractStatus(depFrontmatter);
290
+
291
+ // Check if status is completed
292
+ if (status === 'completed') {
293
+ printSuccess(`Task ${depId} - Status: completed ✓`, chalk);
294
+ resolvedCount++;
295
+ } else {
296
+ printWarning(`Task ${depId} - Status: ${status || 'unknown'} ✗`, chalk);
297
+ allResolved = false;
298
+ unresolvedDeps.push(`${depId} (${status || 'unknown'})`);
299
+ }
300
+ }
301
+
302
+ console.log('');
303
+ printInfo('=========================================');
304
+ printInfo('Dependency Check Summary');
305
+ printInfo('=========================================');
306
+ printInfo(`Total dependencies: ${totalDeps}`);
307
+ printInfo(`Resolved: ${resolvedCount}`);
308
+ printInfo(`Unresolved: ${totalDeps - resolvedCount}`);
309
+ console.log('');
310
+
311
+ if (allResolved) {
312
+ printSuccess(`All dependencies are resolved! Task ${taskId} is ready to execute.`, chalk);
313
+ process.exit(0);
314
+ } else {
315
+ printError(`Task ${taskId} has unresolved dependencies:`, chalk);
316
+ unresolvedDeps.forEach(dep => {
317
+ console.log(dep);
318
+ });
319
+ printInfo('Please complete the dependencies before executing this task.');
320
+ process.exit(1);
321
+ }
322
+ };
323
+
324
+ // Run the script
325
+ if (require.main === module) {
326
+ main().catch((error) => {
327
+ console.error('Script execution failed:', error);
328
+ process.exit(1);
329
+ });
330
+ }
331
+
332
+ module.exports = { main };
@@ -37,7 +37,7 @@ Before starting execution check if you are in the `main` branch. If so, create a
37
37
  ```bash
38
38
  # For each task in current phase
39
39
  for TASK_ID in $PHASE_TASKS; do
40
- if ! @templates/ai-task-manager/config/scripts/check-task-dependencies.sh "$1" "$TASK_ID"; then
40
+ if ! node .ai/task-manager/config/scripts/check-task-dependencies.js "$1" "$TASK_ID"; then
41
41
  echo "ERROR: Task $TASK_ID has unresolved dependencies - cannot proceed with phase execution"
42
42
  echo "Please resolve dependencies before continuing with blueprint execution"
43
43
  exit 1
@@ -16,9 +16,9 @@ You are responsible for executing a single task within a plan while maintaining
16
16
 
17
17
  ## Input Requirements
18
18
  - Plan ID: $1 (required)
19
- - Task ID: $2 (required)
19
+ - Task ID: $2 (required)
20
20
  - Task management directory structure: `@.ai/task-manager/`
21
- - Dependency checking script: `@templates/ai-task-manager/config/scripts/check-task-dependencies.sh`
21
+ - Dependency checking script: `.ai/task-manager/config/scripts/check-task-dependencies.js`
22
22
 
23
23
  ### Input Validation
24
24
 
@@ -87,7 +87,7 @@ Check current task status to ensure it can be executed:
87
87
  # Extract current status from task frontmatter
88
88
  CURRENT_STATUS=$(awk '
89
89
  /^---$/ { if (++delim == 2) exit }
90
- /^status:/ {
90
+ /^status:/ {
91
91
  gsub(/^status:[ \t]*/, "")
92
92
  gsub(/^["'\'']/, "")
93
93
  gsub(/["'\'']$/, "")
@@ -125,7 +125,7 @@ Use the dependency checking script to validate all dependencies:
125
125
 
126
126
  ```bash
127
127
  # Call the dependency checking script
128
- if ! @templates/ai-task-manager/config/scripts/check-task-dependencies.sh "$PLAN_ID" "$TASK_ID"; then
128
+ if ! node .ai/task-manager/config/scripts/check-task-dependencies.js "$PLAN_ID" "$TASK_ID"; then
129
129
  echo ""
130
130
  echo "Task execution blocked by unresolved dependencies."
131
131
  echo "Please complete the required dependencies first."
@@ -144,7 +144,7 @@ Read task skills and select appropriate task-specific agent:
144
144
  # Extract skills from task frontmatter
145
145
  TASK_SKILLS=$(awk '
146
146
  /^---$/ { if (++delim == 2) exit }
147
- /^skills:/ {
147
+ /^skills:/ {
148
148
  in_skills = 1
149
149
  # Check if skills are on the same line
150
150
  if (match($0, /\[.*\]/)) {
@@ -191,7 +191,7 @@ echo "Updating task status to in-progress..."
191
191
  # Create temporary file with updated status
192
192
  TEMP_FILE=$(mktemp)
193
193
  awk '
194
- /^---$/ {
194
+ /^---$/ {
195
195
  if (++delim == 1) {
196
196
  print
197
197
  next
@@ -201,9 +201,9 @@ awk '
201
201
  next
202
202
  }
203
203
  }
204
- /^status:/ && delim == 1 {
204
+ /^status:/ && delim == 1 {
205
205
  print "status: \"in-progress\""
206
- next
206
+ next
207
207
  }
208
208
  { print }
209
209
  ' "$TASK_FILE" > "$TEMP_FILE"
@@ -220,7 +220,7 @@ Deploy the task using the Task tool with full context:
220
220
 
221
221
  **Task Deployment**: Use your internal Task tool to execute the task with the following context:
222
222
  - Task file path: `$TASK_FILE`
223
- - Plan directory: `$PLAN_DIR`
223
+ - Plan directory: `$PLAN_DIR`
224
224
  - Required skills: `$TASK_SKILLS`
225
225
  - Agent selection: Based on skills analysis or general-purpose agent
226
226
 
@@ -236,7 +236,7 @@ After task completion, update the status based on execution outcome:
236
236
  ```bash
237
237
  TEMP_FILE=$(mktemp)
238
238
  awk '
239
- /^---$/ {
239
+ /^---$/ {
240
240
  if (++delim == 1) {
241
241
  print
242
242
  next
@@ -246,9 +246,9 @@ awk '
246
246
  next
247
247
  }
248
248
  }
249
- /^status:/ && delim == 1 {
249
+ /^status:/ && delim == 1 {
250
250
  print "status: \"completed\""
251
- next
251
+ next
252
252
  }
253
253
  { print }
254
254
  ' "$TASK_FILE" > "$TEMP_FILE"
@@ -270,7 +270,7 @@ echo "Task execution failed - updating status..."
270
270
 
271
271
  TEMP_FILE=$(mktemp)
272
272
  awk '
273
- /^---$/ {
273
+ /^---$/ {
274
274
  if (++delim == 1) {
275
275
  print
276
276
  next
@@ -280,9 +280,9 @@ awk '
280
280
  next
281
281
  }
282
282
  }
283
- /^status:/ && delim == 1 {
283
+ /^status:/ && delim == 1 {
284
284
  print "status: \"failed\""
285
- next
285
+ next
286
286
  }
287
287
  { print }
288
288
  ' "$TASK_FILE" > "$TEMP_FILE"
@@ -312,7 +312,7 @@ exit 1
312
312
  This command integrates with the existing task management system by:
313
313
  - Using established plan and task location patterns
314
314
  - Leveraging the dependency checking script for validation
315
- - Following status management conventions
315
+ - Following status management conventions
316
316
  - Maintaining compatibility with execute-blueprint workflows
317
317
  - Preserving task isolation and dependency order
318
318
 
@@ -1,185 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Script: check-task-dependencies.sh
4
- # Purpose: Check if a task has all of its dependencies resolved (completed)
5
- # Usage: ./check-task-dependencies.sh <plan-id> <task-id>
6
- # Returns: 0 if all dependencies are resolved, 1 if not
7
-
8
- set -e
9
-
10
- # Color codes for output
11
- RED='\033[0;31m'
12
- GREEN='\033[0;32m'
13
- YELLOW='\033[1;33m'
14
- NC='\033[0m' # No Color
15
-
16
- # Function to print colored output
17
- print_error() {
18
- echo -e "${RED}ERROR: $1${NC}" >&2
19
- }
20
-
21
- print_success() {
22
- echo -e "${GREEN}✓ $1${NC}"
23
- }
24
-
25
- print_warning() {
26
- echo -e "${YELLOW}⚠ $1${NC}"
27
- }
28
-
29
- print_info() {
30
- echo -e "$1"
31
- }
32
-
33
- # Check arguments
34
- if [ $# -ne 2 ]; then
35
- print_error "Invalid number of arguments"
36
- echo "Usage: $0 <plan-id> <task-id>"
37
- echo "Example: $0 16 03"
38
- exit 1
39
- fi
40
-
41
- PLAN_ID="$1"
42
- TASK_ID="$2"
43
-
44
- # Find the plan directory
45
- PLAN_DIR=$(find .ai/task-manager/{plans,archive} -type d -name "${PLAN_ID}--*" 2>/dev/null | head -1)
46
-
47
- if [ -z "$PLAN_DIR" ]; then
48
- print_error "Plan with ID ${PLAN_ID} not found"
49
- exit 1
50
- fi
51
-
52
- print_info "Found plan directory: ${PLAN_DIR}"
53
-
54
- # Construct task file path
55
- # Handle both padded (01, 02) and unpadded (1, 2) task IDs
56
- TASK_FILE=""
57
- if [ -f "${PLAN_DIR}/tasks/${TASK_ID}--"*.md ]; then
58
- TASK_FILE=$(ls "${PLAN_DIR}/tasks/${TASK_ID}--"*.md 2>/dev/null | head -1)
59
- elif [ -f "${PLAN_DIR}/tasks/0${TASK_ID}--"*.md ]; then
60
- # Try with zero-padding if direct match fails
61
- TASK_FILE=$(ls "${PLAN_DIR}/tasks/0${TASK_ID}--"*.md 2>/dev/null | head -1)
62
- fi
63
-
64
- if [ -z "$TASK_FILE" ] || [ ! -f "$TASK_FILE" ]; then
65
- print_error "Task with ID ${TASK_ID} not found in plan ${PLAN_ID}"
66
- exit 1
67
- fi
68
-
69
- print_info "Checking task: $(basename "$TASK_FILE")"
70
- echo ""
71
-
72
- # Extract dependencies from task frontmatter
73
- # Using awk to parse YAML frontmatter
74
- DEPENDENCIES=$(awk '
75
- /^---$/ { if (++delim == 2) exit }
76
- /^dependencies:/ {
77
- dep_section = 1
78
- # Check if dependencies are on the same line
79
- if (match($0, /\[.*\]/)) {
80
- gsub(/^dependencies:[ \t]*\[/, "")
81
- gsub(/\].*$/, "")
82
- gsub(/[ \t]/, "")
83
- print
84
- dep_section = 0
85
- }
86
- next
87
- }
88
- dep_section && /^[^ ]/ { dep_section = 0 }
89
- dep_section && /^[ \t]*-/ {
90
- gsub(/^[ \t]*-[ \t]*/, "")
91
- gsub(/[ \t]*$/, "")
92
- print
93
- }
94
- ' "$TASK_FILE" | tr ',' '\n' | sed 's/^[ \t]*//;s/[ \t]*$//' | grep -v '^$')
95
-
96
- # Check if there are any dependencies
97
- if [ -z "$DEPENDENCIES" ]; then
98
- print_success "Task has no dependencies - ready to execute!"
99
- exit 0
100
- fi
101
-
102
- # Display dependencies
103
- print_info "Task dependencies found:"
104
- echo "$DEPENDENCIES" | while read -r dep; do
105
- echo " - Task ${dep}"
106
- done
107
- echo ""
108
-
109
- # Check each dependency
110
- ALL_RESOLVED=true
111
- UNRESOLVED_DEPS=""
112
- RESOLVED_COUNT=0
113
- TOTAL_DEPS=$(echo "$DEPENDENCIES" | wc -l)
114
-
115
- print_info "Checking dependency status..."
116
- echo ""
117
-
118
- for DEP_ID in $DEPENDENCIES; do
119
- # Find dependency task file
120
- DEP_FILE=""
121
-
122
- # Try exact match first
123
- if [ -f "${PLAN_DIR}/tasks/${DEP_ID}--"*.md ]; then
124
- DEP_FILE=$(ls "${PLAN_DIR}/tasks/${DEP_ID}--"*.md 2>/dev/null | head -1)
125
- elif [ -f "${PLAN_DIR}/tasks/0${DEP_ID}--"*.md ]; then
126
- # Try with zero-padding
127
- DEP_FILE=$(ls "${PLAN_DIR}/tasks/0${DEP_ID}--"*.md 2>/dev/null | head -1)
128
- else
129
- # Try removing potential zero-padding from DEP_ID
130
- UNPADDED_DEP=$(echo "$DEP_ID" | sed 's/^0*//')
131
- if [ -f "${PLAN_DIR}/tasks/${UNPADDED_DEP}--"*.md ]; then
132
- DEP_FILE=$(ls "${PLAN_DIR}/tasks/${UNPADDED_DEP}--"*.md 2>/dev/null | head -1)
133
- elif [ -f "${PLAN_DIR}/tasks/0${UNPADDED_DEP}--"*.md ]; then
134
- DEP_FILE=$(ls "${PLAN_DIR}/tasks/0${UNPADDED_DEP}--"*.md 2>/dev/null | head -1)
135
- fi
136
- fi
137
-
138
- if [ -z "$DEP_FILE" ] || [ ! -f "$DEP_FILE" ]; then
139
- print_error "Dependency task ${DEP_ID} not found"
140
- ALL_RESOLVED=false
141
- UNRESOLVED_DEPS="${UNRESOLVED_DEPS}${DEP_ID} (not found)\n"
142
- continue
143
- fi
144
-
145
- # Extract status from dependency task
146
- STATUS=$(awk '
147
- /^---$/ { if (++delim == 2) exit }
148
- /^status:/ {
149
- gsub(/^status:[ \t]*/, "")
150
- gsub(/^["'\'']/, "")
151
- gsub(/["'\'']$/, "")
152
- print
153
- exit
154
- }
155
- ' "$DEP_FILE")
156
-
157
- # Check if status is completed
158
- if [ "$STATUS" = "completed" ]; then
159
- print_success "Task ${DEP_ID} - Status: completed ✓"
160
- ((RESOLVED_COUNT++))
161
- else
162
- print_warning "Task ${DEP_ID} - Status: ${STATUS:-unknown} ✗"
163
- ALL_RESOLVED=false
164
- UNRESOLVED_DEPS="${UNRESOLVED_DEPS}${DEP_ID} (${STATUS:-unknown})\n"
165
- fi
166
- done
167
-
168
- echo ""
169
- print_info "========================================="
170
- print_info "Dependency Check Summary"
171
- print_info "========================================="
172
- print_info "Total dependencies: ${TOTAL_DEPS}"
173
- print_info "Resolved: ${RESOLVED_COUNT}"
174
- print_info "Unresolved: $((TOTAL_DEPS - RESOLVED_COUNT))"
175
- echo ""
176
-
177
- if [ "$ALL_RESOLVED" = true ]; then
178
- print_success "All dependencies are resolved! Task ${TASK_ID} is ready to execute."
179
- exit 0
180
- else
181
- print_error "Task ${TASK_ID} has unresolved dependencies:"
182
- echo -e "$UNRESOLVED_DEPS"
183
- print_info "Please complete the dependencies before executing this task."
184
- exit 1
185
- fi