amazingteam 3.0.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 (164) hide show
  1. package/.ai-team/agents/architect.md +144 -0
  2. package/.ai-team/agents/ci-analyst.md +188 -0
  3. package/.ai-team/agents/developer.md +176 -0
  4. package/.ai-team/agents/planner.md +355 -0
  5. package/.ai-team/agents/qa.md +189 -0
  6. package/.ai-team/agents/reviewer.md +211 -0
  7. package/.ai-team/agents/triage.md +146 -0
  8. package/.ai-team/commands/ci-analyze.md +116 -0
  9. package/.ai-team/commands/design.md +100 -0
  10. package/.ai-team/commands/implement.md +108 -0
  11. package/.ai-team/commands/release-check.md +142 -0
  12. package/.ai-team/commands/review.md +142 -0
  13. package/.ai-team/commands/test.md +115 -0
  14. package/.ai-team/commands/triage.md +138 -0
  15. package/.ai-team/memory/architect/architecture_notes.md +67 -0
  16. package/.ai-team/memory/architect/design_rationale.md +113 -0
  17. package/.ai-team/memory/architect/module_map.md +84 -0
  18. package/.ai-team/memory/ci-analyst/failure_patterns.md +102 -0
  19. package/.ai-team/memory/ci-analyst/runbook_references.md +87 -0
  20. package/.ai-team/memory/developer/bug_investigation.md +102 -0
  21. package/.ai-team/memory/developer/build_issues.md +115 -0
  22. package/.ai-team/memory/developer/implementation_notes.md +83 -0
  23. package/.ai-team/memory/failures/failure_library.md +103 -0
  24. package/.ai-team/memory/planner/decomposition_notes.md +82 -0
  25. package/.ai-team/memory/planner/flow_rules.md +86 -0
  26. package/.ai-team/memory/planner/github_issue_patterns.md +229 -0
  27. package/.ai-team/memory/qa/regression_cases.md +101 -0
  28. package/.ai-team/memory/qa/test_strategy.md +138 -0
  29. package/.ai-team/memory/qa/validation_notes.md +110 -0
  30. package/.ai-team/memory/reviewer/quality_rules.md +105 -0
  31. package/.ai-team/memory/reviewer/recurring_risks.md +109 -0
  32. package/.ai-team/memory/reviewer/review_notes.md +124 -0
  33. package/.ai-team/memory/triage/classification_heuristics.md +82 -0
  34. package/.ai-team/memory/triage/debug_notes.md +87 -0
  35. package/.ai-team/opencode.template.jsonc +216 -0
  36. package/.ai-team/skills/bugfix-playbook/skill.md +174 -0
  37. package/.ai-team/skills/ci-failure-analysis/skill.md +176 -0
  38. package/.ai-team/skills/issue-triage/skill.md +163 -0
  39. package/.ai-team/skills/regression-checklist/skill.md +176 -0
  40. package/.ai-team/skills/release-readiness-check/skill.md +216 -0
  41. package/.ai-team/skills/repo-architecture-reader/skill.md +139 -0
  42. package/.ai-team/skills/safe-refactor-checklist/skill.md +215 -0
  43. package/.ai-team/skills/task-breakdown-and-dispatch/skill.md +151 -0
  44. package/.ai-team/skills/test-first-feature-dev/skill.md +205 -0
  45. package/.ai-team/workflows/ci.yml +81 -0
  46. package/.ai-team/workflows/nightly-ai-maintenance.yml +129 -0
  47. package/.ai-team/workflows/opencode.yml +33 -0
  48. package/.ai-team/workflows/pr-check.yml +41 -0
  49. package/.foundation/foundation.lock +38 -0
  50. package/.foundation/local-overrides.md +97 -0
  51. package/.foundation/upgrade-history.md +38 -0
  52. package/.opencode/agents/architect.md +38 -0
  53. package/.opencode/agents/ci-analyst.md +38 -0
  54. package/.opencode/agents/developer.md +43 -0
  55. package/.opencode/agents/planner.md +47 -0
  56. package/.opencode/agents/qa.md +34 -0
  57. package/.opencode/agents/reviewer.md +38 -0
  58. package/.opencode/agents/triage.md +37 -0
  59. package/.opencode/commands/auto.md +264 -0
  60. package/.opencode/commands/breakdown-issue.md +94 -0
  61. package/.opencode/commands/ci-analyze.md +15 -0
  62. package/.opencode/commands/close-parent-task.md +122 -0
  63. package/.opencode/commands/design.md +15 -0
  64. package/.opencode/commands/dispatch-next.md +102 -0
  65. package/.opencode/commands/implement.md +16 -0
  66. package/.opencode/commands/release-check.md +16 -0
  67. package/.opencode/commands/resume.md +88 -0
  68. package/.opencode/commands/review.md +15 -0
  69. package/.opencode/commands/show-blockers.md +97 -0
  70. package/.opencode/commands/summarize-parent.md +121 -0
  71. package/.opencode/commands/test.md +15 -0
  72. package/.opencode/commands/triage.md +109 -0
  73. package/.opencode/skills/bugfix-playbook/SKILL.md +81 -0
  74. package/.opencode/skills/ci-failure-analysis/SKILL.md +94 -0
  75. package/.opencode/skills/issue-triage/SKILL.md +80 -0
  76. package/.opencode/skills/regression-checklist/SKILL.md +81 -0
  77. package/.opencode/skills/release-readiness-check/SKILL.md +81 -0
  78. package/.opencode/skills/repo-architecture-reader/SKILL.md +65 -0
  79. package/.opencode/skills/safe-refactor-checklist/SKILL.md +76 -0
  80. package/.opencode/skills/task-breakdown-and-dispatch/SKILL.md +255 -0
  81. package/.opencode/skills/test-first-feature-dev/SKILL.md +78 -0
  82. package/AGENTS.md +879 -0
  83. package/CHANGELOG.md +261 -0
  84. package/LICENSE +21 -0
  85. package/README.md +1215 -0
  86. package/VERSION +1 -0
  87. package/action/__tests__/downloader.test.js +251 -0
  88. package/action/__tests__/merger.test.js +156 -0
  89. package/action/__tests__/path-resolver.test.js +199 -0
  90. package/action/__tests__/validator.test.js +310 -0
  91. package/action/action.yml +61 -0
  92. package/action/index.js +223 -0
  93. package/action/lib/downloader.js +344 -0
  94. package/action/lib/merger.js +170 -0
  95. package/action/lib/path-resolver.js +176 -0
  96. package/action/lib/setup.js +286 -0
  97. package/action/lib/validator.js +324 -0
  98. package/cli/__tests__/cli.test.js +270 -0
  99. package/cli/amazingteam.cjs +225 -0
  100. package/cli/commands/check-update.cjs +159 -0
  101. package/cli/commands/init.cjs +412 -0
  102. package/cli/commands/local.cjs +264 -0
  103. package/cli/commands/migrate.cjs +316 -0
  104. package/cli/commands/status.cjs +241 -0
  105. package/cli/commands/upgrade.cjs +213 -0
  106. package/cli/commands/validate.cjs +259 -0
  107. package/cli/commands/version.cjs +59 -0
  108. package/cli/sync.cjs +237 -0
  109. package/dist/index.js +35 -0
  110. package/docs/architecture/overview.md +138 -0
  111. package/docs/blocker_resolution_design.md +372 -0
  112. package/docs/bootstrap-model.md +356 -0
  113. package/docs/config-reference.md +458 -0
  114. package/docs/how-to-use.md +178 -0
  115. package/docs/migration-to-v3.md +355 -0
  116. package/docs/overlay-guide.md +156 -0
  117. package/docs/patterns/README.md +67 -0
  118. package/docs/quick-start-v3.md +330 -0
  119. package/docs/releases/README.md +64 -0
  120. package/docs/runbooks/ci/README.md +62 -0
  121. package/docs/runbooks/ci/build-debug.md +120 -0
  122. package/docs/runbooks/ci/flaky-tests.md +127 -0
  123. package/docs/runbooks/getting-started.md +81 -0
  124. package/docs/upgrade-policy.md +188 -0
  125. package/docs/versioning.md +199 -0
  126. package/overlays/README.md +30 -0
  127. package/overlays/ai-agent-product/.ai-team/skills/llm-integration/skill.md +99 -0
  128. package/overlays/ai-agent-product/docs/ai-agent-architecture.md +68 -0
  129. package/overlays/ai-agent-product/overlay.yaml +26 -0
  130. package/overlays/cpp-qt-desktop/.ai-team/skills/qt-signals-slots/skill.md +60 -0
  131. package/overlays/cpp-qt-desktop/docs/qt-conventions.md +64 -0
  132. package/overlays/cpp-qt-desktop/overlay.yaml +22 -0
  133. package/overlays/python-backend/.ai-team/skills/python-testing/skill.md +90 -0
  134. package/overlays/python-backend/docs/python-style.md +78 -0
  135. package/overlays/python-backend/overlay.yaml +22 -0
  136. package/overlays/web-fullstack/.ai-team/skills/frontend-testing/skill.md +70 -0
  137. package/overlays/web-fullstack/docs/frontend-conventions.md +68 -0
  138. package/overlays/web-fullstack/overlay.yaml +26 -0
  139. package/package.json +84 -0
  140. package/presets/default.yaml +161 -0
  141. package/presets/go.yaml +43 -0
  142. package/presets/python.yaml +43 -0
  143. package/presets/typescript.yaml +40 -0
  144. package/schemas/config.schema.json +239 -0
  145. package/scripts/diff_foundation_vs_project.sh +134 -0
  146. package/scripts/generate_docs.sh +200 -0
  147. package/scripts/init_project.sh +455 -0
  148. package/scripts/plan_upgrade.sh +268 -0
  149. package/scripts/upgrade_foundation.sh +365 -0
  150. package/scripts/validate-foundation.cjs +278 -0
  151. package/scripts/validate_foundation.sh +192 -0
  152. package/scripts/validate_project_setup.sh +171 -0
  153. package/tasks/README.md +94 -0
  154. package/tasks/_template/analysis.md +76 -0
  155. package/tasks/_template/design.md +121 -0
  156. package/tasks/_template/implementation.md +121 -0
  157. package/tasks/_template/release.md +119 -0
  158. package/tasks/_template/review.md +131 -0
  159. package/tasks/_template/subtasks/task.yaml +24 -0
  160. package/tasks/_template/task.yaml +75 -0
  161. package/tasks/_template/validation.md +128 -0
  162. package/templates/amazingteam.yml +81 -0
  163. package/templates/gitignore +14 -0
  164. package/templates/opencode.jsonc +216 -0
