fix: lint and formatting issues in non-interactive installation PR

- Fix ESLint errors: use switch over else-if, remove unused catch bindings, use slice over substring, use replaceAll over replace
- Fix Prettier formatting issues across all modified files
- Fix markdown lint: wrap bare URL in angle brackets

All tests passing: schemas, installation, validation, lint, markdown lint, and formatting checks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Nikita Levyankov 2025-12-18 12:23:46 +02:00
parent 57bd2c0731
commit 1dca5fb4b7
7 changed files with 73 additions and 67 deletions

View File

@ -21,6 +21,7 @@ npx bmad-method@alpha install -y
``` ```
This installs BMAD with: This installs BMAD with:
- Default user name from system (USER environment variable) - Default user name from system (USER environment variable)
- Intermediate skill level - Intermediate skill level
- Default output folder (`_bmad-output`) - Default output folder (`_bmad-output`)
@ -49,10 +50,11 @@ cat _bmad/bmm/config.yaml
``` ```
Example output: Example output:
```yaml ```yaml
user_name: Alice user_name: Alice
user_skill_level: intermediate user_skill_level: intermediate
output_folder: "{project-root}/_bmad-output" output_folder: '{project-root}/_bmad-output'
communication_language: English communication_language: English
``` ```
@ -169,29 +171,29 @@ npx bmad-method@alpha install -y \
### Core Options ### Core Options
| Option | Description | Default | Example | | Option | Description | Default | Example |
|--------|-------------|---------|---------| | --------------------------------- | ---------------------- | -------------- | ---------------------------------- |
| `-y, --non-interactive` | Skip all prompts | `false` | `install -y` | | `-y, --non-interactive` | Skip all prompts | `false` | `install -y` |
| `--user-name <name>` | User name | System user | `--user-name=Alice` | | `--user-name <name>` | User name | System user | `--user-name=Alice` |
| `--skill-level <level>` | Skill level | `intermediate` | `--skill-level=advanced` | | `--skill-level <level>` | Skill level | `intermediate` | `--skill-level=advanced` |
| `--output-folder <path>` | Output folder | `_bmad-output` | `--output-folder=.artifacts` | | `--output-folder <path>` | Output folder | `_bmad-output` | `--output-folder=.artifacts` |
| `--communication-language <lang>` | Communication language | `English` | `--communication-language=Spanish` | | `--communication-language <lang>` | Communication language | `English` | `--communication-language=Spanish` |
| `--document-language <lang>` | Document language | `English` | `--document-language=French` | | `--document-language <lang>` | Document language | `English` | `--document-language=French` |
### Module & Selection Options ### Module & Selection Options
| Option | Description | Example | | Option | Description | Example |
|--------|-------------|---------| | -------------------- | ------------------------- | ---------------------------------- |
| `--modules <list>` | Comma-separated modules | `--modules=core,bmm,bmbb` | | `--modules <list>` | Comma-separated modules | `--modules=core,bmm,bmbb` |
| `--agents <list>` | Comma-separated agents | `--agents=dev,architect,pm` | | `--agents <list>` | Comma-separated agents | `--agents=dev,architect,pm` |
| `--workflows <list>` | Comma-separated workflows | `--workflows=create-prd,dev-story` | | `--workflows <list>` | Comma-separated workflows | `--workflows=create-prd,dev-story` |
### Team & Profile Options ### Team & Profile Options
| Option | Description | Example | | Option | Description | Example |
|--------|-------------|---------| | ------------------ | ----------------------- | ------------------- |
| `--team <name>` | Install predefined team | `--team=fullstack` | | `--team <name>` | Install predefined team | `--team=fullstack` |
| `--profile <name>` | Installation profile | `--profile=minimal` | | `--profile <name>` | Installation profile | `--profile=minimal` |
## Team-Based Installation ## Team-Based Installation
@ -206,6 +208,7 @@ npx bmad-method@alpha install -y --team=fullstack
``` ```
**Includes:** **Includes:**
- Agents: analyst, architect, pm, sm, ux-designer - Agents: analyst, architect, pm, sm, ux-designer
- Module: BMM - Module: BMM
@ -218,6 +221,7 @@ npx bmad-method@alpha install -y --team=gamedev
``` ```
**Includes:** **Includes:**
- Agents: game-designer, game-dev, game-architect, game-scrum-master - Agents: game-designer, game-dev, game-architect, game-scrum-master
- Workflows: brainstorm-game, game-brief, gdd, narrative - Workflows: brainstorm-game, game-brief, gdd, narrative
- Module: BMGD (Game Development) - Module: BMGD (Game Development)
@ -252,6 +256,7 @@ npx bmad-method@alpha install -y --profile=minimal
``` ```
**Includes:** **Includes:**
- Modules: core - Modules: core
- Agents: dev - Agents: dev
- Workflows: create-tech-spec, quick-dev - Workflows: create-tech-spec, quick-dev
@ -265,6 +270,7 @@ npx bmad-method@alpha install -y --profile=solo-dev
``` ```
**Includes:** **Includes:**
- Modules: core, bmm - Modules: core, bmm
- Agents: dev, architect, analyst, tech-writer - Agents: dev, architect, analyst, tech-writer
- Workflows: create-tech-spec, quick-dev, dev-story, code-review, create-prd, create-architecture - Workflows: create-tech-spec, quick-dev, dev-story, code-review, create-prd, create-architecture
@ -278,6 +284,7 @@ npx bmad-method@alpha install -y --profile=full
``` ```
**Includes:** **Includes:**
- All modules - All modules
- All agents - All agents
- All workflows - All workflows
@ -291,6 +298,7 @@ npx bmad-method@alpha install -y --profile=team
``` ```
**Includes:** **Includes:**
- Modules: core, bmm - Modules: core, bmm
- Agents: dev, architect, pm, sm, analyst, ux-designer - Agents: dev, architect, pm, sm, analyst, ux-designer
- Workflows: create-product-brief, create-prd, create-architecture, create-epics-and-stories, sprint-planning, create-story, dev-story, code-review, workflow-init - Workflows: create-product-brief, create-prd, create-architecture, create-epics-and-stories, sprint-planning, create-story, dev-story, code-review, workflow-init
@ -437,4 +445,4 @@ fi
## Feedback ## Feedback
Found an issue or have a suggestion? Please report it at: Found an issue or have a suggestion? Please report it at:
https://github.com/bmad-code-org/BMAD-METHOD/issues <https://github.com/bmad-code-org/BMAD-METHOD/issues>

