aios-core 4.0.2 → 4.0.4

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/registry-update-log.jsonl +113 -0
  5. package/.aios-core/development/scripts/approval-workflow.js +642 -642
  6. package/.aios-core/development/scripts/backup-manager.js +606 -606
  7. package/.aios-core/development/scripts/branch-manager.js +389 -389
  8. package/.aios-core/development/scripts/code-quality-improver.js +1311 -1311
  9. package/.aios-core/development/scripts/commit-message-generator.js +849 -849
  10. package/.aios-core/development/scripts/conflict-resolver.js +674 -674
  11. package/.aios-core/development/scripts/dependency-analyzer.js +637 -637
  12. package/.aios-core/development/scripts/diff-generator.js +351 -351
  13. package/.aios-core/development/scripts/elicitation-engine.js +384 -384
  14. package/.aios-core/development/scripts/elicitation-session-manager.js +299 -299
  15. package/.aios-core/development/scripts/git-wrapper.js +461 -461
  16. package/.aios-core/development/scripts/manifest-preview.js +244 -244
  17. package/.aios-core/development/scripts/metrics-tracker.js +775 -775
  18. package/.aios-core/development/scripts/modification-validator.js +554 -554
  19. package/.aios-core/development/scripts/pattern-learner.js +1224 -1224
  20. package/.aios-core/development/scripts/performance-analyzer.js +757 -757
  21. package/.aios-core/development/scripts/refactoring-suggester.js +1138 -1138
  22. package/.aios-core/development/scripts/rollback-handler.js +530 -530
  23. package/.aios-core/development/scripts/security-checker.js +358 -358
  24. package/.aios-core/development/scripts/template-engine.js +239 -239
  25. package/.aios-core/development/scripts/template-validator.js +278 -278
  26. package/.aios-core/development/scripts/test-generator.js +843 -843
  27. package/.aios-core/development/scripts/transaction-manager.js +589 -589
  28. package/.aios-core/development/scripts/usage-tracker.js +673 -673
  29. package/.aios-core/development/scripts/validate-filenames.js +226 -226
  30. package/.aios-core/development/scripts/version-tracker.js +526 -526
  31. package/.aios-core/development/scripts/yaml-validator.js +396 -396
  32. package/.aios-core/development/templates/service-template/README.md.hbs +158 -158
  33. package/.aios-core/development/templates/service-template/__tests__/index.test.ts.hbs +237 -237
  34. package/.aios-core/development/templates/service-template/client.ts.hbs +403 -403
  35. package/.aios-core/development/templates/service-template/errors.ts.hbs +182 -182
  36. package/.aios-core/development/templates/service-template/index.ts.hbs +120 -120
  37. package/.aios-core/development/templates/service-template/package.json.hbs +87 -87
  38. package/.aios-core/development/templates/service-template/types.ts.hbs +145 -145
  39. package/.aios-core/development/templates/squad-template/LICENSE +21 -21
  40. package/.aios-core/docs/SHARD-TRANSLATION-GUIDE.md +335 -0
  41. package/.aios-core/docs/component-creation-guide.md +458 -0
  42. package/.aios-core/docs/session-update-pattern.md +307 -0
  43. package/.aios-core/docs/standards/AIOS-FRAMEWORK-MASTER.md +1963 -0
  44. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-SUMMARY.md +1190 -0
  45. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1.md +439 -0
  46. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO.md +5398 -0
  47. package/.aios-core/docs/standards/V3-ARCHITECTURAL-DECISIONS.md +523 -0
  48. package/.aios-core/docs/template-syntax.md +267 -0
  49. package/.aios-core/docs/troubleshooting-guide.md +625 -0
  50. package/.aios-core/infrastructure/templates/aios-sync.yaml.template +193 -193
  51. package/.aios-core/infrastructure/templates/coderabbit.yaml.template +279 -279
  52. package/.aios-core/infrastructure/templates/github-workflows/ci.yml.template +169 -169
  53. package/.aios-core/infrastructure/templates/github-workflows/pr-automation.yml.template +330 -330
  54. package/.aios-core/infrastructure/templates/github-workflows/release.yml.template +196 -196
  55. package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +63 -63
  56. package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -18
  57. package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -85
  58. package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -145
  59. package/.aios-core/infrastructure/tests/utilities-audit-results.json +501 -0
  60. package/.aios-core/install-manifest.yaml +97 -97
  61. package/.aios-core/local-config.yaml.template +68 -68
  62. package/.aios-core/manifests/agents.csv +1 -0
  63. package/.aios-core/manifests/schema/manifest-schema.json +190 -190
  64. package/.aios-core/manifests/tasks.csv +121 -0
  65. package/.aios-core/manifests/workers.csv +204 -0
  66. package/.aios-core/monitor/hooks/lib/__init__.py +1 -1
  67. package/.aios-core/monitor/hooks/lib/enrich.py +58 -58
  68. package/.aios-core/monitor/hooks/lib/send_event.py +47 -47
  69. package/.aios-core/monitor/hooks/notification.py +29 -29
  70. package/.aios-core/monitor/hooks/post_tool_use.py +45 -45
  71. package/.aios-core/monitor/hooks/pre_compact.py +29 -29
  72. package/.aios-core/monitor/hooks/pre_tool_use.py +40 -40
  73. package/.aios-core/monitor/hooks/stop.py +29 -29
  74. package/.aios-core/monitor/hooks/subagent_stop.py +29 -29
  75. package/.aios-core/monitor/hooks/user_prompt_submit.py +38 -38
  76. package/.aios-core/product/templates/adr.hbs +125 -125
  77. package/.aios-core/product/templates/component-react-tmpl.tsx +98 -98
  78. package/.aios-core/product/templates/dbdr.hbs +241 -241
  79. package/.aios-core/product/templates/engine/schemas/adr.schema.json +102 -102
  80. package/.aios-core/product/templates/engine/schemas/dbdr.schema.json +205 -205
  81. package/.aios-core/product/templates/engine/schemas/epic.schema.json +175 -175
  82. package/.aios-core/product/templates/engine/schemas/pmdr.schema.json +175 -175
  83. package/.aios-core/product/templates/engine/schemas/prd-v2.schema.json +300 -300
  84. package/.aios-core/product/templates/engine/schemas/prd.schema.json +152 -152
  85. package/.aios-core/product/templates/engine/schemas/story.schema.json +222 -222
  86. package/.aios-core/product/templates/engine/schemas/task.schema.json +154 -154
  87. package/.aios-core/product/templates/epic.hbs +212 -212
  88. package/.aios-core/product/templates/eslintrc-security.json +32 -32
  89. package/.aios-core/product/templates/github-actions-cd.yml +212 -212
  90. package/.aios-core/product/templates/github-actions-ci.yml +172 -172
  91. package/.aios-core/product/templates/pmdr.hbs +186 -186
  92. package/.aios-core/product/templates/prd-v2.0.hbs +216 -216
  93. package/.aios-core/product/templates/prd.hbs +201 -201
  94. package/.aios-core/product/templates/shock-report-tmpl.html +502 -502
  95. package/.aios-core/product/templates/story.hbs +263 -263
  96. package/.aios-core/product/templates/task.hbs +170 -170
  97. package/.aios-core/product/templates/tmpl-comment-on-examples.sql +158 -158
  98. package/.aios-core/product/templates/tmpl-migration-script.sql +91 -91
  99. package/.aios-core/product/templates/tmpl-rls-granular-policies.sql +104 -104
  100. package/.aios-core/product/templates/tmpl-rls-kiss-policy.sql +10 -10
  101. package/.aios-core/product/templates/tmpl-rls-roles.sql +135 -135
  102. package/.aios-core/product/templates/tmpl-rls-simple.sql +77 -77
  103. package/.aios-core/product/templates/tmpl-rls-tenant.sql +152 -152
  104. package/.aios-core/product/templates/tmpl-rollback-script.sql +77 -77
  105. package/.aios-core/product/templates/tmpl-seed-data.sql +140 -140
  106. package/.aios-core/product/templates/tmpl-smoke-test.sql +16 -16
  107. package/.aios-core/product/templates/tmpl-staging-copy-merge.sql +139 -139
  108. package/.aios-core/product/templates/tmpl-stored-proc.sql +140 -140
  109. package/.aios-core/product/templates/tmpl-trigger.sql +152 -152
  110. package/.aios-core/product/templates/tmpl-view-materialized.sql +133 -133
  111. package/.aios-core/product/templates/tmpl-view.sql +177 -177
  112. package/.aios-core/product/templates/token-exports-css-tmpl.css +240 -240
  113. package/.aios-core/quality/schemas/quality-metrics.schema.json +233 -233
  114. package/.aios-core/scripts/migrate-framework-docs.sh +300 -300
  115. package/.aios-core/scripts/pm.sh +0 -0
  116. package/.claude/hooks/enforce-architecture-first.py +196 -0
  117. package/.claude/hooks/install-hooks.sh +41 -0
  118. package/.claude/hooks/mind-clone-governance.py +192 -0
  119. package/.claude/hooks/pre-commit-mmos-guard.sh +99 -0
  120. package/.claude/hooks/pre-commit-version-check.sh +156 -0
  121. package/.claude/hooks/read-protection.py +151 -0
  122. package/.claude/hooks/slug-validation.py +176 -0
  123. package/.claude/hooks/sql-governance.py +182 -0
  124. package/.claude/hooks/write-path-validation.py +194 -0
  125. package/.claude/rules/agent-authority.md +105 -0
  126. package/.claude/rules/coderabbit-integration.md +93 -0
  127. package/.claude/rules/ids-principles.md +112 -0
  128. package/.claude/rules/story-lifecycle.md +139 -0
  129. package/.claude/rules/workflow-execution.md +150 -0
  130. package/LICENSE +48 -48
  131. package/README.md +30 -7
  132. package/bin/aios-minimal.js +0 -0
  133. package/bin/aios.js +15 -15
  134. package/package.json +2 -4
  135. package/packages/aios-install/bin/aios-install.js +0 -0
  136. package/packages/aios-install/bin/edmcp.js +0 -0
  137. package/packages/aios-pro-cli/bin/aios-pro.js +0 -0
  138. package/scripts/check-markdown-links.py +352 -352
  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;