aios-core 4.1.0 → 4.2.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.
Files changed (145) hide show
  1. package/.aios-core/.session/current-session.json +14 -0
  2. package/.aios-core/core/registry/registry-schema.json +166 -166
  3. package/.aios-core/core/registry/service-registry.json +6585 -6585
  4. package/.aios-core/data/entity-registry.yaml +208 -8
  5. package/.aios-core/data/registry-update-log.jsonl +165 -0
  6. package/.aios-core/development/scripts/approval-workflow.js +642 -642
  7. package/.aios-core/development/scripts/backup-manager.js +606 -606
  8. package/.aios-core/development/scripts/branch-manager.js +389 -389
  9. package/.aios-core/development/scripts/code-quality-improver.js +1311 -1311
  10. package/.aios-core/development/scripts/commit-message-generator.js +849 -849
  11. package/.aios-core/development/scripts/conflict-resolver.js +674 -674
  12. package/.aios-core/development/scripts/dependency-analyzer.js +637 -637
  13. package/.aios-core/development/scripts/diff-generator.js +351 -351
  14. package/.aios-core/development/scripts/elicitation-engine.js +384 -384
  15. package/.aios-core/development/scripts/elicitation-session-manager.js +299 -299
  16. package/.aios-core/development/scripts/git-wrapper.js +461 -461
  17. package/.aios-core/development/scripts/manifest-preview.js +244 -244
  18. package/.aios-core/development/scripts/metrics-tracker.js +775 -775
  19. package/.aios-core/development/scripts/modification-validator.js +554 -554
  20. package/.aios-core/development/scripts/pattern-learner.js +1224 -1224
  21. package/.aios-core/development/scripts/performance-analyzer.js +757 -757
  22. package/.aios-core/development/scripts/refactoring-suggester.js +1138 -1138
  23. package/.aios-core/development/scripts/rollback-handler.js +530 -530
  24. package/.aios-core/development/scripts/security-checker.js +358 -358
  25. package/.aios-core/development/scripts/template-engine.js +239 -239
  26. package/.aios-core/development/scripts/template-validator.js +278 -278
  27. package/.aios-core/development/scripts/test-generator.js +843 -843
  28. package/.aios-core/development/scripts/transaction-manager.js +589 -589
  29. package/.aios-core/development/scripts/usage-tracker.js +673 -673
  30. package/.aios-core/development/scripts/validate-filenames.js +226 -226
  31. package/.aios-core/development/scripts/version-tracker.js +526 -526
  32. package/.aios-core/development/scripts/yaml-validator.js +396 -396
  33. package/.aios-core/development/tasks/validate-next-story.md +99 -2
  34. package/.aios-core/development/templates/service-template/README.md.hbs +158 -158
  35. package/.aios-core/development/templates/service-template/__tests__/index.test.ts.hbs +237 -237
  36. package/.aios-core/development/templates/service-template/client.ts.hbs +403 -403
  37. package/.aios-core/development/templates/service-template/errors.ts.hbs +182 -182
  38. package/.aios-core/development/templates/service-template/index.ts.hbs +120 -120
  39. package/.aios-core/development/templates/service-template/package.json.hbs +87 -87
  40. package/.aios-core/development/templates/service-template/types.ts.hbs +145 -145
  41. package/.aios-core/development/templates/squad-template/LICENSE +21 -21
  42. package/.aios-core/docs/SHARD-TRANSLATION-GUIDE.md +335 -0
  43. package/.aios-core/docs/component-creation-guide.md +458 -0
  44. package/.aios-core/docs/session-update-pattern.md +307 -0
  45. package/.aios-core/docs/standards/AIOS-FRAMEWORK-MASTER.md +1963 -0
  46. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-SUMMARY.md +1190 -0
  47. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1.md +439 -0
  48. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO.md +5398 -0
  49. package/.aios-core/docs/standards/V3-ARCHITECTURAL-DECISIONS.md +523 -0
  50. package/.aios-core/docs/template-syntax.md +267 -0
  51. package/.aios-core/docs/troubleshooting-guide.md +625 -0
  52. package/.aios-core/infrastructure/templates/aios-sync.yaml.template +193 -193
  53. package/.aios-core/infrastructure/templates/coderabbit.yaml.template +279 -279
  54. package/.aios-core/infrastructure/templates/github-workflows/ci.yml.template +169 -169
  55. package/.aios-core/infrastructure/templates/github-workflows/pr-automation.yml.template +330 -330
  56. package/.aios-core/infrastructure/templates/github-workflows/release.yml.template +196 -196
  57. package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +63 -63
  58. package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -18
  59. package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -85
  60. package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -145
  61. package/.aios-core/infrastructure/tests/utilities-audit-results.json +501 -0
  62. package/.aios-core/install-manifest.yaml +101 -101
  63. package/.aios-core/local-config.yaml.template +70 -70
  64. package/.aios-core/manifests/agents.csv +29 -0
  65. package/.aios-core/manifests/schema/manifest-schema.json +190 -190
  66. package/.aios-core/manifests/tasks.csv +198 -0
  67. package/.aios-core/manifests/workers.csv +204 -0
  68. package/.aios-core/monitor/hooks/lib/__init__.py +1 -1
  69. package/.aios-core/monitor/hooks/lib/enrich.py +58 -58
  70. package/.aios-core/monitor/hooks/lib/send_event.py +47 -47
  71. package/.aios-core/monitor/hooks/notification.py +29 -29
  72. package/.aios-core/monitor/hooks/post_tool_use.py +45 -45
  73. package/.aios-core/monitor/hooks/pre_compact.py +29 -29
  74. package/.aios-core/monitor/hooks/pre_tool_use.py +40 -40
  75. package/.aios-core/monitor/hooks/stop.py +29 -29
  76. package/.aios-core/monitor/hooks/subagent_stop.py +29 -29
  77. package/.aios-core/monitor/hooks/user_prompt_submit.py +38 -38
  78. package/.aios-core/product/templates/adr.hbs +125 -125
  79. package/.aios-core/product/templates/component-react-tmpl.tsx +98 -98
  80. package/.aios-core/product/templates/dbdr.hbs +241 -241
  81. package/.aios-core/product/templates/engine/schemas/adr.schema.json +102 -102
  82. package/.aios-core/product/templates/engine/schemas/dbdr.schema.json +205 -205
  83. package/.aios-core/product/templates/engine/schemas/epic.schema.json +175 -175
  84. package/.aios-core/product/templates/engine/schemas/pmdr.schema.json +175 -175
  85. package/.aios-core/product/templates/engine/schemas/prd-v2.schema.json +300 -300
  86. package/.aios-core/product/templates/engine/schemas/prd.schema.json +152 -152
  87. package/.aios-core/product/templates/engine/schemas/story.schema.json +222 -222
  88. package/.aios-core/product/templates/engine/schemas/task.schema.json +154 -154
  89. package/.aios-core/product/templates/epic.hbs +212 -212
  90. package/.aios-core/product/templates/eslintrc-security.json +32 -32
  91. package/.aios-core/product/templates/github-actions-cd.yml +212 -212
  92. package/.aios-core/product/templates/github-actions-ci.yml +172 -172
  93. package/.aios-core/product/templates/pmdr.hbs +186 -186
  94. package/.aios-core/product/templates/prd-v2.0.hbs +216 -216
  95. package/.aios-core/product/templates/prd.hbs +201 -201
  96. package/.aios-core/product/templates/shock-report-tmpl.html +502 -502
  97. package/.aios-core/product/templates/story.hbs +263 -263
  98. package/.aios-core/product/templates/task.hbs +170 -170
  99. package/.aios-core/product/templates/tmpl-comment-on-examples.sql +158 -158
  100. package/.aios-core/product/templates/tmpl-migration-script.sql +91 -91
  101. package/.aios-core/product/templates/tmpl-rls-granular-policies.sql +104 -104
  102. package/.aios-core/product/templates/tmpl-rls-kiss-policy.sql +10 -10
  103. package/.aios-core/product/templates/tmpl-rls-roles.sql +135 -135
  104. package/.aios-core/product/templates/tmpl-rls-simple.sql +77 -77
  105. package/.aios-core/product/templates/tmpl-rls-tenant.sql +152 -152
  106. package/.aios-core/product/templates/tmpl-rollback-script.sql +77 -77
  107. package/.aios-core/product/templates/tmpl-seed-data.sql +140 -140
  108. package/.aios-core/product/templates/tmpl-smoke-test.sql +16 -16
  109. package/.aios-core/product/templates/tmpl-staging-copy-merge.sql +139 -139
  110. package/.aios-core/product/templates/tmpl-stored-proc.sql +140 -140
  111. package/.aios-core/product/templates/tmpl-trigger.sql +152 -152
  112. package/.aios-core/product/templates/tmpl-view-materialized.sql +133 -133
  113. package/.aios-core/product/templates/tmpl-view.sql +177 -177
  114. package/.aios-core/product/templates/token-exports-css-tmpl.css +240 -240
  115. package/.aios-core/quality/schemas/quality-metrics.schema.json +233 -233
  116. package/.aios-core/scripts/migrate-framework-docs.sh +300 -300
  117. package/.aios-core/scripts/pm.sh +0 -0
  118. package/.claude/hooks/enforce-architecture-first.py +196 -196
  119. package/.claude/hooks/mind-clone-governance.py +192 -192
  120. package/.claude/hooks/read-protection.py +151 -151
  121. package/.claude/hooks/slug-validation.py +176 -176
  122. package/.claude/hooks/sql-governance.py +182 -182
  123. package/.claude/hooks/write-path-validation.py +194 -194
  124. package/.claude/rules/agent-authority.md +105 -0
  125. package/.claude/rules/coderabbit-integration.md +93 -0
  126. package/.claude/rules/ids-principles.md +112 -0
  127. package/.claude/rules/story-lifecycle.md +139 -0
  128. package/.claude/rules/workflow-execution.md +150 -0
  129. package/LICENSE +48 -48
  130. package/bin/aios-minimal.js +0 -0
  131. package/bin/aios.js +0 -0
  132. package/package.json +1 -1
  133. package/packages/aios-install/bin/aios-install.js +0 -0
  134. package/packages/aios-install/bin/edmcp.js +0 -0
  135. package/packages/aios-pro-cli/bin/aios-pro.js +0 -0
  136. package/packages/installer/src/wizard/pro-setup.js +433 -49
  137. package/scripts/check-markdown-links.py +352 -352
  138. package/scripts/code-intel-health-check.js +343 -0
  139. package/scripts/dashboard-parallel-dev.sh +0 -0
  140. package/scripts/dashboard-parallel-phase3.sh +0 -0
  141. package/scripts/dashboard-parallel-phase4.sh +0 -0
  142. package/scripts/glue/README.md +355 -0
  143. package/scripts/glue/compose-agent-prompt.cjs +362 -0
  144. package/scripts/install-monitor-hooks.sh +0 -0
  145. package/.aios-core/lib/build.json +0 -1