View File

@ -885,22 +885,37 @@ class ConfigCollector {
// Resolution order: CLI → ENV → existing → default → hardcoded // Resolution order: CLI → ENV → existing → default → hardcoded
if (moduleName === 'core') { if (moduleName === 'core') {
// Core module has special mappings // Core module has special mappings
if (key === 'user_name') { switch (key) {
value = resolveValue(cliOptions.userName, null, envDefaults.userName); case 'user_name': {
} else if (key === 'user_skill_level') { value = resolveValue(cliOptions.userName, null, envDefaults.userName);
value = resolveValue(cliOptions.skillLevel, null, item.default || 'intermediate');
} else if (key === 'communication_language') { break;
value = resolveValue( }
cliOptions.communicationLanguage, case 'user_skill_level': {
null, value = resolveValue(cliOptions.skillLevel, null, item.default || 'intermediate');
envDefaults.communicationLanguage,
); break;
} else if (key === 'document_output_language') { }
value = resolveValue(cliOptions.documentLanguage, null, envDefaults.documentLanguage); case 'communication_language': {
} else if (key === 'output_folder') { value = resolveValue(cliOptions.communicationLanguage, null, envDefaults.communicationLanguage);
value = resolveValue(cliOptions.outputFolder, null, item.default);
} else if (item.default !== undefined) { break;
value = item.default; }
case 'document_output_language': {
value = resolveValue(cliOptions.documentLanguage, null, envDefaults.documentLanguage);
break;
}
case 'output_folder': {
value = resolveValue(cliOptions.outputFolder, null, item.default);
break;
}
default: {
if (item.default !== undefined) {
value = item.default;
}
}
} }
} else { } else {
// For other modules, use defaults // For other modules, use defaults

View File

@ -26,7 +26,7 @@ function getUserName() {
if (userInfo.username) { if (userInfo.username) {
return userInfo.username; return userInfo.username;
} }
} catch (error) { } catch {
// os.userInfo() can fail in some environments // os.userInfo() can fail in some environments
} }

View File

@ -161,7 +161,7 @@ class ManifestGenerator {
// Wildcard matching: create-* matches create-prd, create-tech-spec, etc. // Wildcard matching: create-* matches create-prd, create-tech-spec, etc.
if (pattern.includes('*')) { if (pattern.includes('*')) {
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$'); const regex = new RegExp('^' + pattern.replaceAll('*', '.*') + '$');
return regex.test(workflowName); return regex.test(workflowName);
} }
@ -318,7 +318,7 @@ class ManifestGenerator {
// Wildcard matching: dev* matches dev, dev-story, etc. // Wildcard matching: dev* matches dev, dev-story, etc.
if (pattern.includes('*')) { if (pattern.includes('*')) {
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$'); const regex = new RegExp('^' + pattern.replaceAll('*', '.*') + '$');
return regex.test(agentName); return regex.test(agentName);
} }

View File

@ -58,9 +58,9 @@ function separateModifiers(list) {
for (const item of list) { for (const item of list) {
if (item.startsWith('+')) { if (item.startsWith('+')) {
result.add.push(item.substring(1)); result.add.push(item.slice(1));
} else if (item.startsWith('-')) { } else if (item.startsWith('-')) {
result.remove.push(item.substring(1)); result.remove.push(item.slice(1));
} else { } else {
result.base.push(item); result.base.push(item);
} }
@ -118,9 +118,7 @@ function parseOptions(cliOptions) {
if (normalized.profile) { if (normalized.profile) {
const profile = getProfile(normalized.profile); const profile = getProfile(normalized.profile);
if (!profile) { if (!profile) {
throw new Error( throw new Error(`Unknown profile: ${normalized.profile}. Valid profiles: minimal, full, solo-dev, team`);
`Unknown profile: ${normalized.profile}. Valid profiles: minimal, full, solo-dev, team`,
);
} }
// Profile provides defaults, but CLI options override // Profile provides defaults, but CLI options override
@ -136,9 +134,7 @@ function parseOptions(cliOptions) {
normalized.agents = Array.isArray(profile.agents) ? profile.agents : profile.agents; normalized.agents = Array.isArray(profile.agents) ? profile.agents : profile.agents;
} }
if (!normalized.workflows) { if (!normalized.workflows) {
normalized.workflows = Array.isArray(profile.workflows) normalized.workflows = Array.isArray(profile.workflows) ? profile.workflows : profile.workflows;
? profile.workflows
: profile.workflows;
} }
} }
@ -157,9 +153,7 @@ function validateOptions(options) {
if (options.skillLevel) { if (options.skillLevel) {
const validLevels = ['beginner', 'intermediate', 'advanced']; const validLevels = ['beginner', 'intermediate', 'advanced'];
if (!validLevels.includes(options.skillLevel.toLowerCase())) { if (!validLevels.includes(options.skillLevel.toLowerCase())) {
errors.push( errors.push(`Invalid skill level: ${options.skillLevel}. Valid values: beginner, intermediate, advanced`);
`Invalid skill level: ${options.skillLevel}. Valid values: beginner, intermediate, advanced`,
);
} }
} }
@ -167,9 +161,7 @@ function validateOptions(options) {
if (options.profile) { if (options.profile) {
const validProfiles = ['minimal', 'full', 'solo-dev', 'team']; const validProfiles = ['minimal', 'full', 'solo-dev', 'team'];
if (!validProfiles.includes(options.profile.toLowerCase())) { if (!validProfiles.includes(options.profile.toLowerCase())) {
errors.push( errors.push(`Invalid profile: ${options.profile}. Valid values: minimal, full, solo-dev, team`);
`Invalid profile: ${options.profile}. Valid values: minimal, full, solo-dev, team`,
);
} }
} }

View File

@ -28,14 +28,7 @@ const PROFILES = {
description: 'Single developer setup - dev tools and planning workflows', description: 'Single developer setup - dev tools and planning workflows',
modules: ['core', 'bmm'], modules: ['core', 'bmm'],
agents: ['dev', 'architect', 'analyst', 'tech-writer'], agents: ['dev', 'architect', 'analyst', 'tech-writer'],
workflows: [ workflows: ['create-tech-spec', 'quick-dev', 'dev-story', 'code-review', 'create-prd', 'create-architecture'],
'create-tech-spec',
'quick-dev',
'dev-story',
'code-review',
'create-prd',
'create-architecture',
],
}, },
team: { team: {

View File

@ -49,7 +49,7 @@ async function discoverTeams(projectRoot) {
} }
return teams; return teams;
} catch (error) { } catch {
// If glob fails, return empty array // If glob fails, return empty array
return []; return [];
} }
@ -75,9 +75,7 @@ async function loadTeam(teamName, projectRoot) {
if (!team) { if (!team) {
// Provide helpful error with suggestions // Provide helpful error with suggestions
const availableTeams = teams.map((t) => t.name).join(', '); const availableTeams = teams.map((t) => t.name).join(', ');
throw new Error( throw new Error(`Team '${teamName}' not found. Available teams: ${availableTeams || 'none'}`);
`Team '${teamName}' not found. Available teams: ${availableTeams || 'none'}`,
);
} }
// Load full team definition // Load full team definition
@ -130,12 +128,12 @@ function applyTeamModifiers(team, agentModifiers = [], workflowModifiers = []) {
// Parse and apply agent modifiers // Parse and apply agent modifiers
for (const modifier of agentModifiers) { for (const modifier of agentModifiers) {
if (modifier.startsWith('+')) { if (modifier.startsWith('+')) {
const agent = modifier.substring(1); const agent = modifier.slice(1);
if (!result.agents.includes(agent)) { if (!result.agents.includes(agent)) {
result.agents.push(agent); result.agents.push(agent);
} }
} else if (modifier.startsWith('-')) { } else if (modifier.startsWith('-')) {
const agent = modifier.substring(1); const agent = modifier.slice(1);
result.agents = result.agents.filter((a) => a !== agent); result.agents = result.agents.filter((a) => a !== agent);
} }
} }
@ -143,12 +141,12 @@ function applyTeamModifiers(team, agentModifiers = [], workflowModifiers = []) {
// Parse and apply workflow modifiers // Parse and apply workflow modifiers
for (const modifier of workflowModifiers) { for (const modifier of workflowModifiers) {
if (modifier.startsWith('+')) { if (modifier.startsWith('+')) {
const workflow = modifier.substring(1); const workflow = modifier.slice(1);
if (!result.workflows.includes(workflow)) { if (!result.workflows.includes(workflow)) {
result.workflows.push(workflow); result.workflows.push(workflow);
} }
} else if (modifier.startsWith('-')) { } else if (modifier.startsWith('-')) {
const workflow = modifier.substring(1); const workflow = modifier.slice(1);
result.workflows = result.workflows.filter((w) => w !== workflow); result.workflows = result.workflows.filter((w) => w !== workflow);
} }
} }