create-byan-agent 1.1.2 → 1.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 (76) hide show
  1. package/CHANGELOG.md +250 -177
  2. package/LICENSE +21 -21
  3. package/README.md +1245 -421
  4. package/bin/create-byan-agent-backup.js +220 -220
  5. package/bin/create-byan-agent-fixed.js +301 -301
  6. package/bin/create-byan-agent.js +322 -301
  7. package/lib/errors.js +61 -0
  8. package/lib/exit-codes.js +54 -0
  9. package/lib/platforms/claude-code.js +113 -0
  10. package/lib/platforms/codex.js +92 -0
  11. package/lib/platforms/copilot-cli.js +123 -0
  12. package/lib/platforms/index.js +14 -0
  13. package/lib/platforms/vscode.js +51 -0
  14. package/lib/utils/config-loader.js +79 -0
  15. package/lib/utils/file-utils.js +104 -0
  16. package/lib/utils/git-detector.js +35 -0
  17. package/lib/utils/logger.js +64 -0
  18. package/lib/utils/node-detector.js +58 -0
  19. package/lib/utils/os-detector.js +74 -0
  20. package/lib/utils/yaml-utils.js +87 -0
  21. package/lib/yanstaller/backuper.js +308 -0
  22. package/lib/yanstaller/detector.js +141 -0
  23. package/lib/yanstaller/index.js +93 -0
  24. package/lib/yanstaller/installer.js +225 -0
  25. package/lib/yanstaller/interviewer.js +250 -0
  26. package/lib/yanstaller/recommender.js +298 -0
  27. package/lib/yanstaller/troubleshooter.js +498 -0
  28. package/lib/yanstaller/validator.js +578 -0
  29. package/lib/yanstaller/wizard.js +211 -0
  30. package/package.json +61 -55
  31. package/templates/.github/agents/bmad-agent-bmad-master.md +15 -15
  32. package/templates/.github/agents/bmad-agent-bmb-agent-builder.md +15 -15
  33. package/templates/.github/agents/bmad-agent-bmb-module-builder.md +15 -15
  34. package/templates/.github/agents/bmad-agent-bmb-workflow-builder.md +15 -15
  35. package/templates/.github/agents/bmad-agent-bmm-analyst.md +15 -15
  36. package/templates/.github/agents/bmad-agent-bmm-architect.md +15 -15
  37. package/templates/.github/agents/bmad-agent-bmm-dev.md +15 -15
  38. package/templates/.github/agents/bmad-agent-bmm-pm.md +15 -15
  39. package/templates/.github/agents/bmad-agent-bmm-quick-flow-solo-dev.md +15 -15
  40. package/templates/.github/agents/bmad-agent-bmm-quinn.md +15 -15
  41. package/templates/.github/agents/bmad-agent-bmm-sm.md +15 -15
  42. package/templates/.github/agents/bmad-agent-bmm-tech-writer.md +15 -15
  43. package/templates/.github/agents/bmad-agent-bmm-ux-designer.md +15 -15
  44. package/templates/.github/agents/bmad-agent-byan-test.md +32 -0
  45. package/templates/.github/agents/bmad-agent-byan.md +224 -224
  46. package/templates/.github/agents/bmad-agent-carmack.md +18 -0
  47. package/templates/.github/agents/bmad-agent-cis-brainstorming-coach.md +15 -15
  48. package/templates/.github/agents/bmad-agent-cis-creative-problem-solver.md +15 -15
  49. package/templates/.github/agents/bmad-agent-cis-design-thinking-coach.md +15 -15
  50. package/templates/.github/agents/bmad-agent-cis-innovation-strategist.md +15 -15
  51. package/templates/.github/agents/bmad-agent-cis-presentation-master.md +15 -15
  52. package/templates/.github/agents/bmad-agent-cis-storyteller.md +15 -15
  53. package/templates/.github/agents/bmad-agent-marc.md +48 -48
  54. package/templates/.github/agents/bmad-agent-patnote.md +48 -0
  55. package/templates/.github/agents/bmad-agent-rachid.md +47 -47
  56. package/templates/.github/agents/bmad-agent-tea-tea.md +15 -15
  57. package/templates/.github/agents/bmad-agent-test-dynamic.md +21 -0
  58. package/templates/.github/agents/expert-merise-agile.md +1 -0
  59. package/templates/.github/agents/franck.md +379 -0
  60. package/templates/_bmad/bmb/agents/agent-builder.md +59 -59
  61. package/templates/_bmad/bmb/agents/byan-test.md +116 -116
  62. package/templates/_bmad/bmb/agents/byan.md +215 -215
  63. package/templates/_bmad/bmb/agents/marc.md +303 -303
  64. package/templates/_bmad/bmb/agents/module-builder.md +60 -60
  65. package/templates/_bmad/bmb/agents/patnote.md +495 -495
  66. package/templates/_bmad/bmb/agents/rachid.md +184 -184
  67. package/templates/_bmad/bmb/agents/workflow-builder.md +61 -61
  68. package/templates/_bmad/bmb/workflows/byan/data/mantras.yaml +272 -272
  69. package/templates/_bmad/bmb/workflows/byan/data/templates.yaml +59 -59
  70. package/templates/_bmad/bmb/workflows/byan/delete-agent-workflow.md +657 -657
  71. package/templates/_bmad/bmb/workflows/byan/edit-agent-workflow.md +688 -688
  72. package/templates/_bmad/bmb/workflows/byan/interview-workflow.md +753 -753
  73. package/templates/_bmad/bmb/workflows/byan/quick-create-workflow.md +450 -450
  74. package/templates/_bmad/bmb/workflows/byan/templates/base-agent-template.md +79 -79
  75. package/templates/_bmad/bmb/workflows/byan/validate-agent-workflow.md +676 -676
  76. package/templates/_bmad/core/agents/carmack.md +238 -238