@@ -1,462 +1,462 @@
1
- const { exec } = require('child_process');
2
- const { promisify } = require('util');
3
- const execAsync = promisify(exec);
4
- const _path = require('path');
5
- const _fs = require('fs').promises;
6
- const chalk = require('chalk');
7
-
8
- /**
9
- * Git operations wrapper for AIOS framework modifications
10
- */
11
- class GitWrapper {
12
- constructor(options = {}) {
13
- this.rootPath = options.rootPath || process.cwd();
14
- this.gitPath = options.gitPath || 'git';
15
- this.defaultBranch = options.defaultBranch || 'main';
16
- this.metaAgentPrefix = options.metaAgentPrefix || 'meta-agent/';
17
- }
18
-
19
- /**
20
- * Execute a git command
21
- * @private
22
- */
23
- async execGit(command, options = {}) {
24
- try {
25
- const { stdout, stderr } = await execAsync(`${this.gitPath} ${command}`, {
26
- cwd: this.rootPath,
27
- ...options
28
- });
29
-
30
- if (stderr && !options.ignoreStderr) {
31
- console.warn(chalk.yellow(`Git warning: ${stderr}`));
32
- }
33
-
34
- return stdout.trim();
35
- } catch (_error) {
36
- throw new Error(`Git command failed: ${error.message}`);
37
- }
38
- }
39
-
40
- /**
41
- * Check if git is initialized
42
- * @returns {Promise<boolean>}
43
- */
44
- async isGitInitialized() {
45
- try {
46
- await this.execGit('status');
47
- return true;
48
- } catch (_error) {
49
- return false;
50
- }
51
- }
52
-
53
- /**
54
- * Initialize git repository if not already initialized
55
- * @returns {Promise<void>}
56
- */
57
- async initializeRepository() {
58
- const initialized = await this.isGitInitialized();
59
- if (!initialized) {
60
- await this.execGit('init');
61
- console.log(chalk.green('✅ Git repository initialized'));
62
- }
63
- }
64
-
65
- /**
66
- * Get current branch name
67
- * @returns {Promise<string>}
68
- */
69
- async getCurrentBranch() {
70
- return await this.execGit('rev-parse --abbrev-ref HEAD');
71
- }
72
-
73
- /**
74
- * Create a new branch
75
- * @param {string} branchName - Name of the branch to create
76
- * @param {boolean} checkout - Whether to checkout the branch
77
- * @returns {Promise<void>}
78
- */
79
- async createBranch(branchName, checkout = true) {
80
- try {
81
- if (checkout) {
82
- await this.execGit(`checkout -b ${branchName}`);
83
- } else {
84
- await this.execGit(`branch ${branchName}`);
85
- }
86
- console.log(chalk.green(`✅ Created branch: ${branchName}`));
87
- } catch (_error) {
88
- // Branch might already exist
89
- if (error.message.includes('already exists')) {
90
- console.log(chalk.yellow(`Branch already exists: ${branchName}`));
91
- if (checkout) {
92
- await this.checkoutBranch(branchName);
93
- }
94
- } else {
95
- throw error;
96
- }
97
- }
98
- }
99
-
100
- /**
101
- * Checkout an existing branch
102
- * @param {string} branchName - Name of the branch to checkout
103
- * @returns {Promise<void>}
104
- */
105
- async checkoutBranch(branchName) {
106
- await this.execGit(`checkout ${branchName}`);
107
- console.log(chalk.green(`✅ Checked out branch: ${branchName}`));
108
- }
109
-
110
- /**
111
- * Create a branch for meta-agent modifications
112
- * @param {string} modificationName - Name of the modification
113
- * @returns {Promise<string>} Branch name
114
- */
115
- async createModificationBranch(modificationName) {
116
- const timestamp = new Date().toISOString().substring(0, 10);
117
- const branchName = `${this.metaAgentPrefix}${modificationName}-${timestamp}`;
118
- await this.createBranch(branchName);
119
- return branchName;
120
- }
121
-
122
- /**
123
- * Stage files for commit
124
- * @param {Array<string>} files - Files to stage
125
- * @returns {Promise<void>}
126
- */
127
- async stageFiles(files) {
128
- if (!Array.isArray(files) || files.length === 0) {
129
- throw new Error('No files provided to stage');
130
- }
131
-
132
- for (const file of files) {
133
- await this.execGit(`add "${file}"`);
134
- }
135
-
136
- console.log(chalk.green(`✅ Staged ${files.length} files`));
137
- }
138
-
139
- /**
140
- * Commit changes with message
141
- * @param {string} message - Commit message
142
- * @param {Object} options - Commit options
143
- * @returns {Promise<string>} Commit hash
144
- */
145
- async commit(message, options = {}) {
146
- const {
147
- author = 'aios-developer <aios-developer@aios-fullstack.local>',
148
- signoff = true
149
- } = options;
150
-
151
- let command = `commit -m "${message.replace(/"/g, '\\"')}"`;
152
-
153
- if (author) {
154
- command += ` --author="${author}"`;
155
- }
156
-
157
- if (signoff) {
158
- command += ' --signoff';
159
- }
160
-
161
- const output = await this.execGit(command);
162
- const hashMatch = output.match(/\[[\w-]+ ([\w]+)\]/);
163
- const commitHash = hashMatch ? hashMatch[1] : 'unknown';
164
-
165
- console.log(chalk.green(`✅ Committed: ${commitHash}`));
166
- return commitHash;
167
- }
168
-
169
- /**
170
- * Create a commit for component modifications
171
- * @param {Array<string>} files - Files to commit
172
- * @param {string} message - Commit message
173
- * @param {Object} metadata - Additional metadata
174
- * @returns {Promise<string>} Commit hash
175
- */
176
- async commitModification(files, message, metadata = {}) {
177
- await this.stageFiles(files);
178
-
179
- // Add metadata to commit message
180
- let fullMessage = message;
181
- if (metadata.componentType && metadata.componentName) {
182
- fullMessage = `${metadata.componentType}(${metadata.componentName}): ${message}`;
183
- }
184
-
185
- if (metadata.breakingChange) {
186
- fullMessage += '\n\nBREAKING CHANGE: ' + metadata.breakingChange;
187
- }
188
-
189
- if (metadata.approvedBy) {
190
- fullMessage += `\n\nApproved-by: ${metadata.approvedBy}`;
191
- }
192
-
193
- fullMessage += '\n\nGenerated by: aios-developer meta-agent';
194
-
195
- return await this.commit(fullMessage);
196
- }
197
-
198
- /**
199
- * Get git status
200
- * @returns {Promise<Object>} Status information
201
- */
202
- async getStatus() {
203
- const porcelainStatus = await this.execGit('status --porcelain');
204
- const branch = await this.getCurrentBranch();
205
-
206
- const files = {
207
- modified: [],
208
- added: [],
209
- deleted: [],
210
- untracked: []
211
- };
212
-
213
- if (porcelainStatus) {
214
- const lines = porcelainStatus.split('\n');
215
- for (const line of lines) {
216
- if (!line) continue;
217
-
218
- const status = line.substring(0, 2);
219
- const filename = line.substring(3);
220
-
221
- if (status.includes('M')) files.modified.push(filename);
222
- else if (status.includes('A')) files.added.push(filename);
223
- else if (status.includes('D')) files.deleted.push(filename);
224
- else if (status === '??') files.untracked.push(filename);
225
- }
226
- }
227
-
228
- return {
229
- branch,
230
- clean: porcelainStatus === '',
231
- files
232
- };
233
- }
234
-
235
- /**
236
- * Get commit history
237
- * @param {number} limit - Number of commits to retrieve
238
- * @returns {Promise<Array>} Commit history
239
- */
240
- async getHistory(limit = 10) {
241
- const format = '%H|%an|%ae|%at|%s';
242
- const output = await this.execGit(`log -${limit} --format="${format}"`);
243
-
244
- if (!output) return [];
245
-
246
- return output.split('\n').map(line => {
247
- const [hash, author, email, timestamp, subject] = line.split('|');
248
- return {
249
- hash,
250
- author,
251
- email,
252
- date: new Date(parseInt(timestamp) * 1000),
253
- subject
254
- };
255
- });
256
- }
257
-
258
- /**
259
- * Check for conflicts
260
- * @returns {Promise<Array>} List of conflicted files
261
- */
262
- async getConflicts() {
263
- try {
264
- const output = await this.execGit('diff --name-only --diff-filter=U');
265
- return output ? output.split('\n').filter(Boolean) : [];
266
- } catch (_error) {
267
- return [];
268
- }
269
- }
270
-
271
- /**
272
- * Merge a branch
273
- * @param {string} branchName - Branch to merge
274
- * @param {Object} options - Merge options
275
- * @returns {Promise<Object>} Merge result
276
- */
277
- async mergeBranch(branchName, options = {}) {
278
- const {
279
- strategy = 'recursive',
280
- message = null,
281
- noFastForward = true
282
- } = options;
283
-
284
- let command = `merge ${branchName}`;
285
-
286
- if (strategy) {
287
- command += ` --strategy=${strategy}`;
288
- }
289
-
290
- if (noFastForward) {
291
- command += ' --no-ff';
292
- }
293
-
294
- if (message) {
295
- command += ` -m "${message.replace(/"/g, '\\"')}"`;
296
- }
297
-
298
- try {
299
- const output = await this.execGit(command);
300
- return {
301
- success: true,
302
- message: output
303
- };
304
- } catch (_error) {
305
- // Check for conflicts
306
- const conflicts = await this.getConflicts();
307
- if (conflicts.length > 0) {
308
- return {
309
- success: false,
310
- conflicts,
311
- error: 'Merge conflicts detected'
312
- };
313
- }
314
- throw error;
315
- }
316
- }
317
-
318
- /**
319
- * Create a tag
320
- * @param {string} tagName - Name of the tag
321
- * @param {string} message - Tag message
322
- * @returns {Promise<void>}
323
- */
324
- async createTag(tagName, message) {
325
- await this.execGit(`tag -a ${tagName} -m "${message.replace(/"/g, '\\"')}"`);
326
- console.log(chalk.green(`✅ Created tag: ${tagName}`));
327
- }
328
-
329
- /**
330
- * Push changes to remote
331
- * @param {string} remote - Remote name
332
- * @param {string} branch - Branch name
333
- * @param {Object} options - Push options
334
- * @returns {Promise<void>}
335
- */
336
- async push(remote = 'origin', branch = null, options = {}) {
337
- const currentBranch = branch || await this.getCurrentBranch();
338
- let command = `push ${remote} ${currentBranch}`;
339
-
340
- if (options.tags) {
341
- command += ' --tags';
342
- }
343
-
344
- if (options.force) {
345
- command += ' --force';
346
- }
347
-
348
- if (options.setUpstream) {
349
- command = `push -u ${remote} ${currentBranch}`;
350
- }
351
-
352
- await this.execGit(command);
353
- console.log(chalk.green(`✅ Pushed to ${remote}/${currentBranch}`));
354
- }
355
-
356
- /**
357
- * Get diff between commits or working tree
358
- * @param {Object} options - Diff options
359
- * @returns {Promise<string>} Diff output
360
- */
361
- async getDiff(options = {}) {
362
- const {
363
- from = 'HEAD',
364
- to = null,
365
- files = [],
366
- nameOnly = false
367
- } = options;
368
-
369
- let command = 'diff';
370
-
371
- if (nameOnly) {
372
- command += ' --name-only';
373
- }
374
-
375
- if (to) {
376
- command += ` ${from} ${to}`;
377
- } else {
378
- command += ` ${from}`;
379
- }
380
-
381
- if (files.length > 0) {
382
- command += ` -- ${files.join(' ')}`;
383
- }
384
-
385
- return await this.execGit(command);
386
- }
387
-
388
- /**
389
- * Stash changes
390
- * @param {string} message - Stash message
391
- * @returns {Promise<void>}
392
- */
393
- async stash(message = 'Meta-agent modifications') {
394
- await this.execGit(`stash push -m "${message}"`);
395
- console.log(chalk.green('✅ Changes stashed'));
396
- }
397
-
398
- /**
399
- * Apply stash
400
- * @param {string} stashRef - Stash reference
401
- * @returns {Promise<void>}
402
- */
403
- async stashApply(stashRef = 'stash@{0}') {
404
- await this.execGit(`stash apply ${stashRef}`);
405
- console.log(chalk.green('✅ Stash applied'));
406
- }
407
-
408
- /**
409
- * Get remote information
410
- * @returns {Promise<Array>} Remote information
411
- */
412
- async getRemotes() {
413
- const output = await this.execGit('remote -v');
414
- if (!output) return [];
415
-
416
- const remotes = {};
417
- output.split('\n').forEach(line => {
418
- const [name, url, type] = line.split(/\s+/);
419
- if (!remotes[name]) {
420
- remotes[name] = {};
421
- }
422
- remotes[name][type.replace(/[()]/g, '')] = url;
423
- });
424
-
425
- return Object.entries(remotes).map(([name, urls]) => ({
426
- name,
427
- fetchUrl: urls.fetch,
428
- pushUrl: urls.push
429
- }));
430
- }
431
-
432
- /**
433
- * Generate commit message for modifications
434
- * @param {Object} modification - Modification details
435
- * @returns {string} Generated commit message
436
- */
437
- generateCommitMessage(modification) {
438
- const {
439
- action,
440
- componentType,
441
- _componentName,
442
- summary,
443
- details = [],
444
- breakingChanges = []
445
- } = modification;
446
-
447
- let message = `${action}(${componentType}): ${summary}`;
448
-
449
- if (details.length > 0) {
450
- message += '\n\n' + details.map(d => `- ${d}`).join('\n');
451
- }
452
-
453
- if (breakingChanges.length > 0) {
454
- message += '\n\nBREAKING CHANGES:\n' +
455
- breakingChanges.map(bc => `- ${bc}`).join('\n');
456
- }
457
-
458
- return message;
459
- }
460
- }
461
-
1
+ const { exec } = require('child_process');
2
+ const { promisify } = require('util');
3
+ const execAsync = promisify(exec);
4
+ const _path = require('path');
5
+ const _fs = require('fs').promises;
6
+ const chalk = require('chalk');
7
+
8
+ /**
9
+ * Git operations wrapper for AIOS framework modifications
10
+ */
11
+ class GitWrapper {
12
+ constructor(options = {}) {
13
+ this.rootPath = options.rootPath || process.cwd();
14
+ this.gitPath = options.gitPath || 'git';
15
+ this.defaultBranch = options.defaultBranch || 'main';
16
+ this.metaAgentPrefix = options.metaAgentPrefix || 'meta-agent/';
17
+ }
18
+
19
+ /**
20
+ * Execute a git command
21
+ * @private
22
+ */
23
+ async execGit(command, options = {}) {
24
+ try {
25
+ const { stdout, stderr } = await execAsync(`${this.gitPath} ${command}`, {
26
+ cwd: this.rootPath,
27
+ ...options
28
+ });
29
+
30
+ if (stderr && !options.ignoreStderr) {
31
+ console.warn(chalk.yellow(`Git warning: ${stderr}`));
32
+ }
33
+
34
+ return stdout.trim();
35
+ } catch (_error) {
36
+ throw new Error(`Git command failed: ${error.message}`);
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Check if git is initialized
42
+ * @returns {Promise<boolean>}
43
+ */
44
+ async isGitInitialized() {
45
+ try {
46
+ await this.execGit('status');
47
+ return true;
48
+ } catch (_error) {
49
+ return false;
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Initialize git repository if not already initialized
55
+ * @returns {Promise<void>}
56
+ */
57
+ async initializeRepository() {
58
+ const initialized = await this.isGitInitialized();
59
+ if (!initialized) {
60
+ await this.execGit('init');
61
+ console.log(chalk.green('✅ Git repository initialized'));
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Get current branch name
67
+ * @returns {Promise<string>}
68
+ */
69
+ async getCurrentBranch() {
70
+ return await this.execGit('rev-parse --abbrev-ref HEAD');
71
+ }
72
+
73
+ /**
74
+ * Create a new branch
75
+ * @param {string} branchName - Name of the branch to create
76
+ * @param {boolean} checkout - Whether to checkout the branch
77
+ * @returns {Promise<void>}
78
+ */
79
+ async createBranch(branchName, checkout = true) {
80
+ try {
81
+ if (checkout) {
82
+ await this.execGit(`checkout -b ${branchName}`);
83
+ } else {
84
+ await this.execGit(`branch ${branchName}`);
85
+ }
86
+ console.log(chalk.green(`✅ Created branch: ${branchName}`));
87
+ } catch (_error) {
88
+ // Branch might already exist
89
+ if (error.message.includes('already exists')) {
90
+ console.log(chalk.yellow(`Branch already exists: ${branchName}`));
91
+ if (checkout) {
92
+ await this.checkoutBranch(branchName);
93
+ }
94
+ } else {
95
+ throw error;
96
+ }
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Checkout an existing branch
102
+ * @param {string} branchName - Name of the branch to checkout
103
+ * @returns {Promise<void>}
104
+ */
105
+ async checkoutBranch(branchName) {
106
+ await this.execGit(`checkout ${branchName}`);
107
+ console.log(chalk.green(`✅ Checked out branch: ${branchName}`));
108
+ }
109
+
110
+ /**
111
+ * Create a branch for meta-agent modifications
112
+ * @param {string} modificationName - Name of the modification
113
+ * @returns {Promise<string>} Branch name
114
+ */
115
+ async createModificationBranch(modificationName) {
116
+ const timestamp = new Date().toISOString().substring(0, 10);
117
+ const branchName = `${this.metaAgentPrefix}${modificationName}-${timestamp}`;
118
+ await this.createBranch(branchName);
119
+ return branchName;
120
+ }
121
+
122
+ /**
123
+ * Stage files for commit
124
+ * @param {Array<string>} files - Files to stage
125
+ * @returns {Promise<void>}
126
+ */
127
+ async stageFiles(files) {
128
+ if (!Array.isArray(files) || files.length === 0) {
129
+ throw new Error('No files provided to stage');
130
+ }
131
+
132
+ for (const file of files) {
133
+ await this.execGit(`add "${file}"`);
134
+ }
135
+
136
+ console.log(chalk.green(`✅ Staged ${files.length} files`));
137
+ }
138
+
139
+ /**
140
+ * Commit changes with message
141
+ * @param {string} message - Commit message
142
+ * @param {Object} options - Commit options
143
+ * @returns {Promise<string>} Commit hash
144
+ */
145
+ async commit(message, options = {}) {
146
+ const {
147
+ author = 'aios-developer <aios-developer@aios-fullstack.local>',
148
+ signoff = true
149
+ } = options;
150
+
151
+ let command = `commit -m "${message.replace(/"/g, '\\"')}"`;
152
+
153
+ if (author) {
154
+ command += ` --author="${author}"`;
155
+ }
156
+
157
+ if (signoff) {
158
+ command += ' --signoff';
159
+ }
160
+
161
+ const output = await this.execGit(command);
162
+ const hashMatch = output.match(/\[[\w-]+ ([\w]+)\]/);
163
+ const commitHash = hashMatch ? hashMatch[1] : 'unknown';
164
+
165
+ console.log(chalk.green(`✅ Committed: ${commitHash}`));
166
+ return commitHash;
167
+ }
168
+
169
+ /**
170
+ * Create a commit for component modifications
171
+ * @param {Array<string>} files - Files to commit
172
+ * @param {string} message - Commit message
173
+ * @param {Object} metadata - Additional metadata
174
+ * @returns {Promise<string>} Commit hash
175
+ */
176
+ async commitModification(files, message, metadata = {}) {
177
+ await this.stageFiles(files);
178
+
179
+ // Add metadata to commit message
180
+ let fullMessage = message;
181
+ if (metadata.componentType && metadata.componentName) {
182
+ fullMessage = `${metadata.componentType}(${metadata.componentName}): ${message}`;
183
+ }
184
+
185
+ if (metadata.breakingChange) {
186
+ fullMessage += '\n\nBREAKING CHANGE: ' + metadata.breakingChange;
187
+ }
188
+
189
+ if (metadata.approvedBy) {
190
+ fullMessage += `\n\nApproved-by: ${metadata.approvedBy}`;
191
+ }
192
+
193
+ fullMessage += '\n\nGenerated by: aios-developer meta-agent';
194
+
195
+ return await this.commit(fullMessage);
196
+ }
197
+
198
+ /**
199
+ * Get git status
200
+ * @returns {Promise<Object>} Status information
201
+ */
202
+ async getStatus() {
203
+ const porcelainStatus = await this.execGit('status --porcelain');
204
+ const branch = await this.getCurrentBranch();
205
+
206
+ const files = {
207
+ modified: [],
208
+ added: [],
209
+ deleted: [],
210
+ untracked: []
211
+ };
212
+
213
+ if (porcelainStatus) {
214
+ const lines = porcelainStatus.split('\n');
215
+ for (const line of lines) {
216
+ if (!line) continue;
217
+
218
+ const status = line.substring(0, 2);
219
+ const filename = line.substring(3);
220
+
221
+ if (status.includes('M')) files.modified.push(filename);
222
+ else if (status.includes('A')) files.added.push(filename);
223
+ else if (status.includes('D')) files.deleted.push(filename);
224
+ else if (status === '??') files.untracked.push(filename);
225
+ }
226
+ }
227
+
228
+ return {
229
+ branch,
230
+ clean: porcelainStatus === '',
231
+ files
232
+ };
233
+ }
234
+
235
+ /**
236
+ * Get commit history
237
+ * @param {number} limit - Number of commits to retrieve
238
+ * @returns {Promise<Array>} Commit history
239
+ */
240
+ async getHistory(limit = 10) {
241
+ const format = '%H|%an|%ae|%at|%s';
242
+ const output = await this.execGit(`log -${limit} --format="${format}"`);
243
+
244
+ if (!output) return [];
245
+
246
+ return output.split('\n').map(line => {
247
+ const [hash, author, email, timestamp, subject] = line.split('|');
248
+ return {
249
+ hash,
250
+ author,
251
+ email,
252
+ date: new Date(parseInt(timestamp) * 1000),
253
+ subject
254
+ };
255
+ });
256
+ }
257
+
258
+ /**
259
+ * Check for conflicts
260
+ * @returns {Promise<Array>} List of conflicted files
261
+ */
262
+ async getConflicts() {
263
+ try {
264
+ const output = await this.execGit('diff --name-only --diff-filter=U');
265
+ return output ? output.split('\n').filter(Boolean) : [];
266
+ } catch (_error) {
267
+ return [];
268
+ }
269
+ }
270
+
271
+ /**
272
+ * Merge a branch
273
+ * @param {string} branchName - Branch to merge
274
+ * @param {Object} options - Merge options
275
+ * @returns {Promise<Object>} Merge result
276
+ */
277
+ async mergeBranch(branchName, options = {}) {
278
+ const {
279
+ strategy = 'recursive',
280
+ message = null,
281
+ noFastForward = true
282
+ } = options;
283
+
284
+ let command = `merge ${branchName}`;
285
+
286
+ if (strategy) {
287
+ command += ` --strategy=${strategy}`;
288
+ }
289
+
290
+ if (noFastForward) {
291
+ command += ' --no-ff';
292
+ }
293
+
294
+ if (message) {
295
+ command += ` -m "${message.replace(/"/g, '\\"')}"`;
296
+ }
297
+
298
+ try {
299
+ const output = await this.execGit(command);
300
+ return {
301
+ success: true,
302
+ message: output
303
+ };
304
+ } catch (_error) {
305
+ // Check for conflicts
306
+ const conflicts = await this.getConflicts();
307
+ if (conflicts.length > 0) {
308
+ return {
309
+ success: false,
310
+ conflicts,
311
+ error: 'Merge conflicts detected'
312
+ };
313
+ }
314
+ throw error;
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Create a tag
320
+ * @param {string} tagName - Name of the tag
321
+ * @param {string} message - Tag message
322
+ * @returns {Promise<void>}
323
+ */
324
+ async createTag(tagName, message) {
325
+ await this.execGit(`tag -a ${tagName} -m "${message.replace(/"/g, '\\"')}"`);
326
+ console.log(chalk.green(`✅ Created tag: ${tagName}`));
327
+ }
328
+
329
+ /**
330
+ * Push changes to remote
331
+ * @param {string} remote - Remote name
332
+ * @param {string} branch - Branch name
333
+ * @param {Object} options - Push options
334
+ * @returns {Promise<void>}
335
+ */
336
+ async push(remote = 'origin', branch = null, options = {}) {
337
+ const currentBranch = branch || await this.getCurrentBranch();
338
+ let command = `push ${remote} ${currentBranch}`;
339
+
340
+ if (options.tags) {
341
+ command += ' --tags';
342
+ }
343
+
344
+ if (options.force) {
345
+ command += ' --force';
346
+ }
347
+
348
+ if (options.setUpstream) {
349
+ command = `push -u ${remote} ${currentBranch}`;
350
+ }
351
+
352
+ await this.execGit(command);
353
+ console.log(chalk.green(`✅ Pushed to ${remote}/${currentBranch}`));
354
+ }
355
+
356
+ /**
357
+ * Get diff between commits or working tree
358
+ * @param {Object} options - Diff options
359
+ * @returns {Promise<string>} Diff output
360
+ */
361
+ async getDiff(options = {}) {
362
+ const {
363
+ from = 'HEAD',
364
+ to = null,
365
+ files = [],
366
+ nameOnly = false
367
+ } = options;
368
+
369
+ let command = 'diff';
370
+
371
+ if (nameOnly) {
372
+ command += ' --name-only';
373
+ }
374
+
375
+ if (to) {
376
+ command += ` ${from} ${to}`;
377
+ } else {
378
+ command += ` ${from}`;
379
+ }
380
+
381
+ if (files.length > 0) {
382
+ command += ` -- ${files.join(' ')}`;
383
+ }
384
+
385
+ return await this.execGit(command);
386
+ }
387
+
388
+ /**
389
+ * Stash changes
390
+ * @param {string} message - Stash message
391
+ * @returns {Promise<void>}
392
+ */
393
+ async stash(message = 'Meta-agent modifications') {
394
+ await this.execGit(`stash push -m "${message}"`);
395
+ console.log(chalk.green('✅ Changes stashed'));
396
+ }
397
+
398
+ /**
399
+ * Apply stash
400
+ * @param {string} stashRef - Stash reference
401
+ * @returns {Promise<void>}
402
+ */
403
+ async stashApply(stashRef = 'stash@{0}') {
404
+ await this.execGit(`stash apply ${stashRef}`);
405
+ console.log(chalk.green('✅ Stash applied'));
406
+ }
407
+
408
+ /**
409
+ * Get remote information
410
+ * @returns {Promise<Array>} Remote information
411
+ */
412
+ async getRemotes() {
413
+ const output = await this.execGit('remote -v');
414
+ if (!output) return [];
415
+
416
+ const remotes = {};
417
+ output.split('\n').forEach(line => {
418
+ const [name, url, type] = line.split(/\s+/);
419
+ if (!remotes[name]) {
420
+ remotes[name] = {};
421
+ }
422
+ remotes[name][type.replace(/[()]/g, '')] = url;
423
+ });
424
+
425
+ return Object.entries(remotes).map(([name, urls]) => ({
426
+ name,
427
+ fetchUrl: urls.fetch,
428
+ pushUrl: urls.push
429
+ }));
430
+ }
431
+
432
+ /**
433
+ * Generate commit message for modifications
434
+ * @param {Object} modification - Modification details
435
+ * @returns {string} Generated commit message
436
+ */
437
+ generateCommitMessage(modification) {
438
+ const {
439
+ action,
440
+ componentType,
441
+ _componentName,
442
+ summary,
443
+ details = [],
444
+ breakingChanges = []
445
+ } = modification;
446
+
447
+ let message = `${action}(${componentType}): ${summary}`;
448
+
449
+ if (details.length > 0) {
450
+ message += '\n\n' + details.map(d => `- ${d}`).join('\n');
451
+ }
452
+
453
+ if (breakingChanges.length > 0) {
454
+ message += '\n\nBREAKING CHANGES:\n' +
455
+ breakingChanges.map(bc => `- ${bc}`).join('\n');
456
+ }
457
+
458
+ return message;
459
+ }
460
+ }
461
+
462
462
  module.exports = GitWrapper;