Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .aiox-core/core/execution/build-state-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ class BuildStateManager {
}

this.storyId = storyId;
this.rootPath = options.rootPath || process.cwd();
this.planDir = options.planDir || path.join(this.rootPath, 'plan');
this.rootPath = options.rootPath ?? process.cwd();
this.planDir = options.planDir ?? path.join(this.rootPath, 'plan');
this.config = { ...DEFAULT_CONFIG, ...options.config };

// State file paths
Expand Down Expand Up @@ -213,7 +213,7 @@ class BuildStateManager {
plan: options.plan || null,
checkpoints: [],
metrics: {
totalSubtasks: options.totalSubtasks || 0,
totalSubtasks: options.totalSubtasks ?? 0,
completedSubtasks: 0,
totalAttempts: 0,
totalFailures: 0,
Expand Down Expand Up @@ -355,10 +355,10 @@ class BuildStateManager {
subtaskId,
status: options.status || 'completed',
gitCommit: options.gitCommit || null,
filesModified: options.filesModified || [],
filesModified: options.filesModified ?? [],
metrics: {
duration: options.duration || 0,
attempts: options.attempts || 1,
duration: options.duration ?? 0,
attempts: options.attempts ?? 1,
},
};

Expand Down
26 changes: 13 additions & 13 deletions .aiox-core/core/execution/result-aggregator.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ class ResultAggregator extends EventEmitter {
super();

// Root path for reports
this.rootPath = config.rootPath || process.cwd();
this.reportDir = config.reportDir || path.join(this.rootPath, 'plan');
this.rootPath = config.rootPath ?? process.cwd();
this.reportDir = config.reportDir ?? path.join(this.rootPath, 'plan');

// Conflict detection settings
this.detectConflicts = config.detectConflicts !== false;

// Aggregation history
this.history = [];
this.maxHistory = config.maxHistory || 50;
this.maxHistory = config.maxHistory ?? 50;
}

/**
Expand All @@ -36,8 +36,8 @@ class ResultAggregator extends EventEmitter {

const aggregation = {
id: `agg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
waveIndex: waveResults.waveIndex || waveResults.wave,
startedAt: waveResults.startedAt || new Date().toISOString(),
waveIndex: waveResults.waveIndex ?? waveResults.wave,
startedAt: waveResults.startedAt ?? new Date().toISOString(),
completedAt: new Date().toISOString(),
tasks: [],
conflicts: [],
Expand All @@ -46,15 +46,15 @@ class ResultAggregator extends EventEmitter {
};

// Collect task results
const results = waveResults.results || [];
const results = waveResults.results ?? [];
for (const result of results) {
aggregation.tasks.push({
taskId: result.taskId,
agentId: result.agentId || 'unknown',
agentId: result.agentId ?? 'unknown',
success: result.success,
filesModified: result.filesModified || this.extractFilesFromOutput(result.output),
duration: result.duration || 0,
output: this.summarizeOutput(result.output || result.result?.output),
filesModified: result.filesModified ?? this.extractFilesFromOutput(result.output),
duration: result.duration ?? 0,
output: this.summarizeOutput(result.output ?? result.result?.output),
error: result.error,
});
}
Expand Down Expand Up @@ -138,7 +138,7 @@ class ResultAggregator extends EventEmitter {
const conflicts = [];

for (const task of tasks) {
const files = task.filesModified || [];
const files = task.filesModified ?? [];

for (const file of files) {
if (fileModifications.has(file)) {
Expand Down Expand Up @@ -304,7 +304,7 @@ class ResultAggregator extends EventEmitter {
const tasks = aggregation.tasks;
const successful = tasks.filter((t) => t.success).length;
const failed = tasks.filter((t) => !t.success).length;
const totalDuration = tasks.reduce((sum, t) => sum + (t.duration || 0), 0);
const totalDuration = tasks.reduce((sum, t) => sum + (t.duration ?? 0), 0);

// Calculate wall time
const wallTime = Date.now() - startTime;
Expand Down Expand Up @@ -336,7 +336,7 @@ class ResultAggregator extends EventEmitter {
calculateOverallMetrics(consolidated) {
const allTasks = consolidated.allTasks;
const successful = allTasks.filter((t) => t.success).length;
const totalDuration = allTasks.reduce((sum, t) => sum + (t.duration || 0), 0);
const totalDuration = allTasks.reduce((sum, t) => sum + (t.duration ?? 0), 0);

// Calculate wave metrics
const waveSuccessRates = consolidated.waves.map((w) => w.metrics.successRate);
Expand Down
10 changes: 5 additions & 5 deletions .aiox-core/core/execution/wave-executor.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class WaveExecutor extends EventEmitter {
waves: [
{
index: 1,
tasks: context.tasks || [],
tasks: context.tasks ?? [],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Normalize tasks to arrays before use to avoid runtime failures.

With ??, values like ''/false now pass through instead of falling back to []. Downstream, this can break at Line 94 (wave.tasks.map(...)) and during wave execution.

🛠️ Proposed fix
@@
-      analysis = {
+      analysis = {
         waves: [
           {
             index: 1,
-            tasks: context.tasks ?? [],
+            tasks: Array.isArray(context.tasks) ? context.tasks : [],
           },
         ],
       };
@@
-      this.emit('wave_started', {
+      const waveTasks = Array.isArray(wave.tasks) ? wave.tasks : [];
+      this.emit('wave_started', {
         waveIndex: wave.index,
-        tasks: wave.tasks.map((t) => ({ id: t.id, description: t.description })),
-        totalTasks: wave.tasks.length,
+        tasks: waveTasks.map((t) => ({ id: t.id, description: t.description })),
+        totalTasks: waveTasks.length,
       });
@@
-    const tasks = wave.tasks ?? [];
+    const tasks = Array.isArray(wave.tasks) ? wave.tasks : [];

As per coding guidelines, "Check for proper input validation on public API methods."

Also applies to: 151-151

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.aiox-core/core/execution/wave-executor.js at line 67, Summary: The object
property assignments use "tasks: context.tasks ?? []" which lets non-array falsy
values (e.g., '', false) pass through and later break code like wave.tasks.map;
normalize to arrays. Fix: replace uses of "tasks: context.tasks ?? []" (and the
similar occurrence around the second mention) with a normalization that ensures
an array, e.g. set tasks to Array.isArray(context.tasks) ? context.tasks : []
(or wrap non-array single values in [context.tasks] if intended), and update any
construction sites that create "wave" so wave.tasks is always an array before
being iterated (reference the property assignment where tasks is set and the
downstream wave.tasks.map usage).

},
],
};
Expand Down Expand Up @@ -101,7 +101,7 @@ class WaveExecutor extends EventEmitter {
wave: wave.index,
results: waveResult,
allSucceeded: waveResult.every((r) => r.success),
duration: waveResult.reduce((sum, r) => sum + (r.duration || 0), 0),
duration: waveResult.reduce((sum, r) => sum + (r.duration ?? 0), 0),
});

this.emit('wave_completed', {
Expand Down Expand Up @@ -148,7 +148,7 @@ class WaveExecutor extends EventEmitter {
* @returns {Promise<Array>} - Task results
*/
async executeWave(wave, context) {
const tasks = wave.tasks || [];
const tasks = wave.tasks ?? [];

if (tasks.length === 0) {
return [];
Expand All @@ -175,7 +175,7 @@ class WaveExecutor extends EventEmitter {
success: result.value.success,
result: result.value,
critical: task.critical || false,
duration: result.value.duration || 0,
duration: result.value.duration ?? 0,
});
} else {
allResults.push({
Expand Down Expand Up @@ -314,7 +314,7 @@ class WaveExecutor extends EventEmitter {
const allTasks = waveResults.flatMap((w) => w.results);
const successful = allTasks.filter((t) => t.success).length;
const failed = allTasks.filter((t) => !t.success).length;
const totalDuration = allTasks.reduce((sum, t) => sum + (t.duration || 0), 0);
const totalDuration = allTasks.reduce((sum, t) => sum + (t.duration ?? 0), 0);

// Calculate wall time (actual elapsed time)
const wallTime = waveResults.reduce((sum, w) => {
Expand Down
10 changes: 5 additions & 5 deletions .aiox-core/install-manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# - File types for categorization
#
version: 5.0.3
generated_at: "2026-03-11T15:04:09.395Z"
generated_at: "2026-03-18T02:09:42.143Z"
generator: scripts/generate-install-manifest.js
file_count: 1090
files:
Expand Down Expand Up @@ -405,7 +405,7 @@ files:
type: core
size: 31780
- path: core/execution/build-state-manager.js
hash: sha256:415fca3ad3d750db1f41f14f33971cf661ee9d6073a570175d695bb3c1be655c
hash: sha256:7b13b18fa3ef9d624ea23ce25b30d88311f0d225125b2b7b07e76bdf57eb30c5
type: core
size: 48976
- path: core/execution/context-injector.js
Expand All @@ -425,7 +425,7 @@ files:
type: core
size: 9033
- path: core/execution/result-aggregator.js
hash: sha256:fc662bbc649bf704a8f6e70d0203fab389c664a6b4b2932510f84c251ae26610
hash: sha256:5346bf5ac07f4e837ba3c44115ac73eede3eeea1d342fae1f30d01663e32240f
type: core
size: 14553
- path: core/execution/semantic-merge-engine.js
Expand All @@ -437,7 +437,7 @@ files:
type: core
size: 25738
- path: core/execution/wave-executor.js
hash: sha256:4e2324edb37ae0729062b5ac029f2891e050e7efd3a48d0f4a1dc4f227a6716b
hash: sha256:950f659dd9d7176b39450c95f1903ea8868efd7324603040b770a80e2063310c
type: core
size: 11060
- path: core/graph-dashboard/cli.js
Expand Down Expand Up @@ -1221,7 +1221,7 @@ files:
type: data
size: 9575
- path: data/entity-registry.yaml
hash: sha256:cc1bf74d3ef4e90b7a396d5b77259e540b2f9bd4a5b4b1da4977fe49ae83525d
hash: sha256:7ab5f897a51bbe4b63db9250ba3496c911462ab761a7655672a0bf50f0a821e8
type: data
size: 521869
- path: data/learned-patterns.yaml
Expand Down
Loading