@@ -0,0 +1,412 @@
1
+ /**
2
+ * Init Command
3
+ * Initialize AmazingTeam in a project
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const readline = require('readline');
9
+
10
+ const VERSION = require('../../package.json').version;
11
+
12
+ const COLORS = {
13
+ reset: '\x1b[0m',
14
+ green: '\x1b[32m',
15
+ yellow: '\x1b[33m',
16
+ blue: '\x1b[34m',
17
+ red: '\x1b[31m',
18
+ cyan: '\x1b[36m'
19
+ };
20
+
21
+ function log(message, color = 'reset') {
22
+ console.log(`${COLORS[color] || ''}${message}${COLORS.reset}`);
23
+ }
24
+
25
+ function createRL() {
26
+ return readline.createInterface({
27
+ input: process.stdin,
28
+ output: process.stdout
29
+ });
30
+ }
31
+
32
+ function question(rl, prompt, defaultValue = null) {
33
+ return new Promise(resolve => {
34
+ const displayPrompt = defaultValue
35
+ ? `${prompt} (${defaultValue}): `
36
+ : `${prompt}: `;
37
+ rl.question(displayPrompt, answer => {
38
+ resolve(answer || defaultValue);
39
+ });
40
+ });
41
+ }
42
+
43
+ function fileExists(filePath) {
44
+ return fs.existsSync(filePath);
45
+ }
46
+
47
+ function getTemplate(name) {
48
+ const templates = {
49
+ 'amazingteam.config.yaml': `# AmazingTeam Project Configuration
50
+ # Generated by amazingteam init
51
+
52
+ version: "1.0"
53
+
54
+ project:
55
+ name: "{{PROJECT_NAME}}"
56
+ description: "{{PROJECT_DESCRIPTION}}"
57
+ language: "{{LANGUAGE}}"
58
+ framework: "{{FRAMEWORK}}"
59
+
60
+ ai_team:
61
+ version: "{{AI_TEAM_VERSION}}"
62
+
63
+ build:
64
+ command: "{{BUILD_COMMAND}}"
65
+ test: "{{TEST_COMMAND}}"
66
+ lint: "{{LINT_COMMAND}}"
67
+
68
+ # Uncomment to use an overlay:
69
+ # overlay: "{{OVERLAY}}"
70
+
71
+ # Custom rules (optional)
72
+ rules:
73
+ test_coverage_threshold: 80
74
+ max_function_lines: 30
75
+ `,
76
+
77
+ 'opencode.jsonc': `{
78
+ "$schema": "https://opencode.ai/config.json",
79
+ "model": "default",
80
+ "small_model": "default",
81
+ "default_agent": "build",
82
+ "instructions": ["AGENTS.md"],
83
+ "autoupdate": true,
84
+ "permission": {
85
+ "edit": "ask",
86
+ "bash": "ask"
87
+ },
88
+ "tools": {
89
+ "write": true,
90
+ "edit": true,
91
+ "bash": true
92
+ }
93
+ }
94
+ `,
95
+
96
+ 'gitignore_additions': `
97
+ # AmazingTeam local foundation (downloaded by \`amazingteam local\`)
98
+ .ai-team-local/
99
+
100
+ # AmazingTeam cache
101
+ .ai-team-cache/
102
+ `
103
+ };
104
+
105
+ return templates[name] || '';
106
+ }
107
+
108
+ function getWorkflowTemplate(version) {
109
+ return `# AmazingTeam GitHub Action Workflow
110
+ # This workflow enables AI-powered development in your repository
111
+
112
+ name: AmazingTeam
113
+
114
+ on:
115
+ issue_comment:
116
+ types: [created]
117
+ pull_request_review_comment:
118
+ types: [created]
119
+
120
+ jobs:
121
+ ai-team:
122
+ if: |
123
+ startsWith(github.event.comment.body, '/ai') ||
124
+ startsWith(github.event.comment.body, '/opencode') ||
125
+ startsWith(github.event.comment.body, '/oc')
126
+
127
+ runs-on: ubuntu-latest
128
+
129
+ permissions:
130
+ id-token: write
131
+ contents: write
132
+ pull-requests: write
133
+ issues: write
134
+
135
+ steps:
136
+ - name: Checkout repository
137
+ uses: actions/checkout@v4
138
+ with:
139
+ fetch-depth: 0
140
+ token: \${{ secrets.GITHUB_TOKEN }}
141
+
142
+ - name: Configure git
143
+ run: |
144
+ git config --global user.name "opencode-bot"
145
+ git config --global user.email "opencode-bot@users.noreply.github.com"
146
+
147
+ - name: Setup AmazingTeam
148
+ uses: your-org/amazingteam-action@v${version}
149
+ with:
150
+ version: '${version}'
151
+ config: 'amazingteam.config.yaml'
152
+
153
+ - name: Run OpenCode
154
+ uses: anomalyco/opencode/github@latest
155
+ env:
156
+ ALIBABA_CODING_PLAN_API_KEY: \${{ secrets.ALIBABA_CODING_PLAN_API_KEY }}
157
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
158
+ with:
159
+ model: alibaba-coding-plan/glm-5
160
+ `;
161
+ }
162
+
163
+ function getLanguageDefaults(language) {
164
+ const defaults = {
165
+ typescript: {
166
+ framework: 'node',
167
+ buildCommand: 'npm run build',
168
+ testCommand: 'npm test',
169
+ lintCommand: 'npm run lint'
170
+ },
171
+ javascript: {
172
+ framework: 'node',
173
+ buildCommand: 'npm run build',
174
+ testCommand: 'npm test',
175
+ lintCommand: 'npm run lint'
176
+ },
177
+ python: {
178
+ framework: 'fastapi',
179
+ buildCommand: 'python -m build',
180
+ testCommand: 'pytest',
181
+ lintCommand: 'ruff check .'
182
+ },
183
+ go: {
184
+ framework: 'gin',
185
+ buildCommand: 'go build ./...',
186
+ testCommand: 'go test ./...',
187
+ lintCommand: 'golangci-lint run'
188
+ },
189
+ java: {
190
+ framework: 'spring',
191
+ buildCommand: './mvnw package',
192
+ testCommand: './mvnw test',
193
+ lintCommand: './mvnw checkstyle:check'
194
+ },
195
+ cpp: {
196
+ framework: 'qt',
197
+ buildCommand: 'cmake --build build',
198
+ testCommand: 'ctest --test-dir build',
199
+ lintCommand: 'clang-tidy'
200
+ },
201
+ rust: {
202
+ framework: 'cargo',
203
+ buildCommand: 'cargo build',
204
+ testCommand: 'cargo test',
205
+ lintCommand: 'cargo clippy'
206
+ }
207
+ };
208
+
209
+ return defaults[language] || defaults.typescript;
210
+ }
211
+
212
+ async function run(options, positional) {
213
+ const rl = createRL();
214
+
215
+ try {
216
+ log('\nšŸš€ AmazingTeam Foundation Initializer\n', 'cyan');
217
+
218
+ const projectPath = process.cwd();
219
+ const projectName = positional[0] || path.basename(projectPath);
220
+
221
+ // Check if already initialized
222
+ const configPath = path.join(projectPath, 'amazingteam.config.yaml');
223
+ if (fileExists(configPath) && !options.force) {
224
+ log('āš ļø AmazingTeam already initialized in this directory.', 'yellow');
225
+ log(' Use --force to reinitialize.\n');
226
+ rl.close();
227
+ return;
228
+ }
229
+
230
+ // Interactive prompts or use options
231
+ let language = options.language;
232
+ let framework = options.framework;
233
+ let description = options.description;
234
+ let overlay = options.overlay;
235
+
236
+ if (!options.language) {
237
+ language = await question(rl, 'Language', 'typescript');
238
+ }
239
+
240
+ if (!options.framework) {
241
+ const defaultFramework = getLanguageDefaults(language).framework;
242
+ framework = await question(rl, 'Framework', defaultFramework);
243
+ }
244
+
245
+ if (!options.description) {
246
+ description = await question(rl, 'Description', 'My awesome project');
247
+ }
248
+
249
+ if (!options.overlay && options.overlay !== null) {
250
+ const overlayAnswer = await question(rl, 'Overlay (leave empty for none)', '');
251
+ overlay = overlayAnswer || null;
252
+ }
253
+
254
+ const langDefaults = getLanguageDefaults(language);
255
+
256
+ log('\nšŸ“¦ Creating project structure...', 'blue');
257
+
258
+ // Create directories
259
+ const dirs = [
260
+ '.ai-team/memory/planner',
261
+ '.ai-team/memory/architect',
262
+ '.ai-team/memory/developer',
263
+ '.ai-team/memory/qa',
264
+ '.ai-team/memory/reviewer',
265
+ '.ai-team/memory/triage',
266
+ '.ai-team/memory/ci-analyst',
267
+ '.ai-team/memory/failures',
268
+ '.github/workflows',
269
+ 'tasks/_template',
270
+ 'src'
271
+ ];
272
+
273
+ for (const dir of dirs) {
274
+ const fullPath = path.join(projectPath, dir);
275
+ if (!fileExists(fullPath)) {
276
+ fs.mkdirSync(fullPath, { recursive: true });
277
+ }
278
+ }
279
+
280
+ log('šŸ“ Creating configuration files...', 'blue');
281
+
282
+ // Generate amazingteam.config.yaml
283
+ let configContent = getTemplate('amazingteam.config.yaml');
284
+ configContent = configContent
285
+ .replace(/\{\{PROJECT_NAME\}\}/g, projectName)
286
+ .replace(/\{\{PROJECT_DESCRIPTION\}\}/g, description)
287
+ .replace(/\{\{LANGUAGE\}\}/g, language)
288
+ .replace(/\{\{FRAMEWORK\}\}/g, framework)
289
+ .replace(/\{\{AI_TEAM_VERSION\}\}/g, VERSION)
290
+ .replace(/\{\{BUILD_COMMAND\}\}/g, langDefaults.buildCommand)
291
+ .replace(/\{\{TEST_COMMAND\}\}/g, langDefaults.testCommand)
292
+ .replace(/\{\{LINT_COMMAND\}\}/g, langDefaults.lintCommand)
293
+ .replace(/\{\{OVERLAY\}\}/g, overlay || '');
294
+
295
+ fs.writeFileSync(configPath, configContent);
296
+
297
+ // Generate opencode.jsonc
298
+ const opencodePath = path.join(projectPath, 'opencode.jsonc');
299
+ fs.writeFileSync(opencodePath, getTemplate('opencode.jsonc'));
300
+
301
+ // Generate workflow
302
+ const workflowPath = path.join(projectPath, '.github', 'workflows', 'amazingteam.yml');
303
+ fs.writeFileSync(workflowPath, getWorkflowTemplate(VERSION));
304
+
305
+ // Update .gitignore
306
+ log('šŸ“ Updating .gitignore...', 'blue');
307
+ const gitignorePath = path.join(projectPath, '.gitignore');
308
+ let gitignoreContent = '';
309
+
310
+ if (fileExists(gitignorePath)) {
311
+ gitignoreContent = fs.readFileSync(gitignorePath, 'utf-8');
312
+ if (!gitignoreContent.includes('.ai-team-local/')) {
313
+ gitignoreContent += getTemplate('gitignore_additions');
314
+ fs.writeFileSync(gitignorePath, gitignoreContent);
315
+ }
316
+ } else {
317
+ fs.writeFileSync(gitignorePath, getTemplate('gitignore_additions').trim() + '\n');
318
+ }
319
+
320
+ // Create placeholder memory files
321
+ log('šŸ“‹ Creating memory placeholders...', 'blue');
322
+ const memoryFiles = {
323
+ 'planner': ['decomposition_notes.md', 'flow_rules.md'],
324
+ 'architect': ['architecture_notes.md', 'module_map.md'],
325
+ 'developer': ['implementation_notes.md', 'bug_investigation.md'],
326
+ 'qa': ['test_strategy.md', 'validation_notes.md'],
327
+ 'reviewer': ['review_notes.md', 'quality_rules.md'],
328
+ 'triage': ['classification_heuristics.md', 'debug_notes.md'],
329
+ 'ci-analyst': ['failure_patterns.md', 'runbook_references.md'],
330
+ 'failures': ['failure_library.md']
331
+ };
332
+
333
+ for (const [role, files] of Object.entries(memoryFiles)) {
334
+ for (const file of files) {
335
+ const filePath = path.join(projectPath, '.ai-team', 'memory', role, file);
336
+ if (!fileExists(filePath)) {
337
+ fs.writeFileSync(filePath, `# ${role} ${file.replace('.md', '').replace(/_/g, ' ')}\n\n`);
338
+ }
339
+ }
340
+ }
341
+
342
+ // Create task template
343
+ const taskTemplatePath = path.join(projectPath, 'tasks', '_template', 'task.yaml');
344
+ if (!fileExists(taskTemplatePath)) {
345
+ fs.writeFileSync(taskTemplatePath, `id: template
346
+ title: Task Title
347
+ type: feature
348
+ status: backlog
349
+ priority: medium
350
+ owner_role: developer
351
+ depends_on: []
352
+ blocked_by: []
353
+ acceptance_criteria: []
354
+ risk_level: low
355
+ module_scope: []
356
+ `);
357
+ }
358
+
359
+ log('\nāœ… AmazingTeam initialized successfully!\n', 'green');
360
+
361
+ log('Next steps:', 'cyan');
362
+ log(' 1. Review and customize amazingteam.config.yaml');
363
+ log(' 2. Add your GitHub secrets:');
364
+ log(' - ALIBABA_CODING_PLAN_API_KEY or OPENCODE_API_KEY');
365
+ log(' 3. Run `amazingteam local` for local development');
366
+ log(' 4. Create your first issue!\n');
367
+
368
+ log('Configuration:', 'cyan');
369
+ log(` Project: ${projectName}`);
370
+ log(` Language: ${language}`);
371
+ log(` Framework: ${framework}`);
372
+ log(` Version: ${VERSION}`);
373
+ if (overlay) {
374
+ log(` Overlay: ${overlay}`);
375
+ }
376
+ log('');
377
+
378
+ } finally {
379
+ rl.close();
380
+ }
381
+ }
382
+
383
+ function help() {
384
+ return `
385
+ ${COLORS.cyan}amazingteam init${COLORS.reset} - Initialize AmazingTeam in a project
386
+
387
+ ${COLORS.yellow}Usage:${COLORS.reset}
388
+ amazingteam init [project-name] [options]
389
+
390
+ ${COLORS.yellow}Options:${COLORS.reset}
391
+ --language, -l <lang> Programming language (default: typescript)
392
+ --framework <fw> Framework (default: based on language)
393
+ --overlay, -o <name> Apply overlay (python-backend, web-fullstack, etc.)
394
+ --description, -d <desc> Project description
395
+ --force Force reinitialization
396
+
397
+ ${COLORS.yellow}Examples:${COLORS.reset}
398
+ amazingteam init Interactive initialization
399
+ amazingteam init my-project Create project with defaults
400
+ amazingteam init -l python -o python-backend Python with overlay
401
+ amazingteam init --force Reinitialize existing project
402
+
403
+ ${COLORS.yellow}Created Files:${COLORS.reset}
404
+ amazingteam.config.yaml Project configuration
405
+ opencode.jsonc OpenCode configuration
406
+ .github/workflows/amazingteam.yml GitHub Action workflow
407
+ .ai-team/memory/ Role memory directories
408
+ tasks/_template/ Task template directory
409
+ `;
410
+ }
411
+
412
+ module.exports = { run, help };
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Local Command
3
+ * Download foundation for local development
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const { execSync } = require('child_process');
9
+
10
+ const VERSION = require('../../package.json').version;
11
+ const PACKAGE_NAME = 'amazingteam';
12
+ const REGISTRY = 'https://registry.npmjs.org';
13
+ const CACHE_DIR = path.join(process.env.HOME || process.env.USERPROFILE, '.ai-team-cache');
14
+ const LOCAL_DIR = '.ai-team-local';
15
+
16
+ function downloadFromNpm(version, destDir) {
17
+ const url = `${REGISTRY}/${PACKAGE_NAME}/-/${PACKAGE_NAME}-${version}.tgz`;
18
+ const tarballPath = path.join(destDir, `${PACKAGE_NAME}-${version}.tgz`);
19
+
20
+ console.log(`Downloading from NPM: ${url}`);
21
+
22
+ try {
23
+ execSync(`curl -L -o "${tarballPath}" "${url}"`, { stdio: 'inherit' });
24
+ } catch (err) {
25
+ throw new Error(`Failed to download: ${err.message}`);
26
+ }
27
+
28
+ return tarballPath;
29
+ }
30
+
31
+ function extractTarball(tarballPath, destDir) {
32
+ console.log('Extracting...');
33
+
34
+ try {
35
+ execSync(`tar -xzf "${tarballPath}" -C "${destDir}"`, { stdio: 'inherit' });
36
+ } catch (err) {
37
+ throw new Error(`Failed to extract: ${err.message}`);
38
+ }
39
+ }
40
+
41
+ function readConfig(configPath) {
42
+ if (!fs.existsSync(configPath)) {
43
+ return null;
44
+ }
45
+
46
+ const content = fs.readFileSync(configPath, 'utf-8');
47
+ const config = {};
48
+
49
+ content.split('\n').forEach(line => {
50
+ const match = line.match(/^(\w+):\s*["']?([^"'\n]+)["']?/);
51
+ if (match) {
52
+ config[match[1]] = match[2];
53
+ }
54
+
55
+ const nestedMatch = line.match(/^ (\w+):\s*["']?([^"'\n]+)["']?/);
56
+ if (nestedMatch) {
57
+ const parent = line.split(' ')[0]?.match(/^(\w+):/)?.[1];
58
+ if (parent && !config[parent]) {
59
+ config[parent] = {};
60
+ }
61
+ if (config[parent]) {
62
+ config[parent][nestedMatch[1]] = nestedMatch[2];
63
+ }
64
+ }
65
+ });
66
+
67
+ return config;
68
+ }
69
+
70
+ function generateLocalOpenCodeConfig(projectDir, foundationDir, config) {
71
+ return `{
72
+ "$schema": "https://opencode.ai/config.json",
73
+ "model": "default",
74
+ "small_model": "default",
75
+ "default_agent": "build",
76
+ "instructions": [
77
+ "${foundationDir}/AGENTS.md",
78
+ "AGENTS.md"
79
+ ],
80
+ "autoupdate": true,
81
+ "permission": {
82
+ "edit": "ask",
83
+ "bash": "ask"
84
+ },
85
+ "tools": {
86
+ "write": true,
87
+ "edit": true,
88
+ "bash": true
89
+ },
90
+ "skills": {
91
+ "test-first-feature-dev": {
92
+ "path": "${foundationDir}/.opencode/skills/test-first-feature-dev/SKILL.md"
93
+ },
94
+ "bugfix-playbook": {
95
+ "path": "${foundationDir}/.opencode/skills/bugfix-playbook/SKILL.md"
96
+ },
97
+ "repo-architecture-reader": {
98
+ "path": "${foundationDir}/.opencode/skills/repo-architecture-reader/SKILL.md"
99
+ },
100
+ "task-breakdown-and-dispatch": {
101
+ "path": "${foundationDir}/.opencode/skills/task-breakdown-and-dispatch/SKILL.md"
102
+ }
103
+ }
104
+ }`;
105
+ }
106
+
107
+ async function run(options, positional) {
108
+ const projectPath = process.cwd();
109
+ const configPath = path.join(projectPath, 'amazingteam.config.yaml');
110
+ const localPath = path.join(projectPath, LOCAL_DIR);
111
+
112
+ console.log('\nšŸ“„ Downloading AmazingTeam Foundation for local use\n');
113
+
114
+ // Check if initialized
115
+ if (!fs.existsSync(configPath)) {
116
+ console.error('āŒ AmazingTeam not initialized in this directory.');
117
+ console.error(' Run "amazingteam init" first.\n');
118
+ process.exit(1);
119
+ }
120
+
121
+ // Read config
122
+ const config = readConfig(configPath);
123
+ const targetVersion = config?.ai_team?.version || VERSION;
124
+
125
+ console.log(`Target version: ${targetVersion}`);
126
+
127
+ // Check if using local path
128
+ if (options.from) {
129
+ const fromPath = path.resolve(options.from);
130
+
131
+ if (!fs.existsSync(fromPath)) {
132
+ console.error(`āŒ Local path not found: ${fromPath}\n`);
133
+ process.exit(1);
134
+ }
135
+
136
+ console.log(`Using local foundation: ${fromPath}`);
137
+
138
+ // Create symlink or copy
139
+ if (fs.existsSync(localPath)) {
140
+ fs.rmSync(localPath, { recursive: true });
141
+ }
142
+
143
+ // Copy instead of symlink for reliability
144
+ console.log('Copying foundation files...');
145
+ fs.cpSync(fromPath, localPath, { recursive: true });
146
+
147
+ console.log(`\nāœ… Foundation copied to ${LOCAL_DIR}/\n`);
148
+ } else {
149
+ // Download from NPM
150
+ console.log('Downloading from NPM...\n');
151
+
152
+ // Create cache directory
153
+ if (!fs.existsSync(CACHE_DIR)) {
154
+ fs.mkdirSync(CACHE_DIR, { recursive: true });
155
+ }
156
+
157
+ // Check cache
158
+ const cachedPath = path.join(CACHE_DIR, `v${targetVersion}`);
159
+
160
+ if (fs.existsSync(cachedPath) && !options.force) {
161
+ console.log(`Using cached version: ${cachedPath}`);
162
+ } else {
163
+ // Download
164
+ const tempDir = path.join(CACHE_DIR, 'temp');
165
+ if (!fs.existsSync(tempDir)) {
166
+ fs.mkdirSync(tempDir, { recursive: true });
167
+ }
168
+
169
+ try {
170
+ const tarballPath = downloadFromNpm(targetVersion, tempDir);
171
+ extractTarball(tarballPath, tempDir);
172
+
173
+ // Move to cache
174
+ const extractedPath = path.join(tempDir, 'package');
175
+ if (fs.existsSync(cachedPath)) {
176
+ fs.rmSync(cachedPath, { recursive: true });
177
+ }
178
+ fs.renameSync(extractedPath, cachedPath);
179
+
180
+ // Cleanup
181
+ fs.unlinkSync(tarballPath);
182
+ fs.rmSync(tempDir, { recursive: true });
183
+
184
+ console.log('āœ… Download complete');
185
+ } catch (error) {
186
+ console.error('āŒ Download failed:', error.message);
187
+ console.log('\nAlternatives:');
188
+ console.log(' - Check your network connection');
189
+ console.log(' - Use --from /path/to/local/foundation for offline mode');
190
+ console.log('');
191
+ process.exit(1);
192
+ }
193
+ }
194
+
195
+ // Copy to local directory
196
+ console.log(`\nCopying to ${LOCAL_DIR}/...`);
197
+
198
+ if (fs.existsSync(localPath)) {
199
+ fs.rmSync(localPath, { recursive: true });
200
+ }
201
+
202
+ fs.cpSync(cachedPath, localPath, { recursive: true });
203
+
204
+ console.log('āœ… Copy complete');
205
+ }
206
+
207
+ // Generate local opencode.jsonc
208
+ console.log('\nšŸ“ Generating opencode.jsonc for local development...');
209
+
210
+ const opencodeContent = generateLocalOpenCodeConfig(projectPath, localPath, config);
211
+ const opencodePath = path.join(projectPath, 'opencode.jsonc');
212
+
213
+ // Backup existing if different
214
+ if (fs.existsSync(opencodePath)) {
215
+ const existing = fs.readFileSync(opencodePath, 'utf-8');
216
+ if (existing !== opencodeContent) {
217
+ fs.writeFileSync(opencodePath + '.backup', existing);
218
+ console.log(' (Backed up existing opencode.jsonc)');
219
+ }
220
+ }
221
+
222
+ fs.writeFileSync(opencodePath, opencodeContent);
223
+ console.log('āœ… Generated opencode.jsonc');
224
+
225
+ // Summary
226
+ console.log('\nšŸŽ‰ Local setup complete!\n');
227
+ console.log('Foundation files:', LOCAL_DIR);
228
+ console.log('OpenCode config: opencode.jsonc');
229
+ console.log('\nYou can now use OpenCode locally with full AmazingTeam capabilities.\n');
230
+
231
+ // Update .gitignore reminder
232
+ console.log('Reminder: Add .ai-team-local/ to .gitignore if not already done.');
233
+ console.log('');
234
+ }
235
+
236
+ function help() {
237
+ return `
238
+ amazingteam local - Download foundation for local development
239
+
240
+ Usage:
241
+ amazingteam local [options]
242
+
243
+ Options:
244
+ --from <path> Use local foundation path (offline mode)
245
+ --force Force re-download even if cached
246
+
247
+ Examples:
248
+ amazingteam local Download from NPM
249
+ amazingteam local --from ../foundation Use local copy
250
+ amazingteam local --force Force re-download
251
+
252
+ What it does:
253
+ 1. Downloads AmazingTeam Foundation to .ai-team-local/
254
+ 2. Generates opencode.jsonc with local paths
255
+ 3. Caches downloads in ~/.ai-team-cache/
256
+
257
+ The local foundation allows you to use OpenCode locally
258
+ with all AmazingTeam skills and configurations.
259
+
260
+ Note: .ai-team-local/ should be in .gitignore.
261
+ `;
262
+ }
263
+
264
+ module.exports = { run, help };