aios-core 3.2.0 → 3.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/.aios-core/core-config.yaml +44 -0
- package/.aios-core/infrastructure/scripts/ide-sync/agent-parser.js +251 -0
- package/.aios-core/infrastructure/scripts/ide-sync/index.js +480 -0
- package/.aios-core/infrastructure/scripts/ide-sync/redirect-generator.js +200 -0
- package/.aios-core/infrastructure/scripts/ide-sync/transformers/antigravity.js +105 -0
- package/.aios-core/infrastructure/scripts/ide-sync/transformers/claude-code.js +84 -0
- package/.aios-core/infrastructure/scripts/ide-sync/transformers/cursor.js +93 -0
- package/.aios-core/infrastructure/scripts/ide-sync/transformers/trae.js +125 -0
- package/.aios-core/infrastructure/scripts/ide-sync/transformers/windsurf.js +106 -0
- package/.aios-core/infrastructure/scripts/ide-sync/validator.js +273 -0
- package/.aios-core/install-manifest.yaml +41 -5
- package/package.json +10 -1
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validator - Verifies IDE sync status
|
|
3
|
+
* @story 6.19 - IDE Command Auto-Sync System
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs-extra');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const crypto = require('crypto');
|
|
9
|
+
const { getRedirectFilenames } = require('./redirect-generator');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Calculate content hash for comparison
|
|
13
|
+
* @param {string} content - File content
|
|
14
|
+
* @returns {string} - SHA256 hash
|
|
15
|
+
*/
|
|
16
|
+
function hashContent(content) {
|
|
17
|
+
// Normalize line endings for cross-platform consistency
|
|
18
|
+
const normalized = content.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
19
|
+
return crypto.createHash('sha256').update(normalized, 'utf8').digest('hex');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Check if a file exists at target path
|
|
24
|
+
* @param {string} filePath - Path to check
|
|
25
|
+
* @returns {boolean} - True if file exists
|
|
26
|
+
*/
|
|
27
|
+
function fileExists(filePath) {
|
|
28
|
+
return fs.existsSync(filePath);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Read file content if it exists
|
|
33
|
+
* @param {string} filePath - Path to read
|
|
34
|
+
* @returns {string|null} - File content or null
|
|
35
|
+
*/
|
|
36
|
+
function readFileIfExists(filePath) {
|
|
37
|
+
try {
|
|
38
|
+
if (fs.existsSync(filePath)) {
|
|
39
|
+
return fs.readFileSync(filePath, 'utf8');
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
// Ignore read errors
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Validate sync status for a single IDE
|
|
49
|
+
* @param {object[]} expectedFiles - Array of {filename, content} expected
|
|
50
|
+
* @param {string} targetDir - Target directory to check
|
|
51
|
+
* @param {object} redirectsConfig - Redirects configuration
|
|
52
|
+
* @returns {object} - Validation result
|
|
53
|
+
*/
|
|
54
|
+
function validateIdeSync(expectedFiles, targetDir, redirectsConfig) {
|
|
55
|
+
const result = {
|
|
56
|
+
targetDir,
|
|
57
|
+
missing: [],
|
|
58
|
+
drift: [],
|
|
59
|
+
orphaned: [],
|
|
60
|
+
synced: [],
|
|
61
|
+
total: {
|
|
62
|
+
expected: expectedFiles.length,
|
|
63
|
+
missing: 0,
|
|
64
|
+
drift: 0,
|
|
65
|
+
orphaned: 0,
|
|
66
|
+
synced: 0,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// Track expected filenames
|
|
71
|
+
const expectedFilenames = new Set(expectedFiles.map(f => f.filename));
|
|
72
|
+
|
|
73
|
+
// Add redirect filenames to expected
|
|
74
|
+
const redirectFilenames = getRedirectFilenames(redirectsConfig);
|
|
75
|
+
for (const rf of redirectFilenames) {
|
|
76
|
+
expectedFilenames.add(rf);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Check each expected file
|
|
80
|
+
for (const expected of expectedFiles) {
|
|
81
|
+
const targetPath = path.join(targetDir, expected.filename);
|
|
82
|
+
const actualContent = readFileIfExists(targetPath);
|
|
83
|
+
|
|
84
|
+
if (actualContent === null) {
|
|
85
|
+
// File is missing
|
|
86
|
+
result.missing.push({
|
|
87
|
+
filename: expected.filename,
|
|
88
|
+
path: targetPath,
|
|
89
|
+
});
|
|
90
|
+
result.total.missing++;
|
|
91
|
+
} else {
|
|
92
|
+
// Compare content
|
|
93
|
+
const expectedHash = hashContent(expected.content);
|
|
94
|
+
const actualHash = hashContent(actualContent);
|
|
95
|
+
|
|
96
|
+
if (expectedHash !== actualHash) {
|
|
97
|
+
// Content differs (drift)
|
|
98
|
+
result.drift.push({
|
|
99
|
+
filename: expected.filename,
|
|
100
|
+
path: targetPath,
|
|
101
|
+
expectedHash,
|
|
102
|
+
actualHash,
|
|
103
|
+
});
|
|
104
|
+
result.total.drift++;
|
|
105
|
+
} else {
|
|
106
|
+
// File is synced
|
|
107
|
+
result.synced.push({
|
|
108
|
+
filename: expected.filename,
|
|
109
|
+
path: targetPath,
|
|
110
|
+
});
|
|
111
|
+
result.total.synced++;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Check for orphaned files (files in target not in expected)
|
|
117
|
+
if (fs.existsSync(targetDir)) {
|
|
118
|
+
try {
|
|
119
|
+
const actualFiles = fs.readdirSync(targetDir).filter(f => f.endsWith('.md'));
|
|
120
|
+
|
|
121
|
+
for (const file of actualFiles) {
|
|
122
|
+
if (!expectedFilenames.has(file)) {
|
|
123
|
+
result.orphaned.push({
|
|
124
|
+
filename: file,
|
|
125
|
+
path: path.join(targetDir, file),
|
|
126
|
+
});
|
|
127
|
+
result.total.orphaned++;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
// Ignore directory read errors
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Validate sync status for all IDEs
|
|
140
|
+
* @param {object} ideConfigs - Map of IDE name to {expectedFiles, targetDir}
|
|
141
|
+
* @param {object} redirectsConfig - Redirects configuration
|
|
142
|
+
* @returns {object} - Full validation result
|
|
143
|
+
*/
|
|
144
|
+
function validateAllIdes(ideConfigs, redirectsConfig) {
|
|
145
|
+
const results = {
|
|
146
|
+
ides: {},
|
|
147
|
+
summary: {
|
|
148
|
+
total: 0,
|
|
149
|
+
synced: 0,
|
|
150
|
+
missing: 0,
|
|
151
|
+
drift: 0,
|
|
152
|
+
orphaned: 0,
|
|
153
|
+
pass: true,
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
for (const [ideName, config] of Object.entries(ideConfigs)) {
|
|
158
|
+
const ideResult = validateIdeSync(
|
|
159
|
+
config.expectedFiles,
|
|
160
|
+
config.targetDir,
|
|
161
|
+
redirectsConfig
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
results.ides[ideName] = ideResult;
|
|
165
|
+
|
|
166
|
+
// Update summary
|
|
167
|
+
results.summary.total += ideResult.total.expected;
|
|
168
|
+
results.summary.synced += ideResult.total.synced;
|
|
169
|
+
results.summary.missing += ideResult.total.missing;
|
|
170
|
+
results.summary.drift += ideResult.total.drift;
|
|
171
|
+
results.summary.orphaned += ideResult.total.orphaned;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Pass if no missing or drift
|
|
175
|
+
results.summary.pass =
|
|
176
|
+
results.summary.missing === 0 && results.summary.drift === 0;
|
|
177
|
+
|
|
178
|
+
return results;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Format validation result as report string
|
|
183
|
+
* @param {object} results - Validation results
|
|
184
|
+
* @param {boolean} verbose - Include detailed file lists
|
|
185
|
+
* @returns {string} - Formatted report
|
|
186
|
+
*/
|
|
187
|
+
function formatValidationReport(results, verbose = false) {
|
|
188
|
+
const lines = [];
|
|
189
|
+
|
|
190
|
+
lines.push('# IDE Sync Validation Report');
|
|
191
|
+
lines.push('');
|
|
192
|
+
|
|
193
|
+
// Summary
|
|
194
|
+
lines.push('## Summary');
|
|
195
|
+
lines.push('');
|
|
196
|
+
lines.push(`| Metric | Count |`);
|
|
197
|
+
lines.push(`|--------|-------|`);
|
|
198
|
+
lines.push(`| Total Expected | ${results.summary.total} |`);
|
|
199
|
+
lines.push(`| Synced | ${results.summary.synced} |`);
|
|
200
|
+
lines.push(`| Missing | ${results.summary.missing} |`);
|
|
201
|
+
lines.push(`| Drift | ${results.summary.drift} |`);
|
|
202
|
+
lines.push(`| Orphaned | ${results.summary.orphaned} |`);
|
|
203
|
+
lines.push('');
|
|
204
|
+
|
|
205
|
+
const status = results.summary.pass ? '✅ PASS' : '❌ FAIL';
|
|
206
|
+
lines.push(`**Status:** ${status}`);
|
|
207
|
+
lines.push('');
|
|
208
|
+
|
|
209
|
+
// Per-IDE details
|
|
210
|
+
if (verbose) {
|
|
211
|
+
lines.push('## IDE Details');
|
|
212
|
+
lines.push('');
|
|
213
|
+
|
|
214
|
+
for (const [ideName, ideResult] of Object.entries(results.ides)) {
|
|
215
|
+
lines.push(`### ${ideName}`);
|
|
216
|
+
lines.push('');
|
|
217
|
+
lines.push(`- Target: \`${ideResult.targetDir}\``);
|
|
218
|
+
lines.push(`- Synced: ${ideResult.total.synced}`);
|
|
219
|
+
lines.push(`- Missing: ${ideResult.total.missing}`);
|
|
220
|
+
lines.push(`- Drift: ${ideResult.total.drift}`);
|
|
221
|
+
lines.push(`- Orphaned: ${ideResult.total.orphaned}`);
|
|
222
|
+
lines.push('');
|
|
223
|
+
|
|
224
|
+
if (ideResult.missing.length > 0) {
|
|
225
|
+
lines.push('**Missing Files:**');
|
|
226
|
+
for (const f of ideResult.missing) {
|
|
227
|
+
lines.push(`- ${f.filename}`);
|
|
228
|
+
}
|
|
229
|
+
lines.push('');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (ideResult.drift.length > 0) {
|
|
233
|
+
lines.push('**Drifted Files:**');
|
|
234
|
+
for (const f of ideResult.drift) {
|
|
235
|
+
lines.push(`- ${f.filename}`);
|
|
236
|
+
}
|
|
237
|
+
lines.push('');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (ideResult.orphaned.length > 0) {
|
|
241
|
+
lines.push('**Orphaned Files:**');
|
|
242
|
+
for (const f of ideResult.orphaned) {
|
|
243
|
+
lines.push(`- ${f.filename}`);
|
|
244
|
+
}
|
|
245
|
+
lines.push('');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Fix instructions
|
|
251
|
+
if (!results.summary.pass) {
|
|
252
|
+
lines.push('## How to Fix');
|
|
253
|
+
lines.push('');
|
|
254
|
+
lines.push('Run the following command to sync IDE files:');
|
|
255
|
+
lines.push('');
|
|
256
|
+
lines.push('```bash');
|
|
257
|
+
lines.push('npm run sync:ide');
|
|
258
|
+
lines.push('```');
|
|
259
|
+
lines.push('');
|
|
260
|
+
lines.push('Then commit the generated files.');
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return lines.join('\n');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
module.exports = {
|
|
267
|
+
hashContent,
|
|
268
|
+
fileExists,
|
|
269
|
+
readFileIfExists,
|
|
270
|
+
validateIdeSync,
|
|
271
|
+
validateAllIdes,
|
|
272
|
+
formatValidationReport,
|
|
273
|
+
};
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
# - SHA256 hashes for change detection
|
|
8
8
|
# - File types for categorization
|
|
9
9
|
#
|
|
10
|
-
version: 3.
|
|
11
|
-
generated_at: "2025-12-
|
|
10
|
+
version: 3.4.0
|
|
11
|
+
generated_at: "2025-12-23T02:05:10.189Z"
|
|
12
12
|
generator: scripts/generate-install-manifest.js
|
|
13
|
-
file_count:
|
|
13
|
+
file_count: 564
|
|
14
14
|
files:
|
|
15
15
|
- path: cli/commands/generate/index.js
|
|
16
16
|
hash: sha256:36f8e38ab767fa5478d8dabac548c66dc2c0fc521c216e954ac33fcea0ba597b
|
|
@@ -165,9 +165,9 @@ files:
|
|
|
165
165
|
type: cli
|
|
166
166
|
size: 5907
|
|
167
167
|
- path: core-config.yaml
|
|
168
|
-
hash: sha256:
|
|
168
|
+
hash: sha256:238af11d4bd06c600b65aec6bad627ecd87c1d4c037447bb5aa7befd474ad2f1
|
|
169
169
|
type: config
|
|
170
|
-
size:
|
|
170
|
+
size: 15370
|
|
171
171
|
- path: core/config/config-cache.js
|
|
172
172
|
hash: sha256:527a788cbe650aa6b13d1101ebc16419489bfef20b2ee93042f6eb6a51e898e9
|
|
173
173
|
type: core
|
|
@@ -1368,6 +1368,42 @@ files:
|
|
|
1368
1368
|
hash: sha256:e4354cbceb1d3fe64f0a32b3b69e3f12e55f4a5770412b7cd31f92fe2cf3278c
|
|
1369
1369
|
type: script
|
|
1370
1370
|
size: 9735
|
|
1371
|
+
- path: infrastructure/scripts/ide-sync/agent-parser.js
|
|
1372
|
+
hash: sha256:f18531d68ffec3f661b81c528bff0929bac6fa26213f28affbfebb2faca091db
|
|
1373
|
+
type: script
|
|
1374
|
+
size: 7428
|
|
1375
|
+
- path: infrastructure/scripts/ide-sync/index.js
|
|
1376
|
+
hash: sha256:9e792b680a1ed19893d10fe27aa14f2ccf2235004d62f83bd052d2dde75c1aeb
|
|
1377
|
+
type: script
|
|
1378
|
+
size: 12879
|
|
1379
|
+
- path: infrastructure/scripts/ide-sync/redirect-generator.js
|
|
1380
|
+
hash: sha256:658725f2832d331ee83350e620e5a79a499492172fc8f44174749e3471feb77f
|
|
1381
|
+
type: script
|
|
1382
|
+
size: 4518
|
|
1383
|
+
- path: infrastructure/scripts/ide-sync/transformers/antigravity.js
|
|
1384
|
+
hash: sha256:f78399acdc7557f496abcffcd252e722e91f06afe16859b5066882954d9cd23e
|
|
1385
|
+
type: script
|
|
1386
|
+
size: 2687
|
|
1387
|
+
- path: infrastructure/scripts/ide-sync/transformers/claude-code.js
|
|
1388
|
+
hash: sha256:f028bdef022e54a5f70c92fa6d6b0dc0877c2fc87a9f8d2f477b29d09248dab7
|
|
1389
|
+
type: script
|
|
1390
|
+
size: 2225
|
|
1391
|
+
- path: infrastructure/scripts/ide-sync/transformers/cursor.js
|
|
1392
|
+
hash: sha256:957eb51c7c516f2a73ade0be38d25f97b5508f9816067bfe94ed23e7f17be265
|
|
1393
|
+
type: script
|
|
1394
|
+
size: 2321
|
|
1395
|
+
- path: infrastructure/scripts/ide-sync/transformers/trae.js
|
|
1396
|
+
hash: sha256:c3609987ed07d1c4959ef803548cbd224797db117affb8655c30c04ed524967a
|
|
1397
|
+
type: script
|
|
1398
|
+
size: 2895
|
|
1399
|
+
- path: infrastructure/scripts/ide-sync/transformers/windsurf.js
|
|
1400
|
+
hash: sha256:f0c6ad1cbab8618ea41572a4c667e13d471b49794f5508bc4f9184106f260342
|
|
1401
|
+
type: script
|
|
1402
|
+
size: 2636
|
|
1403
|
+
- path: infrastructure/scripts/ide-sync/validator.js
|
|
1404
|
+
hash: sha256:356c78125db7f88d14f4e521808e96593d729291c3d7a1c36cb02f78b4aef8fc
|
|
1405
|
+
type: script
|
|
1406
|
+
size: 7316
|
|
1371
1407
|
- path: infrastructure/scripts/improvement-engine.js
|
|
1372
1408
|
hash: sha256:2a132e285295fa9455f94c3b3cc2abf0c38a1dc2faa1197bdbe36d80dc69430c
|
|
1373
1409
|
type: script
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aios-core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.esm.js",
|
|
@@ -80,6 +80,12 @@
|
|
|
80
80
|
"release:test": "semantic-release --dry-run --no-ci || echo 'Config test complete - authentication errors are expected locally'",
|
|
81
81
|
"generate:manifest": "node scripts/generate-install-manifest.js",
|
|
82
82
|
"validate:manifest": "node scripts/validate-manifest.js",
|
|
83
|
+
"sync:ide": "node .aios-core/infrastructure/scripts/ide-sync/index.js sync",
|
|
84
|
+
"sync:ide:validate": "node .aios-core/infrastructure/scripts/ide-sync/index.js validate",
|
|
85
|
+
"sync:ide:check": "node .aios-core/infrastructure/scripts/ide-sync/index.js validate --strict",
|
|
86
|
+
"sync:ide:cursor": "node .aios-core/infrastructure/scripts/ide-sync/index.js sync --ide cursor",
|
|
87
|
+
"sync:ide:windsurf": "node .aios-core/infrastructure/scripts/ide-sync/index.js sync --ide windsurf",
|
|
88
|
+
"sync:ide:trae": "node .aios-core/infrastructure/scripts/ide-sync/index.js sync --ide trae",
|
|
83
89
|
"prepublishOnly": "npm run generate:manifest && npm run validate:manifest",
|
|
84
90
|
"prepare": "echo 'Skipping husky - not needed for NPM publish'"
|
|
85
91
|
},
|
|
@@ -156,6 +162,9 @@
|
|
|
156
162
|
],
|
|
157
163
|
"*.md": [
|
|
158
164
|
"prettier --write"
|
|
165
|
+
],
|
|
166
|
+
".aios-core/development/agents/*.md": [
|
|
167
|
+
"npm run sync:ide"
|
|
159
168
|
]
|
|
160
169
|
}
|
|
161
170
|
}
|