Skip to content

Commit cb52030

Browse files
committed
fix(core): deep merge workflow metadata
1 parent c1a9ff6 commit cb52030

3 files changed

Lines changed: 62 additions & 4 deletions

File tree

.aiox-core/core/orchestration/context-manager.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,25 @@
1616

1717
const fs = require('fs-extra');
1818
const path = require('path');
19+
const { isPlainObject } = require('../config/merge-utils');
20+
21+
function mergeMetadata(target, source) {
22+
const base = isPlainObject(target) ? target : {};
23+
24+
if (!isPlainObject(source)) {
25+
return { ...base };
26+
}
27+
28+
const result = { ...base };
29+
30+
for (const [key, value] of Object.entries(source)) {
31+
result[key] = isPlainObject(value) && isPlainObject(result[key])
32+
? mergeMetadata(result[key], value)
33+
: value;
34+
}
35+
36+
return result;
37+
}
1938

2039
/**
2140
* Manages workflow execution context and state persistence
@@ -225,7 +244,7 @@ class ContextManager {
225244
*/
226245
async updateMetadata(metadata) {
227246
const state = await this.loadState();
228-
state.metadata = { ...state.metadata, ...metadata };
247+
state.metadata = mergeMetadata(state.metadata, metadata);
229248
this._stateCache = state;
230249
await this._saveState();
231250
}

.aiox-core/install-manifest.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
# - File types for categorization
99
#
1010
version: 5.1.15
11-
generated_at: "2026-05-08T04:49:28.006Z"
11+
generated_at: "2026-05-08T05:02:45.794Z"
1212
generator: scripts/generate-install-manifest.js
1313
file_count: 1111
1414
files:
@@ -845,9 +845,9 @@ files:
845845
type: core
846846
size: 12722
847847
- path: core/orchestration/context-manager.js
848-
hash: sha256:7bf273723a2c08cb84e670b9d4c55aacec51819b1fbd5f3b0c46c4ccfa2ec192
848+
hash: sha256:134ab455731f9435292da7e37e911000d11860c0d8044948e5f9dcd3460b7cd0
849849
type: core
850-
size: 16842
850+
size: 17299
851851
- path: core/orchestration/dashboard-integration.js
852852
hash: sha256:8f2dd7d3885a9eaf58957505d312923e149f2771ae3ca0cda879631683f826c9
853853
type: core

tests/core/orchestration/context-manager.test.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,45 @@ describe('ContextManager', () => {
567567
expect(manager._stateCache.metadata.projectRoot).toBe('/outro/caminho');
568568
});
569569

570+
test('preserva metadados aninhados ao aplicar merge profundo', async () => {
571+
await manager.updateMetadata({
572+
observability: {
573+
attempts: {
574+
total: 1,
575+
lastPhase: 'planning',
576+
},
577+
tags: ['initial'],
578+
nullable: 'keep',
579+
},
580+
});
581+
582+
await manager.updateMetadata({
583+
observability: {
584+
attempts: {
585+
failed: 1,
586+
},
587+
lastError: {
588+
code: 'EACCES',
589+
},
590+
tags: ['latest'],
591+
nullable: null,
592+
},
593+
});
594+
595+
expect(manager._stateCache.metadata.observability).toEqual({
596+
attempts: {
597+
total: 1,
598+
lastPhase: 'planning',
599+
failed: 1,
600+
},
601+
lastError: {
602+
code: 'EACCES',
603+
},
604+
tags: ['latest'],
605+
nullable: null,
606+
});
607+
});
608+
570609
test('persiste estado no disco', async () => {
571610
await manager.updateMetadata({ foo: 'bar' });
572611

0 commit comments

Comments
 (0)