@@ -0,0 +1,578 @@
1
+ /**
2
+ * VALIDATOR Module
3
+ *
4
+ * Validates BYAN installation with 10 automated checks.
5
+ *
6
+ * Phase 4: 32h development
7
+ *
8
+ * @module yanstaller/validator
9
+ */
10
+
11
+ const path = require('path');
12
+ const fileUtils = require('../utils/file-utils');
13
+ const yamlUtils = require('../utils/yaml-utils');
14
+ const { execSync } = require('child_process');
15
+
16
+ /**
17
+ * @typedef {Object} ValidationResult
18
+ * @property {boolean} success - All checks passed
19
+ * @property {CheckResult[]} checks - Individual check results
20
+ * @property {string[]} errors - Critical errors
21
+ * @property {string[]} warnings - Non-critical issues
22
+ */
23
+
24
+ /**
25
+ * @typedef {Object} CheckResult
26
+ * @property {string} id - Check identifier
27
+ * @property {string} name - Human-readable check name
28
+ * @property {boolean} passed
29
+ * @property {string} [message] - Error/warning message if failed
30
+ * @property {string} severity - 'critical' | 'warning'
31
+ */
32
+
33
+ /**
34
+ * Validate BYAN installation
35
+ *
36
+ * @param {import('./installer').InstallConfig} config - Installation config
37
+ * @returns {Promise<ValidationResult>}
38
+ */
39
+ async function validate(config) {
40
+ const checks = [];
41
+ const errors = [];
42
+ const warnings = [];
43
+
44
+ // Run all 10 checks in sequence
45
+ checks.push(await checkBmadStructure(config));
46
+ checks.push(await checkAgentFiles(config));
47
+ checks.push(await checkStubsYamlFrontmatter(config));
48
+ checks.push(await checkConfigFiles(config));
49
+ checks.push(await checkPlatformDetection(config));
50
+ checks.push(await checkFilePermissions(config));
51
+ checks.push(await checkManifests(config));
52
+ checks.push(await checkWorkflows(config));
53
+ checks.push(await checkTemplates(config));
54
+ checks.push(await checkDependencies(config));
55
+
56
+ // Collect errors and warnings
57
+ for (const check of checks) {
58
+ if (!check.passed) {
59
+ if (check.severity === 'critical') {
60
+ errors.push(`[${check.id}] ${check.message}`);
61
+ } else {
62
+ warnings.push(`[${check.id}] ${check.message}`);
63
+ }
64
+ }
65
+ }
66
+
67
+ const allPassed = checks.every(c => c.passed || c.severity === 'warning');
68
+
69
+ return {
70
+ success: allPassed,
71
+ checks,
72
+ errors,
73
+ warnings
74
+ };
75
+ }
76
+
77
+ /**
78
+ * Check 1: _bmad/ structure exists
79
+ */
80
+ async function checkBmadStructure(config) {
81
+ const projectRoot = config.projectRoot || process.cwd();
82
+ const requiredDirs = [
83
+ '_bmad',
84
+ '_bmad/_config',
85
+ '_bmad/_memory',
86
+ '_bmad/_output',
87
+ '_bmad/core/agents',
88
+ '_bmad/bmm/agents',
89
+ '_bmad/bmb/agents',
90
+ '_bmad/tea/agents',
91
+ '_bmad/cis/agents'
92
+ ];
93
+
94
+ const missingDirs = [];
95
+ for (const dir of requiredDirs) {
96
+ const dirPath = path.join(projectRoot, dir);
97
+ if (!await fileUtils.exists(dirPath)) {
98
+ missingDirs.push(dir);
99
+ }
100
+ }
101
+
102
+ if (missingDirs.length > 0) {
103
+ return {
104
+ id: 'bmad-structure',
105
+ name: '_bmad/ structure',
106
+ passed: false,
107
+ message: `Missing directories: ${missingDirs.join(', ')}`,
108
+ severity: 'critical'
109
+ };
110
+ }
111
+
112
+ return {
113
+ id: 'bmad-structure',
114
+ name: '_bmad/ structure',
115
+ passed: true,
116
+ severity: 'critical'
117
+ };
118
+ }
119
+
120
+ /**
121
+ * Check 2: Agent files copied correctly
122
+ */
123
+ async function checkAgentFiles(config) {
124
+ const projectRoot = config.projectRoot || process.cwd();
125
+ const agents = config.agents || [];
126
+
127
+ if (agents.length === 0) {
128
+ return {
129
+ id: 'agent-files',
130
+ name: 'Agent files',
131
+ passed: true,
132
+ message: 'No agents to check',
133
+ severity: 'critical'
134
+ };
135
+ }
136
+
137
+ const modules = ['core', 'bmm', 'bmb', 'tea', 'cis'];
138
+ const missingAgents = [];
139
+
140
+ for (const agentName of agents) {
141
+ let found = false;
142
+ for (const module of modules) {
143
+ const agentPath = path.join(projectRoot, '_bmad', module, 'agents', `${agentName}.md`);
144
+ if (await fileUtils.exists(agentPath)) {
145
+ found = true;
146
+ break;
147
+ }
148
+ }
149
+ if (!found) {
150
+ missingAgents.push(agentName);
151
+ }
152
+ }
153
+
154
+ if (missingAgents.length > 0) {
155
+ return {
156
+ id: 'agent-files',
157
+ name: 'Agent files',
158
+ passed: false,
159
+ message: `Missing agents: ${missingAgents.join(', ')}`,
160
+ severity: 'critical'
161
+ };
162
+ }
163
+
164
+ return {
165
+ id: 'agent-files',
166
+ name: 'Agent files',
167
+ passed: true,
168
+ severity: 'critical'
169
+ };
170
+ }
171
+
172
+ /**
173
+ * Check 3: Platform stubs have valid YAML frontmatter
174
+ */
175
+ async function checkStubsYamlFrontmatter(config) {
176
+ const projectRoot = config.projectRoot || process.cwd();
177
+ const targetPlatforms = config.targetPlatforms || [];
178
+
179
+ if (targetPlatforms.length === 0) {
180
+ return {
181
+ id: 'yaml-frontmatter',
182
+ name: 'YAML frontmatter',
183
+ passed: true,
184
+ message: 'No platforms to check',
185
+ severity: 'critical'
186
+ };
187
+ }
188
+
189
+ const invalidStubs = [];
190
+
191
+ // Check Copilot CLI / VSCode stubs
192
+ if (targetPlatforms.includes('copilot-cli') || targetPlatforms.includes('vscode')) {
193
+ const stubsDir = path.join(projectRoot, '.github', 'agents');
194
+ if (await fileUtils.exists(stubsDir)) {
195
+ const files = await fileUtils.readDir(stubsDir);
196
+ for (const file of files) {
197
+ if (file.endsWith('.md')) {
198
+ const content = await fileUtils.readFile(path.join(stubsDir, file), 'utf8');
199
+ if (!content.startsWith('---')) {
200
+ invalidStubs.push(`.github/agents/${file}`);
201
+ }
202
+ }
203
+ }
204
+ }
205
+ }
206
+
207
+ // Check Codex stubs
208
+ if (targetPlatforms.includes('codex')) {
209
+ const stubsDir = path.join(projectRoot, '.codex', 'prompts');
210
+ if (await fileUtils.exists(stubsDir)) {
211
+ const files = await fileUtils.readDir(stubsDir);
212
+ for (const file of files) {
213
+ if (file.endsWith('.md')) {
214
+ const content = await fileUtils.readFile(path.join(stubsDir, file), 'utf8');
215
+ if (!content.includes('<agent-activation')) {
216
+ invalidStubs.push(`.codex/prompts/${file}`);
217
+ }
218
+ }
219
+ }
220
+ }
221
+ }
222
+
223
+ if (invalidStubs.length > 0) {
224
+ return {
225
+ id: 'yaml-frontmatter',
226
+ name: 'YAML frontmatter',
227
+ passed: false,
228
+ message: `Invalid stubs: ${invalidStubs.join(', ')}`,
229
+ severity: 'critical'
230
+ };
231
+ }
232
+
233
+ return {
234
+ id: 'yaml-frontmatter',
235
+ name: 'YAML frontmatter',
236
+ passed: true,
237
+ severity: 'critical'
238
+ };
239
+ }
240
+
241
+ /**
242
+ * Check 4: Module config files valid
243
+ */
244
+ async function checkConfigFiles(config) {
245
+ const projectRoot = config.projectRoot || process.cwd();
246
+ const modules = ['bmb']; // For now only bmb has config
247
+
248
+ const invalidConfigs = [];
249
+
250
+ for (const module of modules) {
251
+ const configPath = path.join(projectRoot, '_bmad', module, 'config.yaml');
252
+ if (await fileUtils.exists(configPath)) {
253
+ try {
254
+ const configContent = await fileUtils.readFile(configPath, 'utf8');
255
+ const parsedConfig = yamlUtils.load(configContent);
256
+
257
+ // Validate required fields
258
+ if (!parsedConfig.user_name) {
259
+ invalidConfigs.push(`${module}/config.yaml: missing user_name`);
260
+ }
261
+ if (!parsedConfig.communication_language) {
262
+ invalidConfigs.push(`${module}/config.yaml: missing communication_language`);
263
+ }
264
+ } catch (error) {
265
+ invalidConfigs.push(`${module}/config.yaml: parse error - ${error.message}`);
266
+ }
267
+ } else {
268
+ invalidConfigs.push(`${module}/config.yaml: file not found`);
269
+ }
270
+ }
271
+
272
+ if (invalidConfigs.length > 0) {
273
+ return {
274
+ id: 'config-files',
275
+ name: 'Config files',
276
+ passed: false,
277
+ message: invalidConfigs.join(', '),
278
+ severity: 'critical'
279
+ };
280
+ }
281
+
282
+ return {
283
+ id: 'config-files',
284
+ name: 'Config files',
285
+ passed: true,
286
+ severity: 'critical'
287
+ };
288
+ }
289
+
290
+ /**
291
+ * Check 5: Platform detection works
292
+ */
293
+ async function checkPlatformDetection(config) {
294
+ const targetPlatforms = config.targetPlatforms || [];
295
+
296
+ if (targetPlatforms.length === 0) {
297
+ return {
298
+ id: 'platform-detection',
299
+ name: 'Platform detection',
300
+ passed: true,
301
+ message: 'No platforms configured',
302
+ severity: 'critical'
303
+ };
304
+ }
305
+
306
+ const failedPlatforms = [];
307
+
308
+ for (const platformName of targetPlatforms) {
309
+ try {
310
+ const platform = require(`../platforms/${platformName}`);
311
+ const detected = await platform.detect();
312
+
313
+ // If detection failed or returned error object
314
+ if (!detected || (typeof detected === 'object' && !detected.detected)) {
315
+ failedPlatforms.push(platformName);
316
+ }
317
+ } catch (error) {
318
+ failedPlatforms.push(`${platformName} (${error.message})`);
319
+ }
320
+ }
321
+
322
+ if (failedPlatforms.length > 0) {
323
+ return {
324
+ id: 'platform-detection',
325
+ name: 'Platform detection',
326
+ passed: false,
327
+ message: `Failed platforms: ${failedPlatforms.join(', ')}`,
328
+ severity: 'warning' // Warning because platform may be installed but not detected
329
+ };
330
+ }
331
+
332
+ return {
333
+ id: 'platform-detection',
334
+ name: 'Platform detection',
335
+ passed: true,
336
+ severity: 'critical'
337
+ };
338
+ }
339
+
340
+ /**
341
+ * Check 6: File permissions correct
342
+ */
343
+ async function checkFilePermissions(config) {
344
+ const projectRoot = config.projectRoot || process.cwd();
345
+ const testPaths = [
346
+ '_bmad',
347
+ '_bmad/_config',
348
+ '_bmad/bmb/config.yaml'
349
+ ];
350
+
351
+ const permissionIssues = [];
352
+
353
+ for (const testPath of testPaths) {
354
+ const fullPath = path.join(projectRoot, testPath);
355
+ if (await fileUtils.exists(fullPath)) {
356
+ try {
357
+ // Test read permission
358
+ await fileUtils.access(fullPath, fileUtils.constants.R_OK);
359
+
360
+ // Test write permission (only for directories and config files)
361
+ await fileUtils.access(fullPath, fileUtils.constants.W_OK);
362
+ } catch (error) {
363
+ permissionIssues.push(testPath);
364
+ }
365
+ }
366
+ }
367
+
368
+ if (permissionIssues.length > 0) {
369
+ return {
370
+ id: 'file-permissions',
371
+ name: 'File permissions',
372
+ passed: false,
373
+ message: `Permission issues: ${permissionIssues.join(', ')}`,
374
+ severity: 'warning'
375
+ };
376
+ }
377
+
378
+ return {
379
+ id: 'file-permissions',
380
+ name: 'File permissions',
381
+ passed: true,
382
+ severity: 'warning'
383
+ };
384
+ }
385
+
386
+ /**
387
+ * Check 7: Manifest files valid
388
+ */
389
+ async function checkManifests(config) {
390
+ const projectRoot = config.projectRoot || process.cwd();
391
+ const manifestFiles = [
392
+ '_bmad/_config/agent-manifest.csv',
393
+ '_bmad/_config/workflow-manifest.csv',
394
+ '_bmad/_config/task-manifest.csv'
395
+ ];
396
+
397
+ const issues = [];
398
+
399
+ for (const manifestFile of manifestFiles) {
400
+ const manifestPath = path.join(projectRoot, manifestFile);
401
+ if (await fileUtils.exists(manifestPath)) {
402
+ try {
403
+ const content = await fileUtils.readFile(manifestPath, 'utf8');
404
+ const lines = content.split('\n').filter(l => l.trim());
405
+
406
+ // Check header exists
407
+ if (lines.length === 0 || !lines[0].includes(',')) {
408
+ issues.push(`${manifestFile}: invalid format`);
409
+ }
410
+ } catch (error) {
411
+ issues.push(`${manifestFile}: ${error.message}`);
412
+ }
413
+ } else {
414
+ // Manifests are optional, don't fail if missing
415
+ // issues.push(`${manifestFile}: not found`);
416
+ }
417
+ }
418
+
419
+ if (issues.length > 0) {
420
+ return {
421
+ id: 'manifests',
422
+ name: 'Manifest files',
423
+ passed: false,
424
+ message: issues.join(', '),
425
+ severity: 'warning'
426
+ };
427
+ }
428
+
429
+ return {
430
+ id: 'manifests',
431
+ name: 'Manifest files',
432
+ passed: true,
433
+ severity: 'warning'
434
+ };
435
+ }
436
+
437
+ /**
438
+ * Check 8: Workflows accessible
439
+ */
440
+ async function checkWorkflows(config) {
441
+ const projectRoot = config.projectRoot || process.cwd();
442
+ const workflowDirs = [
443
+ '_bmad/core/workflows',
444
+ '_bmad/bmm/workflows',
445
+ '_bmad/bmb/workflows',
446
+ '_bmad/tea/workflows',
447
+ '_bmad/cis/workflows'
448
+ ];
449
+
450
+ let workflowCount = 0;
451
+ const issues = [];
452
+
453
+ for (const workflowDir of workflowDirs) {
454
+ const dirPath = path.join(projectRoot, workflowDir);
455
+ if (await fileUtils.exists(dirPath)) {
456
+ try {
457
+ const workflows = await fileUtils.readDir(dirPath);
458
+ workflowCount += workflows.length;
459
+ } catch (error) {
460
+ issues.push(`${workflowDir}: ${error.message}`);
461
+ }
462
+ }
463
+ }
464
+
465
+ if (issues.length > 0) {
466
+ return {
467
+ id: 'workflows',
468
+ name: 'Workflow files',
469
+ passed: false,
470
+ message: issues.join(', '),
471
+ severity: 'warning'
472
+ };
473
+ }
474
+
475
+ return {
476
+ id: 'workflows',
477
+ name: 'Workflow files',
478
+ passed: true,
479
+ message: `${workflowCount} workflows found`,
480
+ severity: 'warning'
481
+ };
482
+ }
483
+
484
+ /**
485
+ * Check 9: Templates valid
486
+ */
487
+ async function checkTemplates(config) {
488
+ const templatesDir = path.join(__dirname, '..', '..', 'templates', '_bmad');
489
+
490
+ if (!await fileUtils.exists(templatesDir)) {
491
+ return {
492
+ id: 'templates',
493
+ name: 'Template files',
494
+ passed: false,
495
+ message: 'Templates directory not found',
496
+ severity: 'warning'
497
+ };
498
+ }
499
+
500
+ const modules = ['core', 'bmm', 'bmb', 'tea', 'cis'];
501
+ const issues = [];
502
+
503
+ for (const module of modules) {
504
+ const agentsDir = path.join(templatesDir, module, 'agents');
505
+ if (!await fileUtils.exists(agentsDir)) {
506
+ issues.push(`${module}/agents missing`);
507
+ }
508
+ }
509
+
510
+ if (issues.length > 0) {
511
+ return {
512
+ id: 'templates',
513
+ name: 'Template files',
514
+ passed: false,
515
+ message: issues.join(', '),
516
+ severity: 'warning'
517
+ };
518
+ }
519
+
520
+ return {
521
+ id: 'templates',
522
+ name: 'Template files',
523
+ passed: true,
524
+ severity: 'warning'
525
+ };
526
+ }
527
+
528
+ /**
529
+ * Check 10: Dependencies installed
530
+ */
531
+ async function checkDependencies(config) {
532
+ const requiredDeps = [
533
+ 'fs-extra',
534
+ 'js-yaml',
535
+ 'chalk'
536
+ ];
537
+
538
+ const missingDeps = [];
539
+
540
+ for (const dep of requiredDeps) {
541
+ try {
542
+ require.resolve(dep);
543
+ } catch {
544
+ missingDeps.push(dep);
545
+ }
546
+ }
547
+
548
+ if (missingDeps.length > 0) {
549
+ return {
550
+ id: 'dependencies',
551
+ name: 'Dependencies',
552
+ passed: false,
553
+ message: `Missing: ${missingDeps.join(', ')}. Run: npm install`,
554
+ severity: 'critical'
555
+ };
556
+ }
557
+
558
+ return {
559
+ id: 'dependencies',
560
+ name: 'Dependencies',
561
+ passed: true,
562
+ severity: 'critical'
563
+ };
564
+ }
565
+
566
+ module.exports = {
567
+ validate,
568
+ checkBmadStructure,
569
+ checkAgentFiles,
570
+ checkStubsYamlFrontmatter,
571
+ checkConfigFiles,
572
+ checkPlatformDetection,
573
+ checkFilePermissions,
574
+ checkManifests,
575
+ checkWorkflows,
576
+ checkTemplates,
577
+ checkDependencies
578
+ };